From f6e4e19a56f83669e8c053011568ff9974705b80 Mon Sep 17 00:00:00 2001 From: Khoren Markosyan Date: Sat, 9 Jul 2022 23:09:41 +0400 Subject: [PATCH] added tryHarder and tryRotate attributes --- ios/Classes/src/native_zxing.cpp | 12 ++-- ios/Classes/src/native_zxing.h | 98 ++++++++++++++++++------------ lib/generated_bindings.dart | 79 +++++++++++++++++------- lib/src/logic/barcode_encoder.dart | 11 +++- lib/src/logic/barcode_reader.dart | 16 +++++ lib/src/logic/barcodes_reader.dart | 24 +++++++- pubspec.yaml | 4 ++ 7 files changed, 176 insertions(+), 68 deletions(-) diff --git a/ios/Classes/src/native_zxing.cpp b/ios/Classes/src/native_zxing.cpp index 0cf522a..aa62fb9 100644 --- a/ios/Classes/src/native_zxing.cpp +++ b/ios/Classes/src/native_zxing.cpp @@ -14,9 +14,9 @@ using namespace ZXing; extern "C" { FUNCTION_ATTRIBUTE - void setLogEnabled(int enabled) + void setLogEnabled(int enable) { - setLoggingEnabled(enabled); + setLoggingEnabled(enable); } FUNCTION_ATTRIBUTE @@ -26,7 +26,7 @@ extern "C" } FUNCTION_ATTRIBUTE - struct CodeResult readBarcode(char *bytes, int format, int width, int height, int cropWidth, int cropHeight) + struct CodeResult readBarcode(char *bytes, int format, int width, int height, int cropWidth, int cropHeight, int tryHarder, int tryRotate) { long long start = get_now(); @@ -39,7 +39,7 @@ extern "C" { image = image.cropped(width / 2 - cropWidth / 2, height / 2 - cropHeight / 2, cropWidth, cropHeight); } - DecodeHints hints = DecodeHints().setTryHarder(false).setTryRotate(true).setFormats(BarcodeFormat(format)); + DecodeHints hints = DecodeHints().setTryHarder(tryHarder).setTryRotate(tryRotate).setFormats(BarcodeFormat(format)); Result result = ReadBarcode(image, hints); struct CodeResult code = {false, nullptr}; @@ -54,7 +54,7 @@ extern "C" } FUNCTION_ATTRIBUTE - struct CodeResults readBarcodes(char *bytes, int format, int width, int height, int cropWidth, int cropHeight) + struct CodeResults readBarcodes(char *bytes, int format, int width, int height, int cropWidth, int cropHeight, int tryHarder, int tryRotate) { long long start = get_now(); @@ -67,7 +67,7 @@ extern "C" { image = image.cropped(width / 2 - cropWidth / 2, height / 2 - cropHeight / 2, cropWidth, cropHeight); } - DecodeHints hints = DecodeHints().setTryHarder(false).setTryRotate(true).setFormats(BarcodeFormat(format)); + DecodeHints hints = DecodeHints().setTryHarder(tryHarder).setTryRotate(tryRotate).setFormats(BarcodeFormat(format)); Results results = ReadBarcodes(image, hints); auto *codes = new struct CodeResult[results.size()]; diff --git a/ios/Classes/src/native_zxing.h b/ios/Classes/src/native_zxing.h index f834ca5..d49b43b 100644 --- a/ios/Classes/src/native_zxing.h +++ b/ios/Classes/src/native_zxing.h @@ -3,6 +3,10 @@ extern "C" { #endif + /** + * @brief Format Enumerates barcode formats known to this package. + * + */ enum Format { None = 0, ///< Used as a return value if no valid barcode has been detected @@ -28,48 +32,63 @@ extern "C" Any = OneDCodes | TwoDCodes, }; + /** + * @brief Pos is a position of a barcode in a image. + * + */ struct Pos { - int topLeftX; - int topLeftY; - int topRightX; - int topRightY; - int bottomLeftX; - int bottomLeftY; - int bottomRightX; - int bottomRightY; + int topLeftX; ///< x coordinate of top left corner of barcode + int topLeftY; ///< y coordinate of top left corner of barcode + int topRightX; ///< x coordinate of top right corner of barcode + int topRightY; ///< y coordinate of top right corner of barcode + int bottomLeftX; ///< x coordinate of bottom left corner of barcode + int bottomLeftY; ///< y coordinate of bottom left corner of barcode + int bottomRightX; ///< x coordinate of bottom right corner of barcode + int bottomRightY; ///< y coordinate of bottom right corner of barcode }; + /** + * @brief The CodeResult class encapsulates the result of decoding a barcode within an image. + */ struct CodeResult { - int isValid; - char *text; - enum Format format; - struct Pos *pos; + int isValid; ///< Whether the barcode was successfully decoded + char *text; ///< The decoded text + enum Format format; ///< The format of the barcode + struct Pos *pos; ///< The position of the barcode within the image }; + /** + * @brief The CodeResults class encapsulates the result of decoding multiple barcodes within an image. + */ struct CodeResults { - int count; - struct CodeResult *results; + int count; ///< The number of barcodes detected + struct CodeResult *results; ///< The results of the barcode decoding }; + /** + * @brief EncodeResult encapsulates the result of encoding a barcode. + * + */ struct EncodeResult { - int isValid; - char *text; - enum Format format; - const unsigned int *data; - int length; - char *error; + int isValid; ///< Whether the barcode was successfully encoded + char *text; ///< The encoded text + enum Format format; ///< The format of the barcode + const unsigned int *data; ///< The encoded data + int length; ///< The length of the encoded data + char *error; ///< The error message }; /** * @brief Enables or disables the logging of the library. + * @param enable Whether to enable or disable the logging. * * @param enabled */ - void setLogEnabled(int enabled); + void setLogEnabled(int enable); /** * Returns the version of the zxing-cpp library. @@ -79,44 +98,47 @@ extern "C" char const *version(); /** - * @brief Reads barcode from image. + * @brief Read barcode from image bytes. * @param bytes Image bytes. - * @param format The format of the barcode - * @param width Image width. - * @param height Image height. + * @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 logEnabled Log enabled. - * @return Barcode result. + * @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. + * @return The barcode result. */ - struct CodeResult readBarcode(char *bytes, int format, int width, int height, int cropWidth, int cropHeight); + struct CodeResult readBarcode(char *bytes, int format, int width, int height, int cropWidth, int cropHeight, int tryHarder, int tryRotate); /** - * @brief Reads barcodes from image. + * @brief Read barcodes from image bytes. * @param bytes Image bytes. - * @param format The format of the barcode - * @param width Image width. - * @param height Image height. + * @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 logEnabled Log enabled. - * @return Barcode results. + * @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. + * @return The barcode results. */ - struct CodeResults readBarcodes(char *bytes, int format, int width, int height, int cropWidth, int cropHeight); + struct CodeResults readBarcodes(char *bytes, int format, int width, int height, int cropWidth, int cropHeight, int tryHarder, int tryRotate); /** * @brief Encode a string into a barcode * @param contents The string to encode - * @param width The width of the barcode - * @param height The height of the barcode + * @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 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 encodeBarcode(char *contents, int width, int height, int format, int margin, int eccLevel); + // Private functions + void resultToCodeResult(struct CodeResult *code, ZXing::Result result); #ifdef __cplusplus diff --git a/lib/generated_bindings.dart b/lib/generated_bindings.dart index e9deca7..fe2943c 100644 --- a/lib/generated_bindings.dart +++ b/lib/generated_bindings.dart @@ -20,13 +20,14 @@ class GeneratedBindings { : _lookup = lookup; /// @brief Enables or disables the logging of the library. + /// @param enable Whether to enable or disable the logging. /// /// @param enabled void setLogEnabled( - int enabled, + int enable, ) { return _setLogEnabled( - enabled, + enable, ); } @@ -47,15 +48,16 @@ class GeneratedBindings { late final _version = _versionPtr.asFunction Function()>(); - /// @brief Reads barcode from image. + /// @brief Read barcode from image bytes. /// @param bytes Image bytes. - /// @param format The format of the barcode - /// @param width Image width. - /// @param height Image height. + /// @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 logEnabled Log enabled. - /// @return Barcode result. + /// @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. + /// @return The barcode result. CodeResult readBarcode( ffi.Pointer bytes, int format, @@ -63,6 +65,8 @@ class GeneratedBindings { int height, int cropWidth, int cropHeight, + int tryHarder, + int tryRotate, ) { return _readBarcode( bytes, @@ -71,25 +75,29 @@ class GeneratedBindings { height, cropWidth, cropHeight, + tryHarder, + tryRotate, ); } late final _readBarcodePtr = _lookup< ffi.NativeFunction< CodeResult Function(ffi.Pointer, ffi.Int, ffi.Int, ffi.Int, - ffi.Int, ffi.Int)>>('readBarcode'); + ffi.Int, ffi.Int, ffi.Int, ffi.Int)>>('readBarcode'); late final _readBarcode = _readBarcodePtr.asFunction< - CodeResult Function(ffi.Pointer, int, int, int, int, int)>(); + CodeResult Function( + ffi.Pointer, int, int, int, int, int, int, int)>(); - /// @brief Reads barcodes from image. + /// @brief Read barcodes from image bytes. /// @param bytes Image bytes. - /// @param format The format of the barcode - /// @param width Image width. - /// @param height Image height. + /// @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 logEnabled Log enabled. - /// @return Barcode results. + /// @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. + /// @return The barcode results. CodeResults readBarcodes( ffi.Pointer bytes, int format, @@ -97,6 +105,8 @@ class GeneratedBindings { int height, int cropWidth, int cropHeight, + int tryHarder, + int tryRotate, ) { return _readBarcodes( bytes, @@ -105,23 +115,25 @@ class GeneratedBindings { height, cropWidth, cropHeight, + tryHarder, + tryRotate, ); } late final _readBarcodesPtr = _lookup< ffi.NativeFunction< CodeResults Function(ffi.Pointer, ffi.Int, ffi.Int, ffi.Int, - ffi.Int, ffi.Int)>>('readBarcodes'); + ffi.Int, ffi.Int, ffi.Int, ffi.Int)>>('readBarcodes'); late final _readBarcodes = _readBarcodesPtr.asFunction< - CodeResults Function(ffi.Pointer, int, int, int, int, int)>(); + CodeResults Function( + ffi.Pointer, int, int, int, int, int, int, int)>(); /// @brief Encode a string into a barcode /// @param contents The string to encode - /// @param width The width of the barcode - /// @param height The height of the barcode + /// @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 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 encodeBarcode( @@ -150,6 +162,7 @@ class GeneratedBindings { EncodeResult Function(ffi.Pointer, int, int, int, int, int)>(); } +/// @brief Format Enumerates barcode formats known to this package. abstract class Format { /// < Used as a return value if no valid barcode has been detected static const int None = 0; @@ -206,64 +219,88 @@ abstract class Format { static const int Any = 65535; } +/// @brief Pos is a position of a barcode in a image. class Pos extends ffi.Struct { + /// < x coordinate of top left corner of barcode @ffi.Int() external int topLeftX; + /// < y coordinate of top left corner of barcode @ffi.Int() external int topLeftY; + /// < x coordinate of top right corner of barcode @ffi.Int() external int topRightX; + /// < y coordinate of top right corner of barcode @ffi.Int() external int topRightY; + /// < x coordinate of bottom left corner of barcode @ffi.Int() external int bottomLeftX; + /// < y coordinate of bottom left corner of barcode @ffi.Int() external int bottomLeftY; + /// < x coordinate of bottom right corner of barcode @ffi.Int() external int bottomRightX; + /// < y coordinate of bottom right corner of barcode @ffi.Int() external int bottomRightY; } +/// @brief The CodeResult class encapsulates the result of decoding a barcode within an image. class CodeResult extends ffi.Struct { + /// < Whether the barcode was successfully decoded @ffi.Int() external int isValid; + /// < The decoded text external ffi.Pointer text; + /// < The format of the barcode @ffi.Int32() external int format; + /// < The position of the barcode within the image external ffi.Pointer pos; } +/// @brief The CodeResults class encapsulates the result of decoding multiple barcodes within an image. class CodeResults extends ffi.Struct { + /// < The number of barcodes detected @ffi.Int() external int count; + /// < The results of the barcode decoding external ffi.Pointer results; } +/// @brief EncodeResult encapsulates the result of encoding a barcode. class EncodeResult extends ffi.Struct { + /// < Whether the barcode was successfully encoded @ffi.Int() external int isValid; + /// < The encoded text external ffi.Pointer text; + /// < The format of the barcode @ffi.Int32() external int format; + /// < The encoded data external ffi.Pointer data; + /// < The length of the encoded data @ffi.Int() external int length; + /// < The error message external ffi.Pointer error; } diff --git a/lib/src/logic/barcode_encoder.dart b/lib/src/logic/barcode_encoder.dart index a221259..5f1d677 100644 --- a/lib/src/logic/barcode_encoder.dart +++ b/lib/src/logic/barcode_encoder.dart @@ -1,7 +1,14 @@ part of 'zxing.dart'; -EncodeResult encodeBarcode(String contents, int width, int height, int format, - int margin, int eccLevel) { +// Encode a string into a barcode +EncodeResult encodeBarcode( + String contents, + int width, + int height, + int format, + int margin, + int eccLevel, +) { return bindings.encodeBarcode( contents.toNativeUtf8().cast(), width, diff --git a/lib/src/logic/barcode_reader.dart b/lib/src/logic/barcode_reader.dart index 3e25eca..10bc7c1 100644 --- a/lib/src/logic/barcode_reader.dart +++ b/lib/src/logic/barcode_reader.dart @@ -6,12 +6,16 @@ Future readBarcodeImagePathString( int format = Format.Any, int cropWidth = 0, int cropHeight = 0, + bool tryHarder = false, + bool tryRotate = true, }) => readBarcodeImagePath( XFile(path), format: format, cropWidth: cropWidth, cropHeight: cropHeight, + tryHarder: tryHarder, + tryRotate: tryRotate, ); /// Reads barcode from XFile image path @@ -20,6 +24,8 @@ Future readBarcodeImagePath( int format = Format.Any, int cropWidth = 0, int cropHeight = 0, + bool tryHarder = false, + bool tryRotate = true, }) async { final Uint8List imageBytes = await path.readAsBytes(); final imglib.Image? image = imglib.decodeImage(imageBytes); @@ -33,6 +39,8 @@ Future readBarcodeImagePath( format: format, cropWidth: cropWidth, cropHeight: cropHeight, + tryHarder: tryHarder, + tryRotate: tryRotate, ); } @@ -42,6 +50,8 @@ Future readBarcodeImageUrl( int format = Format.Any, int cropWidth = 0, int cropHeight = 0, + bool tryHarder = false, + bool tryRotate = true, }) async { final Uint8List imageBytes = (await NetworkAssetBundle(Uri.parse(url)).load(url)).buffer.asUint8List(); @@ -56,6 +66,8 @@ Future readBarcodeImageUrl( format: format, cropWidth: cropWidth, cropHeight: cropHeight, + tryHarder: tryHarder, + tryRotate: tryRotate, ); } @@ -67,6 +79,8 @@ CodeResult readBarcode( int format = Format.Any, int cropWidth = 0, int cropHeight = 0, + bool tryHarder = false, + bool tryRotate = true, }) => bindings.readBarcode( bytes.allocatePointer(), @@ -75,4 +89,6 @@ CodeResult readBarcode( height, cropWidth, cropHeight, + tryHarder ? 1 : 0, + tryRotate ? 1 : 0, ); diff --git a/lib/src/logic/barcodes_reader.dart b/lib/src/logic/barcodes_reader.dart index 80a4000..5b8e980 100644 --- a/lib/src/logic/barcodes_reader.dart +++ b/lib/src/logic/barcodes_reader.dart @@ -6,12 +6,16 @@ Future> readBarcodesImagePathString( int format = Format.Any, int cropWidth = 0, int cropHeight = 0, + bool tryHarder = false, + bool tryRotate = true, }) => readBarcodesImagePath( XFile(path), format: format, cropWidth: cropWidth, cropHeight: cropHeight, + tryHarder: tryHarder, + tryRotate: tryRotate, ); /// Reads barcodes from XFile image path @@ -20,6 +24,8 @@ Future> readBarcodesImagePath( int format = Format.Any, int cropWidth = 0, int cropHeight = 0, + bool tryHarder = false, + bool tryRotate = true, }) async { final Uint8List imageBytes = await path.readAsBytes(); final imglib.Image? image = imglib.decodeImage(imageBytes); @@ -33,6 +39,8 @@ Future> readBarcodesImagePath( format: format, cropWidth: cropWidth, cropHeight: cropHeight, + tryHarder: tryHarder, + tryRotate: tryRotate, ); } @@ -42,6 +50,8 @@ Future> readBarcodesImageUrl( int format = Format.Any, int cropWidth = 0, int cropHeight = 0, + bool tryHarder = false, + bool tryRotate = true, }) async { final Uint8List imageBytes = (await NetworkAssetBundle(Uri.parse(url)).load(url)).buffer.asUint8List(); @@ -56,6 +66,8 @@ Future> readBarcodesImageUrl( format: format, cropWidth: cropWidth, cropHeight: cropHeight, + tryHarder: tryHarder, + tryRotate: tryRotate, ); } @@ -67,9 +79,19 @@ List readBarcodes( int format = Format.Any, int cropWidth = 0, int cropHeight = 0, + bool tryHarder = false, + bool tryRotate = true, }) { final CodeResults result = bindings.readBarcodes( - bytes.allocatePointer(), format, width, height, cropWidth, cropHeight); + bytes.allocatePointer(), + format, + width, + height, + cropWidth, + cropHeight, + tryHarder ? 1 : 0, + tryRotate ? 1 : 0, + ); final List results = []; for (int i = 0; i < result.count; i++) { results.add(result.results.elementAt(i).ref); diff --git a/pubspec.yaml b/pubspec.yaml index 5c94312..d26a4fd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -36,5 +36,9 @@ ffigen: headers: entry-points: - "ios/Classes/src/native_zxing.h" + functions: + exclude: + - resultToCodeResult + # flutter pub publish --dry-run \ No newline at end of file