使用C++实现Windows和Linux的Flutter文档扫描插件

文档扫描应用大都是移动应用。结合手机摄像头可以实现文档拍摄,边缘检测,自动剪裁,透视矫正,滤镜等功能。但是桌面办公也少不了文档处理。这里分享下如何使用Dynamsoft Document Normalizer C++ SDK实现用于桌面文档处理的Flutter插件。

Flutter文档扫描插件下载

需要快速体验可以直接访问
https://pub.dev/packages/flutter_document_scan_sdk

生成配置Flutter桌面插件工程

因为C++ SDK只提供了Windows和Linux的库,所以我们创建一个支持Windows和Linux的Flutter插件工程:

flutter create --org com.dynamsoft --template=plugin --platforms=windows,linux .

我们看到Windows和Linux插件代码都是通过CMake编译的。所以需要打开CMakeLists.txt文件配置下编译环境。

Windows

link_directories("${PROJECT_SOURCE_DIR}/lib/") 

target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin "DynamsoftCorex64" "DynamsoftDocumentNormalizerx64")

set(flutter_document_scan_sdk_bundled_libraries
  "${PROJECT_SOURCE_DIR}/bin/"
  PARENT_SCOPE
)

Linux

link_directories("${PROJECT_SOURCE_DIR}/lib/") 

target_link_libraries(${PLUGIN_NAME} PRIVATE flutter "DynamsoftCore" "DynamsoftDocumentNormalizer")

set(flutter_document_scan_sdk_bundled_libraries
  
  PARENT_SCOPE
)

两个平台有一些差异。用于Windows和Linux的库名字有一些不同。Windows上因为链接的是*.lib文件,最后还需要指定*.dll文件的路径用于打包。

Flutter和C++接口实现

Flutter和底层代码是通过method channel通信的。

首先在flutter_document_scan_sdk_method_channel.dart中定义上层接口:

class MethodChannelFlutterDocumentScanSdk
    extends FlutterDocumentScanSdkPlatform {
   
  
  final methodChannel = const MethodChannel('flutter_document_scan_sdk');

  
  Future<String?> getPlatformVersion() async {
   
    final version =
        await methodChannel.invokeMethod<String>('getPlatformVersion');
    return version;
  }

  
  Future<int?> init(String path, String key) async {
   
    return await methodChannel
        .invokeMethod<int>('init', {
   'path': path, 'key': key});
  }

  
  Future<int?> setParameters(String params) async {
   
    return await methodChannel
        .invokeMethod<int>('setParameters', {
   'params': params});
  }

  
  Future<String?> getParameters() async {
   
    return await methodChannel.invokeMethod<String>('getParameters');
  }

  
  Future<List<DocumentResult>> detect(String file) async {
   
    List? results = await methodChannel.invokeListMethod<dynamic>(
      'detect',
      {
   'file': file},
    );

    return _resultWrapper(results);
  }

  List<DocumentResult> _resultWrapper(List<dynamic>? results) {
   
    List<DocumentResult> output = [];

    if (results != null) {
   
      for (var result in results) {
   
        int confidence = result['confidence'];
        List<Offset> offsets = [];
        int x1 = result['x1'];
        int y1 = result['y1'];
        int x2 = result['x2'];
        int y2 = result['y2'];
        int x3 = result['x3'];
        int y3 = result['y3'];
        int x4 = result['x4'];
        int y4 = result['y4'];
        offsets.add(Offset(x1.toDouble(), y1.toDouble()));
        offsets.add(Offset(x2.toDouble(), y2.toDouble()));
        offsets.add(Offset(x3.toDouble(), y3.toDouble()));
        offsets.add(Offset(x4.toDouble(), y4.toDouble()));
        DocumentResult documentResult = DocumentResult(confidence, offsets, []);
        output.add(documentResult);
      }
    }

    return output;
  }

  
  Future<NormalizedImage?> normalize(String file, dynamic points) async {
   
    Offset offset = points[0];
    int x1 = offset.dx.toInt();
    int y1 = offset.dy.toInt();

    offset = points[1];
    int x2 = offset.dx.toInt();
    int y2 = offset.dy.toInt();

    offset = points[2];
    int x3 = offset.dx.toInt();
    int y3 = offset.dy.toInt();

    offset = points[3];
    int x4 = offset.dx.toInt();
    int y4 = offset.dy.toInt();
    Map? result = await methodChannel.invokeMapMethod<String, dynamic>(
      'normalize',
      {
   
        'file': file,
        'x1': x1,
        'y1': y1,
        'x2': x2,
        'y2': y2,
        'x3': x3,
        'y3': y3,
        'x4': x4,
        'y4': y4
      },
    );

    if (result != null) {
   
      return NormalizedImage(
        result['data'],
        result['width'],
        result['height'],
      );
    }

    return null;
  }

  
  Future<int?> save(String filename) async {
   
    return await methodChannel
        .invokeMethod<int>('save', {
   'filename': filename});
  }
}

然后在C++中解析接口名和参数名。Windows上C++的入口函数是FlutterDocumentScanSdkPlugin::HandleMethodCall,而Linux上是flutter_document_scan_sdk_plugin_handle_method_call

Windows

#include "flutter_document_scan_sdk_plugin.h"

#include <windows.h>

#include <VersionHelpers.h>

#include <flutter/method_channel.h>
#include <flutter/plugin_registrar_windows.h>
#include <flutter/standard_method_codec.h>

#include <memory>
#include <sstream>

void FlutterDocumentScanSdkPlugin::HandleMethodCall(
      const flutter::MethodCall<flutter::EncodableValue> &method_call,
      std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result){
   }

Linux

#include "include/flutter_document_scan_sdk/flutter_document_scan_sdk_plugin.h"

#include <flutter_linux/flutter_linux.h>
#include <gtk/gtk.h>
#include <sys/utsname.h>

#include <cstring>

static void flutter_document_scan_sdk_plugin_handle_method_call(
    FlutterDocumentScanSdkPlugi
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
flutter_map是一个用于在Flutter应用程序中集成地图的插件[^2]。下面是一个使用flutter_map插件的示例: 首先,您需要在`pubspec.yaml`文件中添加flutter_map的依赖项: ```yaml dependencies: flutter_map: ^0.3.0 ``` 然后,运行`flutter packages get`命令来获取依赖项。 接下来,您可以在Flutter应用程序中使用flutter_map插件。以下是一个简单的示例,展示如何在地图上显示一个标记点: ```dart import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:latlong/latlong.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Map Demo', home: Scaffold( appBar: AppBar( title: Text('Flutter Map Demo'), ), body: FlutterMap( options: MapOptions( center: LatLng(51.5, -0.09), zoom: 13.0, ), layers: [ TileLayerOptions( urlTemplate: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", subdomains: ['a', 'b', 'c'], ), MarkerLayerOptions( markers: [ Marker( width: 80.0, height: 80.0, point: LatLng(51.5, -0.09), builder: (ctx) => Container( child: FlutterLogo(), ), ), ], ), ], ), ), ); } } ``` 在上面的示例中,我们创建了一个Flutter应用程序,并在地图上显示了一个标记点。我们使用了`FlutterMap`小部件来显示地图,并使用`MapOptions`来设置地图的中心点和缩放级别。我们还使用了`TileLayerOptions`来指定地图瓦片的URL模板,以及`MarkerLayerOptions`来添加标记点。 请注意,为了使用flutter_map插件,您还需要在`pubspec.yaml`文件中添加`latlong`的依赖项: ```yaml dependencies: latlong: ^0.6.1 ``` 这是一个简单的示例,您可以根据自己的需求进行更多的定制和功能扩展。希望对您有帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值