Gzip Zlib PNG 压缩算法 Gzip源码详解

GZIP源代码分析(一) Gzip是Linux下的压缩软件,.gz后缀的文件就是经gzip压缩后的文件。Gzip的源码当然由压缩和解压缩两部分构成,但本文只打算介绍其压缩部分,这部分的代码风格良好,且注释充分,并能很好的体现所用到的算法,而解压的代码完全是没有注释的一坨,其解压思路我们大致可以根据压缩过程反向推理出来,所以就不管它了。 目录 一、算法介绍 二、实现介绍 …… 一、Gzip中涉及的压 阅读详情

Gzip Zlib PNG 压缩算法 Gzip源码详解

作者: JIURL

                主页: http://jiurl.yeah.net

   日期: 2004-3-1


(测试版)

    gzip,zlib,以及图形格式png,使用的是同一个压缩算法deflate。我们通过对gzip源码的分析来对deflate压缩算法做一个详细的说明。我阅读的gzip版本为 gzip-1.2.4。我
们对算法做三种程度的说明。第一种程度,对gzip所使用压缩算法基本原理的说明。第二种程度,对gzip压缩算法实现方法的说明。第三种程度,对gzip实现源码级的说明。

如果你有时间的话,我建议你先不要看下面的内容,自己尝试通过读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()中。
...





欢迎交流,欢迎交朋友,
欢迎访问
主页 http://jiurl.yeah.net http://jiurl.nease.net 论坛 http://jiurl.cosoft.org.cn/forum

f啊k,不带你们这样的啊,有好事不叫我。

 

 

zlib、gzip与ZIP:从DEFLATE算法到压缩格式的全面解析 数据压缩是计算机科学中用于减少数据存储空间和网络传输量的基础技术,其核心原理在于通过算法消除数据中的冗余信息。DEFLATE算法作为现代无损压缩的基石,结合了LZ77字典编码与霍夫曼编码,在压缩率与速度间取得了优异平衡。该算法的标准实现——zlib库,为上层应用提供了高效的压缩/解压能力,成为众多软件项目的关键依赖。在工程实践中,基于DEFLATE的gzip格式凭借其流式特性和轻量级头部,成为HTTP内容压缩和日志归档的事实标准,能显著提升网络传输效率。而ZIP格式则在此基础上扩展为支持多文件归档的容器格式 阅读详情

相关推荐

zlib deflate gzip区别

适用于单个文件,也使用压缩压缩方法。提供了压缩和解压缩代码,供 zip、gzip、)和许多其他应用程序使用。

SHELLCODE_8BIT的博客 1313

gzip过滤器源码分析

本文参考gzip过滤器的源码 https://github.com/phyber/negroni-gzip/blob/master/gzip/gzip.go 该过滤器是Negroni(https://github.com/urfave/negroni) 的一个中间件,gzip是用来压缩的。 我们关注所有首字母大写的函数,一共有五个。 func (grw *gzipResponseWriter) W...

DDghost的博客 515

gzip源代码gzip源代码

gzip源代码gzip源代码gzip源代码

服务计算:gzip过滤器的源码分析

gzip源代码 // Package gzip implements a gzip compression handler middleware for Negroni. package gzip import ( &amp;quot;compress/gzip&amp;quot; &amp;quot;io/ioutil&amp;quot; &amp;quot;net/http&amp;quot; &amp;quot;strings&amp

ZTao-z的博客 428

gzip源码 (可离线安装gzip)

gzip源码 可以离线安装 gzip 工具 ,请参照压缩包里面的 REAME

gzip-1.3.12.tar.gz源代码

开源的gzip的详细源代码,包括所有的头文件,.c文件以及Word文档。供研究,学习压缩算法的人参考借鉴。

Gzip Zlib PNG 压缩算法 Gzip源码详解 - jiurl的专栏 - 优快云Blog

导读: Gzip Zlib PNG 压缩算法 Gzip源码详解作者: JIURL                 主页: http://jiurl.yeah.net    日期: 2004-3-1 (测试版)    gzip,zlib,以及图形格式png,使用的是同一个压缩算法deflate。我们通过对gzip源码的分析来对deflate压缩算法做一个详细的说

xu的blog 2817

gzip源码,gzip压缩算法

gzip源码,gzip压缩算法。GZIP学习

Gzip Zlib PNG 压缩算法,源码详解 - swo2006 - C++博客

Gzip Zlib PNG 压缩算法,源码详解 - swo2006 - C++博客 http://www.cppblog.com/swo2006/articles/11430.html ...

259

gzip.rar_C gzip源码_c语言gzip_gzip压缩_gzip解压_poetryfem

使用C语言编写的GZIP压缩及解压源代码

Axure RP 10表单数据提交制作

本文介绍了如何使用Axure RP 10实现表单数据提交。

Peppaaa的博客 990

Gzip Zlib PNG 压缩算法

gzip,zlib,以及图形格式png,使用的是同一个压缩算法deflate。我们通过对gzip源码的分析来对deflate压缩算法做一个详细的说明。我阅读的gzip版本为 gzip-1.2.4。我们对算法做三种程度的说明。第一种程度,对gzip所使用压缩算法基本原理的说明。第二种程度,对gzip压缩算法实现方法的说明。第三种程度,对gzip实现源码级的说明。如果你有时间的话,我建议你先不

Orange 634

特斯拉Model 3 BMS主控板拆解:从硬件设计到热管理策略的实战解析

本文深度拆解特斯拉Model 3的BMS主控板,解析其硬件架构与热管理协同策略。文章聚焦于主控板的分区布局、双核MCU的智慧分工,以及从被动监控到主动干预的热管理范式转变,揭示了特斯拉在高压安全、实时控制与系统级工程思维上的设计哲学。

zz67890的博客 593

zlib、libz、gzip和zip基础介绍

文章目录基本概念C或C++调用libz函数压缩和解压问题 基本概念 zlib:zlib是提供数据压缩用的函式库(源码包),由Jean-loup Gailly与Mark Adler所开发。源码下载地址:http://www.zlib.net/ libz:是编译或者交叉编译生成的函数库,名称为libz.a和libz.so (linux下) zip:ZIP文件格式是一种数据压缩和文档储存的文件格式。 gzip:最早由Jean-loup Gailly和Mark Adler创建,用于UNⅨ系统的文件压缩。 DEFL

mayue_web的博客 1万+

VUE3 实战手记(一)集成 EasyUI for Vue 组件库

本文详细介绍了如何在VUE3项目中集成EasyUI for Vue组件库,包括环境准备、基础安装、配置与集成、TypeScript类型问题解决以及组件实战等内容。EasyUI以其轻量级和开箱即用的特性,特别适合快速开发后台管理系统,提升开发效率。

weixin_30628801的博客 529

日志异常检测详细整理,看这一篇就够了(附各项目代码链接)

对于不用的日志键,用它们的参数值向量训练一个参数值异常检测模型来检测有这些参数值反映的系统性能异常。与标准的GAN框架一样,D和G的参数是基于D的输出来更新的,因此鉴别器D可以被训练为尽可能敏感地将正确的标签分配给真实和虚假序列,而生成器将被训练为尽可能聪明地在经过足够多轮的迭代后欺骗鉴别器,即误导D将真实标签分配给虚假序列。LR:逻辑回归是有监督的模型,将处理后的特征矩阵以及标记作为模型的输入,得到训练后的模型,用此模型预测新出现的特征向量,以此判断特征向量是否为异常的,进而判断日志异常。

qq_20368489的博客 1万+

DEFLATE 压缩算法

DEFLATE是同时使用了LZ77算法与哈夫曼编码(Huffman Coding)的一个无损数据压缩算法。它最初是由Phil Katz为他的PKZIP归档工具第二版所定义的,后来定义在RFC 1951规范中。         人们普遍认为DEFLATE不受任何专利所制约,并且在LZW(GIF文件格式使用)相关的专利失效之前,这种格式除了在ZIP文件格式中得到应用之外也在gzip压缩文

peilw625311的专栏 2万+

倒立摆入门详解+pid调参

倒立摆制作全过程 最近在练习pid的控制算法,就选用了2013年的电子设计国赛题目:倒立摆 。 首先给你们看看我的成果 注意哦:倒立摆不是靠上面黄色的传感器保持平衡的,而是通过下面的电机左右扭动使得摆杆不掉下来,难度可不小了。 材料准备 1.机械部分 如图所示选好电机和角位移传感器进行组装就好了,这个部分是我直接网上购买的,如果要自己装也是可以的,不过会比较麻烦,结构差不多的。 2.主控部分 这个部分的话完全是我自己设计的,作用和网上买的一样,因为网上买的话太贵了,有需要的话可以联系我,有pcb文件

small_po_kid的博客 2万+
上一篇: JIURL键盘驱动 3
下一篇: gzip原理与实现
imquestion
博客等级 码龄25年 50粉丝 34原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值