decodeFromBytes

This commit is contained in:
Adam Velebil 2023-10-16 17:17:01 +02:00
parent 3b766fb28f
commit 8a9d465bb1
No known key found for this signature in database
GPG Key ID: C9B1E4A3CBBD2E10
8 changed files with 69 additions and 60 deletions

View File

@ -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

View File

@ -389,7 +389,7 @@ internal class QRScannerView(
fullSize
}
val result = QrCodeScanner.scan(bitmapToProcess)
val result = QrCodeScanner.decodeFromBinaryBitmap(bitmapToProcess)
if (analysisPaused) {
return
}

View File

@ -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<ByteArray>("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<ByteArray>("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"
}
}

View File

@ -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"
}

View File

@ -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
}

View File

@ -28,14 +28,14 @@ class MethodChannelQRScannerZxing extends QRScannerZxingPlatform {
@override
Future<String?> getPlatformVersion() async {
final version =
await methodChannel.invokeMethod<String>('getPlatformVersion');
await methodChannel.invokeMethod<String>('getPlatformVersion');
return version;
}
@override
Future<String?> scanBitmap(Uint8List bitmap) async {
Future<String?> scanBitmap(Uint8List bytes) async {
final version = await methodChannel
.invokeMethod<String>('scanBitmap', {'bitmap': bitmap});
.invokeMethod<String>('scanBitmap', {'bytes': bytes});
return version;
}
}

View File

@ -45,7 +45,7 @@ abstract class QRScannerZxingPlatform extends PlatformInterface {
throw UnimplementedError('platformVersion() has not been implemented.');
}
Future<String?> scanBitmap(Uint8List bitmap) {
throw UnimplementedError('platformVersion() has not been implemented.');
Future<String?> scanBitmap(Uint8List bytes) {
throw UnimplementedError('scanBitmap(Uint8List) has not been implemented.');
}
}

View File

@ -29,8 +29,8 @@ class MockQRScannerZxingPlatform
Future<String?> getPlatformVersion() => Future.value('42');
@override
Future<String?> scanBitmap(Uint8List bitmap) =>
Future.value(bitmap.length.toString());
Future<String?> scanBitmap(Uint8List bytes) =>
Future.value(bytes.length.toString());
}
void main() {