Flutter图像捕获与处理插件dynamsoft_capture_vision_flutter的使用

发布于 1周前 作者 vueper 来自 Flutter

Flutter图像捕获与处理插件dynamsoft_capture_vision_flutter的使用

1. Dynamsoft Capture Vision (DCV) 简介

Dynamsoft Capture Vision (DCV) 是一个集成了多个特定功能产品的SDK,包括:

  • Dynamsoft Camera Enhancer (DCE):提供相机增强和UI配置API。
  • Dynamsoft Barcode Reader (DBR):提供条码解码算法和API。
  • Dynamsoft Label Recognizer (DLR):提供标签内容识别算法和API。
  • Dynamsoft Document Normalizer (DDN):提供文档扫描算法和API。

注意:当前DCV Flutter版本仅支持条码读取功能。

2. 功能特点

支持多种条码类型
  • 一维条码

    • Code 39(包括扩展版)
    • Code 93
    • Code 128
    • Codabar
    • Interleaved 2 of 5
    • EAN-8
    • EAN-13
    • UPC-A
    • UPC-E
    • Industrial 2 of 5
    • MSI(Modified Plessey)
    • Code 11
  • 二维条码

    • QR Code(包括Micro QR Code和Model 1)
    • Data Matrix
    • PDF417(包括Micro PDF417)
    • Aztec Code
    • MaxiCode(mode 2-5)
    • DotCode
  • 其他条码类型

    • GS1 DataBar
    • GS1 Composite Code
    • Patch Code
    • Pharmacode
    • 邮政编码
多个条码扫描

库支持同时扫描多个条码。你可以使用 DBRRuntimeSettings.expectedBarcodeCount 来配置预期的条码数量。

高速、高精度和高可读性条码解码
  • 模糊条码 模糊条码

  • 反色条码 反色条码

  • 变形条码

  • 损坏条码

针对不同场景的自定义

SDK设计灵活,可以根据不同的应用场景进行自定义。如果你对当前性能不满意,可以联系官方获取进一步支持。

3. 入门指南

在本指南中,你将逐步学习如何将Dynamsoft Capture Vision Flutter SDK的条码读取功能集成到你的应用中。

4. 示例代码

以下是一个完整的示例demo,展示了如何使用 dynamsoft_capture_vision_flutter 插件来实现条码扫描功能。

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:dynamsoft_capture_vision_flutter/dynamsoft_capture_vision_flutter.dart';
import 'package:flutter_beep/flutter_beep.dart';
import 'package:image_picker/image_picker.dart';
import 'package:vibration/vibration.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // 将你的Dynamsoft Barcode Reader许可证密钥放在这里
  const String licenseKey =
      'DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTEwMTIwMDkzNiIsIm9yZ2FuaXphdGlvbklEIjoiMjAwMDAxIn0=';

  // 初始化许可证,以便使用条码读取模块的全部功能
  try {
    await DCVBarcodeReader.initLicense(licenseKey);
  } catch (e) {
    print(e);
  }

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '条码读取简单示例',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: '首页'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String? path;

  void _startScanning() {
    Navigator.push(
        context, MaterialPageRoute(builder: (context) => BarcodeScanner()));
  }

  [@override](/user/override)
  void initState() {
    super.initState();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: ListView(
        children: [
          TextButton(
            onPressed: _startScanning,
            child: Text('开始扫描'),
            style: TextButton.styleFrom(backgroundColor: Colors.blue),
          ),
        ],
      ),
    );
  }
}

class BarcodeScanner extends StatefulWidget {
  BarcodeScanner({Key? key}) : super(key: key);

  [@override](/user/override)
  State<BarcodeScanner> createState() => _BarcodeScannerState();
}

class _BarcodeScannerState extends State<BarcodeScanner>
    with WidgetsBindingObserver {
  late final DCVBarcodeReader _barcodeReader;
  late final DCVCameraEnhancer _cameraEnhancer;
  late final ImagePicker _picker;

  final DCVCameraView _cameraView = DCVCameraView();

  List<BarcodeResult> decodeRes = [];
  String? resultText;
  String? base64ResultText;
  bool faceLens = false;

  [@override](/user/override)
  void initState() {
    super.initState();
    WidgetsBinding.instance?.addObserver(this);
    _picker = ImagePicker();
    _sdkInit();
  }

  [@override](/user/override)
  void dispose() {
    WidgetsBinding.instance?.removeObserver(this);
    _cameraEnhancer.close();
    _barcodeReader.stopScanning();
    super.dispose();
  }

  void _sdkInit() async {
    // 创建条码读取器实例
    _barcodeReader = await DCVBarcodeReader.createInstance();
    _cameraEnhancer = await DCVCameraEnhancer.createInstance();

    // 获取条码读取器的当前运行时设置
    DBRRuntimeSettings currentSettings = await _barcodeReader.getRuntimeSettings();

    // 设置要读取的条码格式
    currentSettings.barcodeFormatIds = EnumBarcodeFormat.BF_ONED |
        EnumBarcodeFormat.BF_QR_CODE |
        EnumBarcodeFormat.BF_PDF417 |
        EnumBarcodeFormat.BF_DATAMATRIX;

    // 设置预期的条码数量为0,当你不确定要扫描多少个条码时
    currentSettings.expectedBarcodeCount = 0;

    // 应用新的运行时设置到条码读取器
    await _barcodeReader.updateRuntimeSettings(currentSettings);

    // 定义扫描区域
    _cameraEnhancer.setScanRegion(Region(
        regionTop: 30,
        regionLeft: 15,
        regionBottom: 70,
        regionRight: 85,
        regionMeasuredByPercentage: 1));

    // 启用条码叠加层可见性
    _cameraView.overlayVisible = true;

    // 设置闪光灯按钮
    _cameraView.torchButton = TorchButton(
      visible: true,
    );

    // 设置缩放因子
    _cameraEnhancer.setZoomFactor(2.0);

    // 启用结果验证
    await _barcodeReader.enableResultVerification(true);

    // 监听条码结果回调
    _barcodeReader.receiveResultStream().listen((List<BarcodeResult>? res) {
      if (mounted) {
        setState(() {
          decodeRes = res ?? [];
        });
      }
    });

    // 打开相机
    await _cameraEnhancer.open();

    // 启用视频条码扫描
    _barcodeReader.startScanning();
  }

  /// 获取列表项
  Widget listItem(BuildContext context, int index) {
    BarcodeResult res = decodeRes[index];

    return ListTileTheme(
        textColor: Colors.white,
        child: ListTile(
          title: Text(res.barcodeFormatString),
          subtitle: Text(res.barcodeText),
        ));
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('条码扫描器'),
        ),
        body: Stack(
          children: [
            Container(
              child: _cameraView,
            ),
            Container(
              height: 100,
              child: ListView.builder(
                itemBuilder: listItem,
                itemCount: decodeRes.length,
              ),
            ),
            Positioned(
              top: 150,
              left: 25,
              child: GestureDetector(
                onTap: () {
                  faceLens = !faceLens;
                  _cameraEnhancer.selectCamera(faceLens
                      ? EnumCameraPosition.CP_FRONT
                      : EnumCameraPosition.CP_BACK);
                },
                child: Image.asset(
                  'assets/toggle_lens.png',
                  width: 48,
                  height: 48,
                ),
              ),
            ),
            Positioned(
              bottom: 20,
              left: MediaQuery.of(context).size.width / 2 - 80,
              child: Column(
                children: [
                  Container(
                    width: 160,
                    child: TextButton(
                      onPressed: () => _pickImage(ImageSource.gallery),
                      child: Text('选择照片'),
                      style: TextButton.styleFrom(
                          foregroundColor: Colors.white,
                          backgroundColor: Colors.blue),
                    ),
                  ),
                  Container(
                    width: 160,
                    child: TextButton(
                      onPressed: () => _pickImage(ImageSource.camera),
                      child: Text('拍照'),
                      style: TextButton.styleFrom(
                          foregroundColor: Colors.white,
                          backgroundColor: Colors.blue),
                    ),
                  ),
                ],
              ),
            )
          ],
        ));
  }

  void _pickImage(ImageSource source) async {
    final XFile? image = await _picker.pickImage(source: source);
    final path = image?.path;
    if (path != null) {
      final result = await _barcodeReader.decodeFile(path);

      if (await Vibration.hasVibrator() ?? false) {
        Vibration.vibrate();
      }
      FlutterBeep.beep();

      if (result != null && result.isNotEmpty) {
        resultText = result[0].barcodeText;
        final bytes = result[0].barcodeBytes;
        base64ResultText = utf8.decode(bytes);
        decodeRes.addAll(result);
      }
    }
    setState(() {});
  }

  [@override](/user/override)
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);

    switch (state) {
      case AppLifecycleState.resumed:
        _barcodeReader.startScanning();
        _cameraEnhancer.open();
        break;
      case AppLifecycleState.inactive:
        _cameraEnhancer.close();
        _barcodeReader.stopScanning();
        break;
      case AppLifecycleState.detached:
      case AppLifecycleState.hidden:
      case AppLifecycleState.paused:
        break;
      default:
        break;
    }
  }
}

更多关于Flutter图像捕获与处理插件dynamsoft_capture_vision_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter图像捕获与处理插件dynamsoft_capture_vision_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用dynamsoft_capture_vision_flutter插件进行图像捕获与处理的示例代码。这个插件通常用于从摄像头捕获图像并进行一些基本的图像处理。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加dynamsoft_capture_vision_flutter依赖:

dependencies:
  flutter:
    sdk: flutter
  dynamsoft_capture_vision_flutter: ^最新版本号  # 请替换为实际最新版本号

然后运行flutter pub get来安装依赖。

2. 配置Android权限

由于图像捕获涉及到摄像头权限,你需要在AndroidManifest.xml文件中添加以下权限:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />  # 如果需要音频
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />

3. 请求权限(如果需要)

在Flutter代码中,你可能需要请求这些权限。这里是一个简单的权限请求示例:

import 'package:permission_handler/permission_handler.dart';

Future<void> requestPermissions() async {
  var status = await Permission.camera.status;
  if (!status.isGranted) {
    Map<Permission, PermissionStatus> permissions = await Permission.camera
        .request();
    status = permissions[Permission.camera]!;
  }
  if (!status.isGranted) {
    // 处理权限被拒绝的情况
    return;
  }
}

4. 使用插件捕获和处理图像

以下是一个简单的Flutter应用示例,展示了如何使用dynamsoft_capture_vision_flutter插件来捕获和处理图像:

import 'package:flutter/material.dart';
import 'package:dynamsoft_capture_vision_flutter/dynamsoft_capture_vision_flutter.dart';
import 'dart:typed_data';
import 'dart:ui' as ui;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: CapturePage(),
    );
  }
}

class CapturePage extends StatefulWidget {
  @override
  _CapturePageState createState() => _CapturePageState();
}

class _CapturePageState extends State<CapturePage> {
  late DynamsoftCaptureVision _dynamsoftCaptureVision;
  Uint8List? _capturedImage;

  @override
  void initState() {
    super.initState();
    _dynamsoftCaptureVision = DynamsoftCaptureVision.instance;
    _dynamsoftCaptureVision.init();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Dynamsoft Capture Vision Flutter'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            _capturedImage == null
                ? Text('No image captured yet.')
                : Image.memory(_capturedImage!),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () async {
                Uint8List? imageBytes = await _captureImage();
                if (imageBytes != null) {
                  setState(() {
                    _capturedImage = imageBytes;
                  });
                }
              },
              child: Text('Capture Image'),
            ),
          ],
        ),
      ),
    );
  }

  Future<Uint8List?> _captureImage() async {
    try {
      var result = await _dynamsoftCaptureVision.captureImage();
      if (result != null && result.isSuccess) {
        var imageBytes = result.imageBytes;
        return imageBytes;
      }
    } catch (e) {
      print('Error capturing image: $e');
    }
    return null;
  }

  @override
  void dispose() {
    _dynamsoftCaptureVision.dispose();
    super.dispose();
  }
}

5. 运行应用

确保你的设备或模拟器有摄像头权限,然后运行你的Flutter应用。你应该能够看到一个按钮,点击按钮后,会从摄像头捕获图像并显示在页面上。

注意事项

  • 确保你已经正确配置了插件的依赖和权限。
  • 插件的版本号可能会更新,请查阅最新的文档和示例代码。
  • 插件可能会有一些特定的配置选项,你可以查阅插件的官方文档来获取更多信息。

这个示例展示了基本的图像捕获功能,你可以根据需要进行进一步的图像处理或分析。

回到顶部