diff --git a/example/src/main/java/ch/ubique/qrscanner/example/ComposeActivity.kt b/example/src/main/java/ch/ubique/qrscanner/example/ComposeActivity.kt index cf3b2d6..974204d 100644 --- a/example/src/main/java/ch/ubique/qrscanner/example/ComposeActivity.kt +++ b/example/src/main/java/ch/ubique/qrscanner/example/ComposeActivity.kt @@ -5,7 +5,13 @@ import android.os.Bundle import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.material.Button import androidx.compose.material.Slider import androidx.compose.material.Text @@ -16,6 +22,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import ch.ubique.qrscanner.compose.QrScanner import ch.ubique.qrscanner.example.databinding.ActivityComposeBinding +import ch.ubique.qrscanner.mlkit.decoder.MLKitImageDecoder import ch.ubique.qrscanner.scanner.QrScannerCallback import ch.ubique.qrscanner.state.DecodingState import ch.ubique.qrscanner.zxing.decoder.GlobalHistogramImageDecoder @@ -44,7 +51,7 @@ class ComposeActivity : AppCompatActivity() { binding.composeView.setContent { Box(Modifier.fillMaxSize()) { QrScanner( - imageDecoders = listOf(GlobalHistogramImageDecoder(), HybridImageDecoder()), + imageDecoders = listOf(MLKitImageDecoder(), GlobalHistogramImageDecoder(), HybridImageDecoder()), scannerCallback = scannerCallback, modifier = Modifier.fillMaxSize(), isFlashEnabled = isFlashEnabled.collectAsState(), diff --git a/qrscanner-core/src/main/java/ch/ubique/qrscanner/scanner/ErrorCodes.kt b/qrscanner-core/src/main/java/ch/ubique/qrscanner/scanner/ErrorCodes.kt index 1d339d7..5a15f21 100644 --- a/qrscanner-core/src/main/java/ch/ubique/qrscanner/scanner/ErrorCodes.kt +++ b/qrscanner-core/src/main/java/ch/ubique/qrscanner/scanner/ErrorCodes.kt @@ -1,5 +1,13 @@ package ch.ubique.qrscanner.scanner object ErrorCodes { + /** + * Happens when the image proxy input has the wrong format (YUV format is expected) + */ const val INPUT_WRONG_FORMAT = 1 + + /** + * The image decoder failed to read the image proxy input + */ + const val INPUT_READ_FAILED = 2 } \ No newline at end of file diff --git a/qrscanner-zxing/src/main/java/ch/ubique/qrscanner/zxing/decoder/ZXingImageDecoder.kt b/qrscanner-zxing/src/main/java/ch/ubique/qrscanner/zxing/decoder/ZXingImageDecoder.kt index 4cb4bfd..e467bbd 100644 --- a/qrscanner-zxing/src/main/java/ch/ubique/qrscanner/zxing/decoder/ZXingImageDecoder.kt +++ b/qrscanner-zxing/src/main/java/ch/ubique/qrscanner/zxing/decoder/ZXingImageDecoder.kt @@ -6,7 +6,17 @@ import androidx.camera.core.ImageProxy import ch.ubique.qrscanner.scanner.ErrorCodes import ch.ubique.qrscanner.scanner.ImageDecoder import ch.ubique.qrscanner.state.DecodingState -import com.google.zxing.* +import com.google.zxing.BarcodeFormat +import com.google.zxing.Binarizer +import com.google.zxing.BinaryBitmap +import com.google.zxing.ChecksumException +import com.google.zxing.DecodeHintType +import com.google.zxing.FormatException +import com.google.zxing.LuminanceSource +import com.google.zxing.MultiFormatReader +import com.google.zxing.NotFoundException +import com.google.zxing.PlanarYUVLuminanceSource +import com.google.zxing.RGBLuminanceSource import com.google.zxing.common.GlobalHistogramBinarizer import com.google.zxing.common.HybridBinarizer import kotlinx.coroutines.Dispatchers @@ -31,18 +41,22 @@ abstract class ZXingImageDecoder( override suspend fun decodeFrame(image: ImageProxy): DecodingState = withContext(Dispatchers.IO) { if (image.format in yuvFormats && image.planes.size == 3) { - val buffer = image.planes[0].buffer - val data = buffer.toByteArray() - val source = PlanarYUVLuminanceSource( - data, - image.planes[0].rowStride, - image.height, - 0, - 0, - image.width, - image.height, - false - ) + val source = try { + val buffer = image.planes[0].buffer.asReadOnlyBuffer() + val data = buffer.toByteArray() + PlanarYUVLuminanceSource( + data, + image.planes[0].rowStride, + image.height, + 0, + 0, + image.width, + image.height, + false + ) + } catch (e: Exception) { + return@withContext DecodingState.Error(ErrorCodes.INPUT_READ_FAILED) + } return@withContext decodeLuminanceSource(source) } else {