甚至可以使用例如具有 4 位邻域的算术编码来处理基于每个字形的字体压缩:
[ 4 ] [ 3 ] [ 2 ]
[ 1 ] ( x )
每个像素邻域 p1,p2,p3,p4 编码 x==0 与 x==1 的概率,在处理完位 'x' 后更新;与霍夫曼编码器不同,算术编码器能够以比单个比特更小的单元压缩符号,这是香农信息论给出的限制。
Context, count bits per symbol
Zeros[ 0] = 45 Ones[ 0] = 4 19.987
Zeros[ 1] = 7 Ones[ 1] = 4 10.402
Zeros[ 2] = 6 Ones[ 2] = 0 0.000
Zeros[ 3] = 2 Ones[ 3] = 2 4.000
Zeros[ 4] = 6 Ones[ 4] = 5 10.934
Zeros[ 5] = 0 Ones[ 5] = 1 0.000
Zeros[ 6] = 2 Ones[ 6] = 0 0.000
Zeros[ 7] = 9 Ones[ 7] = 4 11.576
Zeros[ 8] = 5 Ones[ 8] = 13 15.343
Zeros[ 9] = 1 Ones[ 9] = 3 3.245
Zeros[10] = 4 Ones[10] = 0 0.000
Zeros[11] = 1 Ones[11] = 3 3.245
Zeros[12] = 2 Ones[12] = 2 4.000
Zeros[13] = 1 Ones[13] = 0 0.000
Zeros[14] = 1 Ones[14] = 5 3.900
Zeros[15] = 3 Ones[15] = 3 6.000
Total 92.634 bits = 12 bytes
vs. no context,
Zeros = 95 Ones = 49 133.212 bits = 17 bytes
显而易见的问题是如何初始化数组:
1) 使用固定的,即频率的静态模型
2) 使用完全自适应模型,假设开始时有 50:50 的机会
3) 使用一组 (2-256?) 固定模型,最能表征字形
4) 开始使用预先计算的集合中的一些模型并更新
一个完整的模型需要 32 个字节来编码 0..169 的值,因此除非非常强烈(并且巧妙地)压缩,否则不能与字符一起传递。
编辑
如果使用单个(或很少使用全局静态表),也可以将表扩大到 5,6,7 像素邻域,或将像素位置信息嵌入到表中(此方法无法编码条件 'x位于底线'):
[ B ] [ C ] [ D ], where A,B,C,D = 00 for 'white'
[ A ] (x) 11 for 'black'
01/10 for pixel outside canvas
or
[ 1 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] + [ x is next to border? ]
[ 0 ] [ 2 ] (x)
进一步阅读:
-传真压缩/ JBIG
-算术编码