手绘二维码攻略


提到二维码想必大家都不陌生,扫码支付、添加好友以及关注公众号等,随处可见二维码身影。通常我们见到的二维码会有三个用于定位的黑白嵌套的方块,这基本上就是 QR 二维码(Quick Response Code)。

今天我们就手动编码生成一个可以被识别的二维码~

初次尝试,我们把要编码的文本设置得简单些"HELLO WORLD",只包含大写字母和空格。相应地,我们要采用 QR 二维码中较为简单的字符编码模式来将信息转化为一串由 1 和 0 组成的数据编码。

QR 二维码中有版本和纠错级别的概念,这里我们选用版本 1-M,即版本 1,纠错级别 M,编码模式选用字节编码。

  1. 首先得到编码模式指示符:字节编码对应 0100

  2. 其次计算文本信息中字符数,"HELLO WORLD" 10 个字母 1 个空格共计 11 个字符,转化为 9 位的二进制串:000001011

字符编码

接下来我们进入字符编码,先把文本字符分成两两一组:

HE,LL,O空格,WO,RL,D

根据字符索引表查得每个字符对应的索引值:

然后将每组中第一个字符索引值乘以 45 加上第二个字符索引值,将结果转化为 11 位的二进制数,不足 11 位在左侧补 0 以达到长度。

  • HE 对应 779 转化为 01100001011

  • LL 最终转化为 01111000110

  • O空格 最终转化为 10001011100

  • WO 最终转化为 10110111000

  • RL 最终转化为 10011010100

如果要转化的是奇数位字符,那么最后单独的字符这一组将转化为 6 位二进制位:

  • D 对应 13 转化为 001101

二维码数据编码

这样我们得出了 61 位的字符编码。根据 QR 二维码规范,版本 1-M 的二维码需要 128 位长度的数据来填充,目前我们有 4 位编码指示符(0100),9 位字符计数符(000001011) ,和 61 位的字符编码,共计 74 位,还差 54位。

接下来由于差 54 位,很明显大于 4,所以要添加一个 4 位的终止符 0000。这样长度来到了 78 位,接下来我们要继续补 0 使得长度恰好为 8 的整倍数,这里要继续补 2 个 0 得到 80 位。换言之,在本段中相当于在之前 74 位字符后加了 6 位的 0:000000,目前以达 80 位长度。

接下来的规则是在其后交替添加 11101100 和  00010001 直到字符长度达到 128 位。80 位 到 128 位差 48 位,需要交替添加 6 次上述字符串,即在其后添加 11101100  00010001 11101100 11101100  00010001 11101100。

最终我们可以得到 QR 二维码所需的 128 位数据编码

00100000 01011011 00001011 01111000 11010001 01110010 11011100 01001101 01000011 01000000 11101100 00010001 11101100 11101100  00010001 11101100

纠错码

将之前产生的 128 位数据编码每 8 位一组,每组转化为 10 进制数字,由此得到 16 个数字:

32, 91, 11, 120, 209, 114, 220, 77, 67, 64, 236, 17, 236, 17, 236, 17

将其作为信息多项式系数,得到信息多项式:

32 * x^15 + 91 * x^14 + ... + 17 * x^0

由 QR 二维码规范或者相关小工具查得,1-M 二维码需要 10 个纠错码,对应的生成多项式如下:

通过信息多项式与生成多项式除法(过程较复杂,详情可见《QR 二维码纠错码(三)》),我们可以得到 10 个纠错码

196  35  39  119  235  215  231  226  93  23

转化为 10 个 8 位二进制:

11000100 00100011 00100111 01110111 11101011 11010111 11100111 11100010 01011101 00010111

至此,我们已经得到 128 位数据编码80 位纠错码

开始手绘

二维码说白了就是在一系列方格中填充黑白块,版本 1-M QR二维码是 21 x 21 单位的方格集合。为了在电脑端手绘,我采用 Excel 表格来模拟绘制。原理也很简单,打开空白表格,将行高和列宽设置成相同,挑选 21 x 21 的方格区域作为 QR 二维码绘制区域。

首先向其中左上、左下和右上角添加定位模块、隔离模块、时间模块和黑色码元,以及蓝色标注的预留信息区域:

以上标注的黑、白、蓝色区域在 QR 版本 1 的二维码中是固定的,蓝色区域等待之后填充格式信息,浅绿色区域即我们之前得到的 128 位数据编码和 80 位纠错码要填充的区域,我们可以计算下在这 21 x 21 = 441 个格子里,目前黑白蓝色已占据了 233 个,恰好剩余 208 个位置填充数据相关信息。

接下来按照图示红色路线从右下角开始填充这 208 位二进制(因为图示以版本 3 为例,我们的版本 1 更简略):

经过一番填充,进展如下:

预留格式信息

目前只剩蓝色区域的预留格式信息尚未填充,这里预留格式信息需要选择二维码的掩码模式,选定掩码模式后,需要按照掩码规则对该二维码特定位置的单元格进行修改变换。

其实按流程,我们需要将 8 中掩码模式都采用并生成结果二维码,然后根据一个损失评分挑选其中损失分最低的掩码模式。

这里我们随机选择掩码模式 0。根据 QR 二维码的格式版本信息表查得,纠错级别 M、掩码模式 0 情况下的格式信息15 位二进制为 101010000010010。

将 15 位格式信息按照下图 0 到 14 的顺序依次填入二维码表中:

填充完毕如图:

掩码

最后一步,掩码。我们采用的掩码模式 0,即对行和列之和为偶数的坐标点进行变换,例如 [0,0] [1,1] [0,3] [1,3]等坐标点处,若之前为白色则转为黑色,若之前为黑色则转为白色。

掩码只对我们填充的 208 为数据编码和纠错码进行处理,其余预先填好的功能模块和预留区域都不受掩码影响。

经过掩码处理后的 QR 二维码结果如图:

用微信扫一扫,得到扫描结果 "HELLO WORLD",成功~!


后记:

在接触二维码相关资料过程中,因为没找到合适的中文资料,我将一套英文版的 QR 二维码教程给翻译了一遍,列在今天同时发表的副文里从(零)到(六),本文中未展开的细节可以在相关部分找到详细介绍。

本来想着自己手算个 "I LOVE U" 的纠错码的,结果算到一半卡住了,只好退而求其次,选用素材中验证过的 "HELLO WORLD" 当原型来绘制二维码了。

此外,Python 有生成和解析二维码的模块可以直接调用,花精力琢磨二维码编码过程可以帮助更深入了解相关模块其背后机制,甚至于可以依照原理去研究源码,也权当对自己编码算法的一种锻炼吧。

好久没更新,对不住哈,之后继续努力!

发布了70 篇原创文章 · 获赞 46 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_40796925/article/details/102426603