diff --git a/example/.metadata b/example/.metadata index 5a02328..262ceed 100644 --- a/example/.metadata +++ b/example/.metadata @@ -1,10 +1,45 @@ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # -# This file should be version controlled and should not be manually edited. +# This file should be version controlled. version: - revision: 7e9793dee1b85a243edd0e06cb1658e98b077561 + revision: 135454af32477f815a7525073027a3ff9eff1bfd channel: stable project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 135454af32477f815a7525073027a3ff9eff1bfd + base_revision: 135454af32477f815a7525073027a3ff9eff1bfd + - platform: android + create_revision: 135454af32477f815a7525073027a3ff9eff1bfd + base_revision: 135454af32477f815a7525073027a3ff9eff1bfd + - platform: ios + create_revision: 135454af32477f815a7525073027a3ff9eff1bfd + base_revision: 135454af32477f815a7525073027a3ff9eff1bfd + - platform: linux + create_revision: 135454af32477f815a7525073027a3ff9eff1bfd + base_revision: 135454af32477f815a7525073027a3ff9eff1bfd + - platform: macos + create_revision: 135454af32477f815a7525073027a3ff9eff1bfd + base_revision: 135454af32477f815a7525073027a3ff9eff1bfd + - platform: web + create_revision: 135454af32477f815a7525073027a3ff9eff1bfd + base_revision: 135454af32477f815a7525073027a3ff9eff1bfd + - platform: windows + create_revision: 135454af32477f815a7525073027a3ff9eff1bfd + base_revision: 135454af32477f815a7525073027a3ff9eff1bfd + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/example/android/app/src/main/kotlin/com/markosyan/example/MainActivity.kt b/example/android/app/src/main/kotlin/com/markosyan/example/MainActivity.kt new file mode 100644 index 0000000..0540c79 --- /dev/null +++ b/example/android/app/src/main/kotlin/com/markosyan/example/MainActivity.kt @@ -0,0 +1,6 @@ +package com.markosyan.example + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/example/lib/main.dart b/example/lib/main.dart index 4398fd0..c615922 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_zxing/flutter_zxing.dart'; void main() { - setZxingLogEnabled(kDebugMode); + zx.setLogEnabled(kDebugMode); runApp(const MyApp()); } @@ -51,31 +51,47 @@ class _DemoPageState extends State { body: TabBarView( physics: const NeverScrollableScrollPhysics(), children: [ - ReaderWidget( - onScan: (value) { - showMessage(context, 'Scanned: ${value.textString ?? ''}'); - }, - tryInverted: true, - ), - ListView( - children: [ - WriterWidget( - messages: const Messages( - createButton: 'Create Code', - ), - onSuccess: (result, bytes) { - setState(() { - createdCodeBytes = bytes; - }); - }, - onError: (error) { - showMessage(context, 'Error: $error'); - }, + if (kIsWeb) + Center( + child: Text( + 'Web is not supported yet.', + style: Theme.of(context).textTheme.headline6, + ), + ) + else + ReaderWidget( + onScan: (value) { + showMessage(context, 'Scanned: ${value.text ?? ''}'); + }, + tryInverted: true, + ), + if (kIsWeb) + Center( + child: Text( + 'Web is not supported yet.', + style: Theme.of(context).textTheme.headline6, ), - if (createdCodeBytes != null) - Image.memory(createdCodeBytes ?? Uint8List(0), height: 200), - ], - ), + ) + else + ListView( + children: [ + WriterWidget( + messages: const Messages( + createButton: 'Create Code', + ), + onSuccess: (result, bytes) { + setState(() { + createdCodeBytes = bytes; + }); + }, + onError: (error) { + showMessage(context, 'Error: $error'); + }, + ), + if (createdCodeBytes != null) + Image.memory(createdCodeBytes ?? Uint8List(0), height: 200), + ], + ), ], ), ), diff --git a/example/web/favicon.png b/example/web/favicon.png new file mode 100644 index 0000000..8aaa46a Binary files /dev/null and b/example/web/favicon.png differ diff --git a/example/web/icons/Icon-192.png b/example/web/icons/Icon-192.png new file mode 100644 index 0000000..b749bfe Binary files /dev/null and b/example/web/icons/Icon-192.png differ diff --git a/example/web/icons/Icon-512.png b/example/web/icons/Icon-512.png new file mode 100644 index 0000000..88cfd48 Binary files /dev/null and b/example/web/icons/Icon-512.png differ diff --git a/example/web/icons/Icon-maskable-192.png b/example/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000..eb9b4d7 Binary files /dev/null and b/example/web/icons/Icon-maskable-192.png differ diff --git a/example/web/icons/Icon-maskable-512.png b/example/web/icons/Icon-maskable-512.png new file mode 100644 index 0000000..d69c566 Binary files /dev/null and b/example/web/icons/Icon-maskable-512.png differ diff --git a/example/web/index.html b/example/web/index.html new file mode 100644 index 0000000..41b3bc3 --- /dev/null +++ b/example/web/index.html @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + example + + + + + + + + + + diff --git a/example/web/manifest.json b/example/web/manifest.json new file mode 100644 index 0000000..096edf8 --- /dev/null +++ b/example/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/ios/Classes/src/native_zxing.cpp b/ios/Classes/src/native_zxing.cpp index cd276fe..2f79191 100644 --- a/ios/Classes/src/native_zxing.cpp +++ b/ios/Classes/src/native_zxing.cpp @@ -94,7 +94,7 @@ extern "C" { long long start = get_now(); - struct EncodeResult result = {0, contents, Format(format), nullptr, 0, nullptr}; + struct EncodeResult result = {0, contents, format, nullptr, 0, nullptr}; try { auto writer = MultiFormatWriter(BarcodeFormat(format)).setMargin(margin).setEccLevel(eccLevel).setEncoding(CharacterSet::UTF8); @@ -120,7 +120,7 @@ extern "C" { code->isValid = result.isValid(); - code->format = Format(static_cast(result.format())); + code->format = static_cast(result.format()); code->bytes = result.bytes().data(); code->length = result.bytes().size(); diff --git a/ios/Classes/src/native_zxing.h b/ios/Classes/src/native_zxing.h index ec7996c..815753e 100644 --- a/ios/Classes/src/native_zxing.h +++ b/ios/Classes/src/native_zxing.h @@ -3,35 +3,6 @@ extern "C" { #endif - /** - * @brief Format Enumerates barcode formats known to this package. - * - */ - enum Format - { - None = 0, ///< Used as a return value if no valid barcode has been detected - Aztec = (1 << 0), ///< Aztec (2D) - Codabar = (1 << 1), ///< Codabar (1D) - Code39 = (1 << 2), ///< Code39 (1D) - Code93 = (1 << 3), ///< Code93 (1D) - Code128 = (1 << 4), ///< Code128 (1D) - DataBar = (1 << 5), ///< GS1 DataBar, formerly known as RSS 14 - DataBarExpanded = (1 << 6), ///< GS1 DataBar Expanded, formerly known as RSS EXPANDED - DataMatrix = (1 << 7), ///< DataMatrix (2D) - EAN8 = (1 << 8), ///< EAN-8 (1D) - EAN13 = (1 << 9), ///< EAN-13 (1D) - ITF = (1 << 10), ///< ITF (Interleaved Two of Five) (1D) - MaxiCode = (1 << 11), ///< MaxiCode (2D) - PDF417 = (1 << 12), ///< PDF417 (1D) or (2D) - QRCode = (1 << 13), ///< QR Code (2D) - UPCA = (1 << 14), ///< UPC-A (1D) - UPCE = (1 << 15), ///< UPC-E (1D) - - OneDCodes = Codabar | Code39 | Code93 | Code128 | EAN8 | EAN13 | ITF | DataBar | DataBarExpanded | UPCA | UPCE, - TwoDCodes = Aztec | DataMatrix | MaxiCode | PDF417 | QRCode, - Any = OneDCodes | TwoDCodes, - }; - /** * @brief Pos is a position of a barcode in a image. * @@ -57,7 +28,7 @@ extern "C" char *text; ///< The decoded text const unsigned char *bytes; ///< The bytes is the raw / standard content without any modifications like character set conversions int length; ///< The length of the bytes - enum Format format; ///< The format of the barcode + int format; ///< The format of the barcode struct Pos *pos; ///< The position of the barcode within the image }; @@ -78,8 +49,8 @@ extern "C" { int isValid; ///< Whether the barcode was successfully encoded char *text; ///< The encoded text - enum Format format; ///< The format of the barcode - const signed char *data; ///< The encoded data + int format; ///< The format of the barcode + const signed char *data; ///< The encoded data int length; ///< The length of the encoded data char *error; ///< The error message }; diff --git a/lib/flutter_zxing.dart b/lib/flutter_zxing.dart index 4700229..8486b70 100644 --- a/lib/flutter_zxing.dart +++ b/lib/flutter_zxing.dart @@ -1,10 +1,95 @@ -export 'generated_bindings.dart'; -export 'src/logic/zxing.dart'; -export 'src/ui/dynamic_scanner_overlay.dart'; -export 'src/ui/fixed_scanner_overlay.dart'; -export 'src/ui/reader_widget.dart'; -export 'src/ui/scanner_overlay.dart'; -export 'src/ui/writer_widget.dart'; -export 'src/utils/extentions.dart'; -export 'src/utils/image_converter.dart'; -export 'src/utils/messages.dart'; +import 'dart:typed_data'; + +import 'package:camera/camera.dart'; +import 'src/models/models.dart'; + +import 'zxing_cross.dart' + if (dart.library.io) 'zxing_mobile.dart' + if (dart.library.html) 'zxing_web.dart'; + +export 'src/models/models.dart'; +export 'src/ui/ui.dart'; + +final Zxing zx = Zxing(); + +abstract class Zxing { + /// factory constructor to return the correct implementation. + factory Zxing() => getZxing(); + + String version() => ''; + void setLogEnabled(bool enabled) {} + String barcodeFormatName(int format) => ''; + + Encode encodeBarcode( + String contents, { + int format = Format.qrCode, + int width = 300, + int height = 300, + int margin = 0, + int eccLevel = 0, + }); + + /// Starts reading barcode from the camera + Future startCameraProcessing(); + + /// Stops reading barcode from the camera + void stopCameraProcessing(); + + /// Reads barcode from the camera + Future processCameraImage( + CameraImage image, { + Params? params, + }); + + /// Reads barcode from String image path + Future readBarcodeImagePathString( + String path, { + Params? params, + }); + + /// Reads barcode from XFile image path + Future readBarcodeImagePath( + XFile path, { + Params? params, + }); + + /// Reads barcode from image url + Future readBarcodeImageUrl( + String url, { + Params? params, + }); + +// Reads barcode from Uint8List image bytes + Code readBarcode( + Uint8List bytes, { + required int width, + required int height, + Params? params, + }); + + /// Reads barcodes from String image path + Future> readBarcodesImagePathString( + String path, { + Params? params, + }); + + /// Reads barcodes from XFile image path + Future> readBarcodesImagePath( + XFile path, { + Params? params, + }); + + /// Reads barcodes from image url + Future> readBarcodesImageUrl( + String url, { + Params? params, + }); + + /// Reads barcodes from Uint8List image bytes + List readBarcodes( + Uint8List bytes, { + required int width, + required int height, + Params? params, + }); +} diff --git a/lib/generated_bindings.dart b/lib/generated_bindings.dart index 9362d82..269eb8c 100644 --- a/lib/generated_bindings.dart +++ b/lib/generated_bindings.dart @@ -162,63 +162,6 @@ class GeneratedBindings { EncodeResult Function(ffi.Pointer, int, int, int, int, int)>(); } -/// @brief Format Enumerates barcode formats known to this package. -abstract class Format { - /// < Used as a return value if no valid barcode has been detected - static const int None = 0; - - /// < Aztec (2D) - static const int Aztec = 1; - - /// < Codabar (1D) - static const int Codabar = 2; - - /// < Code39 (1D) - static const int Code39 = 4; - - /// < Code93 (1D) - static const int Code93 = 8; - - /// < Code128 (1D) - static const int Code128 = 16; - - /// < GS1 DataBar, formerly known as RSS 14 - static const int DataBar = 32; - - /// < GS1 DataBar Expanded, formerly known as RSS EXPANDED - static const int DataBarExpanded = 64; - - /// < DataMatrix (2D) - static const int DataMatrix = 128; - - /// < EAN-8 (1D) - static const int EAN8 = 256; - - /// < EAN-13 (1D) - static const int EAN13 = 512; - - /// < ITF (Interleaved Two of Five) (1D) - static const int ITF = 1024; - - /// < MaxiCode (2D) - static const int MaxiCode = 2048; - - /// < PDF417 (1D) or (2D) - static const int PDF417 = 4096; - - /// < QR Code (2D) - static const int QRCode = 8192; - - /// < UPC-A (1D) - static const int UPCA = 16384; - - /// < UPC-E (1D) - static const int UPCE = 32768; - static const int OneDCodes = 51070; - static const int TwoDCodes = 14465; - static const int Any = 65535; -} - /// @brief Pos is a position of a barcode in a image. class Pos extends ffi.Struct { /// < x coordinate of top left corner of barcode @@ -271,7 +214,7 @@ class CodeResult extends ffi.Struct { external int length; /// < The format of the barcode - @ffi.Int32() + @ffi.Int() external int format; /// < The position of the barcode within the image @@ -298,7 +241,7 @@ class EncodeResult extends ffi.Struct { external ffi.Pointer text; /// < The format of the barcode - @ffi.Int32() + @ffi.Int() external int format; /// < The encoded data diff --git a/lib/src/logic/barcode_encoder.dart b/lib/src/logic/barcode_encoder.dart index 60cedd4..c96ebd5 100644 --- a/lib/src/logic/barcode_encoder.dart +++ b/lib/src/logic/barcode_encoder.dart @@ -1,20 +1,22 @@ part of 'zxing.dart'; // Encode a string into a barcode -EncodeResult encodeBarcode( +Encode zxingEncodeBarcode( String contents, { - int format = Format.QRCode, + int format = Format.qrCode, int width = 300, int height = 300, int margin = 0, int eccLevel = 0, }) { - return bindings.encodeBarcode( - contents.toNativeUtf8().cast(), - width, - height, - format, - margin, - eccLevel, - ); + return bindings + .encodeBarcode( + contents.toNativeUtf8().cast(), + width, + height, + format, + margin, + eccLevel, + ) + .toEncode(); } diff --git a/lib/src/logic/barcode_reader.dart b/lib/src/logic/barcode_reader.dart index 10bc7c1..a1911e3 100644 --- a/lib/src/logic/barcode_reader.dart +++ b/lib/src/logic/barcode_reader.dart @@ -1,57 +1,37 @@ part of 'zxing.dart'; /// Reads barcode from String image path -Future readBarcodeImagePathString( +Future zxingReadBarcodeImagePathString( String path, { - int format = Format.Any, - int cropWidth = 0, - int cropHeight = 0, - bool tryHarder = false, - bool tryRotate = true, + Params? params, }) => - readBarcodeImagePath( + zxingReadBarcodeImagePath( XFile(path), - format: format, - cropWidth: cropWidth, - cropHeight: cropHeight, - tryHarder: tryHarder, - tryRotate: tryRotate, + params: params, ); /// Reads barcode from XFile image path -Future readBarcodeImagePath( +Future zxingReadBarcodeImagePath( XFile path, { - int format = Format.Any, - int cropWidth = 0, - int cropHeight = 0, - bool tryHarder = false, - bool tryRotate = true, + Params? params, }) async { final Uint8List imageBytes = await path.readAsBytes(); final imglib.Image? image = imglib.decodeImage(imageBytes); if (image == null) { return null; } - return readBarcode( + return zxingReadBarcode( image.getBytes(format: imglib.Format.luminance), width: image.width, height: image.height, - format: format, - cropWidth: cropWidth, - cropHeight: cropHeight, - tryHarder: tryHarder, - tryRotate: tryRotate, + params: params, ); } /// Reads barcode from image url -Future readBarcodeImageUrl( +Future zxingReadBarcodeImageUrl( String url, { - int format = Format.Any, - int cropWidth = 0, - int cropHeight = 0, - bool tryHarder = false, - bool tryRotate = true, + Params? params, }) async { final Uint8List imageBytes = (await NetworkAssetBundle(Uri.parse(url)).load(url)).buffer.asUint8List(); @@ -59,36 +39,30 @@ Future readBarcodeImageUrl( if (image == null) { return null; } - return readBarcode( + return zxingReadBarcode( image.getBytes(format: imglib.Format.luminance), width: image.width, height: image.height, - format: format, - cropWidth: cropWidth, - cropHeight: cropHeight, - tryHarder: tryHarder, - tryRotate: tryRotate, + params: params, ); } // Reads barcode from Uint8List image bytes -CodeResult readBarcode( +Code zxingReadBarcode( Uint8List bytes, { required int width, required int height, - int format = Format.Any, - int cropWidth = 0, - int cropHeight = 0, - bool tryHarder = false, - bool tryRotate = true, + Params? params, }) => - bindings.readBarcode( - bytes.allocatePointer(), - format, - width, - height, - cropWidth, - cropHeight, - tryHarder ? 1 : 0, - tryRotate ? 1 : 0, - ); + bindings + .readBarcode( + bytes.allocatePointer(), + params?.format ?? Format.any, + width, + height, + params?.cropWidth ?? 0, + params?.cropHeight ?? 0, + params?.tryHarder ?? false ? 1 : 0, + params?.tryRotate ?? true ? 1 : 0, + ) + .toCode(); diff --git a/lib/src/logic/barcodes_reader.dart b/lib/src/logic/barcodes_reader.dart index 5b8e980..41960aa 100644 --- a/lib/src/logic/barcodes_reader.dart +++ b/lib/src/logic/barcodes_reader.dart @@ -1,100 +1,72 @@ part of 'zxing.dart'; /// Reads barcodes from String image path -Future> readBarcodesImagePathString( +Future> zxingReadBarcodesImagePathString( String path, { - int format = Format.Any, - int cropWidth = 0, - int cropHeight = 0, - bool tryHarder = false, - bool tryRotate = true, + Params? params, }) => - readBarcodesImagePath( + zxingReadBarcodesImagePath( XFile(path), - format: format, - cropWidth: cropWidth, - cropHeight: cropHeight, - tryHarder: tryHarder, - tryRotate: tryRotate, + params: params, ); /// Reads barcodes from XFile image path -Future> readBarcodesImagePath( +Future> zxingReadBarcodesImagePath( XFile path, { - int format = Format.Any, - int cropWidth = 0, - int cropHeight = 0, - bool tryHarder = false, - bool tryRotate = true, + Params? params, }) async { final Uint8List imageBytes = await path.readAsBytes(); final imglib.Image? image = imglib.decodeImage(imageBytes); if (image == null) { - return []; + return []; } - return readBarcodes( + return zxingReadBarcodes( image.getBytes(format: imglib.Format.luminance), width: image.width, height: image.height, - format: format, - cropWidth: cropWidth, - cropHeight: cropHeight, - tryHarder: tryHarder, - tryRotate: tryRotate, + params: params, ); } /// Reads barcodes from image url -Future> readBarcodesImageUrl( +Future> zxingReadBarcodesImageUrl( String url, { - int format = Format.Any, - int cropWidth = 0, - int cropHeight = 0, - bool tryHarder = false, - bool tryRotate = true, + Params? params, }) async { final Uint8List imageBytes = (await NetworkAssetBundle(Uri.parse(url)).load(url)).buffer.asUint8List(); final imglib.Image? image = imglib.decodeImage(imageBytes); if (image == null) { - return []; + return []; } - return readBarcodes( + return zxingReadBarcodes( image.getBytes(format: imglib.Format.luminance), width: image.width, height: image.height, - format: format, - cropWidth: cropWidth, - cropHeight: cropHeight, - tryHarder: tryHarder, - tryRotate: tryRotate, + params: params, ); } /// Reads barcodes from Uint8List image bytes -List readBarcodes( +List zxingReadBarcodes( Uint8List bytes, { required int width, required int height, - int format = Format.Any, - int cropWidth = 0, - int cropHeight = 0, - bool tryHarder = false, - bool tryRotate = true, + Params? params, }) { final CodeResults result = bindings.readBarcodes( bytes.allocatePointer(), - format, + params?.format ?? Format.any, width, height, - cropWidth, - cropHeight, - tryHarder ? 1 : 0, - tryRotate ? 1 : 0, + params?.cropWidth ?? 0, + params?.cropHeight ?? 0, + params?.tryHarder ?? false ? 1 : 0, + params?.tryRotate ?? true ? 1 : 0, ); - final List results = []; + final List results = []; for (int i = 0; i < result.count; i++) { - results.add(result.results.elementAt(i).ref); + results.add(result.results.elementAt(i).ref.toCode()); } return results; } diff --git a/lib/src/logic/camera_stream.dart b/lib/src/logic/camera_stream.dart index 2afda77..93c4303 100644 --- a/lib/src/logic/camera_stream.dart +++ b/lib/src/logic/camera_stream.dart @@ -3,29 +3,25 @@ part of 'zxing.dart'; IsolateUtils? isolateUtils; /// Starts reading barcode from the camera -Future startCameraProcessing() async { +Future zxingStartCameraProcessing() async { isolateUtils = IsolateUtils(); await isolateUtils?.startReadingBarcode(); } /// Stops reading barcode from the camera -void stopCameraProcessing() => isolateUtils?.stopReadingBarcode(); +void zxingStopCameraProcessing() => isolateUtils?.stopReadingBarcode(); -Future processCameraImage( +Future zxingProcessCameraImage( CameraImage image, { - int format = Format.Any, - double cropPercent = 0.5, - bool tryHarder = false, - bool tryInverted = false, + Params? params, }) async { - final IsolateData isolateData = - IsolateData(image, format, cropPercent, tryHarder, tryInverted); - final CodeResult result = await _inference(isolateData); + final IsolateData isolateData = IsolateData(image, params ?? Params()); + final Code result = await _inference(isolateData); return result; } /// Runs inference in another isolate -Future _inference(IsolateData isolateData) async { +Future _inference(IsolateData isolateData) async { final ReceivePort responsePort = ReceivePort(); isolateUtils?.sendPort ?.send(isolateData..responsePort = responsePort.sendPort); diff --git a/lib/src/logic/zxing.dart b/lib/src/logic/zxing.dart index a46e31f..d2852a3 100644 --- a/lib/src/logic/zxing.dart +++ b/lib/src/logic/zxing.dart @@ -10,6 +10,7 @@ import 'package:flutter/services.dart'; import 'package:image/image.dart' as imglib; import '../../generated_bindings.dart'; +import '../models/models.dart'; import '../utils/extentions.dart'; import '../utils/isolate_utils.dart'; @@ -27,4 +28,14 @@ void setZxingLogEnabled(bool enabled) => bindings.setLogEnabled(enabled ? 1 : 0); /// Returns a readable barcode format name -String barcodeFormatName(int format) => formatNames[format] ?? 'Unknown'; +String zxingBarcodeFormatName(int format) => formatNames[format] ?? 'Unknown'; + +extension Uint8ListBlobConversion on Uint8List { + /// Allocates a pointer filled with the Uint8List data. + Pointer allocatePointer() { + final Pointer blob = calloc(length); + final Int8List blobBytes = blob.asTypedList(length); + blobBytes.setAll(0, this); + return blob.cast(); + } +} diff --git a/lib/src/models/code.dart b/lib/src/models/code.dart new file mode 100644 index 0000000..a597b05 --- /dev/null +++ b/lib/src/models/code.dart @@ -0,0 +1,20 @@ +import 'dart:typed_data'; + +import 'position.dart'; + +// Represents a barcode code +class Code { + Code( + this.isValid, + this.text, + this.rawBytes, + this.format, + this.position, + ); + + bool isValid; // Whether the code is valid + String? text; // The text of the code + Uint8List? rawBytes; // The raw bytes of the code + int? format; // The format of the code + Position? position; // The position of the code +} diff --git a/lib/src/models/encode.dart b/lib/src/models/encode.dart new file mode 100644 index 0000000..b23c749 --- /dev/null +++ b/lib/src/models/encode.dart @@ -0,0 +1,20 @@ +import 'dart:typed_data'; + +// Encapsulates the result of encoding a barcode. +class Encode { + Encode( + this.isValid, + this.format, + this.text, + this.data, + this.length, + this.error, + ); + + bool isValid; // Whether the code is valid + int? format; // The format of the code + String? text; // The text of the code + Uint32List? data; // The raw bytes of the code + int? length; // The length of the raw bytes + String? error; // The error message +} diff --git a/lib/src/models/format.dart b/lib/src/models/format.dart new file mode 100644 index 0000000..2d6e3d0 --- /dev/null +++ b/lib/src/models/format.dart @@ -0,0 +1,82 @@ +// Format Enumerates barcode formats known to this package. +abstract class Format { + // Used as a return value if no valid barcode has been detected + static const int none = 0; + + static const int aztec = 1 << 0; // Aztec (2D) + static const int codabar = 1 << 1; // Codabar (1D) + static const int code39 = 1 << 2; // Code39 (1D) + static const int code93 = 1 << 3; // Code93 (1D) + static const int code128 = 1 << 4; // Code128 (1D) + static const int dataBar = 1 << 5; // GS1 DataBar + static const int dataBarExpanded = 1 << 6; // GS1 DataBar Expanded + static const int dataMatrix = 1 << 7; // DataMatrix (2D) + static const int ean8 = 1 << 8; // EAN-8 (1D) + static const int ean13 = 1 << 9; // EAN-13 (1D) + static const int itf = 1 << 10; // ITF (Interleaved Two of Five) (1D) + static const int maxiCode = 1 << 11; // MaxiCode (2D) + static const int pdf417 = 1 << 12; // PDF417 (1D) or (2D) + static const int qrCode = 1 << 13; // QR Code (2D) + static const int upca = 1 << 14; // UPC-A (1D) + static const int upce = 1 << 15; // UPC-E (1D) + + static const int oneDCodes = codabar | + code39 | + code93 | + code128 | + ean8 | + ean13 | + itf | + dataBar | + dataBarExpanded | + upca | + upce; + static const int twoDCodes = aztec | dataMatrix | maxiCode | pdf417 | qrCode; + static const int any = oneDCodes | twoDCodes; +} + +extension CodeFormat on Format { + String get name => formatNames[this] ?? 'Unknown'; + + static final List writerFormats = [ + Format.qrCode, + Format.dataMatrix, + Format.aztec, + Format.pdf417, + Format.codabar, + Format.code39, + Format.code93, + Format.code128, + Format.ean8, + Format.ean13, + Format.itf, + Format.upca, + Format.upce, + // Format.dataBar, + // Format.dataBarExpanded, + // Format.maxiCode, + ]; +} + +final Map formatNames = { + Format.none: 'None', + Format.aztec: 'Aztec', + Format.codabar: 'CodaBar', + Format.code39: 'Code39', + Format.code93: 'Code93', + Format.code128: 'Code128', + Format.dataBar: 'DataBar', + Format.dataBarExpanded: 'DataBarExpanded', + Format.dataMatrix: 'DataMatrix', + Format.ean8: 'EAN8', + Format.ean13: 'EAN13', + Format.itf: 'ITF', + Format.maxiCode: 'MaxiCode', + Format.pdf417: 'PDF417', + Format.qrCode: 'QR Code', + Format.upca: 'UPCA', + Format.upce: 'UPCE', + Format.oneDCodes: 'OneD', + Format.twoDCodes: 'TwoD', + Format.any: 'Any', +}; diff --git a/lib/src/utils/messages.dart b/lib/src/models/messages.dart similarity index 95% rename from lib/src/utils/messages.dart rename to lib/src/models/messages.dart index a12b7c2..f9915c1 100644 --- a/lib/src/utils/messages.dart +++ b/lib/src/models/messages.dart @@ -1,3 +1,4 @@ +// Contains the messages used in the app class Messages { const Messages({ this.createButton = 'Create', diff --git a/lib/src/models/models.dart b/lib/src/models/models.dart new file mode 100644 index 0000000..cb6861e --- /dev/null +++ b/lib/src/models/models.dart @@ -0,0 +1,6 @@ +export 'code.dart'; +export 'encode.dart'; +export 'format.dart'; +export 'messages.dart'; +export 'params.dart'; +export 'position.dart'; diff --git a/lib/src/models/params.dart b/lib/src/models/params.dart new file mode 100644 index 0000000..bb8b590 --- /dev/null +++ b/lib/src/models/params.dart @@ -0,0 +1,22 @@ +import 'dart:core'; + +import 'format.dart'; + +// Represents the parameters for decoding a barcode +class Params { + Params({ + this.format = Format.any, + this.cropWidth = 0, + this.cropHeight = 0, + this.tryHarder = false, + this.tryRotate = true, + this.tryInverted = false, + }); + + int format; + int cropWidth; + int cropHeight; + bool tryHarder; + bool tryRotate; + bool tryInverted; +} diff --git a/lib/src/models/position.dart b/lib/src/models/position.dart new file mode 100644 index 0000000..7062935 --- /dev/null +++ b/lib/src/models/position.dart @@ -0,0 +1,22 @@ +/// Represents the position of a barcode in an image. +class Position { + Position( + this.topLeftX, + this.topLeftY, + this.topRightX, + this.topRightY, + this.bottomLeftX, + this.bottomLeftY, + this.bottomRightX, + this.bottomRightY, + ); + + int topLeftX; // x coordinate of top left corner of barcode + int topLeftY; // y coordinate of top left corner of barcode + int topRightX; // x coordinate of top right corner of barcode + int topRightY; // y coordinate of top right corner of barcode + int bottomLeftX; // x coordinate of bottom left corner of barcode + int bottomLeftY; // y coordinate of bottom left corner of barcode + int bottomRightX; // x coordinate of bottom right corner of barcode + int bottomRightY; // y coordinate of bottom right corner of barcode +} diff --git a/lib/src/ui/dynamic_scanner_overlay.dart b/lib/src/ui/dynamic_scanner_overlay.dart index 13db456..ad4add3 100644 --- a/lib/src/ui/dynamic_scanner_overlay.dart +++ b/lib/src/ui/dynamic_scanner_overlay.dart @@ -1,18 +1,17 @@ import 'package:flutter/material.dart'; -import '../../flutter_zxing.dart'; +import 'scanner_overlay.dart'; class DynamicScannerOverlay extends ScannerOverlay { - - const DynamicScannerOverlay({ - super.borderColor, - super.borderWidth, - super.overlayColor, - super.borderRadius, - super.borderLength, - this.cutOutSize = 0.5 - }) : assert(cutOutSize >= 0 && cutOutSize <= 1, - 'The cut out size must be between 0 and 1'); + const DynamicScannerOverlay( + {super.borderColor, + super.borderWidth, + super.overlayColor, + super.borderRadius, + super.borderLength, + this.cutOutSize = 0.5}) + : assert(cutOutSize >= 0 && cutOutSize <= 1, + 'The cut out size must be between 0 and 1'); @override final double cutOutSize; @@ -55,7 +54,7 @@ class DynamicScannerOverlay extends ScannerOverlay { rect, backgroundPaint, ) - // Draw top right corner + // Draw top right corner ..drawRRect( RRect.fromLTRBAndCorners( cutOutRect.right - newBorderLength, @@ -66,7 +65,7 @@ class DynamicScannerOverlay extends ScannerOverlay { ), borderPaint, ) - // Draw top left corner + // Draw top left corner ..drawRRect( RRect.fromLTRBAndCorners( cutOutRect.left, @@ -77,7 +76,7 @@ class DynamicScannerOverlay extends ScannerOverlay { ), borderPaint, ) - // Draw bottom right corner + // Draw bottom right corner ..drawRRect( RRect.fromLTRBAndCorners( cutOutRect.right - newBorderLength, @@ -88,7 +87,7 @@ class DynamicScannerOverlay extends ScannerOverlay { ), borderPaint, ) - // Draw bottom left corner + // Draw bottom left corner ..drawRRect( RRect.fromLTRBAndCorners( cutOutRect.left, diff --git a/lib/src/ui/fixed_scanner_overlay.dart b/lib/src/ui/fixed_scanner_overlay.dart index 27a8f1d..d3e6d06 100644 --- a/lib/src/ui/fixed_scanner_overlay.dart +++ b/lib/src/ui/fixed_scanner_overlay.dart @@ -1,23 +1,21 @@ import 'package:flutter/material.dart'; -import '../../flutter_zxing.dart'; +import 'scanner_overlay.dart'; class FixedScannerOverlay extends ScannerOverlay { - - const FixedScannerOverlay({ - super.borderColor, - super.borderWidth, - super.overlayColor, - super.borderRadius, - super.borderLength, - this.cutOutSize = 250 - }) : assert(borderLength <= cutOutSize / 2 + borderWidth * 2, - "Border can't be larger than ${cutOutSize / 2 + borderWidth * 2}"); + const FixedScannerOverlay( + {super.borderColor, + super.borderWidth, + super.overlayColor, + super.borderRadius, + super.borderLength, + this.cutOutSize = 250}) + : assert(borderLength <= cutOutSize / 2 + borderWidth * 2, + "Border can't be larger than ${cutOutSize / 2 + borderWidth * 2}"); @override final double cutOutSize; - @override void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) { final double width = rect.width; @@ -25,11 +23,11 @@ class FixedScannerOverlay extends ScannerOverlay { final double height = rect.height; final double borderOffset = borderWidth / 2; final double newBorderLength = - borderLength > cutOutSize / 2 + borderWidth * 2 - ? borderWidthSize / 2 - : borderLength; + borderLength > cutOutSize / 2 + borderWidth * 2 + ? borderWidthSize / 2 + : borderLength; final double newCutOutSize = - cutOutSize < width ? cutOutSize : width - borderOffset; + cutOutSize < width ? cutOutSize : width - borderOffset; final Paint backgroundPaint = Paint() ..color = overlayColor @@ -61,7 +59,7 @@ class FixedScannerOverlay extends ScannerOverlay { rect, backgroundPaint, ) - // Draw top right corner + // Draw top right corner ..drawRRect( RRect.fromLTRBAndCorners( cutOutRect.right - newBorderLength, @@ -72,7 +70,7 @@ class FixedScannerOverlay extends ScannerOverlay { ), borderPaint, ) - // Draw top left corner + // Draw top left corner ..drawRRect( RRect.fromLTRBAndCorners( cutOutRect.left, @@ -83,7 +81,7 @@ class FixedScannerOverlay extends ScannerOverlay { ), borderPaint, ) - // Draw bottom right corner + // Draw bottom right corner ..drawRRect( RRect.fromLTRBAndCorners( cutOutRect.right - newBorderLength, @@ -94,7 +92,7 @@ class FixedScannerOverlay extends ScannerOverlay { ), borderPaint, ) - // Draw bottom left corner + // Draw bottom left corner ..drawRRect( RRect.fromLTRBAndCorners( cutOutRect.left, diff --git a/lib/src/ui/reader_widget.dart b/lib/src/ui/reader_widget.dart index 0fcae85..d0e8561 100644 --- a/lib/src/ui/reader_widget.dart +++ b/lib/src/ui/reader_widget.dart @@ -7,18 +7,14 @@ import 'package:flutter/material.dart'; // import 'package:flutter_beep/flutter_beep.dart'; -import '../../generated_bindings.dart'; -import '../logic/zxing.dart'; -import '../utils/extentions.dart'; -import 'fixed_scanner_overlay.dart'; -import 'scanner_overlay.dart'; +import '../../flutter_zxing.dart'; class ReaderWidget extends StatefulWidget { const ReaderWidget({ super.key, required this.onScan, this.onControllerCreated, - this.codeFormat = Format.Any, + this.codeFormat = Format.any, this.tryHarder = false, this.tryInverted = false, this.showCroppingRect = true, @@ -33,7 +29,7 @@ class ReaderWidget extends StatefulWidget { const DecoratedBox(decoration: BoxDecoration(color: Colors.black)), }); - final Function(CodeResult) onScan; + final Function(Code) onScan; final Function(CameraController?)? onControllerCreated; final int codeFormat; final bool tryHarder; @@ -77,7 +73,7 @@ class _ReaderWidgetState extends State Future initStateAsync() async { // Spawn a new isolate - await startCameraProcessing(); + await zx.startCameraProcessing(); availableCameras().then((List cameras) { setState(() { @@ -116,7 +112,7 @@ class _ReaderWidgetState extends State @override void dispose() { - stopCameraProcessing(); + zx.stopCameraProcessing(); controller?.removeListener(rebuildOnMount); controller?.dispose(); WidgetsBinding.instance.removeObserver(this); @@ -168,14 +164,22 @@ class _ReaderWidgetState extends State if (!_isProcessing) { _isProcessing = true; try { - final CodeResult result = await processCameraImage( - image, + final double cropPercent = + widget.showCroppingRect ? widget.cropPercent : 0; + final int cropSize = + (min(image.width, image.height) * cropPercent).round(); + final Params params = Params( format: widget.codeFormat, - cropPercent: widget.showCroppingRect ? widget.cropPercent : 0, + cropWidth: cropSize, + cropHeight: cropSize, tryHarder: widget.tryHarder, tryInverted: widget.tryInverted, ); - if (result.isValidBool) { + final Code result = await zx.processCameraImage( + image, + params: params, + ); + if (result.isValid) { widget.onScan(result); setState(() {}); await Future.delayed(widget.scanDelaySuccess); diff --git a/lib/src/ui/ui.dart b/lib/src/ui/ui.dart new file mode 100644 index 0000000..9b064ea --- /dev/null +++ b/lib/src/ui/ui.dart @@ -0,0 +1,5 @@ +export 'dynamic_scanner_overlay.dart'; +export 'fixed_scanner_overlay.dart'; +export 'reader_widget.dart'; +export 'scanner_overlay.dart'; +export 'writer_widget.dart'; diff --git a/lib/src/ui/writer_widget.dart b/lib/src/ui/writer_widget.dart index 9ef8c62..bcd20ce 100644 --- a/lib/src/ui/writer_widget.dart +++ b/lib/src/ui/writer_widget.dart @@ -9,7 +9,7 @@ class WriterWidget extends StatefulWidget { const WriterWidget({ super.key, this.text = '', - this.format = Format.QRCode, + this.format = Format.qrCode, this.width = 120, this.height = 120, this.margin = 0, @@ -26,7 +26,7 @@ class WriterWidget extends StatefulWidget { final int margin; final int eccLevel; final Messages messages; - final Function(EncodeResult result, Uint8List? bytes)? onSuccess; + final Function(Encode result, Uint8List? bytes)? onSuccess; final Function(String error)? onError; @override @@ -46,7 +46,7 @@ class _WriterWidgetState extends State final int _maxTextLength = 2000; final List _supportedFormats = CodeFormat.writerFormats; - int _codeFormat = Format.QRCode; + int _codeFormat = Format.qrCode; @override void initState() { @@ -112,12 +112,12 @@ class _WriterWidgetState extends State items: _supportedFormats .map((int format) => DropdownMenuItem( value: format, - child: Text(barcodeFormatName(format)), + child: Text(zx.barcodeFormatName(format)), )) .toList(), onChanged: (int? format) { setState(() { - _codeFormat = format ?? Format.QRCode; + _codeFormat = format ?? Format.qrCode; }); }, ), @@ -220,7 +220,7 @@ class _WriterWidgetState extends State final int height = int.parse(_heightController.value.text); final int margin = int.parse(_marginController.value.text); final int ecc = int.parse(_eccController.value.text); - final EncodeResult result = encodeBarcode( + final Encode result = zx.encodeBarcode( text, format: _codeFormat, width: width, @@ -229,12 +229,12 @@ class _WriterWidgetState extends State eccLevel: ecc, ); String? error; - if (result.isValidBool) { + if (result.isValid && result.data != null) { try { final imglib.Image img = imglib.Image.fromBytes( width, height, - result.bytes, + result.data!, ); final Uint8List encodedBytes = Uint8List.fromList( imglib.encodeJpg(img), @@ -244,7 +244,7 @@ class _WriterWidgetState extends State error = e.toString(); } } else { - error = result.errorMessage; + error = result.error; } if (error != null) { widget.onError?.call(error); diff --git a/lib/src/utils/extentions.dart b/lib/src/utils/extentions.dart index dd937a3..fbc9f0f 100644 --- a/lib/src/utils/extentions.dart +++ b/lib/src/utils/extentions.dart @@ -3,80 +3,42 @@ import 'dart:typed_data'; import 'package:ffi/ffi.dart'; -import '../../flutter_zxing.dart'; - -extension Uint8ListBlobConversion on Uint8List { - /// Allocates a pointer filled with the Uint8List data. - Pointer allocatePointer() { - final Pointer blob = calloc(length); - final Int8List blobBytes = blob.asTypedList(length); - blobBytes.setAll(0, this); - return blob.cast(); - } -} +import '../../zxing_mobile.dart'; extension CodeExt on CodeResult { - bool get isValidBool => isValid == 1; - String? get textString => - text == nullptr ? null : text.cast().toDartString(); - Uint8List get rawBytes => - Uint8List.fromList(bytes.cast().asTypedList(length)); - String get formatString => barcodeFormatName(format); - Pos get position => pos.ref; + Code toCode() => Code( + isValid == 1, + text == nullptr ? null : text.cast().toDartString(), + bytes == nullptr + ? null + : Uint8List.fromList(bytes.cast().asTypedList(length)), + format, + pos == nullptr ? null : pos.ref.toPosition(), + ); } extension EncodeExt on EncodeResult { - bool get isValidBool => isValid == 1; - String? get textString => - text == nullptr ? null : text.cast().toDartString(); - String get formatString => barcodeFormatName(format); - Uint32List get bytes => - Uint32List.fromList(data.cast().asTypedList(length)); - String get errorMessage => error.cast().toDartString(); + Encode toEncode() => Encode( + isValid == 1, + format, + text == nullptr ? null : text.cast().toDartString(), + data == nullptr + ? null + : Uint32List.fromList(data.cast().asTypedList(length)), + length, + error == nullptr ? null : error.cast().toDartString(), + ); } -extension CodeFormat on Format { - String get name => formatNames[this] ?? 'Unknown'; - - static final List writerFormats = [ - Format.QRCode, - Format.DataMatrix, - Format.Aztec, - Format.PDF417, - Format.Codabar, - Format.Code39, - Format.Code93, - Format.Code128, - Format.EAN8, - Format.EAN13, - Format.ITF, - Format.UPCA, - Format.UPCE, - // Format.DataBar, - // Format.DataBarExpanded, - // Format.MaxiCode, - ]; +extension PoeExt on Pos { + Position toPosition() => Position( + topLeftX, + topLeftY, + topRightX, + topRightY, + bottomLeftX, + bottomLeftY, + bottomRightX, + bottomRightY, + ); } - -final Map formatNames = { - Format.None: 'None', - Format.Aztec: 'Aztec', - Format.Codabar: 'CodaBar', - Format.Code39: 'Code39', - Format.Code93: 'Code93', - Format.Code128: 'Code128', - Format.DataBar: 'DataBar', - Format.DataBarExpanded: 'DataBarExpanded', - Format.DataMatrix: 'DataMatrix', - Format.EAN8: 'EAN8', - Format.EAN13: 'EAN13', - Format.ITF: 'ITF', - Format.MaxiCode: 'MaxiCode', - Format.PDF417: 'PDF417', - Format.QRCode: 'QR Code', - Format.UPCA: 'UPCA', - Format.UPCE: 'UPCE', - Format.OneDCodes: 'OneD', - Format.TwoDCodes: 'TwoD', - Format.Any: 'Any', -}; diff --git a/lib/src/utils/isolate_utils.dart b/lib/src/utils/isolate_utils.dart index bd6b9c5..2a89605 100644 --- a/lib/src/utils/isolate_utils.dart +++ b/lib/src/utils/isolate_utils.dart @@ -1,11 +1,10 @@ import 'dart:isolate'; -import 'dart:math'; import 'dart:typed_data'; import 'package:camera/camera.dart'; -import '../../generated_bindings.dart'; import '../logic/zxing.dart'; +import '../models/models.dart'; import 'image_converter.dart'; // Inspired from https://github.com/am15h/object_detection_flutter @@ -14,16 +13,10 @@ import 'image_converter.dart'; class IsolateData { IsolateData( this.cameraImage, - this.format, - this.cropPercent, - this.tryHarder, - this.tryInverted, + this.params, ); CameraImage cameraImage; - int format; - double cropPercent; - bool tryHarder; - bool tryInverted; + Params params; SendPort? responsePort; } @@ -63,34 +56,23 @@ class IsolateUtils { if (isolateData != null) { try { final CameraImage image = isolateData.cameraImage; - final double cropPercent = isolateData.cropPercent; final Uint8List bytes = await convertImage(image); - final int cropSize = - (min(image.width, image.height) * cropPercent).round(); - final bool tryHarder = isolateData.tryHarder; - final bool tryInverted = isolateData.tryInverted; - CodeResult result = readBarcode( + Code result = zxingReadBarcode( bytes, width: image.width, height: image.height, - format: isolateData.format, - cropWidth: cropSize, - cropHeight: cropSize, - tryHarder: tryHarder, + params: isolateData.params, ); - if (result.isValid == 0 && tryInverted) { + if (!result.isValid && isolateData.params.tryInverted) { // try to invert the image and read again final Uint8List invertedBytes = invertImage(bytes); - result = readBarcode( + result = zxingReadBarcode( invertedBytes, width: image.width, height: image.height, - format: isolateData.format, - cropWidth: cropSize, - cropHeight: cropSize, - tryHarder: tryHarder, + params: isolateData.params, ); } diff --git a/lib/zxing_cross.dart b/lib/zxing_cross.dart new file mode 100644 index 0000000..6262288 --- /dev/null +++ b/lib/zxing_cross.dart @@ -0,0 +1,4 @@ +import 'flutter_zxing.dart'; + +Zxing getZxing() => throw UnsupportedError( + 'Cannot create an instance of FlutterZxing on the current platform.'); diff --git a/lib/zxing_mobile.dart b/lib/zxing_mobile.dart new file mode 100644 index 0000000..15c04d7 --- /dev/null +++ b/lib/zxing_mobile.dart @@ -0,0 +1,149 @@ +import 'dart:typed_data'; + +import 'package:camera/camera.dart'; + +import 'flutter_zxing.dart'; +import 'src/logic/zxing.dart'; + +export 'generated_bindings.dart'; +export 'src/logic/zxing.dart'; +export 'src/models/models.dart'; +export 'src/utils/extentions.dart'; +export 'src/utils/image_converter.dart'; + +Zxing getZxing() => ZxingMobile(); + +class ZxingMobile implements Zxing { + ZxingMobile(); + + @override + String version() => zxingVersion(); + + @override + void setLogEnabled(bool enabled) => setZxingLogEnabled(enabled); + + @override + String barcodeFormatName(int format) => zxingBarcodeFormatName(format); + + @override + Encode encodeBarcode( + String contents, { + int format = Format.qrCode, + int width = 300, + int height = 300, + int margin = 0, + int eccLevel = 0, + }) => + zxingEncodeBarcode( + contents, + format: format, + width: width, + height: height, + margin: margin, + eccLevel: eccLevel, + ); + + @override + Future startCameraProcessing() => zxingStartCameraProcessing(); + + @override + void stopCameraProcessing() => zxingStopCameraProcessing(); + + @override + Future processCameraImage( + CameraImage image, { + Params? params, + }) => + zxingProcessCameraImage( + image, + params: params, + ); + + @override + Future readBarcodeImagePathString( + String path, { + Params? params, + }) => + zxingReadBarcodeImagePathString( + path, + params: params, + ); + + @override + Future readBarcodeImagePath( + XFile path, { + Params? params, + }) => + zxingReadBarcodeImagePath( + path, + params: params, + ); + + @override + Future readBarcodeImageUrl( + String url, { + Params? params, + }) => + zxingReadBarcodeImageUrl( + url, + params: params, + ); + + @override + Code readBarcode( + Uint8List bytes, { + required int width, + required int height, + Params? params, + }) => + zxingReadBarcode( + bytes, + width: width, + height: height, + params: params, + ); + + @override + Future> readBarcodesImagePathString( + String path, { + Params? params, + }) => + zxingReadBarcodesImagePathString( + path, + params: params, + ); + + @override + Future> readBarcodesImagePath( + XFile path, { + Params? params, + }) => + zxingReadBarcodesImagePath( + path, + params: params, + ); + + @override + Future> readBarcodesImageUrl( + String url, { + Params? params, + }) => + zxingReadBarcodesImageUrl( + url, + params: params, + ); + + @override + List readBarcodes( + Uint8List bytes, { + required int width, + required int height, + Params? params, + }) => + zxingReadBarcodes( + bytes, + width: width, + height: height, + params: params, + ); +} diff --git a/lib/zxing_web.dart b/lib/zxing_web.dart new file mode 100644 index 0000000..07b4468 --- /dev/null +++ b/lib/zxing_web.dart @@ -0,0 +1,104 @@ +import 'dart:typed_data'; + +import 'package:camera/camera.dart'; + +import 'flutter_zxing.dart'; + +Zxing getZxing() => ZxingWeb(); + +class ZxingWeb implements Zxing { + ZxingWeb(); + + @override + String version() => 'Unsupported'; + + @override + void setLogEnabled(bool enabled) {} + + @override + String barcodeFormatName(int format) => 'Unsupported'; + + @override + Encode encodeBarcode( + String contents, { + int format = Format.qrCode, + int width = 300, + int height = 300, + int margin = 0, + int eccLevel = 0, + }) => + throw UnimplementedError(); + + @override + Future startCameraProcessing() => throw UnimplementedError(); + + @override + void stopCameraProcessing() => throw UnimplementedError(); + + @override + Future processCameraImage( + CameraImage image, { + Params? params, + }) => + throw UnimplementedError(); + + @override + Future readBarcodeImagePathString( + String path, { + Params? params, + }) => + throw UnimplementedError(); + + @override + Future readBarcodeImagePath( + XFile path, { + Params? params, + }) => + throw UnimplementedError(); + + @override + Future readBarcodeImageUrl( + String url, { + Params? params, + }) => + throw UnimplementedError(); + + @override + Code readBarcode( + Uint8List bytes, { + required int width, + required int height, + Params? params, + }) => + throw UnimplementedError(); + + @override + Future> readBarcodesImagePathString( + String path, { + Params? params, + }) => + throw UnimplementedError(); + + @override + Future> readBarcodesImagePath( + XFile path, { + Params? params, + }) => + throw UnimplementedError(); + + @override + Future> readBarcodesImageUrl( + String url, { + Params? params, + }) => + throw UnimplementedError(); + + @override + List readBarcodes( + Uint8List bytes, { + required int width, + required int height, + Params? params, + }) => + throw UnimplementedError(); +} diff --git a/zxscanner/pubspec.lock b/zxscanner/pubspec.lock index 0828619..cfcff9c 100644 --- a/zxscanner/pubspec.lock +++ b/zxscanner/pubspec.lock @@ -321,7 +321,7 @@ packages: name: flutter_zxing url: "https://pub.dartlang.org" source: hosted - version: "0.8.4" + version: "0.8.5" font_awesome_flutter: dependency: "direct main" description: