编码 | 解码 | 压缩

> mtf | move | front <

// Move-to-Front —— 为更好压缩而动态重排列表

[ADAPTIVE]

自适应

自动适应数据中的局部模式。

[LOCALITY]

利用局部性

最近出现的符号拥有更小的索引,从而获得更好的压缩率。

[BZIP2]

bzip2 组成部分

在 bzip2 压缩流水线中,通常用于 BWT 之后。

>> 技术细节

MTF 的工作原理:

MTF 维护包含所有可能符号的列表。编码某个符号时,输出它在当前列表中的位置,然后把该符号移到列表前端。这样,最近使用的符号会集中在前部、拥有较小索引,后续的熵编码就能更高效地压缩这些数据。

编码示例:

文本:"banana" 初始列表:[a,b,c,d,...] "b":索引 1,将 b→前端 [b,a,c,d,...] "a":索引 1,将 a→前端 [a,b,c,d,...] "n":索引 13,将 n→前端 [n,a,b,c,...] "a":索引 1,将 a→前端 [a,n,b,c,...] "n":索引 1,将 n→前端 [n,a,b,c,...] "a":索引 1,将 a→前端 [a,n,b,c,...] 输出:[1,1,13,1,1,1]

为什么要使用 MTF:

  • >提升局部冗余的可压缩性
  • >与 BWT 配合良好
  • >实现简单
  • >可逆变换
  • >可随模式自动调整

>> 常见问题

什么是 Move-to-Front 编码?

MTF 是一种数据变换算法,它把每个符号编码为在动态更新列表中的索引。每次编码后,该符号会被移到列表前端,这样经常出现的符号就会拥有更小的索引。

为什么要和 BWT 一起使用 MTF?

BWT 会把相似上下文聚集在一起,产生大量局部重复。MTF 将这些重复转换成较小的数字(包含大量 0 和 1),非常适合后续的游程编码或 Huffman 编码来进一步压缩。

MTF 列表是如何运作的?

列表一开始包含按顺序排列的全部 256 个字节值。随着符号被编码,已使用的符号会被移到前端。最近使用的符号停留在前部,索引较小,而长期未使用的符号会逐渐被推到后面、索引变大。

MTF 与其他变换相比有什么特点?

MTF 是专门为接在 BWT 之后而设计的。单独使用时效果有限,但在把 BWT 输出转换为更易压缩的形式方面非常出色。相较算术编码,它更易实现,但压缩最优性略逊一筹。

// 计算示例

#SymbolIndexList
1b1abcdefg…
2a1bacdefg…
3n13abcdefg…
4a1nabcdef…
5n1anbcdef…
6a1nabcdef…

// 代码示例

Input     banana       initial list: a b c d ... z (index from 0)
Output    1 1 13 1 1 1
Encode    output the index of the symbol, then move it to the front
Decode    read index, output list[index], move it to the front
Use       after BWT: runs of equal symbols become runs of 0s,
          which RLE and Huffman/arithmetic coding then compress well (bzip2)

>> 更多问题

问:Move-to-Front 有什么用?

答:MTF 本身不是压缩,而是一种变换:最近出现的符号获得较小的索引,产生大量 0 和 1,便于后续熵编码(哈夫曼、算术编码)压缩。

问:它与 Burrows-Wheeler 变换有什么关系?

答:BWT 会把相同字符聚成连续段,MTF 再把它们变成一串小数字,尤其是 0。bzip2 使用的就是 BWT → MTF → RLE → 哈夫曼 这条链。

问:MTF 是无损且可逆的吗?

答:是。解码端从相同的初始列表出发,重复相同的移动即可还原。初始列表(字符集与顺序)两端必须一致。

其他语言