From 8a9d465bb122937e1a1d4a9fdc8fef93a1445454 Mon Sep 17 00:00:00 2001 From: Adam Velebil Date: Mon, 16 Oct 2023 17:17:01 +0200 Subject: [PATCH] decodeFromBytes --- .../gradle/wrapper/gradle-wrapper.properties | 4 +- .../qrscanner_zxing/QRScannerView.kt | 2 +- .../qrscanner_zxing/QRScannerZxingPlugin.kt | 53 ++++--------------- .../qrscanner_zxing/QrScanner.kt | 44 ++++++++++++++- .../qrscanner_zxing/example/lib/main.dart | 12 +++-- .../lib/qrscanner_zxing_method_channel.dart | 6 +-- .../qrscanner_zxing_platform_interface.dart | 4 +- .../test/qrscanner_zxing_test.dart | 4 +- 8 files changed, 69 insertions(+), 60 deletions(-) diff --git a/android/flutter_plugins/qrscanner_zxing/android/gradle/wrapper/gradle-wrapper.properties b/android/flutter_plugins/qrscanner_zxing/android/gradle/wrapper/gradle-wrapper.properties index 6b665338..2e0997a2 100644 --- a/android/flutter_plugins/qrscanner_zxing/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/flutter_plugins/qrscanner_zxing/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Jun 23 08:50:38 CEST 2017 +#Mon Oct 16 08:48:17 CEST 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/android/flutter_plugins/qrscanner_zxing/android/src/main/kotlin/com/yubico/authenticator/flutter_plugins/qrscanner_zxing/QRScannerView.kt b/android/flutter_plugins/qrscanner_zxing/android/src/main/kotlin/com/yubico/authenticator/flutter_plugins/qrscanner_zxing/QRScannerView.kt index 92cf928b..fb7cbfed 100644 --- a/android/flutter_plugins/qrscanner_zxing/android/src/main/kotlin/com/yubico/authenticator/flutter_plugins/qrscanner_zxing/QRScannerView.kt +++ b/android/flutter_plugins/qrscanner_zxing/android/src/main/kotlin/com/yubico/authenticator/flutter_plugins/qrscanner_zxing/QRScannerView.kt @@ -389,7 +389,7 @@ internal class QRScannerView( fullSize } - val result = QrCodeScanner.scan(bitmapToProcess) + val result = QrCodeScanner.decodeFromBinaryBitmap(bitmapToProcess) if (analysisPaused) { return } diff --git a/android/flutter_plugins/qrscanner_zxing/android/src/main/kotlin/com/yubico/authenticator/flutter_plugins/qrscanner_zxing/QRScannerZxingPlugin.kt b/android/flutter_plugins/qrscanner_zxing/android/src/main/kotlin/com/yubico/authenticator/flutter_plugins/qrscanner_zxing/QRScannerZxingPlugin.kt index 803402b8..2ad04d49 100644 --- a/android/flutter_plugins/qrscanner_zxing/android/src/main/kotlin/com/yubico/authenticator/flutter_plugins/qrscanner_zxing/QRScannerZxingPlugin.kt +++ b/android/flutter_plugins/qrscanner_zxing/android/src/main/kotlin/com/yubico/authenticator/flutter_plugins/qrscanner_zxing/QRScannerZxingPlugin.kt @@ -16,12 +16,6 @@ package com.yubico.authenticator.flutter_plugins.qrscanner_zxing -import android.graphics.Bitmap -import android.graphics.BitmapFactory -import android.util.Log -import com.google.zxing.BinaryBitmap -import com.google.zxing.RGBLuminanceSource -import com.google.zxing.common.HybridBinarizer import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.embedding.engine.plugins.activity.ActivityAware import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding @@ -30,7 +24,6 @@ import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel.MethodCallHandler import io.flutter.plugin.common.MethodChannel.Result import io.flutter.plugin.common.PluginRegistry -import java.lang.Exception class PermissionsResultRegistrar { @@ -76,41 +69,17 @@ class QRScannerZxingPlugin : FlutterPlugin, MethodCallHandler, ActivityAware, "getPlatformVersion" -> { result.success("Android ${android.os.Build.VERSION.RELEASE}") } - "scanBitmap" -> { - val imageFileData = call.argument("bitmap") - var bitmap: Bitmap? = null - try { - imageFileData?.let { byteArray -> - Log.i(TAG, "Received ${byteArray.size} bytes") - val options = BitmapFactory.Options() - options.inSampleSize = 4 - bitmap = BitmapFactory.decodeByteArray(imageFileData, 0, byteArray.size, options) - bitmap?.let { - val intArray = IntArray(it.allocationByteCount) - it.getPixels(intArray, 0, it.width, 0, 0, it.width, it.height) - val luminanceSource = - RGBLuminanceSource(it.rowBytes, it.height, intArray) - val binaryBitmap = BinaryBitmap(HybridBinarizer(luminanceSource)) - val scanResult = QrCodeScanner.scan(binaryBitmap) - Log.i(TAG, "Scan result: $scanResult") - result.success(scanResult) - return - } - } - } catch (e: Exception) { - Log.e(TAG, "Failure decoding data: $e") - result.error("Failed to decode", e.message, e) - return - } finally { - bitmap?.let { - it.recycle() - bitmap = null - } - } - Log.e(TAG, "Failure decoding data: Invalid image format ") - result.error("Failed to decode", "Invalid image format", null) + "scanBitmap" -> { + val bytes = call.argument("bytes") + if (bytes != null) { + val scanResult = QrCodeScanner.decodeFromBytes(bytes) + result.success(scanResult) + } else { + result.error("Failure", "Invalid image", null) + } } + else -> { result.notImplemented() } @@ -142,8 +111,4 @@ class QRScannerZxingPlugin : FlutterPlugin, MethodCallHandler, ActivityAware, ): Boolean { return registrar.onResult(requestCode, permissions, grantResults) } - - companion object { - const val TAG = "QRScannerZxPlugin" - } } diff --git a/android/flutter_plugins/qrscanner_zxing/android/src/main/kotlin/com/yubico/authenticator/flutter_plugins/qrscanner_zxing/QrScanner.kt b/android/flutter_plugins/qrscanner_zxing/android/src/main/kotlin/com/yubico/authenticator/flutter_plugins/qrscanner_zxing/QrScanner.kt index c34ad3ad..7ea6902d 100644 --- a/android/flutter_plugins/qrscanner_zxing/android/src/main/kotlin/com/yubico/authenticator/flutter_plugins/qrscanner_zxing/QrScanner.kt +++ b/android/flutter_plugins/qrscanner_zxing/android/src/main/kotlin/com/yubico/authenticator/flutter_plugins/qrscanner_zxing/QrScanner.kt @@ -1,9 +1,15 @@ package com.yubico.authenticator.flutter_plugins.qrscanner_zxing +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.util.Log import com.google.zxing.BarcodeFormat import com.google.zxing.BinaryBitmap import com.google.zxing.DecodeHintType import com.google.zxing.MultiFormatReader +import com.google.zxing.NotFoundException +import com.google.zxing.RGBLuminanceSource +import com.google.zxing.common.HybridBinarizer object QrCodeScanner { @@ -11,8 +17,42 @@ object QrCodeScanner { it.setHints(mapOf(DecodeHintType.POSSIBLE_FORMATS to listOf(BarcodeFormat.QR_CODE))) } - fun scan(binaryBitmap: BinaryBitmap) : String { - val result: com.google.zxing.Result = qrCodeScanner.decode(binaryBitmap) + fun decodeFromBinaryBitmap(binaryBitmap: BinaryBitmap): String { + val result = qrCodeScanner.decode(binaryBitmap) return result.text } + + fun decodeFromBytes(byteArray: ByteArray): String? { + var bitmap: Bitmap? = null + try { + Log.v(TAG, "Received ${byteArray.size} bytes") + val options = BitmapFactory.Options() + bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size, options) + bitmap?.let { + val pixels = IntArray(it.allocationByteCount) + it.getPixels(pixels, 0, it.width, 0, 0, it.width, it.height) + val luminanceSource = + RGBLuminanceSource(it.width, it.height, pixels) + val binaryBitmap = BinaryBitmap(HybridBinarizer(luminanceSource)) + val scanResult = decodeFromBinaryBitmap(binaryBitmap) + Log.v(TAG, "Scan result: $scanResult") + return scanResult + } + Log.e(TAG, "Could not decode image data.") + return null + } catch (_: NotFoundException) { + Log.e(TAG, "No QR code found/decoded.") + return null + } catch (e: Throwable) { + Log.e(TAG, "Exception while decoding data: ", e) + return null + } finally { + bitmap?.let { + it.recycle() + bitmap = null + } + } + } + + private const val TAG = "QRScanner" } \ No newline at end of file diff --git a/android/flutter_plugins/qrscanner_zxing/example/lib/main.dart b/android/flutter_plugins/qrscanner_zxing/example/lib/main.dart index 12c2c55c..097404b0 100644 --- a/android/flutter_plugins/qrscanner_zxing/example/lib/main.dart +++ b/android/flutter_plugins/qrscanner_zxing/example/lib/main.dart @@ -68,8 +68,10 @@ class AppHomePage extends StatelessWidget { child: const Text("Open QR Scanner")), ElevatedButton( onPressed: () async { + var channel = MethodChannelQRScannerZxing(); + final scaffoldMessenger = ScaffoldMessenger.of(context); final result = await FilePicker.platform.pickFiles( - allowedExtensions: ['png', 'jpg'], + allowedExtensions: ['png', 'jpg', 'gif', 'webp'], type: FileType.custom, allowMultiple: false, lockParentWindow: true, @@ -82,11 +84,13 @@ class AppHomePage extends StatelessWidget { } final bytes = result.files.first.bytes; - if (bytes != null) { - var channel = MethodChannelQRScannerZxing(); var value = await channel.scanBitmap(bytes); - debugPrint(value); + final snackBar = SnackBar( + content: Text(value == null + ? 'No QR code detected' + : 'QR: $value')); + scaffoldMessenger.showSnackBar(snackBar); } else { // no files selected } diff --git a/android/flutter_plugins/qrscanner_zxing/lib/qrscanner_zxing_method_channel.dart b/android/flutter_plugins/qrscanner_zxing/lib/qrscanner_zxing_method_channel.dart index 8642fbbb..225d4db9 100644 --- a/android/flutter_plugins/qrscanner_zxing/lib/qrscanner_zxing_method_channel.dart +++ b/android/flutter_plugins/qrscanner_zxing/lib/qrscanner_zxing_method_channel.dart @@ -28,14 +28,14 @@ class MethodChannelQRScannerZxing extends QRScannerZxingPlatform { @override Future getPlatformVersion() async { final version = - await methodChannel.invokeMethod('getPlatformVersion'); + await methodChannel.invokeMethod('getPlatformVersion'); return version; } @override - Future scanBitmap(Uint8List bitmap) async { + Future scanBitmap(Uint8List bytes) async { final version = await methodChannel - .invokeMethod('scanBitmap', {'bitmap': bitmap}); + .invokeMethod('scanBitmap', {'bytes': bytes}); return version; } } diff --git a/android/flutter_plugins/qrscanner_zxing/lib/qrscanner_zxing_platform_interface.dart b/android/flutter_plugins/qrscanner_zxing/lib/qrscanner_zxing_platform_interface.dart index 54740987..a86861b8 100644 --- a/android/flutter_plugins/qrscanner_zxing/lib/qrscanner_zxing_platform_interface.dart +++ b/android/flutter_plugins/qrscanner_zxing/lib/qrscanner_zxing_platform_interface.dart @@ -45,7 +45,7 @@ abstract class QRScannerZxingPlatform extends PlatformInterface { throw UnimplementedError('platformVersion() has not been implemented.'); } - Future scanBitmap(Uint8List bitmap) { - throw UnimplementedError('platformVersion() has not been implemented.'); + Future scanBitmap(Uint8List bytes) { + throw UnimplementedError('scanBitmap(Uint8List) has not been implemented.'); } } diff --git a/android/flutter_plugins/qrscanner_zxing/test/qrscanner_zxing_test.dart b/android/flutter_plugins/qrscanner_zxing/test/qrscanner_zxing_test.dart index 85ccd7d1..562ae25d 100644 --- a/android/flutter_plugins/qrscanner_zxing/test/qrscanner_zxing_test.dart +++ b/android/flutter_plugins/qrscanner_zxing/test/qrscanner_zxing_test.dart @@ -29,8 +29,8 @@ class MockQRScannerZxingPlatform Future getPlatformVersion() => Future.value('42'); @override - Future scanBitmap(Uint8List bitmap) => - Future.value(bitmap.length.toString()); + Future scanBitmap(Uint8List bytes) => + Future.value(bytes.length.toString()); } void main() {