Files
QRGen/README.md
T
Serendipity 7f3b8b4cc7 docs: 更新全部 markdown 文档 — v0.3.0
- README: 测试数 81、输出格式表 + vCard 10字段、透视矫正、格式扩展
- CHANGELOG: v0.3.0 条目(格式扩展+解码增强+vCard扩展)
- ROADMAP: v0.2.0/v0.3.0 移至已交付,更新下一版本规划
- CLAUDE.md: 测试 81→105、perspective.rs 模块、Web fmt 参数
2026-06-19 21:41:49 +08:00

375 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<p align="center">
<h1>🀫 QRGen</h1>
<p>从零手搓的 QR 码生成/解码器 — ISO/IEC 18004 完整实现</p>
</p>
<p align="center">
<img src="https://img.shields.io/badge/version-0.1.0-blue" alt="version">
<img src="https://img.shields.io/badge/rust-1.95-000000" alt="rust">
<img src="https://img.shields.io/badge/tauri-2.x-ffa03a" alt="tauri">
<img src="https://img.shields.io/badge/react-18-61dafb" alt="react">
<img src="https://img.shields.io/badge/axum-0.8-ff6b35" alt="axum">
<img src="https://img.shields.io/badge/docker-ready-2496ed" alt="docker">
<img src="https://img.shields.io/badge/license-MIT-green" alt="license">
<img src="https://img.shields.io/badge/tests-81%20passed-brightgreen" alt="tests">
<img src="https://img.shields.io/badge/clippy-clean-brightgreen" alt="clippy">
<img src="https://img.shields.io/badge/prettier-formatted-ff69b4" alt="prettier">
<img src="https://img.shields.io/badge/eslint-checked-4b32c3" alt="eslint">
<img src="https://img.shields.io/badge/vitest-12%20passed-brightgreen" alt="vitest">
</p>
---
## 简介
QRGen 是 **从零手写** 的 QR 码(二维码)生成/解码器,完整实现 ISO/IEC 18004 国际标准。不依赖任何第三方 QR 编码/解码库,所有算法(Galois 域运算、Reed-Solomon 纠错编解码、BCH 格式编解码、掩码评分、定位检测)均从底层手搓。
支持 **四种使用方式**:程序库(`qr-core`)、命令行(`qrgen`)、桌面 GUI`qrgen-gui`)、Web 服务(`qrgen-web`)。支持**编码**(文本→QR)和**解码**(QR→文本)双向闭环。
## 架构
```mermaid
graph TB
subgraph Frontend["React 前端 (GUI)"]
App[App.tsx 三栏布局]
Modes[7 种模式表单]
Preview[实时预览区]
Export[导出面板]
History[历史记录]
App --> Modes
App --> Preview
App --> Export
App --> History
end
subgraph Web["Web 服务 (axum)"]
HTML[内嵌 HTML 页面]
API[GET /api/qr + POST /api/decode]
end
subgraph CLI["CLI 命令行"]
Clap[clap 编码 + --decode 解码]
end
subgraph IPC["Tauri IPC 桥接"]
Commands[6 个 Tauri commands]
end
subgraph Core["Rust core 库 (qr-core)"]
Encoder[编码层]
Decoder[解码层]
ECC[纠错层]
Matrix[矩阵层]
Render[渲染层]
Encoder --> ECC
Decoder --> ECC
ECC --> Matrix
Matrix --> Render
end
Modes --> Commands
Commands --> Encoder
Clap --> Encoder
HTML --> API
API --> Encoder
```
### 数据流水线
```mermaid
sequenceDiagram
actor U as 用户
participant UI as React UI / CLI / Web
participant Q as QrCode::encode()
participant E as 编码器
participant RS as Reed-Solomon
participant M as 矩阵布局
participant R as 渲染器
U->>UI: 输入文本
UI->>Q: encode(text, config)
Q->>E: 分析字符集, 自动分段
E->>E: 模式编码
E->>RS: 数据码字
RS->>RS: 纠错码字生成 + 交错
RS->>M: 最终码字序列
M->>M: 功能图案 + 蛇形排列 + 掩码
M->>R: QR 矩阵
R->>UI: PNG / SVG / ASCII
Note over U,R: --- 解码流水线 (逆向) ---
U->>UI: 上传图片
UI->>Q: decode_image(bytes)
Q->>R: 图像二值化 + 定位图案检测
R->>M: 布尔矩阵
M->>M: 读取格式/版本信息 + 解掩码 + 蛇形提取
M->>RS: 数据码字 + 纠错码字
RS->>RS: 去交错 + 伴随式 + Berlekamp-Massey + Chien + Forney
RS->>E: 纠错后数据码字
E->>E: 模式解码(数字/字母/字节/汉字)
E->>UI: 解码文本
```
## 功能
### 核心算法(全部手写)
| 模块 | 内容 | 说明 |
|------|------|------|
| Galois 域 | GF(2⁸) 四则运算 + 幂运算 | 预计算 exp/log 表,本原多项式 0x11D |
| Reed-Solomon | RS 纠错码生成 + 数据交错 | 生成多项式动态构造,多项式长除法 |
| 编码模式 | 数字 / 字母数字 / 字节 / 汉字 | 4 种模式,自动分段选最优 |
| 矩阵布局 | 定位/对齐/时序图案 + 蛇形排列 | 8 种掩码 + 四规则惩罚评分 |
| BCH 编码 | 格式信息 BCH(15,5) + 版本信息 BCH(18,6) | 两级纠错保护 |
| 版本容量 | 40 版本 × 4 纠错级别完整参数表 | 自动版本选择 |
### CLI 命令行
```bash
# 终端 ASCII 预览
qrgen "Hello World"
# 生成 PNG
qrgen "https://example.com" -o qr.png -s 8
# 生成 SVG(高纠错)
qrgen "重要数据" -o qr.svg -l H
# 解码 QR 码图片
qrgen --decode qr.png
```
### GUI 桌面应用
- **7 种编码模式**:文本 / URL / WiFi / vCard(10字段) / Email / 电话 / SMS
- **解码**:选择图片文件,解码 QR 码为文本
- **实时预览**200ms 防抖,PNG 即时渲染
- **多格式导出**:PNG(可调模块大小)/ SVG / 复制到剪贴板
- **历史记录**:最近 50 条,点击回填,支持删除和清空
- **暗色模式**:跟随系统,磨砂玻璃效果
- **纠错级别可调**L (7%) / M (15%) / Q (25%) / H (30%)
### Web 服务
- **内嵌 HTML 界面**:复刻 GUI 三栏布局,7 种编码模式
- **REST API**`GET /api/qr` → PNG / SVG`POST /api/decode` → 上传图片返回文本
- **Docker 部署**17.7MB Alpine 镜像,开箱即用
## 安装
### 从源码构建
```bash
git clone git@lhy-git.liuhangyv.top:Serendipity/QRGen.git
cd QRGen
# 安装前端依赖
cd gui/src-frontend && pnpm install && cd ../..
# CLI
cargo build --release -p qrgen
# Web 服务
cargo build --release -p qrgen-web
# GUI + NSIS 安装包
cd gui/src-frontend && pnpm build && cd ../..
cd gui && src-frontend/node_modules/.bin/tauri.cmd build
```
> **要求**Windows 10+GUI 需 WebView2),Rust 1.95+Node.js 22+
### DockerWeb 服务)
```bash
# 拉取镜像(或本地构建)
docker build -t qrgen-web -f web/Dockerfile .
# 运行
docker run -d --name qrgen-web --restart unless-stopped -p 3000:3000 qrgen-web
# docker-compose
# 见 G:\qrgen-web\docker-compose.yamlNAS 部署用)
```
## 开发
```bash
# 开发模式 GUI(热更新)
cd gui/src-frontend && pnpm dev # 终端1: 前端
cargo run -p qrgen-gui # 终端2: Rust 后端
# CLI 开发
cargo run -p qrgen -- "Hello World"
# Web 开发
cargo run -p qrgen-web # → http://localhost:3000
# Rust 测试
cargo test --lib # 81 unit
# 前端测试
cd gui/src-frontend && pnpm test # vitest
# 前端类型检查
cd gui/src-frontend && pnpm tsc --noEmit
# Rust lint
cargo clippy -- -D warnings
# 前端代码检查
cd gui/src-frontend && pnpm lint # eslint
cd gui/src-frontend && pnpm format:check # prettier
# Git hooks(提交前自动运行)
# pre-commit: lint-stagedprettier + eslint
# commit-msg: commitlintConventional Commits
```
### 技术栈
| 层 | 技术 |
|---|---|
| 桌面框架 | Tauri 2.x |
| GUI 前端 | React 18 + TypeScript (strict) |
| UI 样式 | TailwindCSS 3 |
| 状态管理 | React Context + useReducer |
| Web 服务 | axum 0.8 + tokio |
| 核心库 | Rust (qr-core) |
| CLI | clap + anyhow |
| 前端包管理 | pnpm |
| 桌面打包 | NSIS |
| 容器化 | Docker (alpine, 17.7MB) |
### 项目结构
```
QRGen/
├── core/ # Rust 核心库(算法全部在此)
│ └── src/
│ ├── qr.rs # 顶层 API — QrCode::encode()
│ ├── version.rs # 40 版本容量表 + 自动选择
│ ├── ecc/
│ │ ├── galois.rs # GF(2⁸) 运算 + exp/log 表
│ │ └── reed_solomon.rs # RS 纠错码 + 数据交错
│ ├── decoder/ # QR 解码器(从零手写)
│ │ ├── mod.rs # 顶层 APIdecode_image + decode_matrix
│ │ ├── bch.rs # BCH(15,5)+BCH(18,6) 查表解码
│ │ ├── format.rs # 格式信息 + 版本信息读取
│ │ ├── extract.rs # 逆向蛇形排列提取码字
│ │ ├── deinterleave.rs # 逆向 RS 数据交错
│ │ ├── rs_decode.rs # RS 纠错(伴随式→BM→Chien→Forney
│ │ ├── mode_decode.rs # 逆向 4 种编码模式
│ │ ├── detect.rs # 定位图案检测 + 采样网格
│ │ └── image.rs # 图像加载 + 二值化
│ ├── encoder/
│ │ ├── mode.rs # 4 种编码模式
│ │ ├── segment.rs # 字符串分段
│ │ └── bitstream.rs # 比特流拼接
│ ├── matrix/
│ │ ├── grid.rs # 模块矩阵
│ │ ├── patterns.rs # 定位/对齐/时序图案 + BCH 码
│ │ ├── placement.rs # 蛇形数据排列
│ │ └── mask.rs # 8 掩码 + 四规则评分
│ └── render/
│ ├── png.rs # PNG 输出 (image crate)
│ ├── svg.rs # SVG 输出
│ └── ascii.rs # 终端 ASCII
├── cli/ # CLI 命令行工具
│ └── src/main.rs # clap 参数解析
├── gui/ # Tauri 桌面应用
│ ├── capabilities/default.json # ACL 权限
│ ├── src/
│ │ ├── main.rs # Windows 子系统入口
│ │ └── lib.rs # 6 个 Tauri commands
│ ├── src-frontend/ # React 前端
│ │ └── src/
│ │ ├── App.tsx # 主布局(三栏+底部输入)
│ │ ├── components/ # ModePanel / QrPreview / ExportPanel / HistoryList
│ │ ├── modes/ # 7 种模式表单
│ │ ├── hooks/ # useQrEncode(防抖+编码)
│ │ ├── store/ # Context + useReducer
│ │ ├── types/ # TypeScript 类型
│ │ └── utils/ # qrText.ts 文本构造工具
│ └── tauri.conf.json # 窗口 + NSIS 打包配置
├── web/ # Web 服务
│ ├── Dockerfile # rust-alpine 多阶段构建
│ └── src/
│ ├── main.rs # axum HTTP 服务
│ └── templates/
│ └── index.html # 内嵌 GUI 风格页面
├── .dockerignore
└── Cargo.toml # Workspace: core + cli + gui + web
```
## 支持规格
| 维度 | 范围 |
|------|------|
| QR 版本 | 1 ~ 4021×21 ~ 177×177 模块) |
| 纠错级别 | L (7%) / M (15%) / Q (25%) / H (30%) |
| 编码模式 | 数字 / 字母数字 / 字节 / 汉字 (Shift JIS) |
| 输出格式 | PNG / BMP / JPEG / WebP / SVG / 终端 ASCII |
| vCard 字段 | 姓名/电话/邮箱/公司/职位/地址/网址/生日/备注/照片 (10 字段) |
| 使用方式 | Library / CLI / GUI / Web API |
| 解码 | 从图片识读 QR 码 → 文本(支持旋转矫正) |
| 自动版本选择 | 根据数据长度 + 纠错级别 |
| Docker 镜像 | ~18MB (alpine) |
## 代码示例
`examples/` 目录包含三个示例:
```bash
# 基础编码(默认配置)
cargo run --example basic_qr
# 高纠错级别(H 级,30% 容错)
cargo run --example high_ecc
# 自定义配置(固定版本 + 大尺寸 PNG)
cargo run --example custom_config
```
作为程序库使用(编码 + 解码):
```rust
use qr_core::qr::{QrCode, QrConfig};
use qr_core::decoder;
// 编码:文本 → QR
let qr = QrCode::encode("Hello QR!", QrConfig::default())?;
qr.to_png_bytes(8)?; // PNG 字节
let svg = qr.to_svg(); // SVG 字符串
// 解码:QR 图片 → 文本
let bytes = std::fs::read("qr.png")?;
let result = decoder::decode_image(&bytes)?;
println!("解码结果: {}", result.text);
```
## 发布到 crates.io
`qr-core` 可作为 Rust 库被其他项目引用:
```bash
cargo add qr-core
```
## 社区
- [贡献指南](CONTRIBUTING.md) — 如何参与开发
- [行为准则](CODE_OF_CONDUCT.md) — 社区规范
- [安全策略](SECURITY.md) — 漏洞报告流程
- [变更日志](CHANGELOG.md) — 版本历史
- [Issue 模板](.github/ISSUE_TEMPLATE/) — Bug 报告 / 功能请求
## 许可证
MIT License
## 作者
[刘航宇](https://github.com/LHY0125) — 河南理工大学人工智能协会