匠心千刃 是张风捷特烈通过 Flutter 打造的 全平台 工具产品。基于 fx 应用框架和 tolyui 视图框架构建的软件应用。匠心千刃中对于需要大量计算的场景,将使用 Rust
语言来实现。
- 《Flutter&Rust#01 | 突破能力瓶颈》
- 《Flutter&Rust#02 | 图片灰度 - 性能提升!》
- 《Flutter&Rust#03 | 图片格式转换 jpeg/webp 》
- 《Flutter&Rust#04 | 图片编解码》
- 《Flutter&Rust#05 | 图片亮度调节》
- 《Flutter&Rust#06 | 图片亮度调节》 本文
本文介绍一下匠心千刃中的二维码图片识别。二维码已经和我们日常生活密不可分,乘车出行、消费付款、登录认证、扫描录入、分享信息、特别是疫情三年的健康码,让二维码充斥着电子生活的方方面面。
对于移动端来说,通过设备本身的后置镜头,可以非常方便地捕捉二维码图像进行识别。但对于桌面端或移动端本地的图片来说,识别二维码并不太方便。本文将借助 Rust 的能力,基于 Flutter 构建全平台的,图片二维码识别功能。
1. 交互界面
交互界面如下,用户选择一张图片二维码,然后应用会自动识别二维码中存储的信息。如下所示:
[1]
. 支持选择或拖拽拾取图片
[2]
. 图片选择成功之后,解析图片二维码,展示其中的文字信息
[3]
. 可以移除图片,继续选择其他图片识别
2. 核心识别能力
对图片二维码的识别能力将借助 Rust 的 能力。这里使用了 quircs 库
---->[rust/Cargo.toml]----
quircs = "=0.10.2"
rust 的代码实现也比较简单,通过 detection_qr
函数处理。输入一个文件路径,返回二维码中的字符串数据列表。
pub fn detection_qr(input: &str) -> Vec<String> {
let img = image::open(input).unwrap();
let img_gray = img.into_luma8();
let mut decoder = quircs::Quirc::default();
let codes = decoder.identify(img_gray.width() as usize, img_gray.height() as usize, &img_gray);
let mut ret: Vec<String> = Vec::new();
for code in codes {
let code = code.expect("failed to extract qr code");
let decoded = code.decode().expect("failed to decode qr code");
let str = std::str::from_utf8(&decoded.payload).unwrap().to_string();
ret.push(str);
}
ret
}
之所以是字符串数据列表,是因为一张图片中可能存在多个多个二维码。它们都可以被识别,如下所示:
通过 flutter_rust_bridge_codegen generate 命令,就可以生成对应的 Dart 桥接代码在 Flutter 中使用:
3. Flutter 视图层处理
需求的核心功能已经实现了,下面界面交互的界面处理就交给 Flutter 了。选择图片使用 file_picker 插件:触发下面的函数可以选择一张图片:
void _onTapSelect() async {
FilePickerResult? result = await FilePicker.platform.pickFiles(type: FileType.image);
if (result != null && result.files.isNotEmpty) {
String? path = result.files.first.path;
if (path != null) {
_onFileSelect(path);
}
}
}
另外,拖拽文件使用 desktop_drop 插件。将目标区域嵌套 DropTarget
组件,在 onDragDone
回调函数在可以感知对应文件的路径:
DropTarget(
child: child,
onDragEntered: (v) {},
onDragExited: (v) {},
onDragDone: (value) {
if(value.files.isNotEmpty){
String path = value.files.first.path;
_onFileSelect(path);
}
},
);
无论是点击选择还是拖拽选择,最终的结果都是得到一个图片文件路径,这个路径将成为向 Rust 传输的数据。如下所示,通过 detectionQr
方法得到结果数据,触发重新渲染即可:
void _onFileSelect(String path) async {
List<String> result = await detectionQr(input: path);
filename = p.basename(path);
_result = result.join('\n');
setState(() {});
}
4.尾声
总的来看,过程还是非常简单的。Flutter/Dart 端像是原料的提供商,Rust 则像加工厂,将原料加工完毕返回给 Flutter 渲染。
随着匠心千刃的后续研发,会遇到更多 Dart 和 Rust 桥接的知识。未来匠心千刃也会作为一个工具软件,供用户随意使用。更多精彩内容,敬请期待~
更多文章和视频知识资讯,大家可以关注我的公众号、掘金和 B 站 。