Browse Source

fixed inverted issues

pull/76/head
Khoren Markosyan 2 years ago
parent
commit
4b1ac714cf
  1. 4
      README.md
  2. 203
      example/lib/main.dart
  3. 4
      example/pubspec.lock
  4. 17
      lib/src/logic/barcode_reader.dart
  5. 15
      lib/src/logic/barcodes_reader.dart
  6. 1
      lib/src/logic/zxing.dart
  7. 4
      lib/src/ui/reader_widget.dart
  8. 13
      lib/src/utils/isolate_utils.dart

4
README.md

@ -118,8 +118,8 @@ Widget build(BuildContext context) {
final result = zx.encodeBarcode( final result = zx.encodeBarcode(
'Text to encode', 'Text to encode',
format: Format.QRCode, format: Format.QRCode,
width: 300, width: 120,
height: 300, height: 120,
margin: 10, margin: 10,
eccLevel: 0, eccLevel: 0,
); );

203
example/lib/main.dart

@ -1,6 +1,7 @@
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_zxing/flutter_zxing.dart'; import 'package:flutter_zxing/flutter_zxing.dart';
import 'package:image_picker/image_picker.dart';
void main() { void main() {
zx.setLogEnabled(kDebugMode); zx.setLogEnabled(kDebugMode);
@ -34,6 +35,12 @@ class DemoPage extends StatefulWidget {
class _DemoPageState extends State<DemoPage> { class _DemoPageState extends State<DemoPage> {
Uint8List? createdCodeBytes; Uint8List? createdCodeBytes;
Code? result;
bool showDebugInfo = true;
int successScans = 0;
int failedScans = 0;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return DefaultTabController( return DefaultTabController(
@ -52,26 +59,34 @@ class _DemoPageState extends State<DemoPage> {
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
children: [ children: [
if (kIsWeb) if (kIsWeb)
Center( const UnsupportedPlatformWidget()
child: Text( else if (result != null)
'Web is not supported yet.', ScanResultWidget(
style: Theme.of(context).textTheme.headline6, result: result?.text,
), onScanAgain: () => setState(() => result = null),
) )
else else
Stack(
children: [
ReaderWidget( ReaderWidget(
onScan: (value) { onScan: _onScanSuccess,
showMessage(context, 'Scanned: ${value.text ?? ''}'); onScanFailure: () => _onScanFailure(null),
},
tryInverted: true, tryInverted: true,
), ),
if (kIsWeb) ScanFromGalleryWidget(
Center( onScan: _onScanSuccess,
child: Text( onScanFailure: _onScanFailure,
'Web is not supported yet.',
style: Theme.of(context).textTheme.headline6,
), ),
) if (showDebugInfo)
DebugInfoWidget(
successScans: successScans,
failedScans: failedScans,
onReset: _onReset,
),
],
),
if (kIsWeb)
const UnsupportedPlatformWidget()
else else
ListView( ListView(
children: [ children: [
@ -85,7 +100,7 @@ class _DemoPageState extends State<DemoPage> {
}); });
}, },
onError: (error) { onError: (error) {
showMessage(context, 'Error: $error'); _showMessage(context, 'Error: $error');
}, },
), ),
if (createdCodeBytes != null) if (createdCodeBytes != null)
@ -98,12 +113,162 @@ class _DemoPageState extends State<DemoPage> {
); );
} }
showMessage(BuildContext context, String message) { _onScanSuccess(value) {
debugPrint(message); setState(() {
successScans++;
result = value;
});
}
_onScanFailure(String? error) {
setState(() {
failedScans++;
});
if (error != null) {
_showMessage(context, error);
}
}
_showMessage(BuildContext context, String message) {
ScaffoldMessenger.of(context).hideCurrentSnackBar(); ScaffoldMessenger.of(context).hideCurrentSnackBar();
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(content: Text(message)),
content: Text(message), );
}
_onReset() {
setState(() {
successScans = 0;
failedScans = 0;
});
}
}
class ScanResultWidget extends StatelessWidget {
const ScanResultWidget({
Key? key,
this.result,
this.onScanAgain,
}) : super(key: key);
final String? result;
final Function()? onScanAgain;
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
result ?? '',
style: Theme.of(context).textTheme.headline6,
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: onScanAgain,
child: const Text('Scan Again'),
),
],
),
);
}
}
class ScanFromGalleryWidget extends StatelessWidget {
const ScanFromGalleryWidget({
Key? key,
this.onScan,
this.onScanFailure,
}) : super(key: key);
final Function(Code?)? onScan;
final Function(String)? onScanFailure;
@override
Widget build(BuildContext context) {
return Positioned(
bottom: 20,
right: 20,
child: FloatingActionButton(
onPressed: _onFromGalleryButtonTapped,
child: const Icon(Icons.image),
),
);
}
void _onFromGalleryButtonTapped() async {
final XFile? file =
await ImagePicker().pickImage(source: ImageSource.gallery);
if (file != null) {
final Code? result = await zx.readBarcodeImagePath(
file,
params: Params(tryInverted: true),
);
if (result != null && result.isValid) {
onScan?.call(result);
} else {
onScanFailure?.call('Failed to read barcode from image');
}
}
}
}
class DebugInfoWidget extends StatelessWidget {
const DebugInfoWidget({
Key? key,
required this.successScans,
required this.failedScans,
this.onReset,
}) : super(key: key);
final int successScans;
final int failedScans;
final Function()? onReset;
@override
Widget build(BuildContext context) {
return Align(
alignment: Alignment.topCenter,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Container(
color: Colors.white.withOpacity(0.7),
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'Success: $successScans\nFailed: $failedScans',
style: Theme.of(context).textTheme.headline6,
),
TextButton(
onPressed: onReset,
child: const Text('Reset'),
),
],
),
),
),
),
);
}
}
class UnsupportedPlatformWidget extends StatelessWidget {
const UnsupportedPlatformWidget({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Center(
child: Text(
'This platform is not supported yet.',
style: Theme.of(context).textTheme.headline6,
), ),
); );
} }

4
example/pubspec.lock

@ -148,7 +148,7 @@ packages:
path: ".." path: ".."
relative: true relative: true
source: path source: path
version: "0.9.0" version: "0.9.1"
font_awesome_flutter: font_awesome_flutter:
dependency: "direct main" dependency: "direct main"
description: description:
@ -204,7 +204,7 @@ packages:
name: image_picker_ios name: image_picker_ios
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.8.6+4" version: "0.8.6+5"
image_picker_platform_interface: image_picker_platform_interface:
dependency: transitive dependency: transitive
description: description:

17
lib/src/logic/barcode_reader.dart

@ -53,7 +53,22 @@ Code zxingReadBarcode(
required int width, required int width,
required int height, required int height,
Params? params, Params? params,
}) => }) {
Code result = _readBarcode(bytes, width, height, params);
if (!result.isValid && params != null && params.tryInverted == true) {
// try to invert the image and read again
final Uint8List invertedBytes = invertImage(bytes);
result = _readBarcode(invertedBytes, width, height, params);
}
return result;
}
Code _readBarcode(
Uint8List bytes,
int width,
int height,
Params? params,
) =>
bindings bindings
.readBarcode( .readBarcode(
bytes.allocatePointer(), bytes.allocatePointer(),

15
lib/src/logic/barcodes_reader.dart

@ -54,6 +54,21 @@ List<Code> zxingReadBarcodes(
required int height, required int height,
Params? params, Params? params,
}) { }) {
List<Code> results = _readBarcodes(bytes, width, height, params);
if (results.isEmpty && params != null && params.tryInverted == true) {
// try to invert the image and read again
final Uint8List invertedBytes = invertImage(bytes);
results = _readBarcodes(invertedBytes, width, height, params);
}
return results;
}
List<Code> _readBarcodes(
Uint8List bytes,
int width,
int height,
Params? params,
) {
final CodeResults result = bindings.readBarcodes( final CodeResults result = bindings.readBarcodes(
bytes.allocatePointer(), bytes.allocatePointer(),
params?.format ?? Format.any, params?.format ?? Format.any,

1
lib/src/logic/zxing.dart

@ -12,6 +12,7 @@ import 'package:image/image.dart' as imglib;
import '../../generated_bindings.dart'; import '../../generated_bindings.dart';
import '../models/models.dart'; import '../models/models.dart';
import '../utils/extentions.dart'; import '../utils/extentions.dart';
import '../utils/image_converter.dart';
import '../utils/isolate_utils.dart'; import '../utils/isolate_utils.dart';
part 'barcode_encoder.dart'; part 'barcode_encoder.dart';

4
lib/src/ui/reader_widget.dart

@ -13,6 +13,7 @@ class ReaderWidget extends StatefulWidget {
const ReaderWidget({ const ReaderWidget({
super.key, super.key,
required this.onScan, required this.onScan,
this.onScanFailure,
this.onControllerCreated, this.onControllerCreated,
this.codeFormat = Format.any, this.codeFormat = Format.any,
this.tryHarder = false, this.tryHarder = false,
@ -30,6 +31,7 @@ class ReaderWidget extends StatefulWidget {
}); });
final Function(Code) onScan; final Function(Code) onScan;
final Function()? onScanFailure;
final Function(CameraController?)? onControllerCreated; final Function(CameraController?)? onControllerCreated;
final int codeFormat; final int codeFormat;
final bool tryHarder; final bool tryHarder;
@ -183,6 +185,8 @@ class _ReaderWidgetState extends State<ReaderWidget>
widget.onScan(result); widget.onScan(result);
setState(() {}); setState(() {});
await Future<void>.delayed(widget.scanDelaySuccess); await Future<void>.delayed(widget.scanDelaySuccess);
} else {
widget.onScanFailure?.call();
} }
} on FileSystemException catch (e) { } on FileSystemException catch (e) {
debugPrint(e.message); debugPrint(e.message);

13
lib/src/utils/isolate_utils.dart

@ -58,24 +58,13 @@ class IsolateUtils {
final CameraImage image = isolateData.cameraImage; final CameraImage image = isolateData.cameraImage;
final Uint8List bytes = await convertImage(image); final Uint8List bytes = await convertImage(image);
Code result = zxingReadBarcode( final Code result = zxingReadBarcode(
bytes, bytes,
width: image.width, width: image.width,
height: image.height, height: image.height,
params: isolateData.params, params: isolateData.params,
); );
if (!result.isValid && isolateData.params.tryInverted) {
// try to invert the image and read again
final Uint8List invertedBytes = invertImage(bytes);
result = zxingReadBarcode(
invertedBytes,
width: image.width,
height: image.height,
params: isolateData.params,
);
}
isolateData.responsePort?.send(result); isolateData.responsePort?.send(result);
} catch (e) { } catch (e) {
isolateData.responsePort?.send(e); isolateData.responsePort?.send(e);

Loading…
Cancel
Save