Browse Source

allow to set code format for reader

pull/3/head
Khoren Markosyan 3 years ago
parent
commit
8425459c6a
  1. 10
      example/pubspec.lock
  2. 2
      example/pubspec.yaml
  3. 30
      ios/Classes/src/native_zxing.cpp
  4. 10
      ios/Classes/src/native_zxing.h
  5. 13
      lib/flutter_zxing.dart
  6. 30
      lib/generated_bindings.dart
  7. 25
      lib/isolate_utils.dart
  8. 5
      lib/zxing_reader_widget.dart
  9. 2
      pubspec.yaml

10
example/pubspec.lock

@ -7,7 +7,7 @@ packages:
name: archive name: archive
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.2.2" version: "3.3.0"
async: async:
dependency: transitive dependency: transitive
description: description:
@ -28,7 +28,7 @@ packages:
name: camera name: camera
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.9.4+16" version: "0.9.4+19"
camera_platform_interface: camera_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -302,7 +302,7 @@ packages:
name: share_plus name: share_plus
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.0.1" version: "4.0.3"
share_plus_linux: share_plus_linux:
dependency: transitive dependency: transitive
description: description:
@ -323,7 +323,7 @@ packages:
name: share_plus_platform_interface name: share_plus_platform_interface
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.0" version: "3.0.2"
share_plus_web: share_plus_web:
dependency: transitive dependency: transitive
description: description:
@ -468,7 +468,7 @@ packages:
name: win32 name: win32
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.4.2" version: "2.5.1"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:

2
example/pubspec.yaml

@ -13,7 +13,7 @@ dependencies:
flutter_zxing: flutter_zxing:
path: ../ path: ../
path_provider: ^2.0.9 path_provider: ^2.0.9
share_plus: ^4.0.1 share_plus: ^4.0.3
dev_dependencies: dev_dependencies:
flutter_lints: ^1.0.0 flutter_lints: ^1.0.0

30
ios/Classes/src/native_zxing.cpp

@ -16,7 +16,7 @@ extern "C"
} }
FUNCTION_ATTRIBUTE FUNCTION_ATTRIBUTE
struct CodeResult zxingRead(char *bytes, int width, int height, int cropSize) struct CodeResult zxingRead(char *bytes, int format, int width, int height, int cropWidth, int cropHeight, int logEnabled)
{ {
long long start = get_now(); long long start = get_now();
@ -24,11 +24,12 @@ extern "C"
uint8_t *data = new uint8_t[length]; uint8_t *data = new uint8_t[length];
memcpy(data, bytes, length); memcpy(data, bytes, length);
BarcodeFormats formats = BarcodeFormat::Any; BarcodeFormats formats = BarcodeFormat(format); // BarcodeFormat::Any;
DecodeHints hints = DecodeHints().setTryHarder(false).setTryRotate(true).setFormats(formats); DecodeHints hints = DecodeHints().setTryHarder(false).setTryRotate(true).setFormats(formats);
ImageView image{data, width, height, ImageFormat::Lum}; ImageView image{data, width, height, ImageFormat::Lum};
if (cropSize > 0 && cropSize < width && cropSize < height) { if (cropWidth > 0 && cropHeight > 0 && cropWidth < width && cropHeight < height)
image = image.cropped(width / 2 - cropSize / 2, height / 2 - cropSize / 2, cropSize, cropSize); {
image = image.cropped(width / 2 - cropWidth / 2, height / 2 - cropHeight / 2, cropWidth, cropHeight);
} }
Result result = ReadBarcode(image, hints); Result result = ReadBarcode(image, hints);
@ -43,16 +44,19 @@ extern "C"
} }
int evalInMillis = static_cast<int>(get_now() - start); int evalInMillis = static_cast<int>(get_now() - start);
platform_log("Read done in %dms\n", evalInMillis); if (logEnabled)
{
platform_log("zxingRead: %d ms", evalInMillis);
}
return code; return code;
} }
FUNCTION_ATTRIBUTE FUNCTION_ATTRIBUTE
struct EncodeResult zxingEncode(char *contents, int width, int height, int format, int margin, int eccLevel) struct EncodeResult zxingEncode(char *contents, int width, int height, int format, int margin, int eccLevel, int logEnabled)
{ {
long long start = get_now(); long long start = get_now();
struct EncodeResult result = { nullptr, 0, false, nullptr }; struct EncodeResult result = {nullptr, 0, false, nullptr};
try try
{ {
auto writer = MultiFormatWriter(BarcodeFormat(format)).setMargin(margin).setEccLevel(eccLevel); auto writer = MultiFormatWriter(BarcodeFormat(format)).setMargin(margin).setEccLevel(eccLevel);
@ -63,13 +67,19 @@ extern "C"
} }
catch (const std::exception &e) catch (const std::exception &e)
{ {
platform_log("Can't encode text: %s\nError: %s\n", contents, e.what()); if (logEnabled)
{
platform_log("Can't encode text: %s\nError: %s\n", contents, e.what());
}
result.error = new char[strlen(e.what()) + 1]; result.error = new char[strlen(e.what()) + 1];
strcpy(result.error, e.what()); strcpy(result.error, e.what());
} }
int evalInMillis = static_cast<int>(get_now() - start); int evalInMillis = static_cast<int>(get_now() - start);
platform_log("Encode done in %dms\n", evalInMillis); if (logEnabled)
{
platform_log("zxingEncode: %d ms", evalInMillis);
}
return result; return result;
} }
} }

10
ios/Classes/src/native_zxing.h

@ -53,12 +53,15 @@ extern "C"
/** /**
* @brief Reads barcode from image. * @brief Reads barcode from image.
* @param bytes Image bytes. * @param bytes Image bytes.
* @param format The format of the barcode
* @param width Image width. * @param width Image width.
* @param height Image height. * @param height Image height.
* @param cropSize Crop size. * @param cropWidth Crop width.
* @param cropHeight Crop height.
* @param logEnabled Log enabled.
* @return Barcode result. * @return Barcode result.
*/ */
struct CodeResult zxingRead(char *bytes, int width, int height, int cropSize); struct CodeResult zxingRead(char *bytes, int format, int width, int height, int cropWidth, int cropHeight, int logEnabled);
/** /**
* @brief Encode a string into a barcode * @brief Encode a string into a barcode
@ -67,10 +70,11 @@ extern "C"
* @param height The height of the barcode * @param height The height of the barcode
* @param format The format of the barcode * @param format The format of the barcode
* @param margin The margin of the barcode * @param margin The margin of the barcode
* @param logEnabled Log enabled.
* @param eccLevel The error correction level of the barcode. Used for Aztec, PDF417, and QRCode only, [0-8]. * @param eccLevel The error correction level of the barcode. Used for Aztec, PDF417, and QRCode only, [0-8].
* @return The barcode data * @return The barcode data
*/ */
struct EncodeResult zxingEncode(char *contents, int width, int height, int format, int margin, int eccLevel); struct EncodeResult zxingEncode(char *contents, int width, int height, int format, int margin, int eccLevel, int logEnabled);
#ifdef __cplusplus #ifdef __cplusplus
} }

13
lib/flutter_zxing.dart

@ -18,21 +18,26 @@ class FlutterZxing {
static final bindings = GeneratedBindings(dylib); static final bindings = GeneratedBindings(dylib);
static bool logEnabled = true;
static String zxingVersion() { static String zxingVersion() {
return bindings.zxingVersion().cast<Utf8>().toDartString(); return bindings.zxingVersion().cast<Utf8>().toDartString();
} }
static CodeResult zxingRead( static CodeResult zxingRead(Uint8List bytes, int format, int width,
Uint8List bytes, int width, int height, int cropSize) { int height, int cropWidth, int cropHeight) {
return bindings.zxingRead(bytes.allocatePointer(), width, height, cropSize); return bindings.zxingRead(bytes.allocatePointer(), format, width, height,
cropWidth, cropHeight, _logEnabled);
} }
static EncodeResult zxingEncode(String contents, int width, int height, static EncodeResult zxingEncode(String contents, int width, int height,
int format, int margin, int eccLevel) { int format, int margin, int eccLevel) {
var result = bindings.zxingEncode(contents.toNativeUtf8().cast<Int8>(), var result = bindings.zxingEncode(contents.toNativeUtf8().cast<Int8>(),
width, height, format, margin, eccLevel); width, height, format, margin, eccLevel, _logEnabled);
return result; return result;
} }
static int get _logEnabled => logEnabled ? 1 : 0;
} }
// Getting a library that holds needed symbols // Getting a library that holds needed symbols

30
lib/generated_bindings.dart

@ -34,30 +34,40 @@ class GeneratedBindings {
/// @brief Reads barcode from image. /// @brief Reads barcode from image.
/// @param bytes Image bytes. /// @param bytes Image bytes.
/// @param format The format of the barcode
/// @param width Image width. /// @param width Image width.
/// @param height Image height. /// @param height Image height.
/// @param cropSize Crop size. /// @param cropWidth Crop width.
/// @param cropHeight Crop height.
/// @param logEnabled Log enabled.
/// @return Barcode result. /// @return Barcode result.
CodeResult zxingRead( CodeResult zxingRead(
ffi.Pointer<ffi.Int8> bytes, ffi.Pointer<ffi.Int8> bytes,
int format,
int width, int width,
int height, int height,
int cropSize, int cropWidth,
int cropHeight,
int logEnabled,
) { ) {
return _zxingRead( return _zxingRead(
bytes, bytes,
format,
width, width,
height, height,
cropSize, cropWidth,
cropHeight,
logEnabled,
); );
} }
late final _zxingReadPtr = _lookup< late final _zxingReadPtr = _lookup<
ffi.NativeFunction< ffi.NativeFunction<
CodeResult Function(ffi.Pointer<ffi.Int8>, ffi.Int32, ffi.Int32, CodeResult Function(ffi.Pointer<ffi.Int8>, ffi.Int32, ffi.Int32,
ffi.Int32)>>('zxingRead'); ffi.Int32, ffi.Int32, ffi.Int32, ffi.Int32)>>('zxingRead');
late final _zxingRead = _zxingReadPtr late final _zxingRead = _zxingReadPtr.asFunction<
.asFunction<CodeResult Function(ffi.Pointer<ffi.Int8>, int, int, int)>(); CodeResult Function(
ffi.Pointer<ffi.Int8>, int, int, int, int, int, int)>();
/// @brief Encode a string into a barcode /// @brief Encode a string into a barcode
/// @param contents The string to encode /// @param contents The string to encode
@ -65,6 +75,7 @@ class GeneratedBindings {
/// @param height The height of the barcode /// @param height The height of the barcode
/// @param format The format of the barcode /// @param format The format of the barcode
/// @param margin The margin of the barcode /// @param margin The margin of the barcode
/// @param logEnabled Log enabled.
/// @param eccLevel The error correction level of the barcode. Used for Aztec, PDF417, and QRCode only, [0-8]. /// @param eccLevel The error correction level of the barcode. Used for Aztec, PDF417, and QRCode only, [0-8].
/// @return The barcode data /// @return The barcode data
EncodeResult zxingEncode( EncodeResult zxingEncode(
@ -74,6 +85,7 @@ class GeneratedBindings {
int format, int format,
int margin, int margin,
int eccLevel, int eccLevel,
int logEnabled,
) { ) {
return _zxingEncode( return _zxingEncode(
contents, contents,
@ -82,15 +94,17 @@ class GeneratedBindings {
format, format,
margin, margin,
eccLevel, eccLevel,
logEnabled,
); );
} }
late final _zxingEncodePtr = _lookup< late final _zxingEncodePtr = _lookup<
ffi.NativeFunction< ffi.NativeFunction<
EncodeResult Function(ffi.Pointer<ffi.Int8>, ffi.Int32, ffi.Int32, EncodeResult Function(ffi.Pointer<ffi.Int8>, ffi.Int32, ffi.Int32,
ffi.Int32, ffi.Int32, ffi.Int32)>>('zxingEncode'); ffi.Int32, ffi.Int32, ffi.Int32, ffi.Int32)>>('zxingEncode');
late final _zxingEncode = _zxingEncodePtr.asFunction< late final _zxingEncode = _zxingEncodePtr.asFunction<
EncodeResult Function(ffi.Pointer<ffi.Int8>, int, int, int, int, int)>(); EncodeResult Function(
ffi.Pointer<ffi.Int8>, int, int, int, int, int, int)>();
} }
abstract class Format { abstract class Format {

25
lib/isolate_utils.dart

@ -11,12 +11,14 @@ import 'image_converter.dart';
/// Bundles data to pass between Isolate /// Bundles data to pass between Isolate
class IsolateData { class IsolateData {
CameraImage cameraImage; CameraImage cameraImage;
int format;
double cropPercent; double cropPercent;
SendPort? responsePort; SendPort? responsePort;
IsolateData( IsolateData(
this.cameraImage, this.cameraImage,
this.format,
this.cropPercent, this.cropPercent,
); );
} }
@ -54,15 +56,20 @@ class IsolateUtils {
await for (final IsolateData? isolateData in port) { await for (final IsolateData? isolateData in port) {
if (isolateData != null) { if (isolateData != null) {
final image = isolateData.cameraImage; try {
final cropPercent = isolateData.cropPercent; final image = isolateData.cameraImage;
final bytes = await convertImage(image); final cropPercent = isolateData.cropPercent;
final cropSize = (min(image.width, image.height) * cropPercent).round(); final bytes = await convertImage(image);
final cropSize =
final result = (min(image.width, image.height) * cropPercent).round();
FlutterZxing.zxingRead(bytes, image.width, image.height, cropSize);
final result = FlutterZxing.zxingRead(bytes, isolateData.format,
isolateData.responsePort?.send(result); image.width, image.height, cropSize, cropSize);
isolateData.responsePort?.send(result);
} on Exception catch (e) {
isolateData.responsePort?.send(e);
}
} }
} }
} }

5
lib/zxing_reader_widget.dart

@ -18,6 +18,7 @@ class ZxingReaderWidget extends StatefulWidget {
Key? key, Key? key,
required this.onScan, required this.onScan,
this.onControllerCreated, this.onControllerCreated,
this.codeFormat = Format.Any,
this.beep = true, this.beep = true,
this.showCroppingRect = true, this.showCroppingRect = true,
this.scanDelay = const Duration(milliseconds: 500), // 500ms delay this.scanDelay = const Duration(milliseconds: 500), // 500ms delay
@ -27,6 +28,7 @@ class ZxingReaderWidget extends StatefulWidget {
final Function(CodeResult) onScan; final Function(CodeResult) onScan;
final Function(CameraController?)? onControllerCreated; final Function(CameraController?)? onControllerCreated;
final int codeFormat;
final bool beep; final bool beep;
final bool showCroppingRect; final bool showCroppingRect;
final Duration scanDelay; final Duration scanDelay;
@ -144,7 +146,8 @@ class _ZxingReaderWidgetState extends State<ZxingReaderWidget>
if (!_isProcessing) { if (!_isProcessing) {
_isProcessing = true; _isProcessing = true;
try { try {
var isolateData = IsolateData(image, widget.cropPercent); var isolateData =
IsolateData(image, widget.codeFormat, widget.cropPercent);
/// perform inference in separate isolate /// perform inference in separate isolate
CodeResult result = await inference(isolateData); CodeResult result = await inference(isolateData);

2
pubspec.yaml

@ -8,7 +8,7 @@ environment:
flutter: ">=2.5.0" flutter: ">=2.5.0"
dependencies: dependencies:
camera: ^0.9.4+16 camera: ^0.9.4
ffi: ^1.1.2 ffi: ^1.1.2
flutter: flutter:
sdk: flutter sdk: flutter

Loading…
Cancel
Save