回 帖 发 新 帖 刷新版面

主题:[半原创]GIF文件的数据结构以及播放和分解GIF的源代码

GIF文件的数据结构

  GIF 文件内部是按块划分的,包括控制块和数据块两种。控制块控制数据块的行为,不同的控制块
包含不同的控制参数。数据块只包含一些8bit的字符流,由它前面的控制块来决定它的功能,每个数据
块0—255个字节,数据块的第一个字节指出这个数据块长度(字节数),计算数据块的长度时不包括这
个字节,所以一个空的数据块也有一个字节,那就是数据块的大小&H00。
    控制块中的逻辑屏幕描述块和全局彩色表的作用范围是整个数据流, 其他控制块仅控制跟在它们后
面的图形描述块。
  GIF文件的典型结构如下表所示。
---------------------------------------
顺号  结构名称        长度(字节)
---------------------------------------
1  GIF文件头        6
2  逻辑屏幕描述块      7
3  全局彩色表        最多768
4  图形描述块        10
5  局部彩色表(可重复n次) 最多768
6  表式压缩图像数据
7  图像控制扩展块      8
8  无格式文本扩展块
9  注释扩展块        4-258
10  应用程序扩展块
11  GIF文件结束块      1
----------------------------------------

    
一、控制块

1. GIF文件头
    文件头由6个固定字节组成,它定义GIF数据流,结构如下表所示。

单位:字节
---------------------
偏移量 长度 域名称
---------------------
0   3   GIF标记
3   3   版本号
---------------------
  GIF标记存放的是“GIF”的Ascii码,版本号存放的是1987年5月发布的“87a”或者1989年7月发布
的“89a”,或者更加新的版本号。

2. 逻辑屏幕描述块
  逻辑屏幕描述块紧跟在 GIF文件头之后。
    逻辑屏幕描述块由 7个固定字节组成,包含定义图像显示区域的参数,包括背景颜色信息。这个数
据块中的坐标相对于虚拟屏幕的左上角,不一定是指显示屏幕的绝对坐标。逻辑屏幕描述块的结构如下
表所示:

单位:字节
--------------------------------
偏移量 长度  域名称
--------------------------------
6   2   逻辑屏幕宽度(像素)
8   2   逻辑屏幕高度(像素)
10   1   包装域
11   1   背景颜色索引
12   1   像素宽高比
--------------------------------
说明:
    (1) 包装域是描述彩色表属性的,这一个字节又由4个子域组成:

    0-2位:全局彩色表大小域 Size,表示表示每个像素的位数,它用来计算全局彩色表中包含的
字节数。在全局彩色表标志域 G=0 时就不需要计算,G=1 时就要计算彩色表的大小,具体计算见下
文的"3. 全局彩色表"。
    3位:彩色表排序标志域 S,用来表示全局彩色表中的颜色是否按重要性(或者称使用率)排序。
如果 S=0,表示没有重要性排序;如果 S=1 表示最重要的颜色排在前。这样做的目的是辅助颜色数
比较少的解码器能够选择最好的颜色子集,在这种情况下解码器就可选择彩色表中开始段的彩色来显示
图像。
    4-6位:彩色分辨率域 CR,用来表示原始图像可用的每种基色的位数(实际值减1)。这个位数表示
整个调色板的大小,而不是这幅图像使用的实际的颜色数。例如,如果该域的值 CR=3,说明原始图像
可用每个基色有4位的调色板来生成彩色图像。
    7位:全局彩色表标志域 G 用来说明是否有全局彩色表存在。如果G=1,表示有一个全局彩色表将
紧跟在这个逻辑屏幕描述块之后;这个标志也用来选择背景颜色索引,如果G=1,背景颜色索引域中的
值就用作背景颜色的索引。

    (2)背景颜色索引是彩色表的一个索引值,用来指定背景颜色。如果全局彩色表标志域G=0,这个
域的值也设置为0。
    (3) 像素宽高比域中的值是一个因数,是计算原始图像像素的宽高比的一个近似值。如果该域的值
范围为1~255,宽高比的近似值按下式计算:
    Aspect Ratio = (Pixel Aspect Ratio + 15) / 64
    比值的范围在4:1~1:4之间,其增量为1/64。

3. GIF文件结束块
    结束块在GIF文件的最后,它是一个固定的数值 &H3B。

4、扩展控制块
  这一部分是可选的(需要89a版本),扩展控制块的标记是 &H21(又称扩展导入符),用于识别扩
展块的开始。在扩展导入符后是扩展标签。

①图形控制扩展块用来控制跟在它后面的第一个图象(或文本)的渲染形式,扩展标签为&HF9,其结构
如下表所示:

单位:字节
------------------------------------------
偏移量 长度   域名称        
------------------------------------------
0   1    扩展导入符(&H21) 
1   1    图形控制标签(&HF9)
2   1    块大小域(&H04)      
3   1    包装域       
4   2    延迟时间
6   1    透明色索引
7   1    块结束符(&H00)
------------------------------------------
说明:
    (1)块大小域用来说明该扩展块所包含字节数,该字节数是从块大小域之后到块结束符之前的字节
数,固定为&H4。
    (2)包装域的结构如下表所示:

  0位:透明标志
  1位:用户输入标志,表示在继续处理之前是否需要用户输入(按回车键或鼠标点击等)。在延时
时间和用户输入标志都设置为 1的情况下,继续处理的开始时间取决于用户响应输入在前还是延迟时间
结束在前。
  2-4位:处理方法,处理方法规定图形显示之后译码器要用下表所述方法进行处理:
--------------------------------------
域值 方法
--------------------------------------
0   不使用处理方法
1   不处理图形,图形留在原处
2   显示图形的区域必须恢复成背景颜色
3   恢复成以前显示的图形
4-7 未定义
--------------------------------------
  5-7位:保留的

    (3)延迟时间:单位1/100秒,如果值不为1,表示暂停规定的时间后再继续往下处理数据流。
    (4)透明色索引:当透明标志位设置为1时,透明索引指示处理程序要修改显示设备上的相应像点。
    (5)块结束符表示该图形控制扩展块结束,它是一个固定的数值 &H0,因此称为零长度数据子块。


②无格式文本扩展块
    无格式文本扩展块用来绘制一个简单的文本图象,由纯文本数据(7-bit ASCII 字符)和控制绘制
的参数等组成。绘制文本借助于一个文本框来定义边界,在文本框中划分多个单元格,每个字符占用一
个单元,绘制时按从左到右、从上到下的顺序依次进行,直到最后一个字符或者占满整个文本框(之后
的字符将被忽略,因此定义文本框的大小时应该注意到是否可以容纳整个文本),绘制文本的颜色使用
全局颜色列表,没有则可以使用一个已经保存的前一个颜色列表。另外,图形文本扩展块也属于图形块
(Graphic Rendering Block),可以在它前面定义图形控制扩展对它的表现形式进一步修改。其扩展标
签为&H1,结构如下表所示:

单位:字节
------------------------------------------------------------
顺号 长度   域名称        
------------------------------------------------------------
1   1    扩展导入符(&H21)  
2   1    无格式文本标签(&H1)
3   1    块大小(&H0C) 
4   2    文本框离逻辑屏幕的左边界距离(像素)
5   2    文本框离逻辑屏幕的上边界距离(像素)
6   2    文本框宽度(像素)
7   2    文本框高度(像素)
8   1    每个单元宽度(像素)
9   1    每个单元高度(像素)
10  1    前景色在全局颜色列表中的索引
11  1    背景色在全局颜色列表中的索引
12       文本:一个或多个数据块组成,保存要显示的字符串
13  1    块结束符(&H00)
------------------------------------------------------------
说明:
  (1)由于文本的字体(Font)和尺寸(Size)没有定义,解码器应该根据情况选择最合适的 
  (2)如果一个字符的ASCII码小于&H20或大于&HF7,则这个字符被推荐显示为一个空格(0x20)
  (3)为了兼容性,最好定义字符单元格的大小为8x8或8x16

③注释扩展块
    注释扩展块域的内容用来说明图形、版权、描述等其他任何非图形数据和控制信息的文本信息(解
码器完全可以忽略它)。扩展标签为&HFE。注释扩展块的结构如下表所示:

单位:字节
--------------------------------
顺号 长度   域名称
--------------------------------
1   1    扩展导入符(&H21)
2   1    注释标签(&HFE)
3   1—255  注释数据
4   1    块结束符(&H00)
--------------------------------

④应用扩展块
    应用扩展块是提供给应用程序自己使用的,应用程序可以在这里定义自己的标识、信息等,扩展标
签为&HFF,结构如下表所示:

单位:字节
------------------------------------------------------
顺号 长度   域名称
------------------------------------------------------
1   1    扩展导入符(&H21)
2   1    扩展标签(&HFF)
3   4    块大小(&H0B)
4   8    应用程序标识符(ASCII码),典型值为NETSCAPE
5   3    应用程序鉴别码(ASCII码),典型值为2.0  
7        应用程序自定义数据块,典型值为&H3
8   1    块结束符(&H00)
------------------------------------------------------


二、数据块

1. 全局彩色表
  全局彩色表紧跟在逻辑屏幕描述块之后。
    由于一个 GIF文件可以包含多幅彩色图像,每幅彩色图像也许都包含适合自身特点的彩色表,所以
一个 GIF文件可以有好几个彩色表。但归纳起来只有两类:全局彩色表或局部彩色表。全局彩色表可用
于图像本身没有带彩色表的所有图像和无格式文本扩展块,而局部彩色表只用于紧跟在它后面的一幅图
像。在处理全局彩色表和局部彩色表时需要注意下面一些规则。
    ①如果 GIF文件包含全局彩色表,而且要显示的图像本身又带有局部彩色表,那末显示该幅彩色图
像时就用它自己的彩色表,而不用全局彩色表。在这种情况下,解码器就首先保存全局彩色表,然后使
用局部彩色表来显示图像,最后再回复全局彩色表。
    ②全局彩色表和局部彩色表都是可选择的。由于这个原因,解码器最好要保存全局彩色表,一直到
出现另一个全局彩色表为止。这样做之后,对于包含完全没有彩色表的一幅或者多幅彩色图像的GIF文件
就可以使用最后保存的全局彩色表进行处理。
    ③如果同类型的图像能够使用相同的彩色表来显示,编码器就要尽可能使用一个全局彩色表;如果
没有彩色表可用,解码器就可以使用计算机系统提供的彩色表或者解码器自身的彩色表。
    ④ 全局彩色表存在与否由逻辑屏幕描述块中第5个字节的全局彩色表标志(域G的值)确定。如果
存在,彩色表就紧跟在逻辑屏幕描述块之后。彩色表的表项数目等于2的(n+1)次方,其中n=b2b1b0,每
个表项由3个字节组成,分别代表R、G、B的相对强度,因此彩色表的字节数就等于3×2的(n +1)次方,
最多768个字节。彩色表的结构如下表所示。

单位:字节
-------------------
偏移量 域名称
-------------------
0   红色索引000
1   绿色索引000
2   蓝色索引000
3   红色索引001
4   绿色索引001
5   蓝色索引001
    ...
765  红色索引255
766  绿色索引255
767  蓝色索引255
------------------

2. 局部彩色表
  局部彩色表用于紧跟在它后面的图像。局部彩色表是否存在取决于图像描述块包装域中局部彩色表
标志位的设置。彩色表的结构和大小与全局彩色表完全相同。

3. 图像描述块
  GIF 图像文件格式可包含数量不限的图像,而且也没有一个固定的存放顺序,仅用一个字节的图像
标识符(又称图像分隔符)&H2C来判断是不是图像描述块,一幅图象结束之后紧接着下是一幅图象标识
符。每一幅图像都由一个图像描述块、可有可无的局部彩色表和图像数据组成。每幅图像必须要落在逻
辑屏幕描述块中定义的逻辑屏尺寸范围里。
  图像描述块之前可有一个或者多个控制块(如图形控制扩展块),图像描述块之后可跟着一个局部
彩色表。图像描述块由10个字节组成,结构如下:

单位:字节
-----------------------------------
偏移量 长度 域名称
-----------------------------------
0   1  图像描述块标识符(&H2C)
1  2  图像左边距(像素)
3  2  图像顶边距(像素)
5  2  图像宽度(像素)
7  2  图像高度(像素)
9  1  包装域
-----------------------------------
  图像标识符用来标识图像描述块的开始,图像左边位置是相对于逻辑屏幕最左边的列号,逻辑屏幕
最左边的列定义为0;图像顶部位置是相对于逻辑屏幕顶部的行号,逻辑屏幕顶部的行号定义为0。
  包装域由5个子域组成:

  0-2位:局部彩色表大小域,其值用来计算局部彩色表中包含的字节数。
  3-4位:保留的。
  5位:彩色表排序标志域的含义与全局彩色表中域的含义相同。
  6位:交插显示标志域I,用来表示该图像数据存放方式是连续的还是交插的。GIF文件格式定义了
两种数据存放方式:一种是按图像行连续顺序存放,另一种按交插方式存放。如果I=0,表示连续方式
存放,该方式从左到右、从上到下顺序排列图象的光栅数据,与显示器上显示行的顺序相同;如果I=1
表示交插方式存放,交插方式创建四个通道(pass)保存数据,每个通道提取不同行的数据:

Group 1:每隔8行组成一组,从第0行开始显示 /第1遍交插
Group 2:每隔8行组成一组,从第4行开始显示 /第2遍交插
Group 3:每隔4行组成一组,从第2行开始显示 /第3遍交插
Group 4:每隔2行组成一组,从第1行开始显示 /第4遍交插

  由于显示图像需要较长的时间,使用这种方法存放和显示图像数据,人们就可以在图像显示完成之
前看到这幅图像的概貌,而不觉得显示时间长。

  7位:局部彩色表标志域L,用来说明是否有局部彩色表存在。如果L=1,表示有一个局部彩色表将
紧跟在这个图像描述块之后,如果L=0,表示图像描述块后面没有局部彩色表,该图像要使用全局彩色
表。

4. 表基图像数据
  GIF图像采用了LZW算法对实际的图像数据进行压缩。为了提高压缩编码的效率,对LZW编码器输出
的代码采用可变长度码VLC,不是用位数高度的代码来表示输出,而且代表码字的位数是可变的。
  表基图像数据由“LZW最小编码长度”和“图像数据”两部分组成,下表是一个数据块的结构:

单位:字节
------------------------------
偏移量 域名称
------------------------------
0   LZW最小代码长度域(&H08)
1   块大小(&HFE)(数据子块) 
2   8-bit的数据(下同) 
...   
254   
255   
------------------------------
说明:
  (1)LZW最小代码长度域的值用来确定图像数据中LZW代码使用的初始位数。
  (2)图像数据由数据子块序列组成。数据子块是一个可变长度的数据块(最大为256个字节),其长
度由子块中的第一个字节值确定,计算数据块的大小时不包括这个字节。 


播放和分解GIF动画的源代码在附件中。
说明:
  这个代码不是笔者的原创,而是笔者在枕善居“VB源码”栏目下载的“超好用的纯代码 GIF动画显示控件”。它本来是一个用户控件,只能播放而不能分解GIF,笔者花了整整一个星期的时间把它加以改造,并翻译或添加了注释。

回复列表 (共4个回复)

沙发

顶.
在[url=http://www.mndsoft.com]枕善居[/url]确实有很多好东西..

板凳

谢谢LZ分享,温故而知新啊

3 楼

不错啊

4 楼

谢谢LZ分享

我来回复

您尚未登录,请登录后再回复。点此登录或注册