有关游程编码的定义,在网上有很多较为专业的版本,但我觉得那些较为专业的版本就是把简单的东西搞复杂然后看起来高大上罢了,入门太麻烦。这里我们沿用本章开始提到的那篇博客中的内容:“什么叫游程呢?就是一段完全相同的数的序列。什么叫游程编码呢?说起来原理更简单,就是对一段连续相同的数,记录这个数一次,紧接着记录出现了多少个即可。”,这样说多浅显易懂。举个简单的例子,有如下数列,
1,1,1,1,2,2,2,2,2,2,2,2,4,4,4,4,9,9,9,9,9,9,9,9;
1出现了四次,重复了三次(后面那三个1算作“重复”,注意“出现次数”与“重复次数”的差别),2出现了八次,重复了七次,4出现了四次,重复了三次,9出现了八次,重复了七次。对其用使用游程编码,就是
1*3,2*7,4*3,9*7;
其中,用“*”将实际的数与该数重复的次数区分开来。从上例可以看出,游程编码对这种连续重复出现的数据有很好的压缩效果。注意,我这里使用“*”作为标记只是作为一个例子,用这种方式进行游程编码也只是一个例子,但是符合规则,各位看官不要以为游程编码一定是这么来操作的,游程编码没有这么死板,只要符合上面的基本定义即可,具体怎么操作视情况而定。
在deflate算法中,相应的游程编码有专门的使用细则,这里我只讲是什么,后面再讲为什么,各位看官这里要做的只是了解deflate如何使用游程编码以及使用细则,会用即可,后面会详细分析这块内容。
Deflate算法中的游程编码只对0~15这十六个数进行游程编码(只有这十六个数,不要管为什么,后续会讲),而且只对重复次数不小于三次(那么这个数据的总的出现次数就不能小于四次)时才使用游程编码:
i. 用“16”充当上文例子中的“*”,但是这个“16”只给1~15使用。“16”后面就是表示重复次数(注意区分“出现次数”)的数据,用2bit(两比特)记录,分别是“00,01,10,11”,对应的重复次数分别为“3,4,5,6”(重复次数不小于三次,所以这里从3开始,因为只用两位记录,所以最大的重复次数是6),如果6次之后紧跟着还有重复,那么就再来一个“16”并且后面跟着实际的重复次数即可;
ii. “17”专门给0使用,所以不需要类似“*”的标志来隔开被编码数据与重复次数。“17”后面跟3bit(三比特),对应用二进制表示的闭区间[000, 111],表示0的连续出现次数为闭区间[3, 10]次;
iii. “18”专门给0使用,所以不需要类似“*”的标志来隔开被编码数据与重复次数。“18”后面跟7bit(七比特),对应用二进制表示的闭区间[0000000, 1111111],表示0的连续出现次数为闭区间[11, 138]次。
例如,有如下经过游程编码的数据,请将其解开,
4, 16, 1, 3, 3, 3, 6, 16, 3, 16, 0, 17, 3, 2, 16, 0
a) 看到“4, 16, 1”,这是对4进行游程编码的结果,1表示4的重复次数为四次,即4的出现次数为五次,所以对这三个数解码就是“4, 4, 4, 4, 4”;
b) 看到“3, 3, 3”,就是实际的“3, 3, 3”,未经过游程编码;
c) 看到“6, 16, 3, 16, 0”,这是对6进行游程编码的结果,3表示6的重复次数为六次,后面还有一个“16”,说明后面的0仍然表示6的重复次数,0即表示6重复了三次,所以6总共重复了九次,总共出现了十次,即“6, 6, 6, 6, 6, 6, 6, 6, 6, 6”;
d) 看到“17, 3”,表示0一共出现了六次,即“0, 0, 0, 0, 0, 0”;
e) 看到“2, 16, 0”,即“2, 2, 2, 2”。
从上例我们可以看出,“16”要带着“被编码数”和“被编码数的重复次数”,而17和18因为专门表示0的出现次数,所以只要带着“出现次数”即可。因为“重复次数”和“出现次数”都从3开始,而实际用来表示这两个含义的数据却从0开始(“18”其实是“17”的延续),所以我们在根据重复次数或出现次数手动计算实际值的时候,直接“加三”即可,例如“6, 16, 3”,直接用重复次数3再加上3就是实际的重复次数六了;再比如“17, 3”,用出现次数3加上3就是实际出现次数六了。
总结,这里我们介绍了游程编码的基本原理并了解了deflate中游程编码的实现方式。主要还是想强调一下“重复次数”与“出现次数”的不同,这两个概念搞不清,计算“16”的游程编码时往往就少计算一次!!!而且一个被编码数后面可能连续出现多个16,比如“5, 16, 3, 16, 3, 16, 3, 16, 3, 16, 0”。这里再总结一下这三条细则:
i. 16后面跟2bit 表示[1,15]这15个被编码数的重复次数为[3, 6],对应二进制所表示的十进制数范围(即16后面跟着的数的范围)[0, 3],被编码数要出现在“16”前面;
ii. 17后面跟3bit 0连续出现次数[3,10],17后面那个数的范围[0, 7],被编码数0就不出现了;
iii. 18后面跟7bit 0连续出现次数[11,138],18后面那个数的范围[0, 127],被编码数0就不出现了。