欢迎大家光临【无师自通-教程网】您的到来是我们的荣幸。本站提供photoshop教程,ps教程,flash教程,cad教程,网页制作教程,excel教程,asp教程,vb教程,3d教程,c语言教程,html教程,coreldraw教程,dreamweaver教程,java教程,3dmax教程 等各种教程为主题的内容和服务,相信您会在这里找到您所需要的东东。无师自通伴您一生-谢谢您的光临!!
网站地图 设为首页
简繁切换 加入收藏
栏目待定 留言本站
您现在的位置: 无师自通-教程网 >> 程序设计 >> VC语言 >> VC语言 >> 教程正文

  没有公告

教程: Gzip Zlib PNG 压缩算法,源码详解 更多...
教程: Gzip Zlib PNG 压缩算法,源码详解

   如果你有时间的话,我建议你先不要看下面的内容,自己尝试通过读gzip源码,来了解它的压缩解压缩是如何实现的,这将会是一个非常有趣的智力游戏,千万不要错过。当一个又一个的谜被解开时,那感觉就像唐伯虎同志所说的,“慷慨然诺杯酒中”。(小唐的诗,除了另一个倒霉蛋曹雪芹外,好像不太被人提。)

   1 gzip所使用压缩算法的基本原理

   gzip 对于要压缩的文件,首先使用lz77算法进行压缩,对得到的结果再使用huffman编码的方法进行压缩。所以我们分别对lz77和huffman编码的原理进行说明。

   1.1 ... 1.2 ...

   2 gzip压缩算法实现方法

   2.1 LZ77算法的gzip实现

   首先,gzip 从要压缩的文件中读入64KB的内容到一个叫window的缓冲区中。为了简单起见,我们以32KB以下文件的压缩为例做说明。对于我们这里使用32KB以下文件,gzip将整个文件读入到window缓冲区中。然后使用一个叫strstart的变量在window数组中,从0开始一直向后移动。strstart在每一个位置上,都在它之前的区域中,寻找和当前strstart开始的串的头3个字节匹配的串,并试图从这些匹配串中找到最长的匹配串。

   如果当前的strstart开始的串,可以找到最少为3个字节的匹配串的话,当前的strstart开始的匹配长度那么长的串,将会被一个<匹配长度,到匹配串开头的距离>对替换。

   如果当前的strstart开始的串,找不到任何的最少为3个字节的匹配串的话,那么当前strstart的所在字节将不作改动。

   为了区分是一个<匹配长度,到匹配串开头的距离>对,还是一个没有被改动的字节,还需要为每一个没有被改动的字节或者<匹配长度,到匹配串开头的距离>对,另外再占用一
   位,来进行区分。这位如果为1,表示是一个<匹配长度,到匹配串开头的距离>对,这位如果为0,表示是一个没有被改动的字节。

   现在来说明一下,为什么最小匹配为3个字节。这是由于,gzip 中,<匹配长度,到匹配串开头的距离>对中,"匹配长度"的范围为3-258,也就是256种可能值,需要8bit来保存。"到匹配串开头的距离"的范围为0-32K,需要15bit来保存。所以一个<匹配长度,到匹配串开头的距离>对需要23位,差一位3个字节。如果匹配串小于3个字节的话,使用<匹配长度,到匹配串开头的距离>对进行替换,不但没有压缩,反而还会增大。所以保存<匹配长度,到匹配串开头的距离>对所需要的位数,决定了最小匹配长度至少要为3个字节。

   下面我们就来介绍gzip如何实现寻找当前strstart开始的串的最长匹配串。

   如果每次为当前串寻找匹配串时,都要和之前的每个串的至少3个字节进行比较的话,那么比较量将是非常非常大的。为了提高比较速度,gzip使用了哈希表。这是gzip实现LZ77的关键。这个哈希表是一个叫head的数组(后面我们将看到为什么这个缓冲区叫head)。gzip对windows中的每个串,使用串的头三个字节,也就是strstart,strstart 1,strstart 2,用一个设计好的哈希函数来进行计算,得到一个插入位置ins_h。也就是用串的头三个字节来确定一个插入位置。然后把串的位置,也就是 strstart的值,保存在head数组的第ins_h项中。我们马上就可以看到为什么要这样做。head数组在没有插入任何值时,全部为0。
当某处的当前串的三个字节确定了一个ins_h,并把当时当前串的位置也就是当时的strstart保存在了head[ins_h]中。之后另一处,当另一处的当前串的头三个字节,再为那三个字节时,再使用那个哈希函数来计算,由于是同样的三个字节,同样的哈希函数,得到的ins_h必然和前面得到的ins_h是相同的。于是就会发现head[ins_h]不为0。这就说明了,有一个头三个字节和自己相同的串把自己的位置保存在了这里,现在head[ins_h]中保存的值,也就是那个串的开始位置,我们就可以找到那个串,那个串至少前3个字节和当前串的前3个字节相同(稍后我们就可以看到这种说法不准确,这里是为了说明方便),我们可以找到那个串,做进一步比较,看到底能有多长的匹配。

   我们现在来说明一下,相同的三个字节,通过哈希函数得到的ins_h必然是相同的。而不同的三个字节,通过哈希函数有没有可能得到同一个ins_h,我没有对这个哈希函数做研究,并不清楚,不过一般的哈希函数都是这样的,所以极大可能这里的也会是这种情况,即不同的三个字节,通过哈希函数有可能得到同一个ins_h,不过这并不要紧,我们发现有可能是匹配串之后,还会进行串的比较。

   一个文件中,可能有很多个串的头三个字节都是相同的,也就是说他们计算得到的ins_h都是相同的,如何能保证找到他们中的每一个串呢?gzip使用一个链把他们链在一起。gzip每次把当前串的位置插入head的当前串头三个字节算出的ins_h处时,都会首先把原来的head[ins_h]的值,保存到一个叫prev的数组中,保存的位置就在现在的strstart处。这样当以后某处的当前串计算出ins_h,发现head[ins_h]不空时,就可以到prev[ head[ins_h] ]中找到更前一个的头三个字节相同的串的位置。对此我们举例说明。

   例,串
   0abcdabceabcfabcg
   ^^^^^^^^^^^^^^^^^
   01234567890123456

   整个串被压缩程序处理之后。

   由abc算出ins_h。
   这时的head[ins_h]中为 13,即"abcg"的开始位置。
   这时prev[13]中为 9,即"abcfabcg"的开始位置。
   这时prev[9]中为 5,即"abceabcfabcg"的开始位置。
   这时prev[5]中为 1,即"abcdabceabcfabcg"的开始位置。
   这时prev[1]中为 0。

   我们看到所有头三个字母为abc的串,被链在了一起,从head可以一直找下去,直到找到0。

   现在我们也就知道了,三个字节通过哈希函数计算得到同一ins_h的所有的串被链在了一起,head[ins_h]为链头,prev数组中放着的更早的串。这也就是head和prev名称的由
   来。

   gzip寻找匹配串的另外一个值得注意的实现是,延迟匹配。会进行两次尝试。比如当前串为str,那么str发生匹配以后,并不发生压缩,还会对str 1串进行匹配,然后看哪种
   匹配效果好。

   例子 ...
从这个例子中我们就看到了做另外一次尝试的原因。如果碰到的一个匹配就使用了的话,可能错过更长匹配的机会。现在做两次会有所改善。

   ...

   2.2 问题讨论

   我在这里对gzip压缩算法做出了一些说明,是希望可以和对gzip或者压缩解压缩感兴趣的朋友进行交流。
   我对gzip的了解要比这里说的更多一些,也有更多的例子。如果哪位朋友愿意对下面的问题进行研究,以及其他压缩解压缩的问题进行研究,来这里http://jiurl.cosoft.org.cn/forum/ 和我交流的话,我也愿意就我知道的内容进行更多的说明。

   下面是几个问题

   这种匹配算法,即用3个字节(最小匹配)来计算一个整数,是否比用串比较来得高效,高效到什么程度。

   哈希函数的讨论。不同的三个字节,是否可能得到同一个ins_h。ins_h和计算它的三个字节的关系。

   几次延迟尝试比较好?

   用延迟,两次尝试是否对压缩率的改善是非常有限的?

   影响lz77压缩率的因素。

   压缩的极限。

   2.3 ...

   3 gzip源码分析

   main() 中调用函数 treat_file() 。
   treat_file() 中打开文件,调用函数 zip()。注意这里的 work 的用法,这是一个函数指针。
   zip() 中输出gzip文件格式的头,调用 bi_init,ct_init,lm_init,
   其中在lm_init中将 head 初始化清0。初始化strstart为0。从文件中读入64KB的内容到window缓冲区中。
   由于计算strstart=0时的ins_h,需要0,1,2这三个字节和哈希函数发生关系,所以在lm_init中,预读0,1两个字节,并和哈希函数发生关系。

   然后lm_init调用 deflate()。
   deflate() gzip的LZ77的实现主要deflate()中。
   ...

教程录入:admin    责任编辑:admin 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
     
     
     
     

    access基础知识
    免责声明!本站资料大部分来自于互联网,其版权归原作者或其他合法者所有.如内容涉及或侵犯了您的权益,请通知本人,我将尽快处理!.欢迎您的光临。
    辽ICP备07003958号
    无师自通,伴你一生-教程网