From 8425459c6af03e738794b86a0dca6ff82a160976 Mon Sep 17 00:00:00 2001 From: Khoren Markosyan Date: Sat, 9 Apr 2022 18:48:36 +0400 Subject: [PATCH] allow to set code format for reader --- example/pubspec.lock | 10 +++++----- example/pubspec.yaml | 2 +- ios/Classes/src/native_zxing.cpp | 30 ++++++++++++++++++++---------- ios/Classes/src/native_zxing.h | 10 +++++++--- lib/flutter_zxing.dart | 13 +++++++++---- lib/generated_bindings.dart | 30 ++++++++++++++++++++++-------- lib/isolate_utils.dart | 25 ++++++++++++++++--------- lib/zxing_reader_widget.dart | 5 ++++- pubspec.yaml | 2 +- 9 files changed, 85 insertions(+), 42 deletions(-) diff --git a/example/pubspec.lock b/example/pubspec.lock index 1fd1c8d..1d0bfdf 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -7,7 +7,7 @@ packages: name: archive url: "https://pub.dartlang.org" source: hosted - version: "3.2.2" + version: "3.3.0" async: dependency: transitive description: @@ -28,7 +28,7 @@ packages: name: camera url: "https://pub.dartlang.org" source: hosted - version: "0.9.4+16" + version: "0.9.4+19" camera_platform_interface: dependency: transitive description: @@ -302,7 +302,7 @@ packages: name: share_plus url: "https://pub.dartlang.org" source: hosted - version: "4.0.1" + version: "4.0.3" share_plus_linux: dependency: transitive description: @@ -323,7 +323,7 @@ packages: name: share_plus_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "3.0.2" share_plus_web: dependency: transitive description: @@ -468,7 +468,7 @@ packages: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "2.4.2" + version: "2.5.1" xdg_directories: dependency: transitive description: diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 41773e4..0cc1219 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -13,7 +13,7 @@ dependencies: flutter_zxing: path: ../ path_provider: ^2.0.9 - share_plus: ^4.0.1 + share_plus: ^4.0.3 dev_dependencies: flutter_lints: ^1.0.0 diff --git a/ios/Classes/src/native_zxing.cpp b/ios/Classes/src/native_zxing.cpp index 2a76e52..3e70b0e 100644 --- a/ios/Classes/src/native_zxing.cpp +++ b/ios/Classes/src/native_zxing.cpp @@ -16,7 +16,7 @@ extern "C" } FUNCTION_ATTRIBUTE - struct CodeResult zxingRead(char *bytes, int width, int height, int cropSize) + struct CodeResult zxingRead(char *bytes, int format, int width, int height, int cropWidth, int cropHeight, int logEnabled) { long long start = get_now(); @@ -24,11 +24,12 @@ extern "C" uint8_t *data = new uint8_t[length]; memcpy(data, bytes, length); - BarcodeFormats formats = BarcodeFormat::Any; + BarcodeFormats formats = BarcodeFormat(format); // BarcodeFormat::Any; DecodeHints hints = DecodeHints().setTryHarder(false).setTryRotate(true).setFormats(formats); ImageView image{data, width, height, ImageFormat::Lum}; - if (cropSize > 0 && cropSize < width && cropSize < height) { - image = image.cropped(width / 2 - cropSize / 2, height / 2 - cropSize / 2, cropSize, cropSize); + if (cropWidth > 0 && cropHeight > 0 && cropWidth < width && cropHeight < height) + { + image = image.cropped(width / 2 - cropWidth / 2, height / 2 - cropHeight / 2, cropWidth, cropHeight); } Result result = ReadBarcode(image, hints); @@ -43,16 +44,19 @@ extern "C" } int evalInMillis = static_cast(get_now() - start); - platform_log("Read done in %dms\n", evalInMillis); + if (logEnabled) + { + platform_log("zxingRead: %d ms", evalInMillis); + } return code; } FUNCTION_ATTRIBUTE - struct EncodeResult zxingEncode(char *contents, int width, int height, int format, int margin, int eccLevel) + struct EncodeResult zxingEncode(char *contents, int width, int height, int format, int margin, int eccLevel, int logEnabled) { long long start = get_now(); - - struct EncodeResult result = { nullptr, 0, false, nullptr }; + + struct EncodeResult result = {nullptr, 0, false, nullptr}; try { auto writer = MultiFormatWriter(BarcodeFormat(format)).setMargin(margin).setEccLevel(eccLevel); @@ -63,13 +67,19 @@ extern "C" } catch (const std::exception &e) { - platform_log("Can't encode text: %s\nError: %s\n", contents, e.what()); + if (logEnabled) + { + platform_log("Can't encode text: %s\nError: %s\n", contents, e.what()); + } result.error = new char[strlen(e.what()) + 1]; strcpy(result.error, e.what()); } int evalInMillis = static_cast(get_now() - start); - platform_log("Encode done in %dms\n", evalInMillis); + if (logEnabled) + { + platform_log("zxingEncode: %d ms", evalInMillis); + } return result; } } diff --git a/ios/Classes/src/native_zxing.h b/ios/Classes/src/native_zxing.h index 79b5f73..890efa5 100644 --- a/ios/Classes/src/native_zxing.h +++ b/ios/Classes/src/native_zxing.h @@ -53,12 +53,15 @@ extern "C" /** * @brief Reads barcode from image. * @param bytes Image bytes. + * @param format The format of the barcode * @param width Image width. * @param height Image height. - * @param cropSize Crop size. + * @param cropWidth Crop width. + * @param cropHeight Crop height. + * @param logEnabled Log enabled. * @return Barcode result. */ - struct CodeResult zxingRead(char *bytes, int width, int height, int cropSize); + struct CodeResult zxingRead(char *bytes, int format, int width, int height, int cropWidth, int cropHeight, int logEnabled); /** * @brief Encode a string into a barcode @@ -67,10 +70,11 @@ extern "C" * @param height The height of the barcode * @param format The format of the barcode * @param margin The margin of the barcode + * @param logEnabled Log enabled. * @param eccLevel The error correction level of the barcode. Used for Aztec, PDF417, and QRCode only, [0-8]. * @return The barcode data */ - struct EncodeResult zxingEncode(char *contents, int width, int height, int format, int margin, int eccLevel); + struct EncodeResult zxingEncode(char *contents, int width, int height, int format, int margin, int eccLevel, int logEnabled); #ifdef __cplusplus } diff --git a/lib/flutter_zxing.dart b/lib/flutter_zxing.dart index 72824f4..9bc50ab 100644 --- a/lib/flutter_zxing.dart +++ b/lib/flutter_zxing.dart @@ -18,21 +18,26 @@ class FlutterZxing { static final bindings = GeneratedBindings(dylib); + static bool logEnabled = true; + static String zxingVersion() { return bindings.zxingVersion().cast().toDartString(); } - static CodeResult zxingRead( - Uint8List bytes, int width, int height, int cropSize) { - return bindings.zxingRead(bytes.allocatePointer(), width, height, cropSize); + static CodeResult zxingRead(Uint8List bytes, int format, int width, + int height, int cropWidth, int cropHeight) { + return bindings.zxingRead(bytes.allocatePointer(), format, width, height, + cropWidth, cropHeight, _logEnabled); } static EncodeResult zxingEncode(String contents, int width, int height, int format, int margin, int eccLevel) { var result = bindings.zxingEncode(contents.toNativeUtf8().cast(), - width, height, format, margin, eccLevel); + width, height, format, margin, eccLevel, _logEnabled); return result; } + + static int get _logEnabled => logEnabled ? 1 : 0; } // Getting a library that holds needed symbols diff --git a/lib/generated_bindings.dart b/lib/generated_bindings.dart index 395cac3..d65b1dc 100644 --- a/lib/generated_bindings.dart +++ b/lib/generated_bindings.dart @@ -34,30 +34,40 @@ class GeneratedBindings { /// @brief Reads barcode from image. /// @param bytes Image bytes. + /// @param format The format of the barcode /// @param width Image width. /// @param height Image height. - /// @param cropSize Crop size. + /// @param cropWidth Crop width. + /// @param cropHeight Crop height. + /// @param logEnabled Log enabled. /// @return Barcode result. CodeResult zxingRead( ffi.Pointer bytes, + int format, int width, int height, - int cropSize, + int cropWidth, + int cropHeight, + int logEnabled, ) { return _zxingRead( bytes, + format, width, height, - cropSize, + cropWidth, + cropHeight, + logEnabled, ); } late final _zxingReadPtr = _lookup< ffi.NativeFunction< CodeResult Function(ffi.Pointer, ffi.Int32, ffi.Int32, - ffi.Int32)>>('zxingRead'); - late final _zxingRead = _zxingReadPtr - .asFunction, int, int, int)>(); + ffi.Int32, ffi.Int32, ffi.Int32, ffi.Int32)>>('zxingRead'); + late final _zxingRead = _zxingReadPtr.asFunction< + CodeResult Function( + ffi.Pointer, int, int, int, int, int, int)>(); /// @brief Encode a string into a barcode /// @param contents The string to encode @@ -65,6 +75,7 @@ class GeneratedBindings { /// @param height The height of the barcode /// @param format The format of the barcode /// @param margin The margin of the barcode + /// @param logEnabled Log enabled. /// @param eccLevel The error correction level of the barcode. Used for Aztec, PDF417, and QRCode only, [0-8]. /// @return The barcode data EncodeResult zxingEncode( @@ -74,6 +85,7 @@ class GeneratedBindings { int format, int margin, int eccLevel, + int logEnabled, ) { return _zxingEncode( contents, @@ -82,15 +94,17 @@ class GeneratedBindings { format, margin, eccLevel, + logEnabled, ); } late final _zxingEncodePtr = _lookup< ffi.NativeFunction< EncodeResult Function(ffi.Pointer, ffi.Int32, ffi.Int32, - ffi.Int32, ffi.Int32, ffi.Int32)>>('zxingEncode'); + ffi.Int32, ffi.Int32, ffi.Int32, ffi.Int32)>>('zxingEncode'); late final _zxingEncode = _zxingEncodePtr.asFunction< - EncodeResult Function(ffi.Pointer, int, int, int, int, int)>(); + EncodeResult Function( + ffi.Pointer, int, int, int, int, int, int)>(); } abstract class Format { diff --git a/lib/isolate_utils.dart b/lib/isolate_utils.dart index 8cbdb21..6b18313 100644 --- a/lib/isolate_utils.dart +++ b/lib/isolate_utils.dart @@ -11,12 +11,14 @@ import 'image_converter.dart'; /// Bundles data to pass between Isolate class IsolateData { CameraImage cameraImage; + int format; double cropPercent; SendPort? responsePort; IsolateData( this.cameraImage, + this.format, this.cropPercent, ); } @@ -54,15 +56,20 @@ class IsolateUtils { await for (final IsolateData? isolateData in port) { if (isolateData != null) { - final image = isolateData.cameraImage; - final cropPercent = isolateData.cropPercent; - final bytes = await convertImage(image); - final cropSize = (min(image.width, image.height) * cropPercent).round(); - - final result = - FlutterZxing.zxingRead(bytes, image.width, image.height, cropSize); - - isolateData.responsePort?.send(result); + try { + final image = isolateData.cameraImage; + final cropPercent = isolateData.cropPercent; + final bytes = await convertImage(image); + final cropSize = + (min(image.width, image.height) * cropPercent).round(); + + final result = FlutterZxing.zxingRead(bytes, isolateData.format, + image.width, image.height, cropSize, cropSize); + + isolateData.responsePort?.send(result); + } on Exception catch (e) { + isolateData.responsePort?.send(e); + } } } } diff --git a/lib/zxing_reader_widget.dart b/lib/zxing_reader_widget.dart index 0e4f693..fda0d45 100644 --- a/lib/zxing_reader_widget.dart +++ b/lib/zxing_reader_widget.dart @@ -18,6 +18,7 @@ class ZxingReaderWidget extends StatefulWidget { Key? key, required this.onScan, this.onControllerCreated, + this.codeFormat = Format.Any, this.beep = true, this.showCroppingRect = true, this.scanDelay = const Duration(milliseconds: 500), // 500ms delay @@ -27,6 +28,7 @@ class ZxingReaderWidget extends StatefulWidget { final Function(CodeResult) onScan; final Function(CameraController?)? onControllerCreated; + final int codeFormat; final bool beep; final bool showCroppingRect; final Duration scanDelay; @@ -144,7 +146,8 @@ class _ZxingReaderWidgetState extends State if (!_isProcessing) { _isProcessing = true; try { - var isolateData = IsolateData(image, widget.cropPercent); + var isolateData = + IsolateData(image, widget.codeFormat, widget.cropPercent); /// perform inference in separate isolate CodeResult result = await inference(isolateData); diff --git a/pubspec.yaml b/pubspec.yaml index 4d8f749..66c4911 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,7 +8,7 @@ environment: flutter: ">=2.5.0" dependencies: - camera: ^0.9.4+16 + camera: ^0.9.4 ffi: ^1.1.2 flutter: sdk: flutter