news 2026/10/9 7:44:56

decimen-optical-transfer 的 vendored 解码器:decimen-codec WASM 构建的许可证构成与运行时身份

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
decimen-optical-transfer 的 vendored 解码器:decimen-codec WASM 构建的许可证构成与运行时身份
  • 前端
  • 通信

【免费下载链接】decimen-optical-transfer

项目地址:https://gitcode.com/gh_mirrors/de/decimen-optical-transfer
点击查看免费下载

decimen-codec 是 decimen-optical-transfer 项目内置(vendored)的 QR 解码引擎:一份基于 zxing-cpp 定制编译的 WebAssembly 二进制,配套 embind 胶水与类型声明一起被提交在仓库的vendor/decimen-codec/目录下。它的NOTICE.md用十几行文字交代了这个构建的出处、身份标识和许可证构成,而它在仓库中的真实角色——一条被“跟踪”(tracked)的快速解码路径,以及两条被编译进 WASM 的读取 API——正是整个接收端吞吐设计的核心。本文以该 NOTICE 为骨架,结合仓库源码展开这份构建的身份、接入方式与许可证边界,帮助你快速判断能否在自己的项目里复用这份 vendored 制品。

一、它是什么:QR-only、reader-only 的定制 zxing-cpp 构建

NOTICE.md开门见山给出了三层定义:

  • compiled decoder:仓库 vendored 的不是源码而是编译产物,即vendor/decimen-codec/decimen_codec.wasm;
  • QR-only、reader-only:只保留 QR 码的读取(decode)能力,二维码生成(encoder)等无关能力被编译掉;
  • custom WebAssembly build of zxing-cpp:它基于 zxing-cpp 定制构建,且带有tracked decode path——一个为屏幕→相机这种“已知码大致位置”场景优化的快速解码路径;
  • small embind wrapper:通过 Emscripten 的 embind 导出一小组 JavaScript API,供上层调用。

在 decimen-optical-transfer 仓库里,这个构建不是可选依赖,而是接收端工作的核心:receive/worker.ts顶部注释明确写着“QR decode worker: the decimen-codec engine (a custom zxing-cpp build) compiled to WASM”,并解释了为什么要走 WASM:Safari 从未实现过BarcodeDetector(WebKit bug 281848),因此 WASM 是唯一可移植的 QR 解码途径。

二、它放在哪里:vendored 目录的四个文件

vendor/decimen-codec/目录下共四个文件,职责划分清晰:

文件职责
decimen_codec.wasm编译产物本体,解码引擎的二进制
decimen_codec.jsEmscripten 生成的 embind 胶水层,负责加载 WASM、导出 API
decimen_codec.d.ts手工编写的 TypeScript 类型声明,描述 embind API 的形状
NOTICE.md本篇文章的骨架文档:构建出处、身份与许可证构成
LICENSE.zxing-cpp上游 zxing-cpp 的 Apache-2.0 许可证全文

其中decimen_codec.d.ts开头注明“Source of truth:decimen-codec/wrapper/decimen_codec.cpp”,即类型声明的权威来源是 decimen-codec 上游仓库中的 C++ 包装器源码,本仓库这份.d.ts需要与其保持同步。

两个运行时身份标识:version() 与 build()

NOTICE 指出,“banner on the first line ofdecimen_codec.js”和模块的version()/build()运行时导出共同标识这个构建。类型声明给出了二者的确切语义:

  • version(): string—— 构建时的 decimen-codec package.json 版本号,例如"0.1.0";
  • build(): string—— 构建标识:git 短哈希,若从未提交(dirty)的源码树构建则带-dirty后缀。

这两个导出让接收端(或任何接入方)可以在运行时精确报告“我正在运行哪个版本的解码器”,这在诊断与回归定位中非常有用——docs/technical/diagnostics.md中的诊断运行报告会记录完整环境信息,其中就包括这类构建身份。

三、它如何被接入:两种 WASM 加载方式

receive/wasm-url.ts展示了被托管构建(served builds)的加载方式:

import wasmUrl from "../vendor/decimen-codec/decimen_codec.wasm?url"; export default wasmUrl;

即把.wasm作为独立资源(asset)打包,由 service worker 预缓存;而独立单文件构建(standalone builds)则换成receive/wasm-url.inline.ts对应的内联方案。

内联方案的实现位于build/inline-codec-wasm.ts:由于 Vite 的?inline对.wasm不生效(Vite 会接管该扩展名并让 Rollup 把二进制当 JavaScript 解析),该 Vite 插件改用虚拟模块virtual:codec-wasm-data-url,把vendor/decimen-codec/decimen_codec.wasm读入并编码为data:application/wasm;base64,的 Data URL 导出。这样独立页面可以完全自包含,不依赖外部文件。

在 worker 内部,模块初始化通过locateFile把.wasm重定向到上述 URL:

const ready: Promise<DecimenModule> = DecimenCodec({ locateFile: (path: string, prefix: string) => (path.endsWith(".wasm") ? wasmUrl : prefix + path), });

四、它导出什么:readFull 与 readTracked 双路径

decimen_codec.d.ts完整描述了 embind 导出面,除version()/build()外,核心是两条读取 API 与若干调试 API:

API签名要点用途
readFull(ptr, width, height, tryHarder, maxSymbols, returnErrors) → DecimenResultVector全帧扫描:完整检测流程,可配置 tryHarder、符号数上限与是否返回错误结果
readTracked(ptr, width, height, dim, x0..y3) → DecimenResult跟踪路径:跳过检测,用缓存的四边形 + 模块数直接重建变换、采样网格
trackedMatrix同 readTracked 参数 →Uint8Array \| null调试:原始采样的模块网格(dim×dim,行主序 0/1)
projectPoint四边形 + 模块空间点 →{x, y, valid}调试:把模块空间点投影回图像坐标
binarizedRow(ptr, width, height, y) → Uint8Array \| null调试:二值化矩阵的某一行(每像素 0/1)

相关数据结构包括DecimenPoint(x/y)、DecimenQuad(四个角点,即 topLeft/topRight/bottomRight/bottomLeft)、DecimenResult(valid、error、bytes、position、modules,其中 modules 表示符号的模块数,17 + 4·version,未知时为 0)以及DecimenResultVector(size()/get()/delete(),模拟 C++ 端返回的 vector)。

两条路径的协作:跟踪优先,全量兜底

receive/worker.ts给出了两条路径的实际调用逻辑:

  1. 当裁剪区域(crop)带有上次解码成功的quad与模块数dim时,先走readTracked——变换直接从四边形重建,网格直接采样,完全跳过检测阶段。注释记录基准测试结果:在 V40(版本 40 的 QR 码)上,单次解码比全量路径快2.0–2.6 倍,这省下的是手机端的 CPU 与发热;
  2. 若跟踪命中失败,回落到同一缓冲区上的readFull全量扫描,同时用其结果重新锚定四边形。跟踪是机会主义的,从不承担成败(“Tracked is opportunistic, never load-bearing”)。

全量扫描的调用参数同样值得注意:

const vec = zx.readFull(ptr, pw, ph, true, full ? 12 : 2, full);

即 tryHarder 始终开启(“real marginal captures are where it earns its keep”);全帧扫描允许最多 12 个符号、裁剪扫描只允许 2 个(因为错误结果也计入符号数上限,见注释“error results COUNT against the symbol cap, hence the headroom above 9 codes”);returnErrors在全帧模式下开启,使 zxing 检测到但解码失败的符号仍返回位置信息——ChecksumError等错误结果里的位置依然像素级准确,接收端据此在下一帧对准裁剪框,实现“全帧失败处,裁剪解码成功”。

解码流程以 RGBA 像素为输入:worker 通过_malloc在 WASM 堆分配width×height×4字节,用HEAPU8.set拷入像素后调用读取 API,结束后_free释放。像素可以来自两种捕获模式——跨线程传输的 ArrayBuffer(readback 回退方案)或 ImageBitmap(GPU 侧裁剪,Safari 17+/现代浏览器),后者的好处是主线程完全不碰像素。

预热(warm-up)设计

worker 启动后会用一块 8×8 的全白像素调用一次readFull再丢弃结果,目的是完成 WASM 实例化与首次调用的 JIT,避免真实第一帧为此付出延迟。池(worker pool)通过{id: -1}的 ping 消息忽略这次预热。

五、许可证构成:AGPL 主框架,Apache-2.0 与 MIT 的夹层

NOTICE 的许可证陈述可以拆成三层:

  1. decimen-codec 自身:AGPL-3.0-or-later,与 decimen-optical-transfer 项目整体许可证一致(见仓库根目录 LICENSE)。这也意味着,如果你要在自己的项目里复用这份 vendored 构建,AGPL 的传染性条款需要纳入合规考量;
  2. 上游 zxing-cpp:Apache License, Version 2.0,NOTICE 特别注明 zxing-cpp 是“unmodified”(未修改)——在 decimen-codec 上游源码仓库中以固定版本(pinned submodule)引入。Apache-2.0 与 AGPL-3.0 可以并存,但前者要求再分发时保留其 NOTICE 文本,这正是仓库在vendor/decimen-codec/下保留 LICENSE.zxing-cpp 全文的原因;
  3. Emscripten 运行时输出:MIT-licensed。decimen_codec.js胶水由 Emscripten 生成,Emscripten 的运行时输出以 MIT 许可发布,这是构建链中最宽松的一层。

仓库根目录的 NOTICE 文件对整份制品做了汇总:vendored decimen-codec 构建位于vendor/decimen-codec,AGPL-3.0-or-later,源码维护在 decimen-codec 上游仓库;zxing-cpp 以 Apache-2.0 并入。另外 README.md 的 License 一节还补充了一个项目层面的历史细节:decimen-optical-transfer 自 v0.4.0 起采用 AGPL-3.0-or-later,v0.3.0 及之前的版本曾以 MIT 发布且仍保留原条款。

六、对复用者的三点提示

基于以上源码证据,如果你打算在自己项目中接入这份 vendored 解码器,有几点值得留意:

  1. 加载方式二选一:被托管部署可用.wasm独立资源 + service worker 预缓存;单文件场景用build/inline-codec-wasm.ts的 Data URL 内联方案。两种方案在receive/下都有一一对应的实现可参考;
  2. 运行时身份可校验:接入后调用version()与build()即可确认构建来源,配合 banner 首行可做精确的版本审计;
  3. 许可证边界:分发制品时需同时满足 AGPL-3.0-or-later(decimen-codec 与项目整体)、Apache-2.0(zxing-cpp,保留 NOTICE 文本)与 MIT(Emscripten 运行时输出)三套条款——这正是 vendor/decimen-codec/NOTICE.md 与 LICENSE.zxing-cpp 必须随制品一起分发的根本原因。

如需进一步了解解码器在接收链路中的具体角色与基准测试方法,可继续阅读 docs/technical/architecture.md、docs/technical/diagnostics.md 与receive/worker.ts。

  • 前端
  • 通信

【免费下载链接】decimen-optical-transfer

项目地址:https://gitcode.com/gh_mirrors/de/decimen-optical-transfer
点击查看免费下载

相关推荐

上一篇:Pandoc 转 Typst 引文语法映射:从 pandoc 引用到 Typst 引用标记
下一篇:AI_NovelGenerator 实战指南:基于大语言模型的多章节长篇小说生成全流程

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/9 7:44:47

Android开发环境搭建全攻略:JDK/SDK/Gradle配置与实战

1. 开篇&#xff1a;这个系列要做什么&#xff0c;环境为什么值得单独讲一课做啥子嘛&#xff0c;这四个字是四川话里特别日常的一句&#xff0c;意思就是"做什么呢""干嘛呢"。拿它当项目名&#xff0c;是因为这个系列要做的APP本身就是一个帮你解决"…

作者头像 李华
网站建设 2026/10/9 7:43:21

【Jetpack Compose基础语法学与练】第2课 State状态 + 点击交互

前言 上一节课我们完成最简HelloWorld&#xff0c;认识了 Composable 可组合函数、预览注解。 Compose声明式UI的核心&#xff1a;界面跟随状态自动更新。 本课重点学习状态定义、记忆状态、按钮点击事件&#xff0c;打通「状态‑重组‑界面刷新」完整闭环。 前置&#xff1a;完…

作者头像 李华
网站建设 2026/10/9 7:43:00

Maven从下载到配置全流程:环境变量、镜像加速与避坑指南

用过Java的人都绕不开Maven&#xff0c;但能把Maven顺顺利利装到本地的人&#xff0c;我还真没见过几个。多数人卡住的第一个环节就是“下载”&#xff0c;别笑&#xff0c;这个看似简单的步骤里全是坑&#xff1a;官网慢得像蜗牛、下载到一半断掉、好不容易下完了发现跟JDK版本…

作者头像 李华
网站建设 2026/10/9 7:41:22

基于遗传算法与粒子群算法的智能车动态避障路径规划技术深度学习实战python数据分析与可视化

1.2.2 国外研究现状国外对智能车路径规划技术的研究起步较早&#xff0c;早在20世纪80年代就已经开展了相关的研究工作。卡内基梅隆大学、麻省理工学院、斯坦福大学等高校是该领域的先驱&#xff0c;谷歌、特斯拉、通用汽车等公司也投入了大量资源进行相关技术的研发。在传统路…

作者头像 李华
网站建设 2026/10/9 7:39:48

855协议五端学习版源码解析:从握手到联调避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华