- 前端
- 通信
【免费下载链接】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.js | Emscripten 生成的 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给出了两条路径的实际调用逻辑:
- 当裁剪区域(crop)带有上次解码成功的
quad与模块数dim时,先走readTracked——变换直接从四边形重建,网格直接采样,完全跳过检测阶段。注释记录基准测试结果:在 V40(版本 40 的 QR 码)上,单次解码比全量路径快2.0–2.6 倍,这省下的是手机端的 CPU 与发热; - 若跟踪命中失败,回落到同一缓冲区上的
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 的许可证陈述可以拆成三层:
- decimen-codec 自身:AGPL-3.0-or-later,与 decimen-optical-transfer 项目整体许可证一致(见仓库根目录 LICENSE)。这也意味着,如果你要在自己的项目里复用这份 vendored 构建,AGPL 的传染性条款需要纳入合规考量;
- 上游 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 全文的原因; - 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 解码器,有几点值得留意:
- 加载方式二选一:被托管部署可用
.wasm独立资源 + service worker 预缓存;单文件场景用build/inline-codec-wasm.ts的 Data URL 内联方案。两种方案在receive/下都有一一对应的实现可参考; - 运行时身份可校验:接入后调用
version()与build()即可确认构建来源,配合 banner 首行可做精确的版本审计; - 许可证边界:分发制品时需同时满足 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
相关推荐
Aptos 执行器(Executor)深入解析:从区块执行到状态提交的完整技术指南
Aptos 执行器(Executor)深入解析:从区块执行到状态提交的完整技术指南 导读 Aptos 是一条 Layer 1 区块链,其核心架构是一个 复制状态
前端通信Decimen Optical Transfer 架构解析:三页面、共享核心与单用途构建插件的无框架设计
Decimen Optical Transfer 架构解析:三页面、共享核心与单用途构建插件的无框架设计 本篇技术指南围绕 docs/technical/arc
前端通信如何快速切换游戏DLSS版本:DLSS Swapper让升级降级回退一步到位
如何快速切换游戏DLSS版本:DLSS Swapper让升级降级回退一步到位 游戏更新后画面开始闪烁、帧数莫名下滑,你折腾完驱动又调遍游戏内设置,最后才发现是它
桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考