secant-android-wallet/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/scan/util/QrCodeAnalyzer.kt

68 lines
2.1 KiB
Kotlin

package co.electriccoin.zcash.ui.screen.scan.util
import android.graphics.ImageFormat
import androidx.camera.core.ImageAnalysis
import androidx.camera.core.ImageProxy
import com.google.zxing.BarcodeFormat
import com.google.zxing.BinaryBitmap
import com.google.zxing.DecodeHintType
import com.google.zxing.MultiFormatReader
import com.google.zxing.PlanarYUVLuminanceSource
import com.google.zxing.common.HybridBinarizer
import java.nio.ByteBuffer
// TODO [#437]: https://github.com/zcash/secant-android-wallet/issues/437
class QrCodeAnalyzer(
private val onQrCodeScanned: (String) -> Unit
) : ImageAnalysis.Analyzer {
private val supportedImageFormats = listOf(
ImageFormat.YUV_420_888,
ImageFormat.YUV_422_888,
ImageFormat.YUV_444_888
)
override fun analyze(image: ImageProxy) {
image.use {
if (image.format in supportedImageFormats) {
val bytes = image.planes.first().buffer.toByteArray()
val source = PlanarYUVLuminanceSource(
bytes,
image.width,
image.height,
0,
0,
image.width,
image.height,
false
)
val binaryBmp = BinaryBitmap(HybridBinarizer(source))
runCatching {
val result = MultiFormatReader().apply {
setHints(
mapOf(
DecodeHintType.POSSIBLE_FORMATS to arrayListOf(
BarcodeFormat.QR_CODE
)
)
)
}.decode(binaryBmp)
onQrCodeScanned(result.text)
}.onFailure {
// failed to found QR code in current frame
}
}
}
}
private fun ByteBuffer.toByteArray(): ByteArray {
rewind()
return ByteArray(remaining()).also {
get(it)
}
}
}