QR code 二维码基础入门教程
- 本文为 QR Code Tutorial: Introduction 的总结,详细内容请查看原文
Introduction
History and Information
-
QR code 于 1994 年,由 日本公司 Denso-Wave 发明。其标准为ISO/IEC 18004:2006
-
QR code 最小为 21*21,最大为177*177,其大小被称为“Version”
- Version=1, 21*21
- Version=2, 25*25
- Version=3, 29*29
- …
- Version=40, 177*177
- 计算公式:(V-1)*4+21。其中V为版本号
-
QR code 有4种纠错等级,可恢复的码字比例为
Error Correction Level| Error Correction Capability|
:- | :- |
L | 恢复7%的数据
M | 恢复15%的数据
Q | 恢复25%的数据
H | 恢复30%的数据 -
数据模式包括:数字模式,数字字母模式,8字节模式,日本汉字模式,扩充解释模式(ECI),结构链接模式,FNC1模式 (实际上不同的标准支持的模式类型不同,我们不妨从简单的开始,重点关注前4种模式)
General Overview of Creating a QR Code
- 数据分析。对需要编码的数据进行分析,然后选择最佳的模式
- 数据编码。根据步骤1的模式,对数据进行编码
- 纠错编码。生成纠错码
- 构造最终消息。填充数据码和纠错码填入矩阵
- 在矩形中放置模块。将寻像图形、分隔符等一起放入矩阵
- 掩摸。用8中掩摸对编码区域图形做XOR,评价8种结果,选择最优的一种
- 格式和版本信息。生成版本信息和格式信息
接下来,我们对每个步骤进行说明
数据分析
- 数据编码将输入数据编码为一串0/1比特流,选择合适的数据模式,能够这串流尽量的短
- 各个模式可编码的字符
- 数字模式:数字0-9
- 数字字母模式:数字0-9,所有大写字母,符号 $ % * + - . / : 还有空格。具体请看数字字母模式译码表
- 8字节模式:默认情况下,可编码 ISO-8859-1 所有字符
- 日本汉字模式(Kanji,或者叫双字节模式):编码Shift JIS。也可以编码UTF-8,但是需要的字节可能更多。
- 扩充解释模式:可指定缺省字符集(这里我们不讨论这种模式)
- 结构链接模式:可以将一个数据编码为多个QR code(最多16个,这里我们不讨论这种模式)
- FNC1模式:允许QR code像GS1 code一样(这里我们不讨论这种模式)
- 如何选择合适的模式
- 如何选择合适的模式Plus,摘自QR Code二维码–一种新型的矩阵符号 27页
下列导则可以形成对给定的输入数据决定最短位流的算法的基础。在方括号中的字符数如[5,7,9]分别用于版本19,版本1026和版本27~40.在导则中,术语“专有子集”是指一种模式的字符集中的一组字符,不能与另一种更有限的字符集共享,例如,8位字节字符集的专有子集由JIS
8的值 0 0 H E X 00_{HEX} 00HEX~ F F H E X FF_{HEX} FFHEX组成,但它不包括十六进制的值
20,24,25,2A,2B,2D3D和415A;因为它们是字符字符集的一组字符{A~Z,space,$,%,*,+,-,’, /,:}
- 混合多种模式(这里不讨论这种模式)
- 选择好了合适的模式,接下来是数据编码
数据编码
Step 1 选择纠错等级
Error Correction Level | Error Correction Capability |
---|---|
L | 恢复7%的数据 |
M | 恢复15%的数据 |
Q | 恢复25%的数据 |
H | 恢复30%的数据 |
- 纠错等级越高,纠错码就越多,那么可编码的数据就变少,因此QR code的版本可能要更大
Step 2 确定数据的最小版本
- QR code的数据容量由模式和纠错等级决定,详勘Character Capacities by Version, Mode, and Error Correction
- 如何确定数据的最小版本:
- 确定模式和纠错等级
- 根据输入数据的字符个数,查表得到结果
- 举个例子,输入数据:HELLO WORLD,模式:数字字母模式,纠错等级:Q,字符个数:11,查表得到版本1为最小版本(版本1Q在数字字母模式最多可编码16个字符)。同理,输入数据改为:HELLO THERE WORLD,查表得到版本2为最小版本
- 容量上限。版本40,纠错等级L时,容量最大,可容纳的字符数如下表
编码模式|最大可编码字符数(纠错等级L,版本40)|
-|-|
数字模式| 7089
字母数字模式|4296
8字节模式|2953
日本汉字模式|1817
Step 3 添加模式指示符
- 比特流最前面是模式指示符,模式指示符是一个4比特的指示符,指示符如下
编码模式 | 模式指示符 |
---|---|
数字模式 | 0001 |
数字字母模式 | 0010 |
8字节模式 | 0100 |
日本汉字模式 | 1000 |
ECI模式 | 0111 |
- 国标的指示符长这样:
Step 4 添加字符计数指示符
-
将输入数据的字符数 编码为一串指示符。不同版本字符数字指示符的长度不一样。
-
举个例子:HELLO WORLD,版本1,模式=字母数字模式,字符数=11,那么字符计数指示符的长度为9个比特。11的二进制:1011,不满9位则左边填充0,得到 000001011。结合上一步的模式指示符,当前编码比特流为:0010 0000001011
Step 5 利用模式对输入数据编码
- 不同模式的编码方式不同,通过具体例子我们来不同模式的熟悉编码过程
数字模式编码
- 将输入数据分为3位一组。8675309 -> {867, 530, 9}
- 将每组数据转为二进制,如果一组数据是3个,那么转换为10位二进制,如果是2位,转换为7位,如果是1位,转换为4位
- 867 -> 1101100011
- 530 -> 1000010010
- 9 -> 1001
字母数字模式编码
- 将输入数据分为2个一组。HELLO WORLD -> {HE, LL, O , WO, RL, D}
- 通过查表 字母数字模式的编码/译码表,将数据转为对应的值。{{17,14}, {21,21}, {24,36},{32,24},{27,21},{13}}
- 每组的第一个数乘上45,然后加上第二个数。{17,14} -> 17*45+14=779。
- 将3得到的结果转为11位二进制。779 -> 01100001011
- 如果只有一个字符,,转换为6位二进制。{D} -> {13} -> 001101
- 重复3-5步,得到结果 01100001011 01111000110 10001011100 10110111000 10011010100 001101
8字节模式
- 默认字符集为ISO 8859-1。如果输入字符不在ISO 8859-1中,可转换为UTF-8。
- 通过查表,将输入数据转为16进制。例如,“Hello, world!”
- H → 0x48
- e → 0x65
- l → 0x6c
- l → 0x6c
- o → 0x6f
- , → 0x2c
- → 0x20
- w → 0x77
- o → 0x6f
- r → 0x72
- l → 0x6c
- d → 0x64
- ! → 0x21
- 将十六进制转为二进制
- H → 0x48 → 01001000
- e → 0x65 → 01100101
- l → 0x6c → 01101100
- l → 0x6c → 01101100
- o → 0x6f → 01101111
- , → 0x2c → 00101100
- → 0x20 → 00100000
- w → 0x77 → 01110111
- o → 0x6f → 01101111
- r → 0x72 → 01110010
- l → 0x6c → 01101100
- d → 0x64 → 01100100
- ! → 0x21 → 00100001
日本汉字模式
- 我们先略过
编码结果
- 根据上述编码方式我们目前得到的结果:
模式指示符|字符计数指示符|编码序列|
-|-|-|
0010|000001011|01100001011 01111000110 10001011100 10110111000 10011010100 001101
Step 6 填充空余的比特位
- 通过查表error correction table得到最大数据比特位数。例如,1-Q共有13个码字,每个码字有8位,因此最大数据比特位数:13*8=104
- 添加终止符。终止符位4比特长度:0000。但是如果编码序列为102,只剩下2位,那么只需要填充2位的0。添加了终止符后的编码序列为
模式指示符 | 字符计数指示符 | 编码序列 | 终止符 |
---|---|---|---|
0010 | 000001011 | 01100001011 01111000110 10001011100 10110111000 10011010100 001101 | 0000 |
-
如果当前编码序列的最后一个码字不满8位,那么填充0至8位
当前数据:00100000 01011011 00001011 01111000 11010001 01110010 11011100 01001101 01000011 010000
填充后的数据:00100000 01011011 00001011 01111000 11010001 01110010 11011100 01001101 01000011 010000 00 -
如果当前数据太短了,没有填满最大比特位数,那么重复填充 11101100 00010001
最终数据: 00100000 01011011 00001011 01111000 11010001 01110010 11011100 01001101 01000011 010000 00 11101100 00010001 11101100
最后,用一张图来总结以上过程