参考资料:QR Code Tutorial - Thonky.com,可以看成简单的中文翻译。
二维码的基本结构
Data Module:这是二维码的标准单位。它通常是一个白色背景下的黑色正方形。虽然颜色和对比度可以是不同的,但是黑对白是最理想的。这些黑色方块或数据模块的排列构成了二维码的大部分。
Position Marker:每个二维码上都有三个位置标记。它们由Inner Eye和Outer Eye组成,使扫描仪和照相机能够快速、准确地定位数据模块和扫描方向。
Quiet Zone:这是包含所有数据模块和位置标记的数据模块矩阵各侧的空白区域。它允许扫描仪和读取器以光学方式定位二维码的开始和结束位置。
Alignment pattern:定位图案
二维码的大小
一共有40个版本(Version),最小的是Version 1,大小为21×21(字节),最大的Version 40的大小为177×177(字节),其它的Version k 的长或宽的计算公式为 ( k − 1 ) ∗ 4 + 21 (k-1)*4+21 (k−1)∗4+21。
二维码的数据格式
二维码支持数字(Numeric,0-9),字母(Alphanumeric,0-9,字母,英文标点符号),字节(Byte,ISO-8859-1、UTF-8(一些二维码)),日语字符(Kanji),扩展解释(ECI,UTF-8)等等。
数据编码
二维码使用Reed-Solomon纠错码,二维码一共有4种纠错水平(L、M、Q、H),越高的纠错水平意味着需要越多的字节,QR码就会越大。
Error Correction Level | Error Correction Capability |
---|---|
L | Recovers 7% of data |
M | Recovers 15% of data |
Q | Recovers 25% of data |
H | Recovers 30% of data |
二维码所能承载的数据
以"hello world"一共有11个字符,如果使用version1的Q水平进行编码,一共可以承载16个字符,所有可以写入"hello world"。各种版本的二维码在不同编码水平下对于各种数据格式的承载能力见Character Capacities by Version, Mode, and Error Correction - QR Code Tutorial (thonky.com)。
数据格式标识符
标记将数据变成哪种格式(4位)
Mode Name | Mode Indicator |
---|---|
Numeric Mode | 0001 |
Alphanumeric Mode | 0010 |
Byte Mode | 0100 |
Kanji Mode | 1000 |
ECI Mode | 0111 |
字符个数标识符
标记一共编码了多少个字符,放在数据格式标识符后面,如"HELLO WORLD"一共有11个字符,字符计数为11,二进制表示为1011,补零至9位(version 1、Alphanumeric mode),所以最后结果为 000001011,再加上数据格式标识符 0010 000001011。
Versions 1 through 9 | Versions 10 through 26 | Versions 27 through 40 | |
---|---|---|---|
Numeric mode | 10 bits | 12 bits | 14 bits |
Alphanumeric mode | 9 bits | 11 bits | 13 bits |
Byte mode | 8 bits | 16 bits | 16 bits |
Japanese mode | 8 bits | 10 bits | 12 bits |
具体编码
以Alphanumeric mode为例,字符与编码对应表如下
字符 | 编码 | 字符 | 编码 | 字符 | 编码 | 字符 | 编码 | 字符 | 编码 |
---|---|---|---|---|---|---|---|---|---|
0 | 0 | A | 10 | K | 20 | U | 30 | + | 40 |
1 | 1 | B | 11 | L | 21 | V | 31 | - | 41 |
2 | 2 | C | 12 | M | 22 | W | 32 | . | 42 |
3 | 3 | D | 13 | N | 23 | X | 33 | / | 43 |
4 | 4 | E | 14 | O | 24 | Y | 34 | : | 44 |
5 | 5 | F | 15 | P | 25 | Z | 35 | ||
6 | 6 | G | 16 | Q | 26 | 空格 | 36 | ||
7 | 7 | H | 17 | R | 27 | $ | 37 | ||
8 | 8 | I | 18 | S | 28 | @ | 38 | ||
9 | 9 | J | 19 | T | 29 | * | 39 |
对于"HELLO WORLD"而言,先将其分成两个字符一对,即"HE"、“LL”、"O "、“WO”、“RL”、“D”
对于"HE",H:17、E:14,所以"HE"可以表示为 45 * 17 + 14 = 779,将其编码为11位,即01100001011,最后编码成
01100001011 01111000110 10001011100 10110111000 10011010100 001101(最后一个编码成6位)
补零拆分成8-bits
根据Error Correction Code Words and Block Information - QR Code Tutorial (thonky.com)确定补零个数
假设在version1,纠错水平为Q,此时需要13组码字,所以需要编码成13×8=104比特数的码字
对于version1,纠错水平为Q,编码"HELLO WORLD"需要的字符有
Mode Indicator(4位) | Character Count Indicator(9位) | Encoded Data(61位) | Terminator(4位) |
---|---|---|---|
0010 | 000001011 | 01100001011 01111000110 10001011100 10110111000 10011010100 001101 | 0000 |
上面一共已经有了78个字符,其中Terminator需要加在Encoded Data后面。为了能被8整除,还需再加两个0,一共有80个字符。由于此时还是太短(需要104个字符),所以加入重复序列11101100 00010001,直至达到104个字符。所以最后的字符编码为
0010|0000 01011|011 00001011 01111000 11010001 01110010 11011100 01001101 01000011 01|0000|00| 11101100 00010001 11101100
纠错编码
这里会牵扯到一些关于RS纠错码,还有伽罗华域的问题详见 Error Correction Coding - QR Code Tutorial (thonky.com)
伽罗华域的运算:以 2 8 2^8 28为例
2 0 = 1 ; 2 1 = 2 ; 2 2 = 4 ; 2 3 = 8 ; 2 4 = 16 ; 2 5 = 32 ; 2 6 = 64 ; 2 7 = 128 ; 2 8 = 256 2^0 = 1; 2^1 = 2; 2^2 = 4; 2^3 = 8; 2^4 = 16; 2^5 = 32; 2^6 = 64; 2^7 = 128; 2^8 = 256 20=1;21=2;22=4;23=8;24=16;25=32;26=64;27=128;28=256,当 2 8 = 256 ≥ 256 2^8=256\ge256 28=256≥256,所以要和285(100011101)进行异或操作,得 2 8 = 256 ∧ 285 = 29 2^8=256 \land 285 = 29 28=256∧285=29,相应的 2 9 = 2 8 ∗ 2 = 29 ∗ 2 = 58 2^9 = 2^8 * 2 = 29 * 2=58 29=28∗2=29∗2=58
对于大数字之间的乘法,如果指数超过255,需要对255取余,如 2 170 ∗ 2 164 = 2 334 = 2 334 % 255 = 2 79 2^{170}*2^{164}=2^{334}=2^{334 \% 255}=2^{79} 2170∗2164=2334=2334%255=279,通过查找QR Code Log Antilog Table for Galois Field 256 - QR Code Tutorial (thonky.com)可以发现为 2 79 = 240 2^{79}=240 279=240
生成多项式
信息多项式使用数据码字作为系数,如码字转成整数为25、218和35,信息多项式为 25 x 2 + 218 x + 35 25x^2+218x+35 25x2+218x+35
生成多项式以如下方式给出
(
x
−
a
0
)
.
.
.
(
x
−
a
n
−
1
)
(x-a^0)...(x-a^{n-1})
(x−a0)...(x−an−1)
其中 n 是必须生成的纠错码字的数量,在Error Correction Code Words and Block Information - QR Code Tutorial (thonky.com)中给出。由于是二进制编码,所以
a
a
a为2。
2个纠错码字的情况
首先计算
(
x
−
a
0
)
(
x
−
a
)
=
x
2
+
(
a
+
a
0
)
x
+
a
=
x
2
+
3
x
+
2
(x-a^0)(x-a)=x^2+(a+a^0)x+a=x^2+3x+2
(x−a0)(x−a)=x2+(a+a0)x+a=x2+3x+2(注意伽罗华域中负数等于正数),查找QR Code Log Antilog Table for Galois Field 256 - QR Code Tutorial (thonky.com)可得值为3对应的是
2
25
2^{25}
225,值为2对应的是
2
1
2^1
21,所以可以写成
x
2
+
a
25
x
+
a
1
x
0
x^2+a^{25}x+a^1x^0
x2+a25x+a1x0
3个纠错码字的情况
在2个纠错码字的基础上再乘上
(
x
−
a
2
)
(x-a^2)
(x−a2)
(
x
2
+
a
25
x
+
a
1
x
0
)
(
x
−
a
2
)
=
(
x
2
+
a
25
x
+
a
1
x
0
)
(
x
+
a
2
)
=
x
3
+
(
a
25
+
a
2
)
x
2
+
(
a
1
+
a
27
)
x
1
+
a
3
x
0
=
x
3
+
(
a
25
∧
a
2
)
x
2
+
(
a
1
∧
a
27
)
x
1
+
a
3
x
0
=
x
3
+
(
3
∧
4
)
x
2
+
(
2
∧
12
)
x
1
+
a
3
x
0
=
x
3
+
7
x
2
+
14
x
1
+
a
3
x
0
=
x
3
+
a
198
x
2
+
a
199
x
1
+
a
3
x
0
(x^2+a^{25}x+a^1x^0)(x-a^2)=(x^2+a^{25}x+a^1x^0)(x+a^2) \\=x^3+(a^{25}+a^2)x^2+(a^1+a^{27})x^1+a^3x^0\\ =x^3+(a^{25}\land a^2)x^2+(a^1 \land a^{27})x^1+a^3 x^0\\ =x^3+(3 \land 4)x^2+(2 \land 12)x^1+a^3x^0\\ =x^3+7x^2+14x^1+a^3x^0\\ =x^3+a^{198}x^2+a^{199}x^1+a^3x^0
(x2+a25x+a1x0)(x−a2)=(x2+a25x+a1x0)(x+a2)=x3+(a25+a2)x2+(a1+a27)x1+a3x0=x3+(a25∧a2)x2+(a1∧a27)x1+a3x0=x3+(3∧4)x2+(2∧12)x1+a3x0=x3+7x2+14x1+a3x0=x3+a198x2+a199x1+a3x0
生成纠错码字
使用version1,纠错水平M来构建一个1-M二维码,内容为"HELLO WORLD"
信息多项式
对于信息多项式,"HELLO WORLD"的编码为:
00100000 01011011 00001011 01111000 11010001 01110010 11011100 01001101 01000011 01000000 11101100 00010001 11101100 00010001 11101100 00010001
转成十进制数为:
32, 91, 11, 120, 209, 114, 220, 77, 67, 64, 236, 17, 236, 17, 236, 17
对应的信息多项式:
32 x 15 + 91 x 14 + 11 x 13 + . . . 32x^{15}+91x^{14}+11x^{13}+... 32x15+91x14+11x13+...
生成多项式
由于是1-M,所以根据Error Correction Code Words and Block Information - QR Code Tutorial (thonky.com),一共需要10个纠错码字,可以得到生成多项式为:
x
10
+
a
251
x
24
+
a
67
x
7
+
.
.
.
.
+
a
45
x^{10}+a^{251}x^{24}+a^{67}x^7+....+a^{45}
x10+a251x24+a67x7+....+a45
具体生成多项式的生成可参见Generator Polynomial Tool - QR Code Tutorial (thonky.com)
纠错码字求解
为了确保除法过程中第一项的指数不会变得太小,将信息多项式乘以 x n x^n xn,其中 n 是所需的纠错码字的数量(n=10),结果得到信息多项式为:
32 x 25 + 91 x 24 + 11 x 23 + . . . + 17 x 10 32x^{25}+91x^{24}+11x^{23}+...+17x^{10} 32x25+91x24+11x23+...+17x10
同样针对生成多项式进行相同处理,乘以
x
15
x^{15}
x15,15为信息多项式(未乘以
x
n
x^n
xn)的最高阶数,得到
x
25
+
a
251
x
24
+
a
67
x
23
+
.
.
.
.
+
a
45
x
15
x^{25}+a^{251}x^{24}+a^{67}x^{23}+....+a^{45}x^{15}
x25+a251x24+a67x23+....+a45x15
- 先将生成多项式乘上信息多项式的第一项即 32 = a 5 32=a^5 32=a5,得到结果:
a 5 x 25 + a 256 % 255 x 24 + a 72 x 23 + . . . + a 50 x 15 = a 5 x 25 + a 1 x 24 + a 72 x 23 + . . . + a 50 x 15 a^5x^{25}+a^{256 \% 255}x^{24}+a^{72}x^{23}+...+a^{50}x^{15} \\ =a^5x^{25}+a^{1}x^{24}+a^{72}x^{23}+...+a^{50}x^{15} a5x25+a256%255x24+a72x23+...+a50x15=a5x25+a1x24+a72x23+...+a50x15
转成整数表示: 32 x 25 + 2 x 24 + 101 x 23 + . . . + 5 x 15 32x^{25}+2x^{24}+101x^{23}+...+5x^{15} 32x25+2x24+101x23+...+5x15
- 将第一步的结果与信息多项式进行异或,得到
( 32 ∧ 32 ) x 25 + ( 91 ∧ 2 ) x 24 + ( 11 ∧ 101 ) x 23 + . . . + ( 236 ∧ 5 ) x 15 + . . . + ( 17 ∧ 0 ) x 10 = 0 x 25 + 89 x 24 + 110 x 23 + . . . + 233 x 15 + . . . + 17 x 10 (32\land 32)x^{25}+(91 \land 2)x^{24}+ (11 \land 101)x^{23}+...+(236\land5)x^{15}+...+(17 \land 0)x^{10} \\ = 0x^{25}+89x^{24}+110x^{23}+...+233x^{15}+...+17x^{10} (32∧32)x25+(91∧2)x24+(11∧101)x23+...+(236∧5)x15+...+(17∧0)x10=0x25+89x24+110x23+...+233x15+...+17x10
- 将第二步得到结果的第一项即 89 = a 210 89=a^{210} 89=a210乘上生成多项式,得到
( a 210 ∗ a 0 ) x 24 + ( a 210 ∗ a 251 ) x 23 + ( a 210 ∗ a 67 ) x 22 + . . . + ( a 210 ∗ a 45 ) x 1 4 = a 210 x 24 + a 206 x 23 + a 22 x 22 + . . . + a 0 x 14 (a^{210}*a^0)x^{24}+(a^{210}*a^{251})x^{23}+(a^{210}*a^{67})x^{22} + ...+(a^{210}*a^{45})x^14 \\ =a^{210}x^{24}+a^{206}x^{23}+a^{22}x^{22} + ...+a^0x^{14} (a210∗a0)x24+(a210∗a251)x23+(a210∗a67)x22+...+(a210∗a45)x14=a210x24+a206x23+a22x22+...+a0x14
转成整数表示: 89 x 24 + 83 x 23 + 234 x 22 + . . . + x 14 89x^{24}+83x^{23}+234x^{22}+...+x^{14} 89x24+83x23+234x22+...+x14
- 将第三步的结果与第二步的结果进行异或,得到:
( 89 ∧ 89 ) x 24 + ( 110 ∧ 83 ) x 23 + ( 114 ∧ 234 ) x 22 + . . . + ( 17 ∧ 1 ) x 14 + . . . + ( 17 ∧ 0 ) x 10 = 0 x 24 + 61 x 23 + 152 x 22 + . . . + 16 x 14 + . . . + 17 x 10 (89\land 89)x^{24}+(110 \land 83)x^{23}+ (114 \land 234)x^{22}+...+(17\land1)x^{14}+...+(17 \land 0)x^{10} \\ = 0x^{24}+61x^{23}+152x^{22}+...+16x^{14}+...+17x^{10} (89∧89)x24+(110∧83)x23+(114∧234)x22+...+(17∧1)x14+...+(17∧0)x10=0x24+61x23+152x22+...+16x14+...+17x10
- 重复第3步的操作,将第4步的结果的第一项 61 = a 228 61=a^{228} 61=a228乘上原始的生成多项式,得到
a 228 x 23 + a 224 x 22 + . . . + a 18 x 13 = 61 x 23 + 18 x 22 + . . . + 45 x 13 a^{228}x^{23}+a^{224}x^{22}+...+a^{18}x^{13}=61x^{23}+18x^{22}+...+45x^{13} a228x23+a224x22+...+a18x13=61x23+18x22+...+45x13。
- 将第五步的结果与第4步的结果进行异或
- 继续上述操作,直到最后异或后的多项式只剩下n=10项,最终结果为
196 x 9 + 35 x 8 + 39 x 7 + 119 x 6 + 235 x 5 + 215 x 4 + 231 x 3 + 226 x 2 + 93 x 1 + 23 196x^9+35x^8+39x^7+119x^6+235x^5+215x^4+231x^3+226x^2+93x^1+23 196x9+35x8+39x7+119x6+235x5+215x4+231x3+226x2+93x1+23
最后的纠错码字为 196 35 39 119 235 215 231 226 93 23
编码信息分块
较大的二维码需要将数据码字分解成较小的块,并为每个块分别生成纠错码字。在这种情况下,数据块和纠错码字必须根据 QR 码规范进行交错。
小的二维码
更小的二维码只包含了一个数据码字块,同时只有一组纠错码字,在这种情况,不需要交织,直接将纠错码字放在数据码字块后即可。
分解更大的二维码
对于5-Q二维码,有两个Group,Group1有两个数据块,每个数据块包含了15个数据码字,Group2有两个数据块,每个数据块包含了16个数据码字,一个数据块需要18个纠错码字,所以总共需要生成4组18个纠错码字。下表仅以Group1的Block1作为示例,完整表格见Structure Final Message - QR Code Tutorial (thonky.com)
Group Number | Block Number | Data Codewords in the Group | Data Codewords as Integers |
---|---|---|---|
Group 1 | Block 1 | (codeword #1) 01000011 (codeword #2) 01010101 (codeword #3) 01000110 (codeword #4) 10000110 (codeword #5) 01010111 (codeword #6) 00100110 (codeword #7) 01010101 (codeword #8) 11000010 (codeword #9) 01110111 (codeword #10) 00110010 (codeword #11) 00000110 (codeword #12) 00010010 (codeword #13) 00000110 (codeword #14) 01100111 (codeword #15) 00100110 | Data Codewords from the left, as Integers: 67,85,70,134,87,38,85,194,119,50,6,18,6,103,38 Error Correction Codewords : 213 199 11 45 115 247 241 223 229 248 154 117 154 111 86 161 111 39 |
… | … | … | … |
交织
交织规则:
- 从第一个block里面抽取第一个数据码字
- 接着从第二个block里面抽取第一个数据码字
- 接着从第三个block里面抽取第一个数据码字
- 接着从第四个block里面抽取第一个数据码字
- 接着从第一个block里面抽取第二个数据码字
- 重复上述操作,直至全部数据码字均被抽取
对于纠错码字,也进行相同的交织操作。
交织示例:
交织前的码字:
codeword1 | codeword2 | codeword3 | |
---|---|---|---|
Block1 | 67 | 85 | 70 |
Block2 | 246 | 246 | 66 |
Block3 | 182 | 230 | 247 |
Block4 | 70 | 247 | 118 |
交织后的码字为:
67, 246, 182, 70, 85, 246, 230, 247, 70, 66, 247, 118
将交织后的纠错码字放在交织后的码字后面。再将码字从整数转成8-bit的二进制
在转成8-bit二进制后可能还存在无法填满二维码的情况,需要补零,不同version的二维码补零数为
QR Version | Required Remainder Bits | QR Version | Required Remainder Bits |
---|---|---|---|
1 | 0 | 21 | 4 |
2 | 7 | 22 | 4 |
3 | 7 | 23 | 4 |
4 | 7 | 24 | 4 |
5 | 7 | 25 | 4 |
6 | 7 | 26 | 4 |
7 | 0 | 27 | 4 |
8 | 0 | 28 | 3 |
9 | 0 | 29 | 3 |
10 | 0 | 30 | 3 |
11 | 0 | 31 | 3 |
12 | 0 | 32 | 3 |
13 | 0 | 33 | 3 |
14 | 3 | 34 | 3 |
15 | 3 | 35 | 0 |
16 | 3 | 36 | 0 |
17 | 3 | 37 | 0 |
18 | 3 | 38 | 0 |
19 | 3 | 39 | 0 |
20 | 3 | 40 | 0 |
不同模块的布局
finder patterns:分别放在二维码左上、右上和左下的三个块
separators:finder patterns外面的黄色区域
alignment patterns:与finder patterns类似,不过更小,在version 大于等于2的时候使用,具体位置也由二维码的version决定
timing patterns:连接各个finder patterns的点线
dark module:一个单独的黑色点,总是放在左下角的finder patterns旁边
Finder Patterns
Finder Patterns的位置和大小是固定的,不随version的变化而变化,Finder Patterns的大小与具体形状如下:
如果以二维码的左上角作为原点,可以得到三个Finder Patterns的位置如下(V表示version):
左上:(0,0)
右上:((V-1)*4+21) - 7,0)(Finder Patterns左上角位置)
左下:(0,((V-1)*4 + 21)-7) (Finder Patterns左上角位置)
separators
就是放在Finder Patterns外面的白色的线,与version无关,不多赘述。
Alignment Patterns
当version大于等于2的时候会使用,大小和形状不随version改变而改变,位置参考Alignment Pattern Locations Table - QR Code Tutorial (thonky.com)
如当version=2时,Alignment Patterns的位置为6 18,即应该在(6,6)、(6,18)、(18,6)、(18,18)放置四个Alignment Patterns,如下所示:
但这样会挡住其它的三个Finder Patterns,所以只保留右下的Alignment Patterns,如下所示:
Timing Patterns
Timing Patterns包括两条线,一条水平线和一条垂直线,交替的黑白点。水平线放置在二维码的第6行,垂直线放置在二维码的第6列。Timing Patterns总是以黑色点开始和结束。Timing Patterns可能会与Alignment Patterns重叠,需要保证Timing Patterns在经过Alignment Patterns时也是黑白点交替出现,如下所示:
Dark Module and Reserved Areas
Dark Module的添加位置为([(4 * V) + 9], 8),V为二维码的version
在添加数据码字前,需要保留一些区域作为二维码的格式信息,下图中蓝色区域便是保留的区域
此外对于version大于等于7的二维码,还需要保留存放版本信息的区域,蓝色区域便是保留的区域
排列数据码字
对于转成二进制的数据码字,0表示白色点,1表示黑色点。
码字排列的基本模式如下(下图为version1的排列,所以没有Alignment Patterns和存放版本信息的保留区域):
值得注意的是,由于Timing Patterns存在一条垂直线,所以这条线上不能存放任何码字信息,每次向一个方向排列码字时都会排列两列,向上时的排列方式如下所示:
向下时的排列方式如下所示
注意在排列时不能影响到具有功能的区域,在经过功能区域后立即恢复原先的排列方式



二维码中一共定义了8中mask pattern,详见:QR Mask Patterns Explained - QR Code Tutorial (thonky.com),mask只针对码字,不能mask功能区和保留区域。
为了定义哪一个mask pattern是最好的,定义了四个惩罚规则
- 一行(或一列)中的存在一组五个或更多同色点
- 一个2x2区域为同色
- 一个区域看起来像Finder patterns
- 如果二维码中超过一半的点为黑色或白色
对于规则1:出现5个同色点,则惩罚3,紧接着后面每出现一个同色点,惩罚1,计算横向和纵向的惩罚总和。


对于规则2:每出现一个2×2区域为同色,惩罚3,可以重复计算同色区域
对于规则3:就是要寻找这两种模式的点排列,找到一个惩罚40


对于规则4:
- 统计所有的点数 n n n,再统计黑色点的数量 n d n_d nd;
- 计算百分比 p p p: p = n d n ∗ 100 p=\frac{n_d}{n}*100 p=nnd∗100;
- 计算 p p p前一个5的倍数 p 1 p_1 p1和后一个5的倍数 p 2 p_2 p2, p 1 = p − ( p % 5 ) , p 2 = p 1 + 5 p_1=p-(p \% 5), \;\;p_2=p_1+5 p1=p−(p%5),p2=p1+5;
- 计算 p 1 p_1 p1和 p 2 p_2 p2与50的差值 d 1 d_1 d1和 d 2 d_2 d2: d 1 = a b s ( p 1 − 50 ) , d 2 = a b s ( p 2 − 50 ) d_1=abs(p_1-50),\;\;d_2=abs(p_2-50) d1=abs(p1−50),d2=abs(p2−50);
- 取两个差值中较小的那个差值 d = m i n ( d 1 , d 2 ) d=min(d_1,d_2) d=min(d1,d2)
- 计算惩罚 e e e: e = d 5 ∗ 10 = 2 d e=\frac{d}{5}*10=2d e=5d∗10=2d
如 n = 441 , n d = 213 n=441, \;n_d=213 n=441,nd=213
p = n d n ∗ 100 = 48.29 , p 1 = 45 , p 2 = 50 , d = m i n ( d 1 , d 2 ) = 0 p=\frac{n_d}{n}*100=48.29,\;\;p_1=45,\;\;p_2=50,\;\;d=min(d_1, d_2)=0 p=nnd∗100=48.29,p1=45,p2=50,d=min(d1,d2)=0,最后的惩罚为0。
分别将二维码经过8个mask pattern得到8个二维码,将每个二维码的四个规则的惩罚加起来,最后选择对应惩罚最小的mask pattern。
格式与版本信息
格式信息
格式信息一般为15bits长,其中5bits用来编码纠错水平和使用的mask pattern,然后用5bits的信息来生成10bits长的纠错码,最后将其与101010000010010异或。
纠错水平和对应的编码如下所示
Error Correction Level | Bits | Integer Equivalent |
---|---|---|
L | 01 | 1 |
M | 00 | 0 |
Q | 11 | 3 |
H | 10 | 2 |
对于八个mask pattern,000代表mask pattern0,100表示mask pattern1。
生成10bits纠错码
使用的生成多项式为 x 10 + x 8 + x 5 + x 4 + x 2 + x + 1 x^{10}+x^8+x^5+x^4+x^2+x+1 x10+x8+x5+x4+x2+x+1,对应的二进制串为10100110111
假设5bits的格式字符串为01100,首先将其补零至15bits:01100 —> 011000000000000,将左边的0全部删除:011000000000000 -> 11000000000000
-
将生成多项式10100110111在右侧补零至与当前格式字符串11000000000000长度相等,10100110111 -> 10100110111000,将补零后的生成多项式10100110111000与格式字符串做异或,
10100110111000 ∧ 11000000000000 = 01100110111000 10100110111000 \;\land \;11000000000000=01100110111000 10100110111000∧11000000000000=01100110111000
删除异或结果左边的0,得到 01100110111000 -> 1100110111000
-
第一步的结果为13bits长,继续将生成多项式的右侧补零至与当前格式字符串1100110111000长度相等,10100110111 -> 1010011011100,将其与格式字符串做异或,
1010011011100 ∧ 1100110111000 = 0110101100100 1010011011100 \;\land \;1100110111000=0110101100100 1010011011100∧1100110111000=0110101100100,删除异或结果左边的0,得到110101100100
-
第二步的结果为12bits长,继续上述操作,生成多项式右侧补零成101001101110,与当前格式字符串进行异或得到 101001101110 ∧ 110101100100 = 011100001010 101001101110 \;\land \;110101100100=011100001010 101001101110∧110101100100=011100001010,删除左边的0,得到11100001010
-
第三步的结果为11bits长,还需要继续,生成多项式无需补零,直接与当前格式字符串进行异或得到 10100110111 ∧ 11100001010 = 01000111101 10100110111 \;\land \;11100001010=01000111101 10100110111∧11100001010=01000111101,删除左边的0,得到1000111101。
-
第四步得到的结果为10bits长,如果小于10bits,需要在左侧补零,该字符串便是纠错码
将格式字符串和纠错码放在一起得到011001000111101,最后和101010000010010做异或得到
011001000111101 ^ 101010000010010 = 110011000101111。所有的格式字符串和对应的纠错码可以在Format and Version String Tables - QR Code Tutorial (thonky.com)找到。
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 1 | 1 |
在排列时,按照如下规则:
版本信息
当二维码的version大于等于7时,需要加入18bits的version信息,具体version对应的version信息如Format and Version String Tables - QR Code Tutorial (thonky.com)所示。
version信息的生成
version信息由6bits编码version信息,12bits用于纠错,使用(18,6)Golay码作为纠错码
生成多项式为 x 12 + x 11 + x 10 + x 9 + x 8 + x 5 + x 2 + 1 x^{12}+x^{11}+x^{10}+x^9+x^8+x^5+x^2+1 x12+x11+x10+x9+x8+x5+x2+1,对应的二进制字符串为
1111100100101。
假设version = 7,则编码version信息的6bits为000111,在version信息右侧补零至18bits,000111000000000000,删除左边的0得到111000000000000,将生成多项式补零至与version信息相等的长度1111100100101000将111000000000000与111110010010100做异或,1110000000000 ^ 111110010010100 = 000110010010100,删除结果左侧的0,得到110010010100,该字符串已经满足12 bits,可以作为纠错码,如果小于12bits,在左侧补零。
将原始的6bits信息与12bits的纠错码放在一起得到000111110010010100
version信息的排列
对于左下区域
00 | 03 | 06 | 09 | 12 | 15 |
---|---|---|---|---|---|
01 | 04 | 07 | 10 | 13 | 16 |
02 | 05 | 08 | 11 | 14 | 17 |
对于右上区域
00 | 01 | 02 |
---|---|---|
03 | 04 | 05 |
06 | 07 | 08 |
09 | 10 | 11 |
12 | 13 | 14 |
15 | 16 | 17 |
位置与bit对应
17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 0 |
结语
加入格式和version信息后,选择惩罚最小的mask输出最终矩阵,对于Quiet Zone,只是一个4bits宽的空白区域。
- 选择编码模式
- 编码数据
- 生成纠错码
- 如果需要的话,交织块
- 在矩阵中放置数据和纠错码
- 使用mask pattern,并通过惩罚最小选择mask
- 加入格式和version信息