我想知道我们可以在多大程度上采用无损数据压缩;我无法找到无损算法的在线模拟器来执行一些经验测试。 我可以自己做一个,但不幸的是我没有足够的时间在这个时期;我仍然对我的直觉感到好奇,我将要解释。
我们只采用两种比较流行的算法:Huffman Coding
和Run-lenght Enconding
。
我们假设我们有一个数字A
符号的字母表和该字母表中任意长的符号序列:例如:
Alphabet = {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, X, W, Y, Z}
Sequence1 = SFBJNERUSNJGSDKKDEIJGNMSDJDDSUSJNF
Sequence2 = MNMNMNREGUHSDFJUF
Sequence3 = MMMMMNNNNNASDUERJGASIUJMMMNNNUNS
现在,如果我们只使用n
位的固定长度字对每个符号进行编码,我们就会得到未压缩的序列,即长{,1}位。
如果我们使用Huffman对序列进行编码,我们将使用N
位而不是H
位,从而节省N
位空间。
如果我们使用RLE编码相同的序列,我们将使用(1-H/N)*100%
位,保存R
。
我想知道,如果我们应用(1-R/N)*100%
或RLE + Huffman
会发生什么,我们可以比仅使用其中一个节省更多空间。
这对我来说似乎是一个非常基本的想法,但谷歌搜索我没有设法找到关于这个主题的任何内容。
编辑:嗯,我可能没想到如果我先使用RLE,我将无法使用Huffman,因为单个符号的固定长度代码的相关性将是丢失;但是仍然应该可以先使用霍夫曼,然后再使用RLE。
顺便说一句我对其中的逻辑感兴趣,我的意思是使用串联多个无损压缩算法。
编辑2:当我评论Mark Adler的回复时,我意识到我可能已经找到了问题的答案。就是这样:
作为符号到符号代码的Huffman如何影响检测?
假设我们有以下代码:Huffman + RLE
。
在纯二进制文件中,它将被编码为AABCABAAB
(obv空格仅用于可读性目的)。
霍夫曼会将其编码为00 00 01 10 00 01 00 00 01
。空格更显示字符串未被更改的方式,因此可以检测到完全相同的重复次数,假设我们正在接近此范围内的代码(符号方式)。
这引出了另一个观点(鉴于这已经是一个很长的评论,我不会在这里讨论):逐位分析代码。
所以,我实际上认为我得出了一个结论:我们知道,任何字典(或基于替换的)编码器将可变数量的符号分组为固定长度的码字,而霍夫曼(或任何其他熵编码器)代码固定将长度符号转换为可变数量的比特,从而将熵近似为最小值; ergo ,让Huffman先运行是毫无意义的(而且只是浪费计算量),因为其他算法很可能会引入更多冗余 霍夫曼能够减少的。
当然这只是一篇理论论文,因为在实践中我们可以考虑其他因素(例如计算时间)......更不用说要编码的字符串的不同配置可能导致不同的结果。但是,嗯......这对我来说很有意义。 :)
答案 0 :(得分:4)
这些组合经常进行。你应该读一些关于压缩的书。
LZ77是一种更通用的RLE形式,可复制先前字符串的重复。 (距离1和长度 n 的匹配代码运行最后一个字节的 n 副本。)LZ77通常后跟霍夫曼,算术或范围编码。
霍夫曼应该遵循LZ77或RLE,而不是先于它。霍夫曼编码将使检测重复变得更难,而不是更容易。为了首先使用RLE,您只需将符号集扩展到文字之外。作为一个示例,zip,gzip,zlib等中使用的Deflate格式具有286个符号集,以编码256个字节字节,29个长度前缀代码和流代码的一端。 29个长度前缀代码中的每一个都意味着在代码之后添加0到5位后缀以添加到基值以获得长度。长度代码及其后缀的存在意味着它后面是另一个霍夫曼代码,30个距离代码前缀之一,每个代码前缀为0到13位,用于指定匹配的后退距离。
还有许多其他变换(可能会或可能不会自行压缩),然后是熵编码。这些包括Burrows-Wheeler变换(BWT),Move-To-Front变换(MTF),它经常遵循BWT,图像的离散余弦变换(可以无损地完成,但最常用于有损压缩算法)变换以可逆的方式对数据中的共性进行分组,为熵编码步骤提供更多的增益。