1.概述 GIF(Graphics Interchange Format,图形交换格式)文件是由 CompuServe公司开发的图形文件格式,版权所有,任何商业目的使用均须 CompuServe公司授权。 2.GIF文件存储结构 GIF文件内部是按块划分的,包括控制块( Control Block )和数据块(Data Sub-blocks)两种。控制块是控制数据块行为的,根据不同的控制块包含一些不同的控制参数;数据块只包含一些8-bit的字符流,由它前面的控制块来决定它的功能,每个数据块大小从0到255个字节,数据块的第一个字节指出这个数据块大小(字节数),计算数据块的大小时不包括这个字节,所以一个空的数据块有一个字节,那就是数据块的大小0x00。下表是一个数据块的结构:
一个GIF文件的结构可分为文件头(File Header)、GIF数据流(GIF Data Stream)和文件终结器(Trailer)三个部分。文件头包含GIF文件署名(Signature)和版本号(Version);GIF数据流由控制标识符、图象块(Image Block)和其他的一些扩展块组成;文件终结器只有一个值为0x3B的字符(';')表示文件结束。下表显示了一个GIF文件的组成结构:
下面就具体介绍各个部分: 文件头部分(Header) GIF署名(Signature)和版本号(Version)
GIF数据流部分(GIF Data Stream) 逻辑屏幕标识符(Logical Screen Descriptor)
m - 全局颜色列表标志(Global Color Table Flag),当置位时表示有全局颜色列表,pixel值有意义. 全局颜色列表(Global Color Table)
图象标识符(Image Descriptor)
局部颜色列表(Local Color Table) 基于颜色列表的图象数据(Table-Based Image Data)
GIF图象数据使用了LZW压缩算法(详细介绍请看后面的『LZW算法和GIF数据压缩』),大大减小了图象数据的大小。图象数据在压缩前有两种排列格式:连续的和交织的(由图象标识符的交织标志控制)。连续方式按从左到右、从上到下的顺序排列图象的光栅数据;交织图象按下面的方法处理光栅数据: 创建四个通道(pass)保存数据,每个通道提取不同行的数据: 下面的例子演示了提取交织图象数据的顺序:
图形控制扩展(Graphic Control Extension)
处置方法(Disposal Method):指出处置图形的方法,当值为: 注释扩展(Comment Extension)
图形文本扩展(Plain Text Extension) 这一部分是可选的(需要89a版本),用来绘制一个简单的文本图象,这一部分由用来绘制的纯文本数据(7-bit ASCII字符)和控制绘制的参数等组成。绘制文本借助于一个文本框(Text Grid)来定义边界,在文本框中划分多个单元格,每个字符占用一个单元,绘制时按从左到右、从上到下的顺序依次进行,直到最后一个字符或者占满整个文本框(之后的字符将被忽略,因此定义文本框的大小时应该注意到是否可以容纳整个文本),绘制文本的颜色索引使用全局颜色列表,没有则可以使用一个已经保存的前一个颜色列表。另外,图形文本扩展块也属于图形块(Graphic Rendering Block),可以在它前面定义图形控制扩展对它的表现形式进一步修改。图形文本扩展的组成:
推荐:1.由于文本的字体(Font)和尺寸(Size)没有定义,解码器应该根据情况选择最合适的; 应用程序扩展(Application Extension) 这是提供给应用程序自己使用的(需要89a版本),应用程序可以在这里定义自己的标识、信息等,组成:
文件结尾部分 文件终结器(Trailer) 这一部分只有一个值为0的字节,标识一个GIF文件结束.
2.LZW算法和GIF数据压缩 GIF文件的图象数据使用了可变长度编码的LZW压缩算法(Variable-Length_Code LZW Compression),这是从LZW(Lempel Ziv Compression)压缩算法演变过来的,通过压缩原始数据的重复部分来达到减少文件大小的目的。 标准的LZW压缩原理: LZW压缩的原理:提取原始图象数据中的不同图案,基于这些图案创建一个编译表,然后用编译表中的图案索引来替代原始光栅数据中的相应图案,减少原始数据大小。看起来和调色板图象的实现原理差不多,但是应该注意到的是,我们这里的编译表不是事先创建好的,而是根据原始图象数据动态创建的,解码时还要从已编码的数据中还原出原来的编译表(GIF文件中是不携带编译表信息的),为了更好理解编解码原理,我们来看看具体的处理过程: 编码器(Compressor) 编码数据,第一步,初始化一个编译表,假设这个编译表的大小是12位的,也就是最多有4096个单位,另外假设我们有32个不同的字符(也可以认为图象的每个像素最多有32种颜色),表示为a,b,c,d,e...,初始化编译表:第0项为a,第1项为b,第2项为c...一直到第31项,我们把这32项就称为根。
来看一个具体的例子,我们有一个字母表a,b,c,d.有一个输入的字符流abacaba。现在来初始化编译表:#0=a,#1=b,#2=c,#3=d.现在开始读取第一个字符a,[.c.]a=a,可以在在编译表中找到,修改[.c.]=a;不做任何事继续读取第二个字符b,[.c.]b=ab,在编译表中不能找,那么添加[.c.]b到编译表:#4=ab,同时输出[.c.](也就是a)的索引#0到编码流,修改[.c.]=b;读下一个字符a,[.c.]a=ba,在编译表中不能找到:添加编译表#5=ba,输出[.c.]的索引#1到编码流,修改[.c.]=a;读下一个字符c,[.c.]c=ac,在编译表中不能找到:添加编译表#6=ac,输出[.c.]的索引#0到编码流,修改[.c.]=c;读下一个字符a,[.c.]c=ca,在编译表中不能找到:添加编译表#7=ca,输出[.c.]的索引#2到编码流,修改[.c.]=a;读下一个字符b,[.c.]b=ab,编译表的#4=ab,修改[.c.]=ab;读取最后一个字符a,[.c.]a=aba,在编译表中不能找到:添加编译表#8=aba,输出[.c.]的索引#4到编码流,修改[.c.]=a;好了,现在没有数据了,输出[.c.]的值a的索引#0到编码流,这样最后的输出结果就是:#0#1#0#2#4#0. 解码器(Decompressor) 好了,现在来看看解码数据。数据的解码,其实就是数据编码的逆向过程,要从已经编译的数据(编码流)中找出编译表,然后对照编译表还原图象的光栅数据。
GIF数据压缩 下面是GIF文件的图象数据结构:
把光栅数据序列(数据流)压缩成GIF文件的图象数据(字符流)可以按下面的步骤进行:
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
〈完〉 |
http://www.hf110.com/Article/jswz/bcjs/ozh/200504/889.html