# QR 码生成器 — 设计文档 **日期**: 2026-06-16 **作者**: 刘航宇 **语言**: Rust **项目路径**: `D:\Code\doing_exercises\programs\QRGen\` ## 1. 项目概述 从零实现 ISO/IEC 18004 QR 码生成器,不依赖任何第三方 QR 编码库。算法全手写, 输出 PNG / SVG / 终端 ASCII。后续扩展 Tauri GUI。 ## 2. 支持范围 | 维度 | 范围 | |------|------| | **QR 版本** | 1~40(21×21 ~ 177×177 模块) | | **纠错级别** | L (7%), M (15%), Q (25%), H (30%) | | **编码模式** | 数字 / 字母数字 / 字节 / 汉字 (Shift JIS) | | **输出格式** | PNG(`image` crate)、SVG、终端 ASCII | | **自动版本选择** | 根据数据长度 + 纠错级别自动选最小版本 | ## 3. 项目结构 ``` QRGen/ ├── Cargo.toml # workspace: core + cli ├── core/ # 纯算法库,尽量零依赖 │ ├── Cargo.toml │ └── src/ │ ├── lib.rs │ ├── qr.rs # 顶层 API │ ├── version.rs # 版本参数表 (40 行硬编码) │ ├── encoder/ │ │ ├── mod.rs │ │ ├── mode.rs # 编码模式定义 │ │ ├── segment.rs # 数据分段与模式选择 │ │ └── bitstream.rs # 比特流拼接 │ ├── ecc/ │ │ ├── mod.rs │ │ ├── galois.rs # GF(2⁸) 运算 + 预计算表 │ │ └── reed_solomon.rs # RS 纠错码生成 │ ├── matrix/ │ │ ├── mod.rs │ │ ├── grid.rs # 模块网格数据结构 │ │ ├── patterns.rs # 定位/对齐/时序图案 │ │ ├── placement.rs # 数据字节蛇形排列 │ │ └── mask.rs # 8 种掩码 + 评分 │ └── render/ │ ├── mod.rs │ ├── png.rs # PNG 渲染 (image crate) │ ├── svg.rs # SVG 渲染 │ └── ascii.rs # 终端 ASCII 渲染 ├── cli/ # CLI 工具 │ ├── Cargo.toml │ └── src/ │ └── main.rs └── docs/ └── superpowers/specs/ ``` ## 4. 数据流水线 ``` 输入字符串 → 数据分析 (mode.rs + segment.rs) → Vec → 版本选择 (version.rs) → Version (1~40) → 比特流编码 (bitstream.rs) → Vec (data codewords) → RS 纠错编码 (reed_solomon.rs) → Vec (final sequence) → 模块布局 (matrix/) → Matrix (bitmap) → 掩码评分 (mask.rs) → Matrix (best mask) → 渲染输出 (render/) → PNG / SVG / ASCII ``` ### 4.1 数据分析 1. 扫描输入字符串,分析字符集 2. 根据字符分布选择最优编码模式(混合内容自动分段) 3. 每段包含:模式指示符 + 字符计数 + 编码数据 ### 4.2 版本选择 硬编码 ISO 18004 附录中的容量表(40 版本 × 4 纠错级别), 根据总比特数查表选最小合适版本。用户可手动覆盖。 ### 4.3 比特流编码 - 各段按模式规则编码为比特 - 添加终止符(最多 4 bit) - 补零到 8-bit 边界 - 填充码字 0xEC/0x11 交替至满容量 ### 4.4 RS 纠错编码 - GF(2⁸) 基于 `x⁸ + x⁴ + x³ + x² + 1` (0x11D) - 预计算 exp/log 表加速乘除法 - 生成多项式动态构造 - 多项式长除法求余数(纠错码字) ### 4.5 模块布局 1. 绘制空白矩阵 2. 放置定位图案(3 个角) 3. 放置对齐图案(版本相关数量) 4. 放置时序图案 + 暗模块 5. 保留格式信息区域(15 bit) 6. 保留版本信息区域(版本 ≥ 7,18 bit) 7. 按蛇形路径填入数据比特 8. 尝试 8 种掩码,对每种: - 计算格式信息 - 若版本 ≥ 7 计算版本信息 - 评分 9. 选最低惩罚分掩码,写入最终格式/版本信息 ### 4.6 掩码评分规则 | 规则 | 条件 | 惩罚 | |------|------|------| | 规则 1 | 连续 5+ 同色行/列 | N1 + k-5 | | 规则 2 | 同色 2×2 方块 | 每块 +3 | | 规则 3 | `1011101` 模式 | 每次 +40 | | 规则 4 | 暗模块占比偏离 50% | 每 5% +10 | ### 4.7 渲染输出 - **PNG**: 依赖 `image` crate,逐模块像素填充,可调模块大小 + 白边 - **SVG**: 纯字符串拼接,无依赖,`` 逐模块 - **ASCII**: 终端输出,`██` / ` ` 双字符渲染,利用 Unicode 半方块实现近似正方形 ## 5. CLI 接口 ``` qrgen "content" [options] Options: -o, --output 输出文件(.png/.svg),不指定则终端 ASCII -l, --level 纠错级别 L/M/Q/H [default: M] -v, --version 手动指定版本 (1-40),不指定则自动 -s, --size 模块像素大小(PNG) [default: 4] -m, --margin 白边模块数 [default: 4] --mode 强制编码模式 [auto] --invert 反色 -h, --help 帮助 ``` 示例: ```bash qrgen "https://example.com" # 终端 ASCII qrgen "hello" -o qr.png -s 10 # 大模块 PNG qrgen "data" -o qr.svg -l H # SVG, 高纠错 qrgen "12345" --mode numeric -v 5 # 纯数字, 版本5 ``` ## 6. 核心 API(core/lib.rs) ```rust pub struct QrConfig { pub level: EcLevel, // 默认 M pub version: VersionMode, // 默认 Auto pub mode: ModeHint, // 默认 Auto(混合自动分段) pub margin: u8, // 默认 4 } pub enum VersionMode { Auto, Fixed(u8), } pub struct QrCode { // 内部持有最终的 Matrix + 版本/级别元数据 } impl QrCode { /// 编码字符串,失败返回 Err pub fn encode(text: &str, config: QrConfig) -> Result; /// 导出为 PNG bytes pub fn to_png(&self, module_size: u8) -> Vec; /// 导出为 SVG 字符串 pub fn to_svg(&self) -> String; /// 导出为 ASCII 字符串 pub fn to_ascii(&self, invert: bool) -> String; /// 获取原始模块矩阵(供外部渲染使用) pub fn modules(&self) -> &[Vec]; } ``` ## 7. 测试策略 | 层级 | 内容 | 覆盖率目标 | |------|------|-----------| | **单元测试** | GF(2⁸) 运算、RS 编码、模式编码、掩码评分 | ≥ 80% | | **集成测试** | 已知字符串 → 生成的 PNG 被 zxing 解码验证 | 关键路径 | | **回归测试** | 固定输入 → 固定矩阵黄金数据(标准附录参考值) | 关键算法 | | **属性测试** | 随机字符串 → 编码解码往返 | 可选 | ## 8. 不实现的范围(明确排除) - Micro QR Code - QR Code 解码(本项目只管生成) - 结构化附加(Structured Append) - FNC1 模式 - ECI 编码指示符 - 艺术 QR 码(带 logo 嵌入等) ## 9. 里程碑 1. **M1**: GF(2⁸) + Reed-Solomon — 最核心算法 2. **M2**: 编码 + 比特流 — 能产出有效码字序列 3. **M3**: 矩阵布局 + 掩码 — 能产出完整 QR 矩阵 4. **M4**: 渲染输出 — PNG + SVG + ASCII 5. **M5**: CLI — 完整的命令行工具