Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implemented AutoZoom feature for Android #1243

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ See the example app for detailed implementation information.
| analyzeImage (Gallery) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: |
| returnImage | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: |
| scanWindow | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: |
| autoZoom | :heavy_check_mark: | :x: | :x: | :x: |

## Platform Support

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,11 @@ class MobileScanner(
camera?.cameraControl?.setLinearZoom(scale.toFloat())
}

fun setZoomRatio(zoomRatio: Double) {
if (camera == null) throw ZoomWhenStopped()
camera?.cameraControl?.setZoomRatio(zoomRatio.toFloat())
}

/**
* Reset the zoom rate of the camera.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package dev.steenbakker.mobile_scanner

import android.app.Activity
import android.content.Context
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CameraManager
import android.net.Uri
import android.os.Handler
import android.os.Looper
Expand All @@ -18,6 +21,7 @@ import io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.view.TextureRegistry
import java.io.File
import com.google.mlkit.vision.barcode.ZoomSuggestionOptions

class MobileScannerHandler(
private val activity: Activity,
Expand Down Expand Up @@ -138,13 +142,14 @@ class MobileScannerHandler(
val speed: Int = call.argument<Int>("speed") ?: 1
val timeout: Int = call.argument<Int>("timeout") ?: 250
val cameraResolutionValues: List<Int>? = call.argument<List<Int>>("cameraResolution")
val enableAutoZoom: Boolean = call.argument<Boolean>("autoZoom") ?: false
val cameraResolution: Size? = if (cameraResolutionValues != null) {
Size(cameraResolutionValues[0], cameraResolutionValues[1])
} else {
null
}

val barcodeScannerOptions: BarcodeScannerOptions? = buildBarcodeScannerOptions(formats)
val barcodeScannerOptions: BarcodeScannerOptions? = buildBarcodeScannerOptions(formats, enableAutoZoom)

val position =
if (facing == 0) CameraSelector.DEFAULT_FRONT_CAMERA else CameraSelector.DEFAULT_BACK_CAMERA
Expand Down Expand Up @@ -241,7 +246,7 @@ class MobileScannerHandler(

mobileScanner!!.analyzeImage(
Uri.fromFile(File(filePath)),
buildBarcodeScannerOptions(formats),
buildBarcodeScannerOptions(formats, false),
analyzeImageSuccessCallback,
analyzeImageErrorCallback)
}
Expand All @@ -264,6 +269,14 @@ class MobileScannerHandler(
}
}

private fun setZoomRatio(scale: Float) : Boolean {
try {
mobileScanner!!.setZoomRatio(scale.toDouble())
return true
} catch (e: ZoomWhenStopped) { }
return false
}

private fun resetScale(result: MethodChannel.Result) {
try {
mobileScanner!!.resetScale()
Expand All @@ -280,25 +293,54 @@ class MobileScannerHandler(
result.success(null)
}

private fun buildBarcodeScannerOptions(formats: List<Int>?): BarcodeScannerOptions? {
private fun buildBarcodeScannerOptions(formats: List<Int>?, enableAutoZoom: Boolean): BarcodeScannerOptions? {
val builder : BarcodeScannerOptions.Builder?
if (formats == null) {
return null
}
builder = BarcodeScannerOptions.Builder()
} else {
val formatsList: MutableList<Int> = mutableListOf()

val formatsList: MutableList<Int> = mutableListOf()
for (formatValue in formats) {
formatsList.add(BarcodeFormats.fromRawValue(formatValue).intValue)
}

for (formatValue in formats) {
formatsList.add(BarcodeFormats.fromRawValue(formatValue).intValue)
if (formatsList.size == 1) {
builder = BarcodeScannerOptions.Builder().setBarcodeFormats(formatsList.first())
} else {
builder = BarcodeScannerOptions.Builder().setBarcodeFormats(
formatsList.first(),
*formatsList.subList(1, formatsList.size).toIntArray()
)
}
}

if (formatsList.size == 1) {
return BarcodeScannerOptions.Builder().setBarcodeFormats(formatsList.first())
.build()
if (enableAutoZoom) {
builder.setZoomSuggestionOptions(
ZoomSuggestionOptions.Builder {
setZoomRatio(it)
}.setMaxSupportedZoomRatio(getMaxZoomRatio())
.build())
}

return BarcodeScannerOptions.Builder().setBarcodeFormats(
formatsList.first(),
*formatsList.subList(1, formatsList.size).toIntArray()
).build()
return builder.build()
}

private fun getMaxZoomRatio(): Float {
val cameraManager = activity.getSystemService(Context.CAMERA_SERVICE) as CameraManager
var maxZoom = 1.0F

try {
for (cameraId in cameraManager.cameraIdList) {
val characteristics = cameraManager.getCameraCharacteristics(cameraId)

val maxZoomRatio = characteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM)
if (maxZoomRatio != null && maxZoomRatio > maxZoom) {
maxZoom = maxZoomRatio
}
}
} catch (e: Exception) {
e.printStackTrace()
}
return maxZoom
}
}
1 change: 1 addition & 0 deletions example/lib/barcode_scanner_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class _BarcodeScannerWithControllerState
final MobileScannerController controller = MobileScannerController(
autoStart: false,
torchEnabled: true,
enableAutoZoom: true,
);

@override
Expand Down
7 changes: 7 additions & 0 deletions lib/src/mobile_scanner_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> {
this.formats = const <BarcodeFormat>[],
this.returnImage = false,
this.torchEnabled = false,
this.enableAutoZoom = false,
}) : detectionTimeoutMs =
detectionSpeed == DetectionSpeed.normal ? detectionTimeoutMs : 0,
assert(
Expand Down Expand Up @@ -89,6 +90,11 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> {
/// Defaults to false.
final bool torchEnabled;

/// Whether the Camera should auto zoom.
///
/// Only supported on Android.
final bool enableAutoZoom;

/// The internal barcode controller, that listens for detected barcodes.
final StreamController<BarcodeCapture> _barcodesController =
StreamController.broadcast();
Expand Down Expand Up @@ -304,6 +310,7 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> {
formats: formats,
returnImage: returnImage,
torchEnabled: torchEnabled,
enableAutoZoom: enableAutoZoom,
);

try {
Expand Down
7 changes: 7 additions & 0 deletions lib/src/objects/start_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class StartOptions {
required this.formats,
required this.returnImage,
required this.torchEnabled,
required this.enableAutoZoom,
});

/// The direction for the camera.
Expand All @@ -38,6 +39,11 @@ class StartOptions {
/// Whether the torch should be turned on when the scanner starts.
final bool torchEnabled;

/// Whether the Camera should auto zoom.
///
/// This option is only supported on Android. Other platforms will ignore this option.
final bool enableAutoZoom;

/// Converts this object to a map.
Map<String, Object?> toMap() {
return <String, Object?>{
Expand All @@ -53,6 +59,7 @@ class StartOptions {
'speed': detectionSpeed.rawValue,
'timeout': detectionTimeoutMs,
'torch': torchEnabled,
'autoZoom': enableAutoZoom,
};
}
}
Loading