1. 统计编码(statistical encoders)的算法1.1. 每种编码方法都对每个符号的概率分布做了不同的假定1.2. 需要处理的数据集中符号的概率分布与现有的VLC方法都不能完全匹配1.3. 统计编码算法通过数据集中符号出现的概率来进行编码使结果尽可能与熵接近1.4. 给定任何输入数据,我们都能为其构造出一套自定义的码字集,而无须去匹配现有的VLC方法1.5. 该算法以数据流中符号的频率为依据,为该数据流中的各个符号分配长度可变的码字,从而使最终的输出压缩得更小2. 国际电信联盟H.82建议书(ITU-T,1993)将熵编码定义为“任意无损的压缩或解压数据的方法”3. 熵编码的技术用途3.1. 也可以称为“香农–范诺编码”或“哈夫曼编码”3.2. 给定二进制位率时增加信噪比3.3. 给定信噪比时减少二进制位率4. 香农–范诺编码4.1. 由香农于1948年提出,随后他将它告诉了罗伯特•范诺(Robert Fano),范诺后来将它作为技术报告正式发表了4.2. 最早通过符号及其出现概率来生成VLC的方法之一4.3. 它没有达到最短的码字长度预期,但它已经很接近了4.4. PKZIP/IMPLODE格式使用了两到三棵香农–范诺树(Shannon-Fano tree)5. 哈夫曼编码5.1. 计算机科学和数据通信领域内人员一直都在使用的基本思想之一5.2. 对于给定的数据集,为了产生小的、自定义的VLC,你需要一个输入是概率列表、输出是码字的算法5.3. 哈夫曼编码可能是生成自定义VLC最直接、最有名的方法5.3.1. 给定一组符号及其出现频率,该方法能生成一组符号平均长度最短的VLC5.3.2. 如果使用二叉树,就能利用符号表中的概率与二叉树的分支来创建优化的二进制代码5.4. 工作原理5.4.1. 将数据排序后建立决策树(decision tree),然后从“树干”一直往下直到“树叶”为止,并记录下所做的是/否选择5.4.2. 为了获得给定符号(叶子节点)的码字,需要从根节点“沿着树枝”往下走,并将所得的1和0按从MSB到LSB排列起来,也就是从左排到右5.5. 由于创建哈夫曼树(需使用计算资源)要比传输符号码字对应表(会增加数据流大小)困难得多,因此总是应该将码字对应表加在数据流的前面,而不是在解码时再重新创建一次5.6. 简单、高效,也能为单个的数据符号生成最佳的码字5.7. 对于给定的符号集来说,它并非总是生成最有效的码字5.8. 能生成理想VLC(即码字的平均长度等于符号集的熵)的唯一情形是,各个符号的出现概率等于2的负整数次幂(即是1/2、1/4或1/8这样的值)6. 算术编码6.1. 早在20世纪60年代初,Peter Elias就首先提出了算术压缩背后的概念(即算术编码)6.2. 20世纪70年代,才由IBM公司的Jorma Rissane针对其实现发表了第一个有效的研究,随之而来的还有相应的专利6.3. 会将整个输入流转换为一个长度很长的数值,而它的lb表示则与整个输入流真正的熵值很接近6.4. 它将转换应用到整个源数据上以生成一个输出值,而表示这个输出值所需要的二进制位数比源数据本身少6.5. 现代主流的文件、音频和视频的压缩格式(如LZMA和BZIP这样的文件格式,JPEG、WebP、WebM和H.264这样的音视频格式),在统计编码步骤上都会使用算术编码压缩方法6.6. 工作原理6.6.1. 将字符串转换为一个数,与字符串相比,表示这个数需要的二进制位数要少一些6.7. 目前的主流算法6.7.1. 应用在大多数的多媒体编码器中,甚至有了有效的硬件实现7. 区间编码7.1. Range Coding7.2. 1979年7.3. 所做的事情与算术编码基本相同,却不受算术编码相关专利的约束8. ANS8.1. 2007年8.1.1. 在数据压缩领域里出现的时间还不长8.1.2. 已开始取代过去20多年里占据主流地位的哈夫曼编码和算术编码8.1.2.1. ZHuff、LZTurbo、LZA、Oodle和LZNA这些压缩工具已开始使用ANS8.2. 2013年8.2.1. 又出现了一个被称为有限状态熵(Finite State Entropy,FSE)的更注重性能的版本8.2.1.1. 它只使用加法、掩码和移位运算,使ANS对开发人员更具吸引力8.3. 2015年8.3.1. 推出了一款名为LZFSE的GZIP变种,作为苹果下一代iOS版本的核心API8.4. Jarek Duda引入了一种新的与数据压缩有直接关联的信息论概念:非对称数字系统(asymmetric numeral systems,ANS)8.5. 一种新的精确熵编码方法,所得到的结果可以和最优熵任意接近,它的压缩率与算术编码接近,而性能则与哈夫曼编码相当8.6. 工作原理8.6.1. 根据符号的出现频率对数值区间进行细分8.6.2. 创建一张表,将子区间与离散的整数值关联起来8.6.3. 每个符号都是通过读取和响应表中的数值来处理的8.6.4. 向输出流中写入可变的二进制位位数8.7. tANS是ANS的一种变体,它是围绕着一张表格工作的8.7.1. 创建备查表8.7.1.1. 它使得从符号转换为数值再从数值转换为符号成为可能8.7.1.2. 表中的每个值都是唯一的(即不存在重复)8.7.1.3. 每列都按照值从小到大排序8.7.1.4. 每行的值都要比该行的行号大8.7.2. 想要tANS变成真正的熵编码器8.7.2.1. 在确定每一列值的个数时,需满足该值乘以maxVal后,等于该列符号的出现概率8.7.2.2. 在确定每一行的值时,需确保该行列选择的值与该列符号的出现概率一致,这样当用该值除以行号,所得商就会(近似)等于该列符号的出现概率8.7.3. 压缩来自于逐位输出(bit-wise output)8.7.3.1. 出现可能性越小的符号其列高越低,有效的行号值离最可能出现的符号也就越远(二进制位距离意义上的远)8.7.3.2. 为了得到更小的行号,就需要进行更多次的右移操作,这也意味着每次循环会有更多的二进制位输出到数据流8.7.3.3. 出现可能性越小的符号,就会输出更多的二进制位到最终的数据流中