• Что бы вступить в ряды "Принятый кодер" Вам нужно:
    Написать 10 полезных сообщений или тем и Получить 10 симпатий.
    Для того кто не хочет терять время,может пожертвовать средства для поддержки сервеса, и вступить в ряды VIP на месяц, дополнительная информация в лс.

  • Пользаватели которые будут спамить, уходят в бан без предупреждения. Спам сообщения определяется администрацией и модератором.

  • Гость, Что бы Вы хотели увидеть на нашем Форуме? Изложить свои идеи и пожелания по улучшению форума Вы можете поделиться с нами здесь. ----> Перейдите сюда
  • Все пользователи не прошедшие проверку электронной почты будут заблокированы. Все вопросы с разблокировкой обращайтесь по адресу электронной почте : info@guardianelinks.com . Не пришло сообщение о проверке или о сбросе также сообщите нам.

Creating a Flutter App to Scan MRZ, QR Codes, and Barcodes

Lomanu4 Оффлайн

Lomanu4

Команда форума
Администратор
Регистрация
1 Мар 2015
Сообщения
1,481
Баллы
155

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

and

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

are two Flutter plugins built on top of the Dynamsoft Capture Vision SDK. They provide easy-to-use, cross-platform APIs for adding MRZ recognition and barcode scanning capabilities to Flutter apps. In this article, you'll learn how to create a Flutter app that integrates both plugins to scan machine-readable zones (MRZ) and 1D/2D barcodes. Instead of starting from scratch, we'll combine two existing example projects into a unified solution.

Demo Video: Flutter MRZ and Barcode Scanner

Prerequisites


Steps to Build an MRZ and Barcode Scanner App in Flutter


The app will include:

  • A toggle button to switch between MRZ and Barcode scanning modes
  • A button to load an image file for detection
  • A button to open the camera for live detection
  • A camera view for real-time MRZ and 1D/2D barcode scanning
  • A result view to display scan results from camera streams and images

We'll start by modifying the source code from the Flutter MRZ Scanner project to add UI and functionality.

Step 1: Install Dependencies


Add the following dependencies to your pubspec.yaml file:


flutter_barcode_sdk: ^3.0.3
flutter_ocr_sdk: ^2.0.3
Step 2: Initialize the SDKs


Since both plugins wrap the same Dynamsoft SDK, you can initialize them with a shared license key in global.dart.


FlutterOcrSdk detector = FlutterOcrSdk();
FlutterBarcodeSdk barcodeReader = FlutterBarcodeSdk();
bool isLicenseValid = false;

Future<int> initSDK() async {
String licenseKey =
"LICENSE-KEY";
int? ret = await detector.init(licenseKey);
ret = await barcodeReader.init();
ret = await barcodeReader.setLicense(licenseKey);

if (ret == 0) isLicenseValid = true;
return await detector.loadModel(modelType: ModelType.mrz) ?? -1;
}
Step 3: Toggle MRZ and Barcode Modes


In home_page.dart, update the toggle button to switch between MRZ and Barcode modes:


ToggleButtons(
borderRadius: BorderRadius.circular(10),
isSelected: [isMrzSelected, !isMrzSelected],
selectedColor: Colors.white,
fillColor: Colors.orange,
color: Colors.grey,
children: const [
Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Text('MRZ'),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Text('Barcode'),
),
],
onPressed: (index) {
setState(() {
isMrzSelected = (index == 0);
});
},
)

The global boolean variable isMrzSelected determines which scanning mode is active.

Step 4: Scan from Image File


Update the scanImage() method in home_page.dart to perform MRZ or barcode recognition depending on the selected mode:


void openMrzResultPage(OcrLine information) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MrzResultPage(information: information),
),
);
}

void openBarcodeResultPage(List<BarcodeResult> barcodeResults) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BarcodeResultPage(barcodeResults: barcodeResults),
),
);
}


void scanImage() async {
XFile? photo = await picker.pickImage(source: ImageSource.gallery);

if (photo == null) {
return;
}

if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
File rotatedImage = await FlutterExifRotation.rotateImage(
path: photo.path,
);
photo = XFile(rotatedImage.path);
}

Uint8List fileBytes = await photo.readAsBytes();

ui.Image image = await decodeImageFromList(fileBytes);

ByteData? byteData = await image.toByteData(
format: ui.ImageByteFormat.rawRgba,
);
if (byteData != null) {
if (isMrzSelected) {
List<List<OcrLine>>? results = await detector.recognizeBuffer(
byteData.buffer.asUint8List(),
image.width,
image.height,
byteData.lengthInBytes ~/ image.height,
ImagePixelFormat.IPF_ARGB_8888.index,
ImageRotation.rotation0.value,
);

if (results != null && results[0].isNotEmpty) {
openMrzResultPage(results[0][0]);
} else {
showAlert(context, "OCR Result", "Recognition Failed!");
}
} else {
List<BarcodeResult>? results = await barcodeReader.decodeImageBuffer(
byteData.buffer.asUint8List(),
image.width,
image.height,
byteData.lengthInBytes ~/ image.height,
ImagePixelFormat.IPF_ARGB_8888.index,
);

if (results.isNotEmpty) {
openBarcodeResultPage(results);
} else {
showAlert(context, "Barcode Result", "Detection Failed!");
}
}
}
}

Both result pages already exist in the sample projects. Rename them to avoid conflicts.

Step 5: Real-time Scanning


In camera_manager.dart, update functions like webCamera(), processId(), and _decodeFrame() to call the appropriate APIs based on isMrzSelected. This enables real-time MRZ and barcode scanning across platforms.


Future<void> webCamera() async {
_isWebFrameStarted = true;
try {
while (!(controller == null || isFinished || cbIsMounted() == false)) {
XFile file = await controller!.takePicture();
dynamic results;
if (isMrzSelected) {
results = await detector.recognizeFile(file.path);
ocrLines = results;
} else {
results = await barcodeReader.decodeFile(file.path);
barcodeResults = results;
}

if (results == null || !cbIsMounted()) return;

cbRefreshUi();
if (isReadyToGo && results != null) {
handleResults(results);
}
}
} catch (e) {
print(e);
}
_isWebFrameStarted = false;
}

Future<void> processId(
Uint8List bytes, int width, int height, int stride, int format) async {
int rotation = 0;
bool isAndroidPortrait = false;
if (MediaQuery.of(context).size.width <
MediaQuery.of(context).size.height) {
if (Platform.isAndroid) {
rotation = OCR.ImageRotation.rotation90.value;
isAndroidPortrait = true;
}
}

dynamic results;

if (isMrzSelected) {
ocrLines = await detector.recognizeBuffer(
bytes, width, height, stride, format, rotation);
results = ocrLines;
} else {
barcodeResults = await barcodeReader.decodeImageBuffer(
bytes, width, height, stride, format);

if (isAndroidPortrait &&
barcodeResults != null &&
barcodeResults!.isNotEmpty) {
barcodeResults =
rotate90barcode(barcodeResults!, previewSize!.height.toInt());
}
results = barcodeResults;
}
_isScanAvailable = true;
if (results == null || !cbIsMounted()) return;

cbRefreshUi();
if (isReadyToGo && results != null) {
handleResults(results!);
}
}

Future<void> _decodeFrame(Uint8List rgb, int width, int height) async {
if (isDecoding) return;

isDecoding = true;
dynamic results;
if (isMrzSelected) {
ocrLines = await detector.recognizeBuffer(
rgb,
width,
height,
width * 3,
ImagePixelFormat.IPF_RGB_888.index,
OCR.ImageRotation.rotation0.value);

results = ocrLines;
} else {
barcodeResults = await barcodeReader.decodeImageBuffer(
rgb, width, height, width * 3, ImagePixelFormat.IPF_RGB_888.index);
results = barcodeResults;
}

if (cbIsMounted()) {
cbRefreshUi();
if (isReadyToGo && results != null) {
handleResults(results!);
}
}

isDecoding = false;
}
Step 6: Display Scan Overlays


To render overlays for MRZ and barcode results:


  1. Update createCameraPreview() in camera_page.dart:

    List<Widget> createCameraPreview() {
    Positioned widget;
    if (isMrzSelected) {
    widget = Positioned(
    top: 0.0,
    right: 0.0,
    bottom: 0,
    left: 0.0,
    child: createOverlay(_cameraManager.ocrLines),
    );
    } else {
    widget = Positioned(
    top: 0.0,
    right: 0.0,
    bottom: 0,
    left: 0.0,
    child: createOverlay(_cameraManager.barcodeResults),
    );
    }

    if (!kIsWeb &&
    (Platform.isWindows || Platform.isLinux || Platform.isMacOS)) {
    return [
    SizedBox(width: 640, height: 480, child: _cameraManager.getPreview()),
    widget,
    ];
    } else {
    if (_cameraManager.controller != null &&
    _cameraManager.previewSize != null) {
    double width = _cameraManager.previewSize!.width;
    double height = _cameraManager.previewSize!.height;
    if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
    if (MediaQuery.of(context).size.width <
    MediaQuery.of(context).size.height) {
    width = _cameraManager.previewSize!.height;
    height = _cameraManager.previewSize!.width;
    }
    }

    return [
    SizedBox(
    width: width,
    height: height,
    child: _cameraManager.getPreview(),
    ),
    widget,
    ];
    } else {
    return [const CircularProgressIndicator()];
    }
    }
    }

  2. Add overlay rendering logic for barcodes in global.dart:

    class OverlayPainter extends CustomPainter {
    List<List<OcrLine>>? ocrResults;
    List<BarcodeResult>? barcodeResults;

    OverlayPainter(dynamic results) {
    if (results is List<List<OcrLine>>) {
    ocrResults = results;
    } else if (results is List<BarcodeResult>) {
    barcodeResults = results;
    }
    }

    @override
    void paint(Canvas canvas, Size size) {
    final paint = Paint()
    ..color = Colors.blue
    ..strokeWidth = 5
    ..style = PaintingStyle.stroke;

    final textStyle = TextStyle(
    color: Colors.red,
    fontSize: 16,
    );

    if (ocrResults != null) {
    for (List<OcrLine> area in ocrResults!) {
    for (OcrLine line in area) {
    canvas.drawLine(Offset(line.x1.toDouble(), line.y1.toDouble()),
    Offset(line.x2.toDouble(), line.y2.toDouble()), paint);
    canvas.drawLine(Offset(line.x2.toDouble(), line.y2.toDouble()),
    Offset(line.x3.toDouble(), line.y3.toDouble()), paint);
    canvas.drawLine(Offset(line.x3.toDouble(), line.y3.toDouble()),
    Offset(line.x4.toDouble(), line.y4.toDouble()), paint);
    canvas.drawLine(Offset(line.x4.toDouble(), line.y4.toDouble()),
    Offset(line.x1.toDouble(), line.y1.toDouble()), paint);

    final textSpan = TextSpan(
    text: line.text,
    style: textStyle,
    );

    final textPainter = TextPainter(
    text: textSpan,
    textAlign: TextAlign.left,
    textDirection: TextDirection.ltr,
    );

    textPainter.layout();

    final offset = Offset(
    line.x1.toDouble(),
    line.y1.toDouble(),
    );

    textPainter.paint(canvas, offset);
    }
    }
    }

    if (barcodeResults != null) {
    for (var result in barcodeResults!) {
    double minX = result.x1.toDouble();
    double minY = result.y1.toDouble();
    if (result.x2 < minX) minX = result.x2.toDouble();
    if (result.x3 < minX) minX = result.x3.toDouble();
    if (result.x4 < minX) minX = result.x4.toDouble();
    if (result.y2 < minY) minY = result.y2.toDouble();
    if (result.y3 < minY) minY = result.y3.toDouble();
    if (result.y4 < minY) minY = result.y4.toDouble();

    canvas.drawLine(Offset(result.x1.toDouble(), result.y1.toDouble()),
    Offset(result.x2.toDouble(), result.y2.toDouble()), paint);
    canvas.drawLine(Offset(result.x2.toDouble(), result.y2.toDouble()),
    Offset(result.x3.toDouble(), result.y3.toDouble()), paint);
    canvas.drawLine(Offset(result.x3.toDouble(), result.y3.toDouble()),
    Offset(result.x4.toDouble(), result.y4.toDouble()), paint);
    canvas.drawLine(Offset(result.x4.toDouble(), result.y4.toDouble()),
    Offset(result.x1.toDouble(), result.y1.toDouble()), paint);

    TextPainter textPainter = TextPainter(
    text: TextSpan(
    text: result.text,
    style: const TextStyle(
    color: Colors.yellow,
    fontSize: 22.0,
    ),
    ),
    textAlign: TextAlign.center,
    textDirection: TextDirection.ltr,
    );
    textPainter.layout(minWidth: 0, maxWidth: size.width);
    textPainter.paint(canvas, Offset(minX, minY));
    }
    }
    }

    @override
    bool shouldRepaint(OverlayPainter oldDelegate) => true;
    }
Running the Flutter MRZ/Barcode Scanner App


Run the app on Windows, Linux, Android, iOS, and Web:


flutter run -d chrome # Web
flutter run -d linux # Linux
flutter run -d windows # Windows
flutter run # Android or iOS


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Source Code



Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.




Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

 
Вверх Снизу