QrLuminance.kt

/*
 * This file is part of GNU Taler
 * (C) 2026 Taler Systems S.A.
 *
 * GNU Taler is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 3, or (at your option) any later version.
 *
 * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */

package net.taler.merchantpos.config

import com.google.zxing.PlanarYUVLuminanceSource

import java.nio.ByteBuffer

/** Camera planes may contain padding between rows and between individual pixels. */
internal fun qrLuminance(
    buffer: ByteBuffer,
    width: Int,
    height: Int,
    rowStride: Int,
    pixelStride: Int,
    rotation: Int,
): PlanarYUVLuminanceSource
{
    require(width > 0 && height > 0 && pixelStride > 0)
    require(rowStride.toLong() >= (width - 1L) * pixelStride + 1)
    require(rotation in setOf(0, 90, 180, 270))
    require((height - 1L) * rowStride + (width - 1L) * pixelStride < buffer.remaining())
    val swapped = rotation == 90 || rotation == 270
    val outputWidth = if (swapped) height else width
    val outputHeight = if (swapped) width else height
    val pixels = ByteArray(Math.multiplyExact(width, height))
    val offset = buffer.position()
    for (y in 0 until height)
    {
        for (x in 0 until width)
        {
            val destination =
                when (rotation)
                {
                    90 -> x * outputWidth + height - 1 - y
                    180 -> (height - 1 - y) * outputWidth + width - 1 - x
                    270 -> (width - 1 - x) * outputWidth + y
                    else -> y * outputWidth + x
                }
            pixels[destination] = buffer.get(offset + y * rowStride + x * pixelStride)
        }
    }
    return PlanarYUVLuminanceSource(
        pixels,
        outputWidth,
        outputHeight,
        0,
        0,
        outputWidth,
        outputHeight,
        false,
    )
}