QR code 二维码基础入门教程(三)

QR code 入门教程(三)


承接上文,我们已经说过了数据编码和纠错码的生成,接下来我们继续下面的步骤

结构化最终的数据

  • 所谓的结构化(Structure),说白了就是如何把之前生成的数据排成一个比特流。根据之前内容,我们已经得到了数据流以及纠错码,这些数据目前被放在不同的块(Block)中,如下表
Group Number Block Number Data Codewords in the Group Data Codewords as Integers
Error Correction Codewords for the Block
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 (show how these were calculated):
213 199 11 45 115 247 241 223 229 248 154 117 154 111 86 161 111 39
Block 2 (codeword #16) 11110110
(codeword #17) 11110110
(codeword #18) 01000010
(codeword #19) 00000111
(codeword #20) 01110110
(codeword #21) 10000110
(codeword #22) 11110010
(codeword #23) 00000111
(codeword #24) 00100110
(codeword #25) 01010110
(codeword #26) 00010110
(codeword #27) 11000110
(codeword #28) 11000111
(codeword #29) 10010010
(codeword #30) 00000110
Data Codewords from the left, as Integers:
246,246,66,7,118,134,242,7,38,86,22,198,199,146,6

Error Correction Codewords (show how these were calculated):
87 204 96 60 202 182 124 157 200 134 27 129 209 17 163 163 120 133
Group 2 Block 1 (codeword #31) 10110110
(codeword #32) 11100110
(codeword #33) 11110111
(codeword #34) 01110111
(codeword #35) 00110010
(codeword #36) 00000111
(codeword #37) 01110110
(codeword #38) 10000110
(codeword #39) 01010111
(codeword #40) 00100110
(codeword #41) 01010010
(codeword #42) 00000110
(codeword #43) 10000110
(codeword #44) 10010111
(codeword #45) 00110010
(codeword #46) 00000111
Data Codewords from the left, as Integers:
182,230,247,119,50,7,118,134,87,38,82,6,134,151,50,7

Error Correction Codewords (show how these were calculated):
148 116 177 212 76 133 75 242 238 76 195 230 189 10 108 240 192 141
Block 2 (codeword #47) 01000110
(codeword #48) 11110111
(codeword #49) 01110110
(codeword #50) 01010110
(codeword #51) 11000010
(codeword #52) 00000110
(codeword #53) 10010111
(codeword #54) 00110010
(codeword #55) 11100000
(codeword #56) 11101100
(codeword #57) 00010001
(codeword #58) 11101100
(codeword #59) 00010001
(codeword #60) 11101100
(codeword #61) 00010001
(codeword #62) 11101100
Data Codewords from the left, as Integers:
70,247,118,86,194,6,151,50,16,236,17,236,17,236,17,236

Error Correction Codewords (show how these were calculated):
235 159 5 173 24 147 59 33 106 40 255 172 82 2 131 32 178 236

接下来要做的工作就是把这些数据 “安排的明明白白的”。

Step 2 交错插入块

Step 3 转化为 2 进制

  • 将 Step 2 排列好的数字转为 2 进制。

补零剩余位

  • 有些版本的最终信息比特流没法填满整个QR码,对于这种情况,需要在末尾补零。补零的个数请查看 List of Versions and Required Remainder Bits。其实补零的个数也是可以算出来的,以 5-Q 为例,其中数据码字数为 60,纠错码码字数为 72(18*4),共 (72+60)*8 = 1072 个比特,然后再对比下表(下标来自国标),可以知道 5-Q 的数据容量是 1079,那么 1079 - 1072 = 7,需要补 7 个 0.
    image_1cj4ubbfd1s2h1o1pto91mcdru29.png-412kB

在矩阵中放置模块

像素和模块的区别。模块就是一块黑的或者白的块,模块由若干像素组成。例如一个 21*21 的模块,像素有可能是 42*42,或者 105*105。

功能图形

image_1cj4v5i1u1vkb1oel1kvq1tfq13hbm.png-44.8kB
+ 位置探测图形(Finder Pattern)。三个块,用于定位
+ 分隔符(Separator)。用于将位置探测图形与其他部分分开的功能图形,全都是浅色模块,宽度为 1.
+ 校正图形(Alignment Pattern)。长得有点像位置探测图形,但是更小更多。
+ 定位图形(Timing Pattern)。深色与浅色模块交错的图像,用于确定符号中模块的坐标。深色模块(Dark module)。干啥用的?确定版本信息?我也不清楚。

Step 1:放置位置探测图形

  • 有三个这样的图形image_1cj509ss215rl10qebss11smksd1j.png-1.7kB,它们的左上角位置为: 左上角(0,0)、左下角(0, (V-1)*4+21-7)、右上角((V-1)*4+21-7,0)。

Step 2:添加分隔符

  • 在位置探测图形外面加一圈浅色模块image_1cj50anq71eu29q01lsl1c9v1p6e20.png-1kB

Step 3:添加校正图形

Step 4:添加定位图形

  • 有两条,垂直一条,水平一条。位于两个finder patterns之间,并且开始和结束都是黑色的块。可以与校正图形重叠,因为它们两的颜色是一致的(多么神奇)

Step 5:添加深色模块和保留预留区域

  • 就是一黑点,位置为 (8,4V+9)
  • 还要格式信息区域(Format Inoformation Area),具体位置如蓝色区域
    image_1cj50ttlu165karujh7ilp1hnu44.png-1.7kB image_1cj50u4v94g9lt9b02137p1us64h.png-2.8kB
  • 保留版本信息区域,蓝色位置,一个是6*3,另一个是3*6
    image_1cj50vn0c1ig1lon1dstl8f7r45u.png-4.8kB

Step 6:放置数据比特流

  • 从右下角开始,遇到功能图像则跳过,直到一下个可用位置。放置的顺序如下图
  • 如果遇到了垂直的那条定位图形,直接下一列开始
    image_1cj524rrm1n7q1j811nt61v1711ln6b.png-10.5kB
  • 每次填两列,具体看下图

image_1cj525j9715qm14qfue1hm10616o.png-4kBimage_1cj5261a8d8p1nlhqon12p5iua75.png-6.4kB image_1cj5266sdmpe1jim133n7f61orp7i.png-6.4kB image_1cj526h411ccsta21pd6u031q757v.png-6.4kB

downward.png-1.8kB qr-code-down-1.png-0.9kB image_1cj528fckqk511ep1tkbn7p14pvak.png-7.1kB image_1cj528kg6ucacmf1lmgeqqlu4b1.png-7.1kB

  • 遇到功能图像的时候跳过。

数据掩码

  • 数据和功能图形都放进去了,现在加上掩码,这是为了让读取器能够容易的读取数据
  • 掩码就是就是对块取反,有八种掩码方案,参看 QR Mask Patterns Explained

选择最好的那种掩码

  • 八种掩码,八个结果,对每种结果进行评估取惩罚值最小的那种。
  • 惩罚值计算方法:

    1. The first rule gives the QR code a penalty for each group of five or more same-colored modules in a row (or column).
    2. The second rule gives the QR code a penalty for each 2x2 area of same-colored modules in the matrix.
    3. The third rule gives the QR code a large penalty if there are patterns that look similar to the finder patterns.
    4. The fourth rule gives the QR code a penalty if more than half of the modules are dark or light, with a larger penalty for a larger
      difference.
  • 条件 1,遇到=5个一样的块,惩罚值为3,如果在第一个=5的块后颜色还是一样,惩罚值为1。看图说话
    image_1ciiss38s66s2g61ubbs5q1lnoa8.png-114.8kBimage_1ciiss91g15lnksu14e81caum7cal.png-113.1kB

  • 条件 2,遇到2*2的块,惩罚值为3。
    image_1ciisvpcg1bfe47dgtgei71jcfb2.png-97.3kB

  • 条件 3,找类似位置探测图像的块,简单的说就是找下面两种,惩罚值为40
    image_1ciit2mmo1q1kb9n1ds31vp71hdbbs.png-0.6kB
    image_1ciit2s9ovl518576o71cpk11hkc9.png-0.7kB
    image_1ciit3ud41u05ijk1ugj8j1r7mcm.png-22.6kB

  • 条件 4,这个条件希望深色和浅色模块要尽量一样多,具体步骤是:

    1. 计算矩阵中所有模块的数量
    2. 计算深色模块的占比:(深色模块数 / 总模块数)*100
    3. 然后向前找5的倍数,向后找5的倍数。例如,占比=43,那么前一个5的倍数是40,后面一个是45
    4. 计算与 50% 的绝对值差,例如 |45-50| = 5,|40 - 50| = 10。
    5. 然后除以 5,例如,5/5 = 1, 10/5=2。
    6. 取小的那个值,然后乘上10,得到惩罚值。例如 1,2中1更小,所有惩罚值是1*10=10。

格式和版本信息