From 320532edcdc5952383fc018286db9f7b6f779282 Mon Sep 17 00:00:00 2001 From: Khoren Markosyan Date: Tue, 2 Apr 2024 15:04:15 +0400 Subject: [PATCH] Refactor code --- .vscode/settings.json | 4 +- lib/flutter_zxing.dart | 54 ++------ lib/generated_bindings.dart | 216 ++++++++++++++--------------- lib/src/logic/barcode_encoder.dart | 14 +- lib/src/logic/barcode_reader.dart | 74 +++------- lib/src/logic/barcodes_reader.dart | 72 +++------- lib/src/logic/camera_stream.dart | 9 +- lib/src/logic/zxing.dart | 1 - lib/src/models/params.dart | 16 +++ lib/src/ui/reader_widget.dart | 28 ++-- lib/src/utils/extentions.dart | 32 +++++ lib/src/utils/isolate_utils.dart | 8 +- lib/zxing_mobile.dart | 72 +++------- lib/zxing_web.dart | 53 ++----- src/native_zxing.cpp | 65 +++++---- src/native_zxing.h | 67 +++++---- 16 files changed, 318 insertions(+), 467 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index ef8d17d..ab01654 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,6 +6,8 @@ "codecvt": "cpp", "cmath": "cpp", "array": "cpp", - "new": "cpp" + "new": "cpp", + "ios": "cpp", + "vector": "cpp" } } \ No newline at end of file diff --git a/lib/flutter_zxing.dart b/lib/flutter_zxing.dart index 693613e..0eca1fc 100644 --- a/lib/flutter_zxing.dart +++ b/lib/flutter_zxing.dart @@ -34,66 +34,32 @@ abstract class Zxing { void stopCameraProcessing(); /// Reads barcode from the camera - Future processCameraImage( - CameraImage image, { - DecodeParams? params, - }); + Future processCameraImage(CameraImage image, DecodeParams params); /// Reads barcodes from the camera - Future processCameraImageMulti( - CameraImage image, { - DecodeParams? params, - }); + Future processCameraImageMulti(CameraImage image, DecodeParams params); /// Reads barcode from String image path - Future readBarcodeImagePathString( - String path, { - DecodeParams? params, - }); + Future readBarcodeImagePathString(String path, DecodeParams params); /// Reads barcode from XFile image path - Future readBarcodeImagePath( - XFile path, { - DecodeParams? params, - }); + Future readBarcodeImagePath(XFile path, DecodeParams params); /// Reads barcode from image url - Future readBarcodeImageUrl( - String url, { - DecodeParams? params, - }); + Future readBarcodeImageUrl(String url, DecodeParams params); // Reads barcode from Uint8List image bytes - Code readBarcode( - Uint8List bytes, { - required int width, - required int height, - DecodeParams? params, - }); + Code readBarcode(Uint8List bytes, DecodeParams params); /// Reads barcodes from String image path - Future readBarcodesImagePathString( - String path, { - DecodeParams? params, - }); + Future readBarcodesImagePathString(String path, DecodeParams params); /// Reads barcodes from XFile image path - Future readBarcodesImagePath( - XFile path, { - DecodeParams? params, - }); + Future readBarcodesImagePath(XFile path, DecodeParams params); /// Reads barcodes from image url - Future readBarcodesImageUrl( - String url, { - DecodeParams? params, - }); + Future readBarcodesImageUrl(String url, DecodeParams params); /// Reads barcodes from Uint8List image bytes - Codes readBarcodes( - Uint8List bytes, { - required int width, - required int height, - DecodeParams? params, - }); + Codes readBarcodes(Uint8List bytes, DecodeParams params); } diff --git a/lib/generated_bindings.dart b/lib/generated_bindings.dart index 4a695d3..237ef33 100644 --- a/lib/generated_bindings.dart +++ b/lib/generated_bindings.dart @@ -56,145 +56,131 @@ class GeneratedBindings { _versionPtr.asFunction Function()>(); /// @brief Read barcode from image bytes. - /// @param bytes Image bytes. Owned pointer. Will be freed by native code. - /// @param imageFormat Image format. - /// @param format Specify a set of BarcodeFormats that should be searched for. - /// @param width Image width in pixels. - /// @param height Image height in pixels. - /// @param cropWidth Crop width. - /// @param cropHeight Crop height. - /// @param tryHarder Spend more time to try to find a barcode; optimize for accuracy, not speed. - /// @param tryRotate Also try detecting code in 90, 180 and 270 degree rotated images. + /// @param params Barcode parameters. /// @return The barcode result. CodeResult readBarcode( - ffi.Pointer bytes, - int imageFormat, - int format, - int width, - int height, - int cropWidth, - int cropHeight, - bool tryHarder, - bool tryRotate, - bool tryInvert, + DecodeBarcodeParams params, ) { return _readBarcode( - bytes, - imageFormat, - format, - width, - height, - cropWidth, - cropHeight, - tryHarder, - tryRotate, - tryInvert, + params, ); } - late final _readBarcodePtr = _lookup< - ffi.NativeFunction< - CodeResult Function( - ffi.Pointer, - ffi.Int, - ffi.Int, - ffi.Int, - ffi.Int, - ffi.Int, - ffi.Int, - ffi.Bool, - ffi.Bool, - ffi.Bool)>>('readBarcode'); - late final _readBarcode = _readBarcodePtr.asFunction< - CodeResult Function(ffi.Pointer, int, int, int, int, int, int, - bool, bool, bool)>(); + late final _readBarcodePtr = + _lookup>( + 'readBarcode'); + late final _readBarcode = + _readBarcodePtr.asFunction(); /// @brief Read barcodes from image bytes. - /// @param bytes Image bytes. Owned pointer. Will be freed by native code. - /// @param imageFormat Image format. - /// @param format Specify a set of BarcodeFormats that should be searched for. - /// @param width Image width in pixels. - /// @param height Image height in pixels. - /// @param cropWidth Crop width. - /// @param cropHeight Crop height. - /// @param tryHarder Spend more time to try to find a barcode, optimize for accuracy, not speed. - /// @param tryRotate Also try detecting code in 90, 180 and 270 degree rotated images. + /// @param params Barcode parameters. /// @return The barcode results. CodeResults readBarcodes( - ffi.Pointer bytes, - int imageFormat, - int format, - int width, - int height, - int cropWidth, - int cropHeight, - bool tryHarder, - bool tryRotate, - bool tryInvert, + DecodeBarcodeParams params, ) { return _readBarcodes( - bytes, - imageFormat, - format, - width, - height, - cropWidth, - cropHeight, - tryHarder, - tryRotate, - tryInvert, + params, ); } - late final _readBarcodesPtr = _lookup< - ffi.NativeFunction< - CodeResults Function( - ffi.Pointer, - ffi.Int, - ffi.Int, - ffi.Int, - ffi.Int, - ffi.Int, - ffi.Int, - ffi.Bool, - ffi.Bool, - ffi.Bool)>>('readBarcodes'); - late final _readBarcodes = _readBarcodesPtr.asFunction< - CodeResults Function(ffi.Pointer, int, int, int, int, int, int, - bool, bool, bool)>(); + late final _readBarcodesPtr = + _lookup>( + 'readBarcodes'); + late final _readBarcodes = + _readBarcodesPtr.asFunction(); /// @brief Encode a string into a barcode - /// @param contents The string to encode. Owned pointer. Will be freed by native code. - /// @param width The width of the barcode in pixels. - /// @param height The height of the barcode in pixels. - /// @param format The format of the barcode - /// @param margin The margin of the barcode - /// @param eccLevel The error correction level of the barcode. Used for Aztec, PDF417, and QRCode only, [0-8]. - /// @return The barcode data. + /// @param params The parameters for encoding the barcode + /// @return The barcode data EncodeResult encodeBarcode( - ffi.Pointer contents, - int width, - int height, - int format, - int margin, - int eccLevel, + EncodeBarcodeParams params, ) { return _encodeBarcode( - contents, - width, - height, - format, - margin, - eccLevel, + params, ); } - late final _encodeBarcodePtr = _lookup< - ffi.NativeFunction< - EncodeResult Function(ffi.Pointer, ffi.Int, ffi.Int, - ffi.Int, ffi.Int, ffi.Int)>>('encodeBarcode'); - late final _encodeBarcode = _encodeBarcodePtr.asFunction< - EncodeResult Function(ffi.Pointer, int, int, int, int, int)>(); + late final _encodeBarcodePtr = + _lookup>( + 'encodeBarcode'); + late final _encodeBarcode = _encodeBarcodePtr + .asFunction(); +} + +/// @brief The BarcodeParams class encapsulates parameters for reading barcodes. +final class DecodeBarcodeParams extends ffi.Struct { + /// < Image bytes + external ffi.Pointer bytes; + + /// < Image format + @ffi.Int() + external int imageFormat; + + /// < Specify a set of BarcodeFormats that should be searched for + @ffi.Int() + external int format; + + /// < Image width in pixels + @ffi.Int() + external int width; + + /// < Image height in pixels + @ffi.Int() + external int height; + + /// < Crop left + @ffi.Int() + external int cropLeft; + + /// < Crop top + @ffi.Int() + external int cropTop; + + /// < Crop width + @ffi.Int() + external int cropWidth; + + /// < Crop height + @ffi.Int() + external int cropHeight; + + /// < Spend more time to try to find a barcode, optimize for accuracy, not speed + @ffi.Bool() + external bool tryHarder; + + /// < Also try detecting code in 90, 180 and 270 degree rotated images + @ffi.Bool() + external bool tryRotate; + + /// < Try inverting the image + @ffi.Bool() + external bool tryInvert; +} + +/// @brief The EncodeBarcodeParams class encapsulates parameters for encoding barcodes. +final class EncodeBarcodeParams extends ffi.Struct { + /// < The string to encode + external ffi.Pointer contents; + + /// < The width of the barcode in pixels + @ffi.Int() + external int width; + + /// < The height of the barcode in pixels + @ffi.Int() + external int height; + + /// < The format of the barcode + @ffi.Int() + external int format; + + /// < The margin of the barcode + @ffi.Int() + external int margin; + + /// < The error correction level of the barcode. Used for Aztec, PDF417, and QRCode only, [0-8]. + @ffi.Int() + external int eccLevel; } /// @brief Pos is a position of a barcode in a image. diff --git a/lib/src/logic/barcode_encoder.dart b/lib/src/logic/barcode_encoder.dart index f240e15..dd5dfe0 100644 --- a/lib/src/logic/barcode_encoder.dart +++ b/lib/src/logic/barcode_encoder.dart @@ -4,15 +4,5 @@ part of 'zxing.dart'; Encode zxingEncodeBarcode({ required String contents, required EncodeParams params, -}) { - return bindings - .encodeBarcode( - contents.toNativeUtf8().cast(), - params.width, - params.height, - params.format, - params.margin, - params.eccLevel.value, - ) - .toEncode(); -} +}) => + bindings.encodeBarcode(params.toEncodeBarcodeParams(contents)).toEncode(); diff --git a/lib/src/logic/barcode_reader.dart b/lib/src/logic/barcode_reader.dart index 1c0fd22..1751234 100644 --- a/lib/src/logic/barcode_reader.dart +++ b/lib/src/logic/barcode_reader.dart @@ -2,81 +2,39 @@ part of 'zxing.dart'; /// Reads barcode from String image path Future zxingReadBarcodeImagePathString( - String path, { - DecodeParams? params, -}) => - zxingReadBarcodeImagePath( - XFile(path), - params: params, - ); + String path, DecodeParams params) => + zxingReadBarcodeImagePath(XFile(path), params); /// Reads barcode from XFile image path -Future zxingReadBarcodeImagePath( - XFile path, { - DecodeParams? params, -}) async { +Future zxingReadBarcodeImagePath(XFile path, DecodeParams params) async { final Uint8List imageBytes = await path.readAsBytes(); imglib.Image? image = imglib.decodeImage(imageBytes); - if (image == null) { return Code(); } - image = resizeToMaxSize(image, params?.maxSize); - return zxingReadBarcode( - rgbBytes(image), - width: image.width, - height: image.height, - params: params, - ); + image = resizeToMaxSize(image, params.maxSize); + params.width = image.width; + params.height = image.height; + return zxingReadBarcode(rgbBytes(image), params); } /// Reads barcode from image url -Future zxingReadBarcodeImageUrl( - String url, { - DecodeParams? params, -}) async { +Future zxingReadBarcodeImageUrl(String url, DecodeParams params) async { final Uint8List imageBytes = (await NetworkAssetBundle(Uri.parse(url)).load(url)).buffer.asUint8List(); imglib.Image? image = imglib.decodeImage(imageBytes); if (image == null) { return Code(error: 'Failed to decode image'); } - image = resizeToMaxSize(image, params?.maxSize); - return zxingReadBarcode( - rgbBytes(image), - width: image.width, - height: image.height, - params: params, - ); + image = resizeToMaxSize(image, params.maxSize); + params.width = image.width; + params.height = image.height; + return zxingReadBarcode(rgbBytes(image), params); } // Reads barcode from Uint8List image bytes -Code zxingReadBarcode( - Uint8List bytes, { - required int width, - required int height, - DecodeParams? params, -}) => - _readBarcode(bytes, width, height, params); +Code zxingReadBarcode(Uint8List bytes, DecodeParams params) => + _readBarcode(bytes, params); -Code _readBarcode( - Uint8List bytes, - int width, - int height, - DecodeParams? params, -) { - return bindings - .readBarcode( - bytes.copyToNativePointer(), - params?.imageFormat ?? zx.ImageFormat.lum, - params?.format ?? Format.any, - width, - height, - params?.cropWidth ?? 0, - params?.cropHeight ?? 0, - params?.tryHarder ?? false, - params?.tryRotate ?? true, - params?.tryInverted ?? false, - ) - .toCode(); -} +Code _readBarcode(Uint8List bytes, DecodeParams params) => + bindings.readBarcode(params.toDecodeBarcodeParams(bytes)).toCode(); diff --git a/lib/src/logic/barcodes_reader.dart b/lib/src/logic/barcodes_reader.dart index 257a359..6bd2c96 100644 --- a/lib/src/logic/barcodes_reader.dart +++ b/lib/src/logic/barcodes_reader.dart @@ -2,82 +2,44 @@ part of 'zxing.dart'; /// Reads barcodes from String image path Future zxingReadBarcodesImagePathString( - String path, { - DecodeParams? params, -}) => - zxingReadBarcodesImagePath( - XFile(path), - params: params, - ); + String path, DecodeParams params) => + zxingReadBarcodesImagePath(XFile(path), params); /// Reads barcodes from XFile image path Future zxingReadBarcodesImagePath( - XFile path, { - DecodeParams? params, -}) async { + XFile path, DecodeParams params) async { final Uint8List imageBytes = await path.readAsBytes(); imglib.Image? image = imglib.decodeImage(imageBytes); if (image == null) { return Codes(); } - image = resizeToMaxSize(image, params?.maxSize); - return zxingReadBarcodes( - rgbBytes(image), - width: image.width, - height: image.height, - params: params, - ); + image = resizeToMaxSize(image, params.maxSize); + params.width = image.width; + params.height = image.height; + return zxingReadBarcodes(rgbBytes(image), params); } /// Reads barcodes from image url -Future zxingReadBarcodesImageUrl( - String url, { - DecodeParams? params, -}) async { +Future zxingReadBarcodesImageUrl(String url, DecodeParams params) async { final Uint8List imageBytes = (await NetworkAssetBundle(Uri.parse(url)).load(url)).buffer.asUint8List(); imglib.Image? image = imglib.decodeImage(imageBytes); if (image == null) { return Codes(); } - image = resizeToMaxSize(image, params?.maxSize); - return zxingReadBarcodes( - rgbBytes(image), - width: image.width, - height: image.height, - params: params, - ); + image = resizeToMaxSize(image, params.maxSize); + params.width = image.width; + params.height = image.height; + return zxingReadBarcodes(rgbBytes(image), params); } /// Reads barcodes from Uint8List image bytes -Codes zxingReadBarcodes( - Uint8List bytes, { - required int width, - required int height, - DecodeParams? params, -}) { - return _readBarcodes(bytes, width, height, params); -} - -Codes _readBarcodes( - Uint8List bytes, - int width, - int height, - DecodeParams? params, -) { - final CodeResults result = bindings.readBarcodes( - bytes.copyToNativePointer(), - params?.imageFormat ?? zx.ImageFormat.lum, - params?.format ?? Format.any, - width, - height, - params?.cropWidth ?? 0, - params?.cropHeight ?? 0, - params?.tryHarder ?? false, - params?.tryRotate ?? true, - params?.tryInverted ?? false, - ); +Codes zxingReadBarcodes(Uint8List bytes, DecodeParams params) => + _readBarcodes(bytes, params); +Codes _readBarcodes(Uint8List bytes, DecodeParams params) { + final CodeResults result = + bindings.readBarcodes(params.toDecodeBarcodeParams(bytes)); final List codes = []; if (result.count == 0 || result.results == nullptr) { diff --git a/lib/src/logic/camera_stream.dart b/lib/src/logic/camera_stream.dart index e83418a..2357322 100644 --- a/lib/src/logic/camera_stream.dart +++ b/lib/src/logic/camera_stream.dart @@ -12,13 +12,8 @@ Future zxingStartCameraProcessing() async { void zxingStopCameraProcessing() => isolateUtils?.stopReadingBarcode(); Future zxingProcessCameraImage( - CameraImage image, { - DecodeParams? params, -}) async { - final IsolateData isolateData = IsolateData(image, params ?? DecodeParams()); - final dynamic result = await _inference(isolateData); - return result; -} + CameraImage image, DecodeParams params) => + _inference(IsolateData(image, params)); /// Runs inference in another isolate Future _inference(IsolateData isolateData) async { diff --git a/lib/src/logic/zxing.dart b/lib/src/logic/zxing.dart index 384c78f..0405a4c 100644 --- a/lib/src/logic/zxing.dart +++ b/lib/src/logic/zxing.dart @@ -11,7 +11,6 @@ import 'package:image/image.dart' as imglib; import '../../generated_bindings.dart'; import '../models/models.dart'; -import '../models/models.dart' as zx; import '../utils/extentions.dart'; // import '../utils/image_converter.dart'; import '../utils/image_converter.dart'; diff --git a/lib/src/models/params.dart b/lib/src/models/params.dart index f429cdc..16635c8 100644 --- a/lib/src/models/params.dart +++ b/lib/src/models/params.dart @@ -8,6 +8,10 @@ class DecodeParams { DecodeParams({ this.imageFormat = ImageFormat.lum, this.format = Format.any, + this.width = 0, + this.height = 0, + this.cropLeft = 0, + this.cropTop = 0, this.cropWidth = 0, this.cropHeight = 0, this.tryHarder = false, @@ -23,6 +27,18 @@ class DecodeParams { // Specify a set of BarcodeFormats that should be searched for, the default is all supported formats. int format; + // The width of the image to scan, in pixels. + int width; + + // The height of the image to scan, in pixels. + int height; + + // The left of the area of the image to scan, in pixels. + int cropLeft; + + // The top of the area of the image to scan, in pixels. + int cropTop; + // The width of the area of the image to scan, in pixels. If 0, the entire image width is used. int cropWidth; diff --git a/lib/src/ui/reader_widget.dart b/lib/src/ui/reader_widget.dart index 7ef5888..7a2e763 100644 --- a/lib/src/ui/reader_widget.dart +++ b/lib/src/ui/reader_widget.dart @@ -134,7 +134,7 @@ class ReaderWidget extends StatefulWidget { /// Custom background color for action buttons final Color actionButtonsBackgroundColor; - + /// Custom background border radius for action buttons final BorderRadius? actionButtonsBackgroundBorderRadius; @@ -314,6 +314,10 @@ class _ReaderWidgetState extends State final DecodeParams params = DecodeParams( imageFormat: _imageFormat(image.format.group), format: widget.codeFormat, + width: image.width, + height: image.height, + cropLeft: (image.width - cropSize) ~/ 2, + cropTop: (image.height - cropSize) ~/ 2, cropWidth: cropSize, cropHeight: cropSize, tryHarder: widget.tryHarder, @@ -322,10 +326,7 @@ class _ReaderWidgetState extends State isMultiScan: widget.isMultiScan, ); if (widget.isMultiScan) { - final Codes result = await zx.processCameraImageMulti( - image, - params: params, - ); + final Codes result = await zx.processCameraImageMulti(image, params); if (result.codes.isNotEmpty) { results = result; widget.onMultiScan?.call(result); @@ -338,10 +339,7 @@ class _ReaderWidgetState extends State widget.onMultiScanFailure?.call(result); } } else { - final Code result = await zx.processCameraImage( - image, - params: params, - ); + final Code result = await zx.processCameraImage(image, params); if (result.isValid) { widget.onScan?.call(result); setState(() {}); @@ -432,8 +430,8 @@ class _ReaderWidgetState extends State child: Padding( padding: widget.actionButtonsPadding, child: ClipRRect( - borderRadius: widget.actionButtonsBackgroundBorderRadius - ?? BorderRadius.circular(10.0), + borderRadius: widget.actionButtonsBackgroundBorderRadius ?? + BorderRadius.circular(10.0), child: Container( color: widget.actionButtonsBackgroundColor, child: Row( @@ -443,7 +441,8 @@ class _ReaderWidgetState extends State IconButton( onPressed: _onFlashButtonTapped, color: Colors.white, - icon: _flashIcon(controller?.value.flashMode ?? FlashMode.off), + icon: _flashIcon( + controller?.value.flashMode ?? FlashMode.off), ), if (widget.showGallery) IconButton( @@ -505,8 +504,7 @@ class _ReaderWidgetState extends State isMultiScan: widget.isMultiScan, ); if (widget.isMultiScan) { - final Codes result = - await zx.readBarcodesImagePath(file, params: params); + final Codes result = await zx.readBarcodesImagePath(file, params); if (result.codes.isNotEmpty) { results = result; widget.onMultiScan?.call(result); @@ -516,7 +514,7 @@ class _ReaderWidgetState extends State widget.onMultiScanFailure?.call(result); } } else { - final Code result = await zx.readBarcodeImagePath(file, params: params); + final Code result = await zx.readBarcodeImagePath(file, params); if (result.isValid) { widget.onScan?.call(result); } else { diff --git a/lib/src/utils/extentions.dart b/lib/src/utils/extentions.dart index 8aadbd8..294f789 100644 --- a/lib/src/utils/extentions.dart +++ b/lib/src/utils/extentions.dart @@ -87,3 +87,35 @@ extension PosExt on Pos { bottomRightY, ); } + +extension EncodeParamsExt on EncodeParams { + EncodeBarcodeParams toEncodeBarcodeParams(String contents) { + final Pointer p = calloc(); + p.ref.contents = contents.toNativeUtf8().cast(); + p.ref.width = width; + p.ref.height = height; + p.ref.format = format; + p.ref.margin = margin; + p.ref.eccLevel = eccLevel.value; + return p.ref; + } +} + +extension DecodeParamsExt on DecodeParams { + DecodeBarcodeParams toDecodeBarcodeParams(Uint8List bytes) { + final Pointer p = calloc(); + p.ref.bytes = bytes.copyToNativePointer(); + p.ref.imageFormat = imageFormat; + p.ref.format = format; + p.ref.width = width; + p.ref.height = height; + p.ref.cropLeft = cropLeft; + p.ref.cropTop = cropTop; + p.ref.cropWidth = cropWidth; + p.ref.cropHeight = cropHeight; + p.ref.tryHarder = tryHarder; + p.ref.tryRotate = tryRotate; + p.ref.tryInvert = tryInverted; + return p.ref; + } +} diff --git a/lib/src/utils/isolate_utils.dart b/lib/src/utils/isolate_utils.dart index d7d56ca..5256895 100644 --- a/lib/src/utils/isolate_utils.dart +++ b/lib/src/utils/isolate_utils.dart @@ -57,17 +57,13 @@ class IsolateUtils { try { final CameraImage image = isolateData.cameraImage; final Uint8List bytes = await convertImage(image); - final int width = image.width; - final int height = image.height; final DecodeParams params = isolateData.params; dynamic result; if (params.isMultiScan) { - result = zxingReadBarcodes(bytes, - width: width, height: height, params: params); + result = zxingReadBarcodes(bytes, params); } else { - result = zxingReadBarcode(bytes, - width: width, height: height, params: params); + result = zxingReadBarcode(bytes, params); } isolateData.responsePort?.send(result); } catch (e) { diff --git a/lib/zxing_mobile.dart b/lib/zxing_mobile.dart index 2be6687..7f8fdcd 100644 --- a/lib/zxing_mobile.dart +++ b/lib/zxing_mobile.dart @@ -40,75 +40,43 @@ class ZxingMobile implements Zxing { @override Future processCameraImage( - CameraImage image, { - DecodeParams? params, - }) async => - await zxingProcessCameraImage(image, params: params) as Code; + CameraImage image, DecodeParams params) async => + await zxingProcessCameraImage(image, params) as Code; @override Future processCameraImageMulti( - CameraImage image, { - DecodeParams? params, - }) async => - await zxingProcessCameraImage(image, params: params) as Codes; + CameraImage image, DecodeParams params) async => + await zxingProcessCameraImage(image, params) as Codes; @override - Future readBarcodeImagePathString( - String path, { - DecodeParams? params, - }) => - zxingReadBarcodeImagePathString(path, params: params); + Future readBarcodeImagePathString(String path, DecodeParams params) => + zxingReadBarcodeImagePathString(path, params); @override - Future readBarcodeImagePath( - XFile path, { - DecodeParams? params, - }) => - zxingReadBarcodeImagePath(path, params: params); + Future readBarcodeImagePath(XFile path, DecodeParams params) => + zxingReadBarcodeImagePath(path, params); @override - Future readBarcodeImageUrl( - String url, { - DecodeParams? params, - }) => - zxingReadBarcodeImageUrl(url, params: params); + Future readBarcodeImageUrl(String url, DecodeParams params) => + zxingReadBarcodeImageUrl(url, params); @override - Code readBarcode( - Uint8List bytes, { - required int width, - required int height, - DecodeParams? params, - }) => - zxingReadBarcode(bytes, width: width, height: height, params: params); + Code readBarcode(Uint8List bytes, DecodeParams params) => + zxingReadBarcode(bytes, params); @override - Future readBarcodesImagePathString( - String path, { - DecodeParams? params, - }) => - zxingReadBarcodesImagePathString(path, params: params); + Future readBarcodesImagePathString(String path, DecodeParams params) => + zxingReadBarcodesImagePathString(path, params); @override - Future readBarcodesImagePath( - XFile path, { - DecodeParams? params, - }) => - zxingReadBarcodesImagePath(path, params: params); + Future readBarcodesImagePath(XFile path, DecodeParams params) => + zxingReadBarcodesImagePath(path, params); @override - Future readBarcodesImageUrl( - String url, { - DecodeParams? params, - }) => - zxingReadBarcodesImageUrl(url, params: params); + Future readBarcodesImageUrl(String url, DecodeParams params) => + zxingReadBarcodesImageUrl(url, params); @override - Codes readBarcodes( - Uint8List bytes, { - required int width, - required int height, - DecodeParams? params, - }) => - zxingReadBarcodes(bytes, width: width, height: height, params: params); + Codes readBarcodes(Uint8List bytes, DecodeParams params) => + zxingReadBarcodes(bytes, params); } diff --git a/lib/zxing_web.dart b/lib/zxing_web.dart index 043e1be..37c8e30 100644 --- a/lib/zxing_web.dart +++ b/lib/zxing_web.dart @@ -32,76 +32,43 @@ class ZxingWeb implements Zxing { void stopCameraProcessing() => throw UnimplementedError(); @override - Future processCameraImage( - CameraImage image, { - DecodeParams? params, - }) => + Future processCameraImage(CameraImage image, DecodeParams params) => throw UnimplementedError(); @override Future processCameraImageMulti( - CameraImage image, { - DecodeParams? params, - }) => + CameraImage image, DecodeParams params) => throw UnimplementedError(); @override - Future readBarcodeImagePathString( - String path, { - DecodeParams? params, - }) => + Future readBarcodeImagePathString(String path, DecodeParams params) => throw UnimplementedError(); @override - Future readBarcodeImagePath( - XFile path, { - DecodeParams? params, - }) => + Future readBarcodeImagePath(XFile path, DecodeParams params) => throw UnimplementedError(); @override - Future readBarcodeImageUrl( - String url, { - DecodeParams? params, - }) => + Future readBarcodeImageUrl(String url, DecodeParams params) => throw UnimplementedError(); @override - Code readBarcode( - Uint8List bytes, { - required int width, - required int height, - DecodeParams? params, - }) => + Code readBarcode(Uint8List bytes, DecodeParams params) => throw UnimplementedError(); @override - Future readBarcodesImagePathString( - String path, { - DecodeParams? params, - }) => + Future readBarcodesImagePathString(String path, DecodeParams params) => throw UnimplementedError(); @override - Future readBarcodesImagePath( - XFile path, { - DecodeParams? params, - }) => + Future readBarcodesImagePath(XFile path, DecodeParams params) => throw UnimplementedError(); @override - Future readBarcodesImageUrl( - String url, { - DecodeParams? params, - }) => + Future readBarcodesImageUrl(String url, DecodeParams params) => throw UnimplementedError(); @override - Codes readBarcodes( - Uint8List bytes, { - required int width, - required int height, - DecodeParams? params, - }) => + Codes readBarcodes(Uint8List bytes, DecodeParams params) => throw UnimplementedError(); } diff --git a/src/native_zxing.cpp b/src/native_zxing.cpp index 746c264..cee0706 100644 --- a/src/native_zxing.cpp +++ b/src/native_zxing.cpp @@ -18,6 +18,27 @@ using namespace ZXing; using namespace std; using std::chrono::steady_clock; +// Helper functions + +ImageView createCroppedImageView(const struct DecodeBarcodeParams ¶ms) +{ + ImageView image{reinterpret_cast(params.bytes), params.width, params.height, ImageFormat(params.imageFormat)}; + if (params.cropWidth > 0 && params.cropHeight > 0 && params.cropWidth < params.width && params.cropHeight < params.height) + { + image = image.cropped(params.cropLeft, params.cropTop, params.cropWidth, params.cropHeight); + } + + // Dart passes us an owned image bytes pointer; we need to free it after + delete[] params.bytes; + + return image; +} + +ReaderOptions createReaderOptions(const struct DecodeBarcodeParams ¶ms) +{ + return ReaderOptions().setTryHarder(params.tryHarder).setTryRotate(params.tryRotate).setFormats(BarcodeFormat(params.format)).setTryInvert(params.tryInvert).setReturnErrors(true); +} + // Returns an owned C-string `char*`, copied from a `std::string&`. char *cstrFromString(const std::string &s) { @@ -95,45 +116,29 @@ extern "C" } FUNCTION_ATTRIBUTE - struct CodeResult readBarcode(uint8_t *bytes, int imageFormat, int format, int width, int height, int cropWidth, int cropHeight, bool tryHarder, bool tryRotate, bool tryInvert) + struct CodeResult readBarcode(struct DecodeBarcodeParams params) { auto start = steady_clock::now(); - ImageView image{bytes, width, height, ImageFormat(imageFormat)}; - if (cropWidth > 0 && cropHeight > 0 && cropWidth < width && cropHeight < height) - { - image = image.cropped(width / 2 - cropWidth / 2, height / 2 - cropHeight / 2, cropWidth, cropHeight); - } - ReaderOptions hints = ReaderOptions().setTryHarder(tryHarder).setTryRotate(tryRotate).setFormats(BarcodeFormat(format)).setTryInvert(tryInvert).setReturnErrors(true); + ImageView image = createCroppedImageView(params); + ReaderOptions hints = createReaderOptions(params); Result result = ReadBarcode(image, hints); - // Dart passes us an owned image bytes pointer; we need to free it after - // we're done decoding. - delete[] bytes; - int duration = elapsed_ms(start); platform_log("Read Barcode in: %d ms\n", duration); - - return codeResultFromResult(result, duration, width, height); + return codeResultFromResult(result, duration, params.width, params.height); + ; } FUNCTION_ATTRIBUTE - struct CodeResults readBarcodes(uint8_t *bytes, int imageFormat, int format, int width, int height, int cropWidth, int cropHeight, bool tryHarder, bool tryRotate, bool tryInvert) + struct CodeResults readBarcodes(struct DecodeBarcodeParams params) { auto start = steady_clock::now(); - ImageView image{bytes, width, height, ImageFormat(imageFormat)}; - if (cropWidth > 0 && cropHeight > 0 && cropWidth < width && cropHeight < height) - { - image = image.cropped(width / 2 - cropWidth / 2, height / 2 - cropHeight / 2, cropWidth, cropHeight); - } - ReaderOptions hints = ReaderOptions().setTryHarder(tryHarder).setTryRotate(tryRotate).setFormats(BarcodeFormat(format)).setTryInvert(tryInvert); + ImageView image = createCroppedImageView(params); + ReaderOptions hints = createReaderOptions(params); Results results = ReadBarcodes(image, hints); - // Dart passes us an owned image bytes pointer; we need to free it after - // we're done decoding. - delete[] bytes; - int duration = elapsed_ms(start); platform_log("Read Barcode in: %d ms\n", duration); @@ -146,22 +151,22 @@ extern "C" int i = 0; for (const auto &result : results) { - codes[i] = codeResultFromResult(result, duration, width, height); + codes[i] = codeResultFromResult(result, duration, params.width, params.height); i++; } return CodeResults{i, codes, duration}; } FUNCTION_ATTRIBUTE - struct EncodeResult encodeBarcode(char *contents, int width, int height, int format, int margin, int eccLevel) + struct EncodeResult encodeBarcode(struct EncodeBarcodeParams params) { auto start = steady_clock::now(); - struct EncodeResult result = {0, contents, format, nullptr, 0, nullptr}; + struct EncodeResult result = {0, params.contents, params.format, nullptr, 0, nullptr}; try { - auto writer = MultiFormatWriter(BarcodeFormat(format)).setMargin(margin).setEccLevel(eccLevel).setEncoding(CharacterSet::UTF8); - auto bitMatrix = writer.encode(contents, width, height); + auto writer = MultiFormatWriter(BarcodeFormat(params.format)).setMargin(params.margin).setEccLevel(params.eccLevel).setEncoding(CharacterSet::UTF8); + auto bitMatrix = writer.encode(params.contents, params.width, params.height); auto matrix = ToMatrix(bitMatrix); // We need to return an owned pointer across the ffi boundary. Copy @@ -176,7 +181,7 @@ extern "C" } catch (const exception &e) { - platform_log("Can't encode text: %s\nError: %s\n", contents, e.what()); + platform_log("Can't encode text: %s\nError: %s\n", params.contents, e.what()); result.error = new char[strlen(e.what()) + 1]; strcpy(result.error, e.what()); } diff --git a/src/native_zxing.h b/src/native_zxing.h index 6ade8ac..50bc415 100644 --- a/src/native_zxing.h +++ b/src/native_zxing.h @@ -10,6 +10,38 @@ extern "C" { #endif + /** + * @brief The BarcodeParams class encapsulates parameters for reading barcodes. + */ + struct DecodeBarcodeParams + { + uint8_t *bytes; ///< Image bytes + int imageFormat; ///< Image format + int format; ///< Specify a set of BarcodeFormats that should be searched for + int width; ///< Image width in pixels + int height; ///< Image height in pixels + int cropLeft; ///< Crop left + int cropTop; ///< Crop top + int cropWidth; ///< Crop width + int cropHeight; ///< Crop height + bool tryHarder; ///< Spend more time to try to find a barcode, optimize for accuracy, not speed + bool tryRotate; ///< Also try detecting code in 90, 180 and 270 degree rotated images + bool tryInvert; ///< Try inverting the image + }; + + /** + * @brief The EncodeBarcodeParams class encapsulates parameters for encoding barcodes. + */ + struct EncodeBarcodeParams + { + char *contents; ///< The string to encode + int width; ///< The width of the barcode in pixels + int height; ///< The height of the barcode in pixels + int format; ///< The format of the barcode + int margin; ///< The margin of the barcode + int eccLevel; ///< The error correction level of the barcode. Used for Aztec, PDF417, and QRCode only, [0-8]. + }; + /** * @brief Pos is a position of a barcode in a image. * @@ -85,45 +117,24 @@ extern "C" /** * @brief Read barcode from image bytes. - * @param bytes Image bytes. Owned pointer. Will be freed by native code. - * @param imageFormat Image format. - * @param format Specify a set of BarcodeFormats that should be searched for. - * @param width Image width in pixels. - * @param height Image height in pixels. - * @param cropWidth Crop width. - * @param cropHeight Crop height. - * @param tryHarder Spend more time to try to find a barcode; optimize for accuracy, not speed. - * @param tryRotate Also try detecting code in 90, 180 and 270 degree rotated images. + * @param params Barcode parameters. * @return The barcode result. */ - struct CodeResult readBarcode(uint8_t *bytes, int imageFormat, int format, int width, int height, int cropWidth, int cropHeight, bool tryHarder, bool tryRotate, bool tryInvert); + struct CodeResult readBarcode(struct DecodeBarcodeParams params); /** * @brief Read barcodes from image bytes. - * @param bytes Image bytes. Owned pointer. Will be freed by native code. - * @param imageFormat Image format. - * @param format Specify a set of BarcodeFormats that should be searched for. - * @param width Image width in pixels. - * @param height Image height in pixels. - * @param cropWidth Crop width. - * @param cropHeight Crop height. - * @param tryHarder Spend more time to try to find a barcode, optimize for accuracy, not speed. - * @param tryRotate Also try detecting code in 90, 180 and 270 degree rotated images. + * @param params Barcode parameters. * @return The barcode results. */ - struct CodeResults readBarcodes(uint8_t *bytes, int imageFormat, int format, int width, int height, int cropWidth, int cropHeight, bool tryHarder, bool tryRotate, bool tryInvert); + struct CodeResults readBarcodes(struct DecodeBarcodeParams params); /** * @brief Encode a string into a barcode - * @param contents The string to encode. Owned pointer. Will be freed by native code. - * @param width The width of the barcode in pixels. - * @param height The height of the barcode in pixels. - * @param format The format of the barcode - * @param margin The margin of the barcode - * @param eccLevel The error correction level of the barcode. Used for Aztec, PDF417, and QRCode only, [0-8]. - * @return The barcode data. + * @param params The parameters for encoding the barcode + * @return The barcode data */ - struct EncodeResult encodeBarcode(char *contents, int width, int height, int format, int margin, int eccLevel); + struct EncodeResult encodeBarcode(struct EncodeBarcodeParams params); #ifdef __cplusplus }