Browse Source

added processCameraImage function

pull/3/head
Khoren Markosyan 3 years ago
parent
commit
6a4f75925c
  1. 35
      lib/flutter_zxing.dart
  2. 10
      lib/isolate_utils.dart
  3. 42
      lib/reader_widget.dart

35
lib/flutter_zxing.dart

@ -1,6 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'dart:ffi'; import 'dart:ffi';
import 'dart:io'; import 'dart:io';
import 'dart:isolate';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:camera/camera.dart'; import 'package:camera/camera.dart';
@ -10,6 +11,7 @@ import 'package:flutter/services.dart';
import 'package:image/image.dart' as imglib; import 'package:image/image.dart' as imglib;
import 'generated_bindings.dart'; import 'generated_bindings.dart';
import 'isolate_utils.dart';
export 'generated_bindings.dart'; export 'generated_bindings.dart';
export 'reader_widget.dart'; export 'reader_widget.dart';
@ -17,6 +19,7 @@ export 'writer_widget.dart';
export 'image_converter.dart'; export 'image_converter.dart';
export 'scanner_overlay.dart'; export 'scanner_overlay.dart';
/// The main class for reading barcodes from images or camera.
class FlutterZxing { class FlutterZxing {
static const MethodChannel _channel = MethodChannel('flutter_zxing'); static const MethodChannel _channel = MethodChannel('flutter_zxing');
@ -27,6 +30,8 @@ class FlutterZxing {
static final bindings = GeneratedBindings(dylib); static final bindings = GeneratedBindings(dylib);
static IsolateUtils? isolateUtils;
static bool logEnabled = false; static bool logEnabled = false;
static void setLogEnabled(bool enabled) { static void setLogEnabled(bool enabled) {
@ -36,6 +41,16 @@ class FlutterZxing {
/// Returns a version of the zxing library /// Returns a version of the zxing library
static String version() => bindings.version().cast<Utf8>().toDartString(); static String version() => bindings.version().cast<Utf8>().toDartString();
/// Starts reading barcode from the camera
static Future startCameraProcessing() async {
// Spawn a new isolate
isolateUtils = IsolateUtils();
await isolateUtils?.startReadingBarcode();
}
/// Stops reading barcode from the camera
static stopCameraProcessing() => isolateUtils?.stopReadingBarcode();
/// Reads barcode from String image path /// Reads barcode from String image path
static Future<CodeResult?> readImagePathString( static Future<CodeResult?> readImagePathString(
String path, { String path, {
@ -114,7 +129,25 @@ class FlutterZxing {
return result; return result;
} }
static int get _logEnabled => logEnabled ? 1 : 0; static Future<CodeResult> processCameraImage(
CameraImage image, int format, double cropPercent) async {
var isolateData = IsolateData(image, format, cropPercent);
CodeResult result = await _inference(isolateData);
return result;
}
/// Runs inference in another isolate
static Future<CodeResult> _inference(IsolateData isolateData) async {
ReceivePort responsePort = ReceivePort();
isolateUtils?.sendPort
?.send(isolateData..responsePort = responsePort.sendPort);
var results = await responsePort.first;
return results;
}
static int get _logEnabled {
return logEnabled ? 1 : 0;
}
static String formatName(int format) => _formatNames[format] ?? 'Unknown'; static String formatName(int format) => _formatNames[format] ?? 'Unknown';
} }

10
lib/isolate_utils.dart

@ -33,9 +33,9 @@ class IsolateUtils {
SendPort? get sendPort => _sendPort; SendPort? get sendPort => _sendPort;
Future<void> start() async { Future<void> startReadingBarcode() async {
_isolate = await Isolate.spawn<SendPort>( _isolate = await Isolate.spawn<SendPort>(
entryPoint, readBarcodeEntryPoint,
_receivePort.sendPort, _receivePort.sendPort,
debugName: kDebugName, debugName: kDebugName,
); );
@ -43,13 +43,13 @@ class IsolateUtils {
_sendPort = await _receivePort.first; _sendPort = await _receivePort.first;
} }
void stop() { void stopReadingBarcode() {
_isolate?.kill(priority: Isolate.immediate); _isolate?.kill(priority: Isolate.immediate);
_isolate = null; _isolate = null;
_sendPort = null; _sendPort = null;
} }
static void entryPoint(SendPort sendPort) async { static void readBarcodeEntryPoint(SendPort sendPort) async {
final port = ReceivePort(); final port = ReceivePort();
sendPort.send(port.sendPort); sendPort.send(port.sendPort);
@ -66,7 +66,7 @@ class IsolateUtils {
image.width, image.height, cropSize, cropSize); image.width, image.height, cropSize, cropSize);
isolateData.responsePort?.send(result); isolateData.responsePort?.send(result);
} on Exception catch (e) { } catch (e) {
isolateData.responsePort?.send(e); isolateData.responsePort?.send(e);
} }
} }

42
lib/reader_widget.dart

@ -1,6 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'dart:isolate';
import 'dart:math'; import 'dart:math';
import 'package:camera/camera.dart'; import 'package:camera/camera.dart';
@ -60,8 +59,7 @@ class _ReaderWidgetState extends State<ReaderWidget>
void initStateAsync() async { void initStateAsync() async {
// Spawn a new isolate // Spawn a new isolate
isolateUtils = IsolateUtils(); await FlutterZxing.startCameraProcessing();
await isolateUtils?.start();
availableCameras().then((cameras) { availableCameras().then((cameras) {
setState(() { setState(() {
@ -94,8 +92,8 @@ class _ReaderWidgetState extends State<ReaderWidget>
@override @override
void dispose() { void dispose() {
FlutterZxing.stopCameraProcessing();
controller?.dispose(); controller?.dispose();
isolateUtils?.stop();
super.dispose(); super.dispose();
} }
@ -116,7 +114,7 @@ class _ReaderWidgetState extends State<ReaderWidget>
await controller?.initialize(); await controller?.initialize();
controller?.startImageStream(processCameraImage); controller?.startImageStream(processCameraImage);
} on CameraException catch (e) { } on CameraException catch (e) {
_showCameraException(e); debugPrint('${e.code}: ${e.description}');
} }
controller?.addListener(() { controller?.addListener(() {
@ -131,30 +129,15 @@ class _ReaderWidgetState extends State<ReaderWidget>
widget.onControllerCreated?.call(controller); widget.onControllerCreated?.call(controller);
} }
void _showCameraException(CameraException e) {
logError(e.code, e.description);
showInSnackBar('Error: ${e.code}\n${e.description}');
}
void showInSnackBar(String message) {}
void logError(String code, String? message) {
if (message != null) {
debugPrint('Error: $code\nError Message: $message');
} else {
debugPrint('Error: $code');
}
}
processCameraImage(CameraImage image) async { processCameraImage(CameraImage image) async {
if (!_isProcessing) { if (!_isProcessing) {
_isProcessing = true; _isProcessing = true;
try { try {
var isolateData = CodeResult result = await FlutterZxing.processCameraImage(
IsolateData(image, widget.codeFormat, widget.cropPercent); image,
widget.codeFormat,
/// perform inference in separate isolate widget.cropPercent,
CodeResult result = await inference(isolateData); );
if (result.isValidBool) { if (result.isValidBool) {
if (widget.beep) { if (widget.beep) {
FlutterBeep.beep(); FlutterBeep.beep();
@ -175,15 +158,6 @@ class _ReaderWidgetState extends State<ReaderWidget>
return null; return null;
} }
/// Runs inference in another isolate
Future<CodeResult> inference(IsolateData isolateData) async {
ReceivePort responsePort = ReceivePort();
isolateUtils?.sendPort
?.send(isolateData..responsePort = responsePort.sendPort);
var results = await responsePort.first;
return results;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final size = MediaQuery.of(context).size; final size = MediaQuery.of(context).size;

Loading…
Cancel
Save