如何使用肉眼读取一张二维码
二维码概述
结构
以版本6为例,一张二维码的基本结构可为如下图
其中红色部分为定位图案,绿色区为保留空间,橙色部分为时序图案,始终是黑白相间的,蓝色部分为格式信息,左上角一个和左下角半个与右上角半个,这两个表达的信息是相同的
版本
共有 40 个版本,大小随着版本号增加而增加
格式信息
构成
由15位组成
1-2位为纠错等级:
| 等级 | 二进制 |
|---|---|
| Low | 01 |
| Medium | 00 |
| Quartile | 11 |
| High | 10 |
3-5位为掩码信息:
| 掩码模式 | 计算公式 |
|---|---|
| 000 | (x + y) % 2 |
| 001 | x % 2 |
| 010 | y % 3 |
| 011 | (x + y) % 3 |
| 100 | (x / 2 + y / 3) % 2 |
| 101 | (x * y) % 2 + (x * y) % 3 |
| 110 | ((x * y) % 2 + (x * y) % 3) % 2 |
| 111 | ((x + y) % 2 + (x * y) % 3) % 2 |
6-15位为纠错信息,用不上,不读
使用101010000010010进行异或处理后即为在二维码中看到的样子
读取
如图橙线所框位置,从左往右读
实践
1 | 10101 |
对表,可知等级为 M(00),掩码为 0
版本信息
构成
当版本>=7时,加入了版本信息区域,放置在下图的蓝色位置:
每个版本都有固定的图案,用于识别版本,我们用不上,因为可以直接数
编码区读取方式
如图所示,以二维码右下角为起始,沿着线读,绕过功能区域和格式信息区域,并“穿过”垂直时序图案,并且当版本>=7时,要注意绕过版本信息区
编码模式
构成
由 4 位组成,
| 编码模式 | 二进制 |
|---|---|
| ECI | 0111 |
| Numeric | 0001 |
| Alphanumeric | 0010 |
| Byte(8-bit ) | 0100 |
| Kanji | 1000 |
| Structured Append | 0011 |
| FNC1(1) | 0110 |
| FNC(2) | 1001 |
读取
位于编码区的起始 4 个模块,按上文提到的方式读取
实践
1 | 读取:1101 |
可得为 Byte(8-bit) 模式
正文长度
构成
与编码模式和版本大小有关,以字节编码为例
在版本1-7中,为 8 个 bit
在版本>=7中,为 16 个 bit
实践
以版本 1-7 为例
1 | 读取:10011111 |
正文部分
读取
以 1 个数据分块,Byte 模式为例
跳过编码模式以及正文长度后的 12 个模块,按上文提到的方式读取
实践
读取:11111000
掩码:10011001
结果:01100001
解码:a
数据分块与交织
数据分块
数据分块会将二维码数据分成几个相同长度的块,其数量与二维码版本和纠错等级有关,下表展现了这两者的数量关系:
| Level/Version | Low | Medium | Quartile | High |
|---|---|---|---|---|
| 1 | 1 | 1 | 1 | 1 |
| 2 | 1 | 1 | 1 | 1 |
| 3 | 1 | 1 | 2 | 2 |
| 4 | 1 | 2 | 2 | 4 |
| 5 | 1 | 2 | 4 | 4 |
| 6 | 2 | 4 | 4 | 4 |
| 7 | 2 | 4 | 6 | 5 |
| 8 | 2 | 4 | 6 | 6 |
| 9 | 2 | 5 | 8 | 8 |
| 10 | 4 | 5 | 8 | 8 |
| 11 | 4 | 5 | 8 | 11 |
| 12 | 4 | 8 | 10 | 11 |
| 13 | 4 | 9 | 12 | 16 |
| 14 | 4 | 9 | 16 | 16 |
| 15 | 6 | 10 | 12 | 18 |
| 16 | 6 | 10 | 17 | 16 |
| 17 | 6 | 11 | 16 | 19 |
| 18 | 6 | 13 | 18 | 21 |
| 19 | 7 | 14 | 21 | 25 |
| 20 | 8 | 16 | 20 | 25 |
| 21 | 8 | 17 | 23 | 25 |
| 22 | 9 | 17 | 23 | 34 |
| 23 | 9 | 18 | 25 | 30 |
| 24 | 10 | 20 | 27 | 32 |
| 25 | 12 | 21 | 29 | 35 |
| 26 | 12 | 23 | 34 | 37 |
| 27 | 12 | 25 | 34 | 40 |
| 28 | 13 | 26 | 35 | 42 |
| 29 | 14 | 28 | 38 | 45 |
| 30 | 15 | 29 | 40 | 48 |
| 31 | 16 | 31 | 43 | 51 |
| 32 | 17 | 33 | 45 | 54 |
| 33 | 18 | 35 | 48 | 57 |
| 34 | 19 | 37 | 51 | 60 |
| 35 | 19 | 38 | 53 | 63 |
| 36 | 20 | 40 | 56 | 66 |
| 37 | 21 | 43 | 59 | 70 |
| 38 | 22 | 45 | 62 | 74 |
| 39 | 24 | 47 | 65 | 77 |
| 40 | 25 | 49 | 68 | 81 |
交织特性
当块的数量大于 1 时,交织特性会体现出来,各个块的数据将会被交叉在一起
假如一个字符串被分为两个块的内容如下:
1 | 块1:ABCDEFG... |
那么交织后的内容应该是这样子的:
1 | AaBbCcDdEeFfGg... |
解交织
逆向操作就行,例如这里有 4 个块交织起来:
1 | 你但是放说是一性的原款游对神开戏 |
分离:
1 | 你说的对 |
拼接:
1 | 你说的对但是原神是一款开放性游戏 |
但是这样读有个缺点,每到下一个块时,就要重新开始读,怎么办呢?
这里有个很简单的办法解决这个问题,我们直接每 4 个字分成一段,竖着排列起来:
1 | 你但是放 |
然后从左往右竖着读,怎么样,是不是很简单呢?(
版本 10 解码步骤示例

临时图片,里面的各个区块是随便放置的
1. 读格式信息
1 | 读:11101 |
可得纠错等级为 01 (L),掩码为 000 (第一种)(当然我故意这么设置的,不然掩码计算会复杂一些)
2. 读数据区
掩码0很简单,直接用1001异或就行,
但是重点来了,我们不能直接读4个bit,而是每8个bit读,即读一个字节
对表可知,版本 10 纠错等级为 L 的二维码分成 4 个块,为了方便解交织,我们一次读4个字节
1 | 读:11011001 10111111 10001111 10101111 |
1 | 读:10010110 10101111 01111101 10001110 |
1 | 读:01001111 01101111 00001110 00001100 |
遇到格式信息了,要避开,直接拐弯
此时掩码也要跟着变(0110)
1 | 读:11100001 00100000 01010000 00010000 |
1 | 读:00100001 00110000 01110001 11100000 |
解交织
1 | 块1:0100 00000000 11111101 01101000 01110100 0111 |
可得编码模式为 0100 (Byte),和长度信息 16*15+8+4+1=253(0000000011111101)
以及块1的一个字符“ht”,块 2 的四个字符“code”,块 3 的四个字符“nIsa”,块 4 的四个字符“ayWh”
依次类推,就能得出完整的网址了
剩下的数据留给你们读,快去评论区发布你的成果吧(
参考
- 二维码学习笔记(五) | 数据掩码与版本信息
- 如何用你的双眼读出二维码里的信息!(汉化搬运,英文原版在后文)
实用工具与视频
- Reading QR codes without a computer! (参考 2 的原版,可动态生成教程以及掩码)
- qrframe(自由度超高的二维码生成器,可自定义掩码、编码模式、纠错等级等)
- ASCII码对照表(包含英文字符的二进制表示)
- pixilart(像素画工具,可先导入一张二维码,然后在左侧找到 Crop Tool 修改图画大小为100x100,再在右侧找到加号添加一个图层,使用油漆工具填充绿色,将该图层移至二维码下方,切换至二维码图层,使用选择工具就可以自由操作了)
- QR-Code-generator(该仓库用多种语言制作了二维码生成器,并用注释解释代码含义,可了解二维码的编码过程)
- 视频:[MCBE] 二维码生成器『其三』(该视频很直观地展现了二维码的生成过程)
- 视频:如何手算二维码【高玩】(该视频完整地展示了如何手算二维码,包括纠错码)
- 专栏:如何手算二维码(里面有很详细的表格,包括字符容量表、字符计数指示符位长表和块数量信息表等)
未完待续,更新中…
说些什么吧!