diff --git a/example/lib/main.dart b/example/lib/main.dart index 5a01071..4398fd0 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -55,6 +55,7 @@ class _DemoPageState extends State { onScan: (value) { showMessage(context, 'Scanned: ${value.textString ?? ''}'); }, + tryInverted: true, ), ListView( children: [ diff --git a/lib/src/logic/camera_stream.dart b/lib/src/logic/camera_stream.dart index c396b68..2afda77 100644 --- a/lib/src/logic/camera_stream.dart +++ b/lib/src/logic/camera_stream.dart @@ -11,9 +11,15 @@ Future startCameraProcessing() async { /// Stops reading barcode from the camera void stopCameraProcessing() => isolateUtils?.stopReadingBarcode(); -Future processCameraImage(CameraImage image, - {int format = Format.Any, double cropPercent = 0.5}) async { - final IsolateData isolateData = IsolateData(image, format, cropPercent); +Future processCameraImage( + CameraImage image, { + int format = Format.Any, + double cropPercent = 0.5, + bool tryHarder = false, + bool tryInverted = false, +}) async { + final IsolateData isolateData = + IsolateData(image, format, cropPercent, tryHarder, tryInverted); final CodeResult result = await _inference(isolateData); return result; } diff --git a/lib/src/ui/reader_widget.dart b/lib/src/ui/reader_widget.dart index ef09215..133435d 100644 --- a/lib/src/ui/reader_widget.dart +++ b/lib/src/ui/reader_widget.dart @@ -18,6 +18,8 @@ class ReaderWidget extends StatefulWidget { required this.onScan, this.onControllerCreated, this.codeFormat = Format.Any, + this.tryHarder = false, + this.tryInverted = false, this.showCroppingRect = true, this.scannerOverlay, this.showFlashlight = true, @@ -33,6 +35,8 @@ class ReaderWidget extends StatefulWidget { final Function(CodeResult) onScan; final Function(CameraController?)? onControllerCreated; final int codeFormat; + final bool tryHarder; + final bool tryInverted; final bool showCroppingRect; final ScannerOverlay? scannerOverlay; final bool showFlashlight; @@ -167,6 +171,8 @@ class _ReaderWidgetState extends State image, format: widget.codeFormat, cropPercent: widget.showCroppingRect ? widget.cropPercent : 0, + tryHarder: widget.tryHarder, + tryInverted: widget.tryInverted, ); if (result.isValidBool) { widget.onScan(result); diff --git a/lib/src/utils/image_converter.dart b/lib/src/utils/image_converter.dart index e37ca16..96617b6 100644 --- a/lib/src/utils/image_converter.dart +++ b/lib/src/utils/image_converter.dart @@ -57,3 +57,11 @@ imglib.Image convertYUV420(CameraImage image) { return img; } + +Uint8List invertImage(Uint8List bytes) { + final Uint8List invertedBytes = Uint8List.fromList(bytes); + for (int i = 0; i < invertedBytes.length; i++) { + invertedBytes[i] = 255 - invertedBytes[i]; + } + return invertedBytes; +} diff --git a/lib/src/utils/isolate_utils.dart b/lib/src/utils/isolate_utils.dart index 43e0d33..bd6b9c5 100644 --- a/lib/src/utils/isolate_utils.dart +++ b/lib/src/utils/isolate_utils.dart @@ -16,10 +16,14 @@ class IsolateData { this.cameraImage, this.format, this.cropPercent, + this.tryHarder, + this.tryInverted, ); CameraImage cameraImage; int format; double cropPercent; + bool tryHarder; + bool tryInverted; SendPort? responsePort; } @@ -63,16 +67,33 @@ class IsolateUtils { final Uint8List bytes = await convertImage(image); final int cropSize = (min(image.width, image.height) * cropPercent).round(); + final bool tryHarder = isolateData.tryHarder; + final bool tryInverted = isolateData.tryInverted; - final CodeResult result = readBarcode( + CodeResult result = readBarcode( bytes, width: image.width, height: image.height, format: isolateData.format, cropWidth: cropSize, cropHeight: cropSize, + tryHarder: tryHarder, ); + if (result.isValid == 0 && tryInverted) { + // try to invert the image and read again + final Uint8List invertedBytes = invertImage(bytes); + result = readBarcode( + invertedBytes, + width: image.width, + height: image.height, + format: isolateData.format, + cropWidth: cropSize, + cropHeight: cropSize, + tryHarder: tryHarder, + ); + } + isolateData.responsePort?.send(result); } catch (e) { isolateData.responsePort?.send(e);