欢迎光临散文网 会员登陆 & 注册

如何手算一张二维码

2018-07-06 09:38 作者:高玩梁  | 我要投稿

二维码是由Denso Wave Incorporated创建的特殊类型的条形码。二维码格式在1994年由日本公司Denso-Wave创建,该公司是丰田的子公司,生产汽车零部件(我一个生产汽车零部件的,怎么就创造了二维码呢)。该标准定义在ISO / IEC 18004:2015中(有2016,但是这样的标准太贵了)。二维码使用易于被光学扫描仪读取的像素图案来编码文本和数字。本教程教授大家如何在二维码中编码信息。建议有一定计算机基础的人阅读。(没有也行,只要会数学就行)

如果你仅仅想创建二维码,则不需要阅读本教程。使用这个网站https://cli.im/即可创建二维码。

注意事项:

当你看不懂的时候想想这个


正片开始

1.确定你要编码的东西

二维码有4种编码形式数字,字符,字节和日文(丰田出的标准,当然是有日文了)。每种编码模式将文本编码为一串二进制数字(1和0),但每个模式使用不同的方法将文本转换为二进制数字,并且每个编码模式使用尽可能最短的一串二进制数字来编码数据。因此,第一步应该是进行数据分析,以确定该文本是否可以符合数字,字母,字节或日文模式的编码,然后选择最优化的编码模式。

本文用BILIBILI CHEERS以例子,所以我们采用字符编码


选择错误校正级别

在编码数据之前,首先应当选择错误校正级别。二维码使用里德-所罗门码(不求甚解)。该过程基于编码数据创建纠错码,二维码阅读器可以使用这些纠错码来确定它是否正确地读取数据,并且可以使用纠错码来纠正错误。

二维码中有四种级别的纠错:L,M,Q,H。

下表列出了级别及其纠错能力:

注意: 更高级别的纠错需要更多的字节,因此纠错级别越高,二维码尺寸就越大。

确定最小的版本

二维码一共有40个尺寸。官方叫版本Version。Version 1是21 x 21的矩阵,Version 2是 25 x 25的矩阵,Version 3是29 x 29 的尺寸,每增加一个Version,就会增加4的尺寸。

计算公式是:(V-1)*4 + 21(V是版本号,算出来的结果是边长)。

计算要编码的字符数,并确定对应编码模式的包含的字符数量和符合纠错级别的最小版本。

字符串 BILIBILI CHEERS 有15个字符。 假设纠错级别为H。查看字符容量表,发现版本1下纠错级别H在字符模式下只能包含10个字符。因此,在这种情况下可以使用的最小版本是版本2。

字符容量表

所以我们使用1-Q进行编码BILIBILI CHEERS


增加模式指示符

每个编码模式都具有指示它的四位模式指示符。编码数据必须以适当的模式指示符开始,用于指示后面的位串的模式。

用字符模式编码应该是0010


增加字符计数指示符

字符计数指示符是一串二进制数字,表示正在编码的字符数。字符计数指示符必须放在模式指示符之后。此外,字符计数指示符有特定的位长,具体取决于二维码的版本和编码模式。

具体步骤是:

计算原始输入文本的字符数,将其转为二进制数字。根据版本和编码模式找到对应的位长,不够位长的在前面加0补齐。

编码BILIBILI CHEERS,版本号为1,则字符计数指示符必须为9位长。

BILIBILI CHEERS的字符数为15。在二进制中,15为1111

在左侧填充0,使其长度达到9位:000001111

将这个指示符放在模式指示符之后,获得以下位串:0010 000001111

每种版本的对应的字符计数指示符位长


确定此二维码所需的位数

要确定特定QR码需要多少数据位,请参阅纠错表。

找到当前文本生成二维码所使用的版本和错误纠正级别,并在标有“数据码字总数”的对应列中找到该编号。将此数乘以8以获得此版本和纠错级别所需的数据位的总数。

例如,根据该表,二维码 1-Q 具有13个总数据码字(一个数据码字代表8位二进制数字)。因此,该QR码所需的总比特数为13×8 = 104比特。

纠错码和块信息

分组

字符编码模式将字符每两个分一组,如果分不了就单独一组。

分组后:

(BI), (LI), (BI),(LI),( C), (HE),(ER),(S)

转为二进制

根据字母索引表找到对应的数字:

字母索引表(其中的SP是空格,Char是字符,Value是其索引值)


然后对于每组数字,将第一个数字乘以45加上第二个数字,得到数字结果,然后转成11bits的二进制,如果最后有一个落单的,那就转成6bits的二进制。

举个栗子:

BILIBILI CHEERS 的第一组字符是(BI)。

B → 11

I  → 18

result = (11 * 45) + 18 = 513

转为二进制(位长不足补0):

513 → 01000000001

结果

BILIBILI CHEERS → 01000000001 01111000011 01000000001 01111000011 1100110000 01100001011 001010010001 011100

增加指示符

加上模式和字符计数指示符,最终结果为:

0010 000001111 01000000001 01111000011 01000000001 01111000011 1100110000 01100001011 001010010001 011100


添加终止符(如有需要)

如果位串小于所需位的总数,则必须在字符串的右侧添加最多四个0的终止符。

如果所需位数比位串大四位及以上,则将四个0加到结尾。否则只添加达到所需位数所需的0的个数。

例如,如果在 1-Q 的二维码中编码BILIBILI CHEERS,则所需比特的总数是104比特。BILIBILI CHEERS数据位字符串为96位长。终止符的长度最多只能为4位,因此在字符串的右侧添加4个0。结果字符串仍然太短,无法填充104位容量,但二维码规范要求终止符的长度最多为4个0。如果字符串已经是102位,则终止符的长度将仅为2位。


添加了终止符的BILIBILI CHEERS字符串示例


添加更多0,使长度为8的倍数

添加终止符后,如果字符串中的位数不是8的倍数,首先使用0来填充右侧的字符串,使字符串的长度为8的倍数。

例如,在将终止符添加到BILIBILI CHEERS之后,长度变为100位长。这不是8的倍数。位串显示为8位二进制字节:

00100000 00111101 00000000 10111100 00110100 00000010 11110000 11110011 00000110 00010110 01010010 00101110 0000

添加4个0使其成为8位二进制字节:

00100000 00111101 00000000 10111100 00110100 00000010 11110000 11110011 00000110 00010110 01010010 00101110 00000000

如果字符串仍然太短,则添加补齐码

如果字符串仍然不足以填充最大容量,请将以下字节添加到字符串的末尾,不断重复,直到字符串已达到最大长度:

11101100 00010001

这些字节分别等于236和17,二维码针对在字符串太短的情况特别规定了补齐码。

第一部分告一段落,然后,准备好觉悟吧


当你看不懂的时候想想这个


2.生成纠错码

多项式长除法

纠错码字将使用称为Reed-Solomon纠错的方法来生成,部分过程是执行多项式长除法。也就是说,用一个多项式除以另一个多项式。(本教程用不到,所以这里就不再赘述)

伽罗瓦域

如上所述,为了生成纠错码字,该过程使用称为Reed-Solomon纠错的方法。
而多项式长除法则用到了伽罗瓦域,其本质上是数字的有限集合,以及创建仍在该集合中的数字的一些数学运算。

二维码标准使用逐位模2算法和逐字节模100011101算法。这意味着使用伽罗瓦域28,换句话说是伽罗瓦域256,有时也写为GF(256)

GF(256) 中的数字在0到255(包括)的范围内。也可以用八位字节表示的相同数字范围(最大可能的八位字节是11111111,等于255)。

这意味着GF(256)中的所有数学运算将可以表示为八位字节的数字的运算。

(本篇将使用一种更简单的方法)

公式太多,就直接word截图了
对数与反对数表

生成纠错码

现在终于可以开始生成纠错码字了。

这些码字将被用作消息多项式的系数。此示例使用纠错级别Q和版本1创建1-Q代码。

消息多项式

BILIBILI CHEERS的数据码如下:

00100000 00111101 00000000 10111100 00110100 00000010 11110000 11110011 00000110 00010110 01010010 00101110 00000000

将二进制转为十进制:

32 61 0 188 52 2 240 243 6 22 82 46 0

这些十进制数字是消息多项式的系数。

32x^12+61x^11+188x^9+........+46x+0

 生成多项式

由于这是1-Q码,查找纠错表,可知需要生成13个纠错码字。因此,使用以下生成多项式:

附录A给出了

除法步骤

现在需要用生成多项式除消息多项式,具体步骤和前面介绍的大致相同。

下面是包含伽罗瓦域算法的除法步骤:

  1. 找到适当的项乘以生成多项式,乘法的结果应该具有与消息多项式(在首次乘法步骤中)或余数(在所有后续乘法步骤中)相同的第一项;

  2. 将结果与消息多项式(在首次乘法步骤中)或余数(在所有后续乘法步骤中)进行异或运算。

  3. 重复执行以上步骤n次,其中n是数据码字的数量。

注意这些步骤和正常多项式长除法的步骤之间的差异。在乘法步骤之后进行减法的运算,我们用异或代替。

在划分两个多项式之后,将会有一个余数,该余数的系数就是纠错码字。

符号太多,不如手写快

多项式系数作为纠错码

除法已执行完13次,即消息多项式中项的数量。上述多项式的系数即是用于原始消息多项式的纠错码字:

58 253 16 114 183 245 176 209 91 64 141 165 77


对于较小版本,直接使用数据和纠错码

请注意,较小版本的二维码仅包括一个数据码字块,具有用于该块的一组纠错码字。在这种情况下,不需要交替排列。只需将纠错码字放置在数据码字之后,即可进入下一步,将模块放置在矩阵中。

3.如何放置功能模式和数据位

术语:像素与模块

在本文中,我将二维码的黑白方块称为模块而不是像素。这是为了区分屏幕上的像素和二维码的黑色和白色方块。
例如,版本1的二维码总是2121个模块,即使它在计算机屏幕上占用4242像素,或105x105等等。

功能模式概述

二维码必须包括功能模式。这些是必须放置在二维码的特定区域中的图案,以确保二维码扫描器可以正确地识别和定向用于解码的代码。

下图给出了功能模式是什么以及它们位于何处的示例。


finder patterns 是二维码左上角,右上角和左下角的角落中的三个块。

separators 是finder patterns旁边的空白区域。

alignment patterns类似于finder patterns,但是更小,并且被放置在整个代码中。它们在版本2和更大版本中使用,它们的位置取决于二维码版本。本文用不到

timing patterns是连接finder patterns的虚线。

dark module是一个单一的黑色模块,总是放置在左下角的finder patterns旁边。

添加 Finder Patterns

首先,将finder patterns放入矩阵。

finder patterns(如下所示)外部由一个黑色正方形组成,为77个模块,内部为一个白色正方形为55个模块,中间有一个实心黑色正方形,3*3个模块。

finder patterns

finder patterns被设计为不可能出现在二维码的其他部分内的图案。Finder Patterns的模块宽度具有1:1:3:1:1的比率。二维码扫描器可以搜索亮到暗模块的这个比率以检测finder patterns并且正确地定位二维码用于解码。

无论使用哪个版本,finder patterns始终放置在二维码的左上角,右上角和左下角。

添加 Separators

Separators 是白色模块线,一个模块宽,放置在finder patterns旁边,以将它们与二维码的其余部分分离。

finder patterns外面一圈就是Separators

添加 Timing Patterns

Timing Patterns是暗模块和亮模块交替的两条线,一条水平线和一条垂直线。Timing Patterns放置在Separators之间的二维码的第6行上。

Alignment Patterns可以与Timing Patterns重叠,因为它们的亮和暗模块总是与Timing Patterns的亮和暗模块重合。下图显示不同版本的二维码的Timing Patterns。

暗模块

如上所述,所有二维码在左下角 Finder Patterns 旁边有一个黑暗的模块。
更具体地说,暗模块总是位于坐标([(4 * V)+ 9],8),其中V是二维码的版本。

保留格式信息区

必须为格式信息区域保留Separators旁边的模块条,如下所示:

  • 在左上方Finder Patterns附近,必须在Separators的下方和右侧保留单模块条带。

  • 在右上方Finder Patterns附近,必须在Separators下方保留单模块条带。

  • 在左下方Finder Patterns附近,必须在Separators的右侧保留单模块条带。

放置方法

数据位从矩阵的右下方开始放置,并且在2个模块宽的列中向上前进。当列到达顶部时,下一列在上一列的左侧,并继续向下。每当当前列到达矩阵的边缘时,移动到下一列并改变方向。如果遇到功能模式或保留区,则数据位将放置在下一个未使用的模块中。

向上放置

下图显示了当列向上移动时放置数据位的顺序。

以下示例说明了数据码在首列中向上移动的过程。

向下放置

下图显示了当列向下移动时放置数据位的顺序。

以下示例说明了数据码向下移动的过程。

跳过功能模式

当遇到功能模式时,跳过已被占用的模块,直到到达下一个未使用的模块。

掩码

如果一个模块被掩码覆盖,则亮模块变暗,暗模块变亮。换句话说,就是改变模块的颜色。

掩码图案

二维码标准定义了八个可应用于二维码的掩码图案。

例如,掩码图案#1对二维矩阵中的每两行进行掩码,对于掩码图案#2,对二维矩阵中的每三列进行掩码。

八种掩码图案

当编码二维码时,有八个掩码图案,你可以使用它们来更改输出的矩阵。每个掩码图案根据它们在二维矩阵中的坐标改变位(颜色)。掩码图案的目的是修改二维码图案以使二维码扫描器更容易读取。

每个掩码模式使用公式来确定是否改变当前位的颜色。将当前位的坐标放入公式中,如果结果为0,则使用该坐标处的相反位。例如,如果坐标(1,3)的位为1,并且将该坐标放入公式得到0,则将0置于(1,3)。这里是掩码模式公式的列表。

与表格对照时,请将前面标号换算为十进制

掩码模式只应用于数据模块纠错模块。即下面模块不需要使用掩码:

  • 功能模式

    • finder patterns

    • timing patterns

    • separators

    • alignment patterns(本文用不到)

  • 格式信息区域

  • 版本信息区域

确定最佳掩码

在将掩码图案应用于二维码矩阵时,还需要根据二维码标准中定义的四个评估条件给予评分。二维码编码器必须应用所有的八个掩模图案(就叫掩模),并且对每一个图案进行评估。

无论是哪种掩模模式,最终分数最低的就是用于最终输出的掩码模式。(我们手工画,不需要计算,随便挑一种就行,这里就不详细叙述如何计算,8种模式最后都能扫出来)

我将选择0号掩码

格式字符串

格式信息字符串对当前二维码中使用的错误校正级别和掩码模式进行编码。由于存在四个可能的纠错级别(L,M,Q和H)和7个可能的掩码模式,因此存在 4×7 = 28 个可能的格式信息串。有关28个格式字符串的完整列表,请参阅格式字符串表。

生成格式信息字符串

格式信息字符串是一个15个bits的信息,每一个bit的位置如下图所示:(注意图中的Dark Module,那是永远出现的)

格式字符串表

将格式字符串放入二维码

格式信息字符串放置在最上面的finder patterns的下方和最左侧的finder patterns的右侧,如下图所示。

图像中的数字14指的是格式字符串的最高有效位,数字0指的是最低有效位。

例如,使用上面例子(用的0号掩码,纠错级别位Q)中的格式字符串011010101011111,下面图像中的数字对应于格式字符串位如下:


好了,现在我们把数据准备一下,开始填充

数据码:

00100000 00111101 00000000 10111100 00110100 00000010 11110000 11110011 00000110 00010110 01010010 00101110 00000000

纠错码:

58 253 16 114 183 245 176 209 91 64 141 165 77

将其转换为8位二进制(每个都转换成八位)

00111010 11111101 00010000 01110010 10110111 11110101 10110000 11010001 01011011 01000000 10001101 10100101 01001101

放在数据码后面

00100000 00111101 00000000 10111100 00110100 00000010 11110000 11110011 00000110 00010110 01010010 00101110 00000000 00111010 11111101 00010000 01110010 10110111 11110101 10110000 11010001 01011011 01000000 10001101 10100101 01001101

按照上面的顺序填充


填充完后效果如图(但是这个不能扫描,必须经过掩码操作)

在excel里填充的

我选择0号掩码

000号掩码

放入拷贝台,进行异或运算(记录下两张图不一样的块)


因为在拷贝台上只能看出深色块,所以教大家一个巧法,先把一张放在上面,记录不一样的黑块,标识出来(因为如果上面是黑,下面是白,看不出来,黑把白挡住了),然后再把另一张标识出来

最后画出来,一样就是白块,不一样就是黑块,标识出来的都是黑块

最终成果

请注意:本二维码无法长按识别(网格线干扰)建议用另一台手机扫描

修复内容错误后重新上传

如何手算一张二维码的评论 (共 条)

分享到微博请遵守国家法律