改进的LZSS压缩算法

http://blog.csdn.net/cglover/article/details/1838903

摘  要:本文提出了LZSS压缩算法在进行文本压缩时存在的问题,并给出了解决方法。改进后的算法具有较高的压缩率,实验结果令人满意。

 

关键词:LZSS;数据压缩

 

 

1 引言

 

 

随着计算机技术的高速发展,各种系统数据量越来越大,给信息存储特别是网络传输带来诸多的困难,并己成为有效获取和使用信息的瓶颈。为了节省信息的存储空间和提高信息的传输效率,必须对大量的实际数据进行压缩。实践中采用数据压缩技术,通常可以节省80%以上的费用,并且使得一些困难问题转而在技术上能够实现。

 

目前常用的压缩编码方法分为两大类:一类是无损压缩法,也叫熵编码;另一类是有损压缩法,也叫熵压缩法。熵压缩法压缩了熵,会减少信息量,因而不能完全恢复,对于图像、动画、和音频等多媒体信息是有效的,但对于程序文件、数据库文件等就行不通了。

 

2 LZSS压缩算法

 

LZSS是词典编码无损压缩技术的一种[1]。词典编码无损压缩技术主要有LZ77LZSSLZ78LZW等几种基本算法,它们一起垄断了当今的通用数据压缩领域。LZ78LZW两种算法的编译码方法较为复杂,实现起来较为困难,LZ77的压缩率又相对较低,比较而言LZSS算法在单片机上实现起来较为理想,其压缩率较高,编译码算法也较为简单。LZSS压缩算法的字典模型使用了自适应的方式,也就是说,将已经编码过的信息作为字典,如果要编码的字符串曾经出现过,就输出该字符串的出现位置及长度,否则输出新的字符串。实际使用时,由于被压缩的文件往往较大,一般使用“滑动窗口压缩”方式,就是将一个虚拟的,可以跟随压缩进程滑动的窗口作为术语字典。

 

3改进的LZSS压缩算法

 

3.1 LZSS算法存在的问题

 

LZSS算法是一种很好的算法,但是在实现的过程中发现该算法仍有不少可改进之处。改进算法的思路有两条,一是从过程出发,即提高编码程序的效率,在压缩率保持不变的前提下尽量减少算法复杂度;二是从结果出发,分析压缩代码对,尽量精简压缩代码对每个分量的表示方法,并尽量减少压缩代码所占用的空间,以达到较好的压缩效果。下面分别从这两个方面出发,提出几个改进方案,并给出部分代码实现。

 

在匹配字符串长度编码时,必须考虑到它在大多数情况下不会太大,少数情况下才会发生大字符串的匹配,因此,无论匹配长度为多长,代码对(1,匹配位置,匹配长度)的长度都是固定的,对于较小的匹配长度来说,仍可能存在一定的冗余。例如,当偏移量的位数为12(文本窗口大小为4096字节)、匹配长度的位数为 4(匹配长度最大为16)时,加上1位前缀,输出固定为17位。若匹配长度为2或3,此时只用2位即可表示这个匹配长度,加上12位的偏移量和1位的前缀,只要输出15位,原理上输出代码可减少2位,从而实现了更高效的压缩。但这样一来,匹配长度不固定,在译码时无法正确识别匹配长度,也就无法正确译码。因此需要寻找一种能正确识别变长的匹配长度的机制。

3.2 改进LZSS算法之一——前缀编码

 

在使用可变长的编码方式来表示匹配长度值时,必须设计出一种编码方式,使得译码程序可以方便地分离每个字符的编码部分。于是有了一种叫“前缀编码”的技术,其主导思想是:任何一个字符的编码,都不是另一个字符编码的前缀。即任何一个字符的编码,都不是由另一个字符的编码加上若干位0或1组成。表1为前缀编码的一个最简单的例子。

 

表1 前缀编码举例

 

_____________________________________________

符号     A      B      C      D      E

_____________________________________________

编码     0      10     110    1110    11110

_____________________________________________

 

有了上面的码表,就可以轻松地从下面这串二进制数据流中分辨出真正的信息内容:

 

     1110010101110110111100010→十六进制的DABBDCEAAB

 

适用于此处的好的编码方案很多,在这里介绍其中一种应用非常广泛的 Golomb编码。

 

假设对正整数x进行Golomb编码,选择参数 m,令 

 

式中  bmqr为在编码时取的经验值,则 x 可以被编码为两部分,第一部分是由q110组成,第二部分为m比特二进制数,其值为rm = 0, 1, 2, 3时的Golomb编码表如表2所示。从表2中可见,Golomb编码不但符合前缀编码的规律,而且可以用较少的位表示较小的x值,而用较长的位表示较大的x值。

 

2  Golomb码表

 


   值 x        m = 0       m = 1       m = 2       m = 3

    1             0         0 0        0 00        0 000
    2            10         0 1        0 01        0 001
    3           110        10 0        0 10        0 010
    4          1110        10 1        0 11        0 011
    5         11110       110 0       10 00        0 100
    6        111110       110 1       10 01        0 101
    7       1111110      1110 0       10 10        0 110
    8      11111110      1110 1       10 11        0 111

9     111111110     11110 0      110 00        1 000

 


    这样,如果 x 的取值倾向于比较小的数值时,Golomb 编码就可以有效地节省空间。当然,根据 x 的分布规律不同,我们可以选取不同的 m 值以达到最好的压缩效果。参数 m 的选择,一般经验是取 3 4 即可。

 

3.3改进LZSS算法之二——可变窗口

 

一般来讲,编码的设计要根据待编码的数值的分布情况而定。对于压缩代码对的第二个分量匹配位置,即窗口内的偏移,通常的经验是,偏移接近窗口尾部的情况要多于接近窗口头部的情况,这是因为字符串在与其接近的位置较容易找到匹配串。对于普通的窗口大小(例如 4096 字节)来说,偏移值基本上是均匀分布的,可以用固定的位数来表示它。编码 off 需要的比特数为 

 

Bitnum=Upper-Bound (log2(TEXT-SIZE))

 

Upper-Bound(log2(n))函数取log2(n)的上限,代码实现如下:

 

Int LZARI: UpperLog2 (int n){

 

  Int I=0;

 

  If  (n>0){

 

             Int m=1;

 

             While (1) {

 

                       If (m>=n) return I;

 

                       M<<=1;

 

                       I++;}

 

                                } Else return –1;

 

                     }

 

因此,如果窗口大小为 4096字节,用12位就可以对偏移编码。但是,考虑到在压缩开始时,窗口大小并没有达到TEXT_SIZE,而是随着压缩的进行增长,因此可以根据窗口的当前大小动态地计算偏移值所需要的比特数,这样可以节省空间。如果窗口大小为 2048字节,用 11 位就可以了。

 

3.4改进LZSS算法之三——游程编码算法思想

 

这种算法通过记录待压缩数据中的重复字符来减少数据文件所占用的存储空间。游程编码中必须标出压缩指示符、连续出现的字符和字符重复出现的次数,即至少有3个字节用于压缩开销,因此,只有重复字符连续出现4次以上时,这种压缩算法才有意义。对于无重复的那些字符则不做处理原样输出。

 

在实现游程编码时首先考虑的是选取压缩指示符,其中有很多因素要考虑。首先,选用的压缩指示符最好是源数据流中不曾出现的字符。要达到这个要求有两种途径:

 

1)利用扩展码。在一些编码方案中,如 ASCII码中,除可显示的字符外,还有一部分扩展码。选取其中不常用的那些扩展码可用未作为压缩指示符。

 

2)选用数据源中较少出现的字符作为压缩指示符,若数据源中本来就有该字符,则在该字符前再插入一个同样的字符;还原中遇到该字符时,首先将其删除,再判断其后是否是数字,如是数字,则复制被删除的字符;若是同样的字符,则将其还原。大多数情况下将两者综合使用。

 

对于文本信息文件中的那些规则的信息,首先使用游程编码进行小范围的压缩,压缩后的数据不写入压缩文件,而是存贮在中间数组变量中,调用LZSS继续压缩。

 

LZSS算法利用字典模型进行编码,能取得很高的压缩比。但LZSS算法对上述性质的信息文件,因其建立的二叉树过于庞大而降低了编码的效率,不能很好地利用信息文件特定部分规律性强的特点。游程编码则能压缩这种重复率高的文件,因此,综合应用两种编码可以得到更高的压缩率,提高编码效率。

 

4 改进的LZSS算法的测试及性能分析

 

选择以文本文件进行压缩,源文件大小为1.5 Mb,采用改进LZSS算法压缩后数据量约为0.23Mb(对于不同的文件由于其数据的规律不一,压缩的比例不同,见表3),数据的传输时间可缩短至未压缩前的l6左右,其有效性和稳定性均己得到验证。选择一系列文本文件进行压缩测试,压缩率可达l6l10。这表明该压缩算法对缩短通信时间起到了很大作用。使用该改进算法的文本文件压缩效果与用LZ77LZSS算法压缩的效果的比较如表3所示。

3 几种LZ算法对样本的压缩率比较

 

算法     文件及长度   sm1    sm2     sm3     sm4     sm5     sm6     sm7   

           (KB)      10.5    19.0     46.0     64.0     78.0     176     326   

LZ77                 0.28    0.32     0.41     0.56     0.36     0.58    0.35           

LZSS                 0.22    0.29     0.32     0.45     0.33     0.54    0.32  

改进的LZSS           0.12    0.15     0.33     0.39     0.24     0.41    0.15

5 参考文献

 

[1] 候阳,数据压缩的原理及应用,北京:学苑出版社,1994.

 

[2] 吴乐南,数据压缩的原理及应用,北京:电子工业出版社,1995.

 

[3] 王忠效,姜丹,关于Lempel-Ziv77压缩算法及其实现的研究,计算机研究与发展,1996,33(5)

 

[4] 吴军,王作英,汉语信息熵和语言模型的复杂度,电子学报,1996,24(10)

 

[5] Mark Nelson著,贾东起译.数据压缩技术原理与范例[M].北京:科学出版社,1995.   

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值