Navaron Bracke
Committed by GitHub

Merge pull request #1202 from navaronbracke/always_return_capture_size

feat: Always return capture size
... ... @@ -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.
... ...
... ... @@ -120,7 +120,11 @@ class MobileScanner(
}
if (!returnImage) {
mobileScannerCallback(barcodeMap, null, null, null)
mobileScannerCallback(
barcodeMap,
null,
mediaImage.width,
mediaImage.height)
return@addOnSuccessListener
}
... ...
... ... @@ -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,
// 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(),
)
))
} else {
barcodeHandler.publishEvent(mapOf(
"name" to "barcode",
"data" to barcodes
))
}
}
private val errorCallback: MobileScannerErrorCallback = {error: String ->
... ...
... ... @@ -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])
... ...
... ... @@ -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.
///
... ...
... ... @@ -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;
}
... ...
... ... @@ -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;
... ...
... ... @@ -121,6 +121,7 @@ final class ZXingBarcodeReader extends BarcodeReader {
controller.add(
BarcodeCapture(
barcodes: [result.toBarcode],
size: videoSize,
),
);
}
... ...
... ... @@ -156,7 +156,7 @@ 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() }),
... ... @@ -164,14 +164,18 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler,
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,
])
}
})
... ...