Sander Roest

Fix coordinate space image and barcode.corners

@@ -25,14 +25,10 @@ class _BarcodeScannerPicklistState extends State<BarcodeScannerPicklist> { @@ -25,14 +25,10 @@ class _BarcodeScannerPicklistState extends State<BarcodeScannerPicklist> {
25 final _mobileScannerController = MobileScannerController( 25 final _mobileScannerController = MobileScannerController(
26 // The controller is started from the initState method. 26 // The controller is started from the initState method.
27 autoStart: false, 27 autoStart: false,
28 - // The know the placing of the barcodes, we need to know the size of the  
29 - // canvas they are placed on. Unfortunately the only known reliable way  
30 - // to get the dimensions, is to receive the complete image from the native  
31 - // side.  
32 - // https://github.com/juliansteenbakker/mobile_scanner/issues/1183  
33 - returnImage: true,  
34 ); 28 );
35 29
  30 + final orientation = DeviceOrientation.portraitUp;
  31 +
36 // On this subscription the barcodes are received. 32 // On this subscription the barcodes are received.
37 StreamSubscription<Object?>? _subscription; 33 StreamSubscription<Object?>? _subscription;
38 34
@@ -45,17 +41,8 @@ class _BarcodeScannerPicklistState extends State<BarcodeScannerPicklist> { @@ -45,17 +41,8 @@ class _BarcodeScannerPicklistState extends State<BarcodeScannerPicklist> {
45 41
46 @override 42 @override
47 void initState() { 43 void initState() {
48 - // Enable and disable scanning on the native side, so we don't get a stream  
49 - // of images when not needed. This also improves the behavior (false  
50 - // positives) when the user switches quickly to another barcode after  
51 - // enabling the scanner by releasing the finger.  
52 - _scannerEnabled.addListener(() {  
53 - _scannerEnabled.value  
54 - ? _mobileScannerController.updateScanWindow(null)  
55 - : _mobileScannerController.updateScanWindow(Rect.zero);  
56 - });  
57 // Lock to portrait (may not work on iPad with multitasking). 44 // Lock to portrait (may not work on iPad with multitasking).
58 - SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); 45 + SystemChrome.setPreferredOrientations([orientation]);
59 // Get a stream subscription and listen to received barcodes. 46 // Get a stream subscription and listen to received barcodes.
60 _subscription = _mobileScannerController.barcodes.listen(_handleBarcodes); 47 _subscription = _mobileScannerController.barcodes.listen(_handleBarcodes);
61 super.initState(); 48 super.initState();
@@ -83,7 +70,7 @@ class _BarcodeScannerPicklistState extends State<BarcodeScannerPicklist> { @@ -83,7 +70,7 @@ class _BarcodeScannerPicklistState extends State<BarcodeScannerPicklist> {
83 if (!_scannerEnabled.value || _validBarcodeFound) { 70 if (!_scannerEnabled.value || _validBarcodeFound) {
84 return; 71 return;
85 } 72 }
86 - final barcode = findBarcodeAtCenter(barcodeCapture); 73 + final barcode = findBarcodeAtCenter(barcodeCapture, orientation);
87 if (barcode != null) { 74 if (barcode != null) {
88 _validBarcodeFound = true; 75 _validBarcodeFound = true;
89 Navigator.of(context).pop(barcode); 76 Navigator.of(context).pop(barcode);
1 -import 'package:flutter/material.dart'; 1 +import 'package:flutter/services.dart';
2 import 'package:mobile_scanner/mobile_scanner.dart'; 2 import 'package:mobile_scanner/mobile_scanner.dart';
  3 +import 'package:mobile_scanner_example/picklist/classes/fix_coordinate_space.dart';
3 4
4 /// This function finds the barcode that touches the center of the 5 /// This function finds the barcode that touches the center of the
5 /// image. If no barcode is found that touches the center, null is returned. 6 /// image. If no barcode is found that touches the center, null is returned.
6 /// See [_BarcodeScannerPicklistState] and the returnImage option for more info. 7 /// See [_BarcodeScannerPicklistState] and the returnImage option for more info.
7 /// 8 ///
8 /// https://github.com/juliansteenbakker/mobile_scanner/issues/1183 9 /// https://github.com/juliansteenbakker/mobile_scanner/issues/1183
9 -Barcode? findBarcodeAtCenter(BarcodeCapture barcodeCapture) {  
10 - final imageSize = barcodeCapture.size; 10 +Barcode? findBarcodeAtCenter(
  11 + BarcodeCapture barcodeCapture,
  12 + DeviceOrientation orientation,
  13 +) {
  14 + final imageSize = fixPortraitLandscape(barcodeCapture.size, orientation);
11 for (final barcode in barcodeCapture.barcodes) { 15 for (final barcode in barcodeCapture.barcodes) {
  16 + final corners = fixCorners(barcode.corners);
12 if (_isPolygonTouchingTheCenter( 17 if (_isPolygonTouchingTheCenter(
13 imageSize: imageSize, 18 imageSize: imageSize,
14 - polygon: barcode.corners, 19 + polygon: corners,
15 )) { 20 )) {
16 return barcode; 21 return barcode;
17 } 22 }
  1 +import 'package:flutter/services.dart';
  2 +
  3 +Size fixPortraitLandscape(
  4 + Size imageSize,
  5 + DeviceOrientation orientation,
  6 +) {
  7 + switch (orientation) {
  8 + case DeviceOrientation.portraitUp:
  9 + case DeviceOrientation.portraitDown:
  10 + return Size(imageSize.shortestSide, imageSize.longestSide);
  11 + case DeviceOrientation.landscapeLeft:
  12 + case DeviceOrientation.landscapeRight:
  13 + return Size(imageSize.longestSide, imageSize.shortestSide);
  14 + }
  15 +}
  16 +
  17 +List<Offset> fixCorners(List<Offset> corners) {
  18 + // Clone the original list to avoid side-effects
  19 + final sorted = List<Offset>.from(corners);
  20 +
  21 + sorted.sort((a, b) {
  22 + // Prioritize y-axis (dy), and within that, the x-axis (dx)
  23 + int compare = a.dy.compareTo(b.dy);
  24 + if (compare == 0) {
  25 + compare = a.dx.compareTo(b.dx);
  26 + }
  27 + return compare;
  28 + });
  29 +
  30 + final topLeft = sorted.first; // smallest x, smallest y
  31 + final topRight = sorted[1]; // larger x, smaller y
  32 + final bottomLeft = sorted[2]; // smaller x, larger y
  33 + final bottomRight = sorted.last; // larger x, larger y
  34 +
  35 + return [topLeft, topRight, bottomRight, bottomLeft];
  36 +}