分享

大家都熟知二维码,那么字符串是怎么转换成二维码的呢?原理是啥?

 山峰云绕 2020-04-23

https://m./question/6813881252714643727/?app=news_article&app_id=13&share_ansid=6818576869332353287 




http://toutiao.com/group/6818576869332353287/?iid=0&app=news_article 



移动互联网时代,二维码在我们身边可以随处可见,手机支付有付款码,公交地铁有乘车码,还有最近出现的健康码。

其实不管是付款码还是乘车码,本质上它们都是二维码,那么二维码到底是什么呢?

二维码是什么?

回想一下我们在超市买东西时结账的流程:首先我们打开付款码,接着收营员扫我们的付款码,然后钱就自动从我们的账户中扣除了。

可以看出,扫码付款的过程就是从二维码到人的一个过程,从二维码所代表的信息中找到我们的账户信息并从中扣款。

那么二维码所代表的信息是什么时候确定的?当然是生成二维码的时候啦!

我们要使用手机支付功能,首先必须注册账号,此时账号就代表了我们。打开付款码的时候,系统会将我们的身份信息经过一些计算,最终生成一个二维码并展示给我们。

生成二维码的过程就是将信息转换成二维码的过程,扫码的过程则是将二维码再转换成信息的过程,所以二维码本质上只是信息的一种展示形式而已

二维码结构分析

虽然二维码看起来是毫无规律的,但其实二维码的生成有着固定的格式。

大小

二维码的大小存在 40 种版本(Version),从Version1(21x21的正方形)到Version40(177x177的正方形),每增加一个 Version,大小都会增加 4。

版本越大二维码就会越大,随之所能表示的数据量也就越大。

结构

二维码呈正方形,通常由黑白小方块组成,二维码的整体结构可以分为定位标记、功能区以及数据区三大部分:

  • 定位标记——在二维码的左上角、右上角、左下角有3个类似“回”字的方形图案,这3个图案是用于二维码的定位标记。正因为有定位标记的存在,所以不管我们以什么角度扫描,二维码总是可以被准确的识别出来。二维码中还存在一些小一点“回”字,它们是用于校正定位的标记,并且只会在Version 2及以上版本的二维码中才会出现。

  • 功能区——功能区分为两部分,即图中红色部分和紫色部分。红色部分存放格式信息,用于表示该二维码的纠错级别(至于纠错级别是什么后面在解释),紫色部分存放版本信息,即该二维码的尺寸大小。

  • 数据区——数据区指的是除去定位标记和功能区的其他部分(图中灰色部分),用于保存二维码实际所表示的信息的数据码以及用于纠错的纠错码。

纠错级别

二维码一般有一定的容错率,所以即使二维码被遮挡住一部分,仍然可以被扫描出来,原理就是在生成二维码的过程中对数据做了冗余处理,冗余程度越高容错率就越高(纠错级别越高),二维码能被遮挡的部分自然也就越多。

二维码的纠错级别从低到高分为L(7%)、M(15%)、Q(25%)、H(30%)4个等级,如果需要在二维码中间加logo,那么我们就应该生成H级别的二维码,但也并不是纠错级别越高越好,级别越高需要冗余的数据就越多,那么生成的二维码的复杂程度也就越高,实际使用过程中我们应该根据需求选择合适的纠错级别。

编码模式

我们都知道计算机只认二进制信息,所以我们需要把字符串中的数字、字母、汉字以及各种字符统一转换成由0和1组成的二进制数字串计算机才能识别,所以生成二维码的过程就是将字符串转换成二进制数字串的过程。

最后生成的二进制数字串对应到二维码上,0对应白色的小方块、1对应黑色小方块,按照8个一组依次填充到数据区就是一个完整的可以被识别的二维码了。

根据源字符串类型,二维码主要支持4种标准化的编码模式,分别为数字编码、字符编码、字节编码以及日文编码,当然也支持其他一些特殊的字符集编码以及混合编码。

每种编码模式对应一个4位的二进制的编码模式指示符:

下面以字符编码举个例子,现在有字符串“HELLO WORLD”

1、模式指示符——根据查表可知HELLO WORLD需要使用字符编码模式,所以它的模式指示符为0010。

2、字符计数指示符——表示源字符串的长度,字符计数指示符必须放在模式指示符之后。

字符计数指示符的计算依赖于二维码的版本以及编码模式:

以版本1为例,字符编码需要9bits,HELLO WORLD长度为11,转为二进制为1011,不足9位,左边补5个0得到最终结果000001011,加上模式指示符目前我们得到的二进制数字串为0010 000001011。

3、对原字符串编码,

将HELLO WORLD两两分组得到(H,E)、 (L,L)、(O, )、(W,O)、(R,L)、(D);

根据索引表找到每个字符对应的值,得到(17,14)、 (21,21)、(24,36)、(32,24)、(27,21)、(13);

将每组数字先转成45进制、再将结果转成长度11的二进制串,长度不足的补0。例如(17,14) 转成45进制为17*45+14=779,再将779转成二进制 1100001011,左边补1个0得到01100001011,如果最后一组是单独一个,则转成6位的二进制串,所以字符串HELLO WORLD经过字符编码之后,再加上前面计算好的模式指示符和字符计数指示符之后最终得到

0010 000001011 01100001011 01111000110 10001011100 10110111000 10011010100 001101。

4、 在确定二维码的版本和纠错级别以后,字符串的编码结果应该是一个固定长度的二进制串,如果我们计算的结果长度不够就需要进行不起操作。

例如确定二维码的版本1和纠错级别Q,则最终二进制串的长度需要达到104位。

在第3步中我们得到的最二进制串的长度为74,所以需要进行补齐操作。首先末尾可以至多追加4个0,接着末尾补齐更多的0直到长度是8的倍数,如追加4个0后长度达到78,要达到8的倍数则还需要补2个0;如果这时候长度还没有达到目标,那就在末尾循环追加固定的二进制码11101100 00010001直到达到目标长度。

最后来看一下HELLO WORLD经过字符编码之后结果

掩码图

源字符串在经过编码之后被转换成二进制的数字串,根据这个二进制数字串画出来的二维码通常会存在黑白色块分布不均的情况,这会导致二维码容易扫描失败。

为了解决这个问题,官方提供了8种掩码方案:

我们需要选择一个掩码图与我们生成的二维码再做一次异或操作,这样黑白色块分布就会更加的均匀。

那应该选择哪个掩码图呢?这里面涉及到的原理就比较复杂了,大概过程就是先将8个掩码图与二维码都分别进行异或操作,再按照某个规则计算出8个结果的均匀程度,最后取其中效果最好的一个。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多