方法概述:
1.数据分析:
分析所需要编码的数据流,确定需要编码的字符类型,以选定相应的模式来高效的将数据转变为二进制位流;
根据输入数据多少选择相应的版本和纠错等级。
2.数据编码:
根据所采用的模式的相关规则将数据转为位流,需要模式转换时,可以在新模式段开始前加入模式指示符以进行模式转换;最后将所得的位流每8位分作一个码字,再按需要加入终止符和补齐码。
3.纠错编码:
按版本和纠错等级的需求将数据码字序列分块,按块生成纠错码字。
4.构造最终信息:
将每一块的数据码字和纠错码字装配为最终序列,必要时加剩余位。
5.布置矩阵:
将寻像图形,分隔符,定位图形,校正图形和码字序列放入矩阵。
6.掩码:
在8种掩码中挑选最适合(惩罚值最小的)的掩码。
7.格式和版本信息:
格式信息包括纠错等级和掩码模式共5个二进制位再加10个格式纠错二进制位;
版本信息在Version7以上的版本需要添加。
实例:
编码内容:祝祖国母亲生日快乐❤
——祖国母亲的小儿砸LXW
编码的数据里,主要是汉字以及汉字符,另外还有一个难一点的Emoji表情符,和一个换行符,还有三个字母是笔者名字缩写。
1.数据分析:
对数据分析可知,数据字符种类多,有中文,那么,数字模式、字母数字模式、8位字节模式是显然不行了,我们采用ECI这个模式;另外版本和纠错等级我们可先将数据编好码再选。
2.数据编码:
我们选取的模式为ECI模式,首先,如果不是缺省的ECI,格式为:
标头+一个或多个模式段;
标头:ECI模式指示符,即0111,还要ECI指定符8位,通俗的来讲,我们要什么码来编,就用ECI下对应的编号,比如我们现在要用UTF-8来编码我们的数据,看到下图中,UTF-8的ECI Id为26,化作8为二进制就是0001 1010;
然后我们就把标头编好了,为:0111 0001 1010;
接下来是模式段,我们采用8位字节模式,模式指示符为0100;注意:这个模式指示符不是和开头的ECI模式那里选模式一样,这里的模式不能决定编码方式,它和紧随其后的字符计数指示符对应,可以算出数据码区的长度。
字符计数指示符的位数随版本和模式而不同,其对应表格如下:
所以我们的字符计数指示符的位数为8位,由于笔者我已经提前将数据编码好了,我可以将此处编为0100 0100,即十进制的68,表示后面还有68个8位字节(此处与模式相对应)。截至现在,我们的到的码字已经有:
0111 0001 1010 0100 0100 0100;
我们再来编码内容,第一个字为:祝。
由于我们是采用UTF-8编码的,所以我们需要得到“祝“字的UTF-8码,希望用C/C++实现二维码的,在码值获得可能不太方便,但使用Java的话,就方便多了。
下面我觉得有必要讲一下UTF-8与unicode的联系,
UTF-8其实是建立在unicode的基础之上的,但是unicode对于编号小的数据很不友好,比如1号码,000001(hex)就是它的unicode码值,也就相当于24位二进制位。所以提出了UTF-8,UTF-16,UTF-32等编码方式,UTF-8是使用最多的一种,它和unicode的转换为:
(温馨提示,unicode码值可以在word中使用快捷键alt+X得到)
比如,我们的“祝“字的unicode码值为795D(hex),二进制也就是:
0111 1001 0101 1101,那么转换为UTF-8码为:1110 0111 1010 0101 1001 1101;
好,那么我们对“祝“字的编码即为
1110 0111
1010 0101
1001 1101;
再编“祖“:同理得:
1110 0111
1010 0101
1001 0110;
“国“:
1110 0101
1001 1011
1011 1101
其余汉字省略,
然后我们来到❤处,这是特定应用格式化信息得符号,
https://dict.emojiall.com/zh-hans/emoji
大家可以在这个网址查到它的unicode码,它的unicode码有8位为:2764FE0F(hex),也就是相当于两个汉字。
结合为:
1110 0010
1001 1101
1010 0100
1110 1111
1011 1000
1000 1111
然后再编码下一个字符为回车符,其UTF-8码值等于ASCII码值为13,即
0000 1101
还要有一个换行符,这个换行符是自己手动输入的,上个回车是作者输入❤时自带的;
其UTF-8码也等于其ASCII码值10,即
0000 1010
在然后是“——”这两个符号,这两个符号的unicode码为2014(hex);
即为:
1110 0010
1000 0000
1001 0100
1110 0010
1000 0000
1001 0100
然后又是汉字,我们跳过,来到“L”处,
L的unicode码值为004C(hex),则他的UTF-8编码为:
0100 1100
X为:
0101 1000
W为:
0101 0111
到此,我们算是将数据编完了。
我们现在来选版本和纠错等级:
我们看到下图,每个版本和纠错等级后面的括号中,c表示每块中的纠错码字,k表示总的数据码字,r表示纠错容量;
我们现在不妨选择版本Version4,纠错L,那么我们可以知道,其数据码字数为80,即80*8个二进制位,而目前我们编好的码为70*8个二进制位,因此,我们的终止符应该为
0000 0000,注意终止符在容量不够的时候可以缩短或者省略;现在我们的码字数为72,而我们选的版本和纠错等级对应得数据码字数是80,那么应该添加若干个此序列
1110 1100
0001 0001
直至添满,那么我们应填充
1110 1100
0001 0001
1110 1100
0001 0001
1110 1100
0001 0001
1110 1100
0001 0001
好的,一直到现在,我们已经将数据码字全部编写好了,接下来就是纠错码了。
纠错码字是用数据码字多项式除以生成多项式得到,这著名的Reed-Solomon算法比较复杂,我们要理解清楚galois有限域中的加法和乘法是怎么运算的,这些东西,我看过一些文章,他们都讲的模模糊糊,然后就带过了,因此我打算下一篇文章来讲纠错编码的原理。