216 lines
7.0 KiB
Markdown
216 lines
7.0 KiB
Markdown
# 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<Segment>
|
||
→ 版本选择 (version.rs) → Version (1~40)
|
||
→ 比特流编码 (bitstream.rs) → Vec<u8> (data codewords)
|
||
→ RS 纠错编码 (reed_solomon.rs) → Vec<u8> (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**: 纯字符串拼接,无依赖,`<rect>` 逐模块
|
||
- **ASCII**: 终端输出,`██` / ` ` 双字符渲染,利用 Unicode 半方块实现近似正方形
|
||
|
||
## 5. CLI 接口
|
||
|
||
```
|
||
qrgen "content" [options]
|
||
|
||
Options:
|
||
-o, --output <FILE> 输出文件(.png/.svg),不指定则终端 ASCII
|
||
-l, --level <LEVEL> 纠错级别 L/M/Q/H [default: M]
|
||
-v, --version <VER> 手动指定版本 (1-40),不指定则自动
|
||
-s, --size <PX> 模块像素大小(PNG) [default: 4]
|
||
-m, --margin <N> 白边模块数 [default: 4]
|
||
--mode <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<Self>;
|
||
|
||
/// 导出为 PNG bytes
|
||
pub fn to_png(&self, module_size: u8) -> Vec<u8>;
|
||
|
||
/// 导出为 SVG 字符串
|
||
pub fn to_svg(&self) -> String;
|
||
|
||
/// 导出为 ASCII 字符串
|
||
pub fn to_ascii(&self, invert: bool) -> String;
|
||
|
||
/// 获取原始模块矩阵(供外部渲染使用)
|
||
pub fn modules(&self) -> &[Vec<bool>];
|
||
}
|
||
```
|
||
|
||
## 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 — 完整的命令行工具
|