手绘二维码攻略

提到二维码想必大家都不陌生,扫码支付、添加好友以及关注公众号等,随处可见二维码身影。通常我们见到的二维码会有三个用于定位的黑白嵌套的方块,这基本上就是 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 有生成和解析二维码的模块可以直接调用,花精力琢磨二维码编码过程可以帮助更深入了解相关模块其背后机制,甚至于可以依照原理去研究源码,也权当对自己编码算法的一种锻炼吧。

本文分享自微信公众号 - TTTEED(TEDxPY),作者:TEDxPY

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-09-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 初识 QR 二维码(零)

    提到二维码,想必大家每天都会接触到,扫码支付、扫码添加微信好友等都会用到。关于二维码的生成原理,网上确实有些介绍,但基本涉及到具体编码就一笔带过没有深入了。目前...

    TTTEED
  • QR 数据编码详解(二)

    每种编码模式针对其字符,不断优化以产生最短的编码二进制串。在此过程中它们采用的编码方法是不同的,本篇将主要解释数据编码过程。

    TTTEED
  • 构建最终编码(四)

    经过生成纠错码环节,目前我们已经拥有了数据编码和其对应的纠错码。最初我们提到过,较大的 QR 二维码需要我们数据码拆成小块,而且针对每一块生成对应的纠错码。在这...

    TTTEED
  • 初识 QR 二维码(零)

    提到二维码,想必大家每天都会接触到,扫码支付、扫码添加微信好友等都会用到。关于二维码的生成原理,网上确实有些介绍,但基本涉及到具体编码就一笔带过没有深入了。目前...

    TTTEED
  • Qt for Python的4种基础布局管理

    在上一篇文章中,我们介绍了Qt for Python中主窗口控件MainWindow()的基本使用。

    州的先生
  • 啰里吧嗦kafka

    kafka是一种高吞吐量的分布式发布订阅消息系统,用它可以在不同系统中间传递分发消息

    葫芦娃
  • 异常处理:IDEA Git 修改后的文件无法Commit

    因对IDEA使用不熟,在使用和配置GIT的时候,可能哪里配置错误,导致我一直无法使用IDEA提交项目,并且提示异常: The directory <Projec...

    执笔记忆的空白
  • python笔记:python调用C库

    在python中实现算法性能较差,所以在某些瓶颈处,可以把算法用C语言的实现。编译成动态链接库,再让python调用。

    超级大猪
  • python 倒计时 9,8,7,。。。

    今天找了好几个人写 一个脚本,就是用python 写一个倒计时的脚本。之前用shell写很容易的几句话就能完成。

    py3study
  • 移动搜索SEO:网站移动适配之Meta标注、移动跳转终结篇

    这些天,在给博客的标签页(tag)添加跳转和 META 动态申明时,居然让我醍醐灌顶,发现之前的动态适配的做法是多么的苦逼和小白! 总结前,先来回顾下小白张戈在...

    张戈

扫码关注云+社区

领取腾讯云代金券