Showing
4 changed files
with
97 additions
and
29 deletions
| @@ -166,7 +166,7 @@ class MobileScanner(private val activity: Activity, private val textureRegistry: | @@ -166,7 +166,7 @@ class MobileScanner(private val activity: Activity, private val textureRegistry: | ||
| 166 | result.success(answer) | 166 | result.success(answer) |
| 167 | } else { | 167 | } else { |
| 168 | val facing: Int = call.argument<Int>("facing") ?: 0 | 168 | val facing: Int = call.argument<Int>("facing") ?: 0 |
| 169 | - val ratio: Int? = call.argument<Int>("ratio") | 169 | + val ratio: Int = call.argument<Int>("ratio") ?: 1 |
| 170 | val torch: Boolean = call.argument<Boolean>("torch") ?: false | 170 | val torch: Boolean = call.argument<Boolean>("torch") ?: false |
| 171 | val formats: List<Int>? = call.argument<List<Int>>("formats") | 171 | val formats: List<Int>? = call.argument<List<Int>>("formats") |
| 172 | 172 | ||
| @@ -197,6 +197,7 @@ class MobileScanner(private val activity: Activity, private val textureRegistry: | @@ -197,6 +197,7 @@ class MobileScanner(private val activity: Activity, private val textureRegistry: | ||
| 197 | result.error("textureEntry", "textureEntry is null", null) | 197 | result.error("textureEntry", "textureEntry is null", null) |
| 198 | return@addListener | 198 | return@addListener |
| 199 | } | 199 | } |
| 200 | + | ||
| 200 | // Preview | 201 | // Preview |
| 201 | val surfaceProvider = Preview.SurfaceProvider { request -> | 202 | val surfaceProvider = Preview.SurfaceProvider { request -> |
| 202 | val texture = textureEntry!!.surfaceTexture() | 203 | val texture = textureEntry!!.surfaceTexture() |
| @@ -207,17 +208,15 @@ class MobileScanner(private val activity: Activity, private val textureRegistry: | @@ -207,17 +208,15 @@ class MobileScanner(private val activity: Activity, private val textureRegistry: | ||
| 207 | 208 | ||
| 208 | // Build the preview to be shown on the Flutter texture | 209 | // Build the preview to be shown on the Flutter texture |
| 209 | val previewBuilder = Preview.Builder() | 210 | val previewBuilder = Preview.Builder() |
| 210 | - if (ratio != null) { | ||
| 211 | - previewBuilder.setTargetAspectRatio(ratio) | ||
| 212 | - } | 211 | + .setTargetAspectRatio(ratio) |
| 212 | + | ||
| 213 | preview = previewBuilder.build().apply { setSurfaceProvider(surfaceProvider) } | 213 | preview = previewBuilder.build().apply { setSurfaceProvider(surfaceProvider) } |
| 214 | 214 | ||
| 215 | // Build the analyzer to be passed on to MLKit | 215 | // Build the analyzer to be passed on to MLKit |
| 216 | val analysisBuilder = ImageAnalysis.Builder() | 216 | val analysisBuilder = ImageAnalysis.Builder() |
| 217 | .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) | 217 | .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) |
| 218 | - .setTargetResolution(preview!!.resolutionInfo?.resolution ?: Size(640, 480)) | 218 | + .setTargetAspectRatio(ratio) |
| 219 | 219 | ||
| 220 | - if (ratio != null) { analysisBuilder.setTargetAspectRatio(ratio) } | ||
| 221 | val analysis = analysisBuilder.build().apply { setAnalyzer(executor, analyzer) } | 220 | val analysis = analysisBuilder.build().apply { setAnalyzer(executor, analyzer) } |
| 222 | 221 | ||
| 223 | // Select the correct camera | 222 | // Select the correct camera |
| @@ -227,7 +226,6 @@ class MobileScanner(private val activity: Activity, private val textureRegistry: | @@ -227,7 +226,6 @@ class MobileScanner(private val activity: Activity, private val textureRegistry: | ||
| 227 | 226 | ||
| 228 | val analysisSize = analysis.resolutionInfo?.resolution ?: Size(0, 0) | 227 | val analysisSize = analysis.resolutionInfo?.resolution ?: Size(0, 0) |
| 229 | val previewSize = preview!!.resolutionInfo?.resolution ?: Size(0, 0) | 228 | val previewSize = preview!!.resolutionInfo?.resolution ?: Size(0, 0) |
| 230 | - | ||
| 231 | 229 | ||
| 232 | Log.i("LOG", "Analyzer: $analysisSize") | 230 | Log.i("LOG", "Analyzer: $analysisSize") |
| 233 | Log.i("LOG", "Preview: $previewSize") | 231 | Log.i("LOG", "Preview: $previewSize") |
| @@ -22,10 +22,16 @@ class _BarcodeScannerWithScanWindowState | @@ -22,10 +22,16 @@ class _BarcodeScannerWithScanWindowState | ||
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | Future<void> restart() async { | 24 | Future<void> restart() async { |
| 25 | - await controller.stop(); | 25 | + // await controller.stop(); |
| 26 | await controller.start(); | 26 | await controller.start(); |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | + Future<void> onDetect(Barcode barcode, MobileScannerArguments? _) async { | ||
| 30 | + setState(() => this.barcode = barcode.rawValue); | ||
| 31 | + await Future.delayed(const Duration(seconds: 1)); | ||
| 32 | + setState(() => this.barcode = ''); | ||
| 33 | + } | ||
| 34 | + | ||
| 29 | @override | 35 | @override |
| 30 | Widget build(BuildContext context) { | 36 | Widget build(BuildContext context) { |
| 31 | final scanWindow = Rect.fromCenter( | 37 | final scanWindow = Rect.fromCenter( |
| @@ -41,12 +47,11 @@ class _BarcodeScannerWithScanWindowState | @@ -41,12 +47,11 @@ class _BarcodeScannerWithScanWindowState | ||
| 41 | return Stack( | 47 | return Stack( |
| 42 | children: [ | 48 | children: [ |
| 43 | MobileScanner( | 49 | MobileScanner( |
| 44 | - fit: BoxFit.contain, | 50 | + fit: BoxFit.cover, |
| 45 | scanWindow: scanWindow, | 51 | scanWindow: scanWindow, |
| 46 | controller: controller, | 52 | controller: controller, |
| 47 | - onDetect: (barcode, _) => setState(() { | ||
| 48 | - this.barcode = barcode.rawValue; | ||
| 49 | - }), | 53 | + onDetect: onDetect, |
| 54 | + allowDuplicates: true, | ||
| 50 | ), | 55 | ), |
| 51 | CustomPaint( | 56 | CustomPaint( |
| 52 | painter: ScannerOverlay(scanWindow), | 57 | painter: ScannerOverlay(scanWindow), |
| 1 | import 'package:flutter/foundation.dart'; | 1 | import 'package:flutter/foundation.dart'; |
| 2 | -import 'package:flutter/material.dart'; | 2 | +import 'package:flutter/material.dart' hide applyBoxFit; |
| 3 | import 'package:mobile_scanner/mobile_scanner.dart'; | 3 | import 'package:mobile_scanner/mobile_scanner.dart'; |
| 4 | +import 'package:mobile_scanner/src/objects/barcode_utility.dart'; | ||
| 4 | 5 | ||
| 5 | enum Ratio { ratio_4_3, ratio_16_9 } | 6 | enum Ratio { ratio_4_3, ratio_16_9 } |
| 6 | 7 | ||
| @@ -89,22 +90,17 @@ class _MobileScannerState extends State<MobileScanner> | @@ -89,22 +90,17 @@ class _MobileScannerState extends State<MobileScanner> | ||
| 89 | Size textureSize, | 90 | Size textureSize, |
| 90 | Size widgetSize, | 91 | Size widgetSize, |
| 91 | ) { | 92 | ) { |
| 92 | - | ||
| 93 | /// map the texture size to get its new size after fitted to screen | 93 | /// map the texture size to get its new size after fitted to screen |
| 94 | - final fittedSizes = applyBoxFit(fit, textureSize, widgetSize); | ||
| 95 | - final fittedTextureSize = fittedSizes.destination; | 94 | + final fittedTextureSize = applyBoxFit(fit, textureSize, widgetSize); |
| 96 | 95 | ||
| 97 | /// create a new rectangle that represents the texture on the screen | 96 | /// create a new rectangle that represents the texture on the screen |
| 98 | final minX = widgetSize.width / 2 - fittedTextureSize.width / 2; | 97 | final minX = widgetSize.width / 2 - fittedTextureSize.width / 2; |
| 99 | final minY = widgetSize.height / 2 - fittedTextureSize.height / 2; | 98 | final minY = widgetSize.height / 2 - fittedTextureSize.height / 2; |
| 100 | - final width = fittedTextureSize.width; | ||
| 101 | - final height = fittedTextureSize.height; | ||
| 102 | - final textureWindow = Rect.fromLTWH(minX, minY, width, height); | 99 | + final textureWindow = Offset(minX, minY) & fittedTextureSize; |
| 103 | 100 | ||
| 104 | /// create a new scan window and with only the area of the rect intersecting the texture window | 101 | /// create a new scan window and with only the area of the rect intersecting the texture window |
| 105 | final scanWindowInTexture = scanWindow.intersect(textureWindow); | 102 | final scanWindowInTexture = scanWindow.intersect(textureWindow); |
| 106 | 103 | ||
| 107 | - | ||
| 108 | /// update the scanWindow left and top to be relative to the texture not the widget | 104 | /// update the scanWindow left and top to be relative to the texture not the widget |
| 109 | final newLeft = scanWindowInTexture.left - textureWindow.left; | 105 | final newLeft = scanWindowInTexture.left - textureWindow.left; |
| 110 | final newTop = scanWindowInTexture.top - textureWindow.top; | 106 | final newTop = scanWindowInTexture.top - textureWindow.top; |
| @@ -114,21 +110,12 @@ class _MobileScannerState extends State<MobileScanner> | @@ -114,21 +110,12 @@ class _MobileScannerState extends State<MobileScanner> | ||
| 114 | /// new scanWindow that is adapted to the boxfit and relative to the texture | 110 | /// new scanWindow that is adapted to the boxfit and relative to the texture |
| 115 | final windowInTexture = Rect.fromLTWH(newLeft, newTop, newWidth, newHeight); | 111 | final windowInTexture = Rect.fromLTWH(newLeft, newTop, newWidth, newHeight); |
| 116 | 112 | ||
| 117 | - print(windowInTexture); | ||
| 118 | - | ||
| 119 | /// get the scanWindow as a percentage of the texture | 113 | /// get the scanWindow as a percentage of the texture |
| 120 | final percentageLeft = windowInTexture.left / fittedTextureSize.width; | 114 | final percentageLeft = windowInTexture.left / fittedTextureSize.width; |
| 121 | final percentageTop = windowInTexture.top / fittedTextureSize.height; | 115 | final percentageTop = windowInTexture.top / fittedTextureSize.height; |
| 122 | final percentageRight = windowInTexture.right / fittedTextureSize.width; | 116 | final percentageRight = windowInTexture.right / fittedTextureSize.width; |
| 123 | final percentagebottom = windowInTexture.bottom / fittedTextureSize.height; | 117 | final percentagebottom = windowInTexture.bottom / fittedTextureSize.height; |
| 124 | 118 | ||
| 125 | - print(Rect.fromLTRB( | ||
| 126 | - percentageLeft, | ||
| 127 | - percentageTop, | ||
| 128 | - percentageRight, | ||
| 129 | - percentagebottom, | ||
| 130 | - )); | ||
| 131 | - | ||
| 132 | /// this rectangle can be send to native code and used to cut out a rectangle of the scan image | 119 | /// this rectangle can be send to native code and used to cut out a rectangle of the scan image |
| 133 | return Rect.fromLTRB( | 120 | return Rect.fromLTRB( |
| 134 | percentageLeft, | 121 | percentageLeft, |
| 1 | +import 'dart:math' as math; | ||
| 2 | + | ||
| 1 | import 'package:flutter/material.dart'; | 3 | import 'package:flutter/material.dart'; |
| 2 | import 'package:mobile_scanner/mobile_scanner.dart'; | 4 | import 'package:mobile_scanner/mobile_scanner.dart'; |
| 3 | 5 | ||
| @@ -147,3 +149,79 @@ WiFi? toWiFi(Map? data) { | @@ -147,3 +149,79 @@ WiFi? toWiFi(Map? data) { | ||
| 147 | return null; | 149 | return null; |
| 148 | } | 150 | } |
| 149 | } | 151 | } |
| 152 | + | ||
| 153 | +Size applyBoxFit(BoxFit fit, Size input, Size output) { | ||
| 154 | + if (input.height <= 0.0 || | ||
| 155 | + input.width <= 0.0 || | ||
| 156 | + output.height <= 0.0 || | ||
| 157 | + output.width <= 0.0) { | ||
| 158 | + return Size.zero; | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + Size destination; | ||
| 162 | + | ||
| 163 | + final inputAspectRatio = input.width / input.height; | ||
| 164 | + final outputAspectRatio = output.width / output.height; | ||
| 165 | + | ||
| 166 | + switch (fit) { | ||
| 167 | + case BoxFit.fill: | ||
| 168 | + destination = output; | ||
| 169 | + break; | ||
| 170 | + case BoxFit.contain: | ||
| 171 | + if (outputAspectRatio > inputAspectRatio) { | ||
| 172 | + destination = Size( | ||
| 173 | + input.width * output.height / input.height, | ||
| 174 | + output.height, | ||
| 175 | + ); | ||
| 176 | + } else { | ||
| 177 | + destination = Size( | ||
| 178 | + output.width, | ||
| 179 | + input.height * output.width / input.width, | ||
| 180 | + ); | ||
| 181 | + } | ||
| 182 | + break; | ||
| 183 | + | ||
| 184 | + case BoxFit.cover: | ||
| 185 | + if (outputAspectRatio > inputAspectRatio) { | ||
| 186 | + destination = Size( | ||
| 187 | + output.width, | ||
| 188 | + input.height * (output.width / input.width), | ||
| 189 | + ); | ||
| 190 | + } else { | ||
| 191 | + destination = Size( | ||
| 192 | + input.width * (output.height / input.height), | ||
| 193 | + output.height, | ||
| 194 | + ); | ||
| 195 | + } | ||
| 196 | + break; | ||
| 197 | + case BoxFit.fitWidth: | ||
| 198 | + destination = Size( | ||
| 199 | + output.width, | ||
| 200 | + input.height * (output.width / input.width), | ||
| 201 | + ); | ||
| 202 | + break; | ||
| 203 | + case BoxFit.fitHeight: | ||
| 204 | + destination = Size( | ||
| 205 | + input.width * (output.height / input.height), | ||
| 206 | + output.height, | ||
| 207 | + ); | ||
| 208 | + break; | ||
| 209 | + case BoxFit.none: | ||
| 210 | + destination = Size( | ||
| 211 | + math.min(input.width, output.width), | ||
| 212 | + math.min(input.height, output.height), | ||
| 213 | + ); | ||
| 214 | + break; | ||
| 215 | + case BoxFit.scaleDown: | ||
| 216 | + destination = input; | ||
| 217 | + if (destination.height > output.height) { | ||
| 218 | + destination = Size(output.height * inputAspectRatio, output.height); | ||
| 219 | + } | ||
| 220 | + if (destination.width > output.width) { | ||
| 221 | + destination = Size(output.width, output.width / inputAspectRatio); | ||
| 222 | + } | ||
| 223 | + break; | ||
| 224 | + } | ||
| 225 | + | ||
| 226 | + return destination; | ||
| 227 | +} |
-
Please register or login to post a comment