Skip to content

Commit

Permalink
Merge pull request #1202 from navaronbracke/always_return_capture_size
Browse files Browse the repository at this point in the history
feat: Always return capture size
  • Loading branch information
navaronbracke authored Oct 5, 2024
2 parents 17255d4 + b0d58a7 commit 7edd187
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 41 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ Improvements:
* [MacOS] Added support for `analyzeImage`.
* [MacOS] Added a Privacy Manifest.
* [web] Added the size information to barcode results.
* [web] Added the video output size information to barcode capture.
* Added support for barcode formats to image analysis.
* Updated the scanner to report any scanning errors that were encountered during processing.
* Introduced a new getter `hasCameraPermission` for the `MobileScannerState`.
* Fixed a bug in the lifecycle handling sample. Now instead of checking `isInitialized`,
the sample recommends using `hasCameraPermission`, which also guards against camera permission errors.
* Updated the behavior of `returnImage` to only determine if the camera output bytes should be sent.
* Updated the behavior of `BarcodeCapture.size` to always be provided when available, regardless of `returnImage`.

Bugs fixed:
* Fixed a bug that would cause the scanner to emit an error when it was already started. Now it ignores any calls to start while it is starting.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,11 @@ class MobileScanner(
}

if (!returnImage) {
mobileScannerCallback(barcodeMap, null, null, null)
mobileScannerCallback(
barcodeMap,
null,
mediaImage.width,
mediaImage.height)
return@addOnSuccessListener
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,17 @@ class MobileScannerHandler(
private var analyzerResult: MethodChannel.Result? = null

private val callback: MobileScannerCallback = { barcodes: List<Map<String, Any?>>, image: ByteArray?, width: Int?, height: Int? ->
if (image != null) {
barcodeHandler.publishEvent(mapOf(
"name" to "barcode",
"data" to barcodes,
"image" to mapOf(
"bytes" to image,
"width" to width?.toDouble(),
"height" to height?.toDouble(),
)
))
} else {
barcodeHandler.publishEvent(mapOf(
"name" to "barcode",
"data" to barcodes
))
}
barcodeHandler.publishEvent(mapOf(
"name" to "barcode",
"data" to barcodes,
// The image dimensions are always provided.
// The image bytes are only non-null when `returnImage` is true.
"image" to mapOf(
"bytes" to image,
"width" to width?.toDouble(),
"height" to height?.toDouble(),
)
))
}

private val errorCallback: MobileScannerErrorCallback = {error: String ->
Expand Down
20 changes: 8 additions & 12 deletions ios/Classes/MobileScannerPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,22 +69,18 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin {
return
}

if (!MobileScannerPlugin.returnImage) {
barcodeHandler.publishEvent([
"name": "barcode",
"data": barcodesMap,
])
return
}
// The image dimensions are always provided.
// The image bytes are only non-null when `returnImage` is true.
let imageData: [String: Any?] = [
"bytes": MobileScannerPlugin.returnImage ? FlutterStandardTypedData(bytes: image.jpegData(compressionQuality: 0.8)!) : nil,
"width": image.size.width,
"height": image.size.height,
]

barcodeHandler.publishEvent([
"name": "barcode",
"data": barcodesMap,
"image": [
"bytes": FlutterStandardTypedData(bytes: image.jpegData(compressionQuality: 0.8)!),
"width": image.size.width,
"height": image.size.height,
],
"image": imageData,
])
}, torchModeChangeCallback: { torchState in
barcodeHandler.publishEvent(["name": "torchState", "data": torchState])
Expand Down
3 changes: 1 addition & 2 deletions lib/src/mobile_scanner_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,7 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> {
/// If this is empty, all supported formats are detected.
final List<BarcodeFormat> formats;

/// Whether scanned barcodes should contain the image
/// that is embedded into the barcode.
/// Whether the [BarcodeCapture.image] bytes should be provided.
///
/// If this is false, [BarcodeCapture.image] will always be null.
///
Expand Down
4 changes: 1 addition & 3 deletions lib/src/objects/barcode_capture.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ class BarcodeCapture {
/// This is the data that was used to detect the available [barcodes], the input [image] and the [size].
final Object? raw;

/// The size of the input [image].
///
/// If [image] is null, this will be [Size.zero].
/// The size of the camera input [image].
final Size size;
}
1 change: 1 addition & 0 deletions lib/src/web/mobile_scanner_web.dart
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ class MobileScannerWeb extends MobileScannerPlatform {
final JSArray<JSString>? facingModes = capabilities.facingModeNullable;

// TODO: this is an empty array on MacOS Chrome, where there is no facing mode, but one, user facing camera.
// We might be able to add a workaround, using the label of the video track.
// Facing mode is not supported by this track, do nothing.
if (facingModes == null || facingModes.toDart.isEmpty) {
return;
Expand Down
1 change: 1 addition & 0 deletions lib/src/web/zxing/zxing_barcode_reader.dart
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ final class ZXingBarcodeReader extends BarcodeReader {
controller.add(
BarcodeCapture(
barcodes: [result.toBarcode],
size: videoSize,
),
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,22 +156,26 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler,
})

DispatchQueue.main.async {
if (!MobileScannerPlugin.returnImage) {
guard let image = cgImage else {
self?.sink?([
"name": "barcode",
"data": barcodes.map({ $0.toMap() }),
])
return
}


// The image dimensions are always provided.
// The image bytes are only non-null when `returnImage` is true.
let imageData: [String: Any?] = [
"bytes": MobileScannerPlugin.returnImage ? FlutterStandardTypedData(bytes: image.jpegData(compressionQuality: 0.8)!) : nil,
"width": Double(image.width),
"height": Double(image.height),
]

self?.sink?([
"name": "barcode",
"data": barcodes.map({ $0.toMap() }),
"image": cgImage == nil ? nil : [
"bytes": FlutterStandardTypedData(bytes: cgImage!.jpegData(compressionQuality: 0.8)!),
"width": Double(cgImage!.width),
"height": Double(cgImage!.height),
],
"image": imageData,
])
}
})
Expand Down

0 comments on commit 7edd187

Please sign in to comment.