君子性非异也,善假于物也。

如有恒,何须三更起,半夜眠;最怕莫,三天打鱼两天晒网,竹篮打水一场空!
posts - 31, comments - 23, trackbacks - 0, articles - 30
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

Gif 文件格式

Posted on 2006-10-29 09:24 neter 阅读(472) 评论(0)  编辑 收藏 引用 所属分类: 数字图像
Gif动画文件在网络传播中应用较为广泛。虽然目前有关gif动画文件的处理工具也可件一二,本人认为对于gif文件的进一步利用仍有许多值得开发子处。为了方便有此意向的读者有明确的开发依据,本人特将gif89a的英文说明文档中与gif开发有用的部分作了解释性翻译,希望能对有关gif的开发起到一定的帮助作用。下面就是具体的译解。

一、编码器

   编码器是用于生成gif文件的程序。通过光栅数据和其他信息,编码器生成用于再现原始图形所必须的控制块和数据块。它负责完成如下工作:
   -将所有对再生原始图片所必须的信息包含进来。
   -确保数据流标记着包含所有数据块定义的最早的版本号;这是为了确保可以有尽可能多的解码器能够处理该数据流。
   -使得对图片的编码方法对解码器最为优化,尽可能避免信息的冗余。
   -为了便于扩展,应该避免对图片的分组,因为在解码时这种分组可能需要对硬件参数进行重新设置。
   -将定义为保留的字段的每一位都置为零。注意,逻辑视频、描述符合图像描述符中的某些字段在87a版本中是保留的,但在89a版本中却是有用的。

二、解码器

   解码器是用于处理gif数据流的程序。它顺序地处理数据流,分析各种数据块和子块,使用控制信息来设置硬件及处理参数,并且解释数据来显示图像。
解码器负责完成如下工作:
   ·依次处理数据流中的每个图像,按照控制信息中的设定处理图像间的延时。
   ·按照在数据流中设置的控制信息,尽可能接近地设置硬件参数。

三、关于色表

   gif格式利用色表来显示基于光栅的图像。色表分为全局色表和局部色表。全局色表对于那些没有设置局部色表的图像起作用。全局色表的作用域是整个数据流。局部色表对于紧接在其后的单张图像起作用。这两种色表都是可选的。正因为这样,在某个gif数据流中就有可能出现很多根本不具有任何色表的图像。因为会有如上情况发生,所以解码器通常会保留最后一个全局色表直到得到一个新的全局色表。如果一个数据流中既没有全局色表也没有局部色表,解码器就会用从上一个数据流中保留下来的全局色表来执行。可以在一组数据流中仅设置一个全局色表来适应一系列图片。如果确实没有色表,解码器会使用系统色表或者它自己的色表。应该说明的是,这样的色表用黑和白作为两个开始项,所以单色图像可以充分显示。
   Gif格式规定一个数据流只能包含头部、逻辑视屏描述符、全局色表和gif尾记录。

四、块、扩充和域

   gif数据流中的数据块可以分为三组:控制块、成象块和特殊用途块。控制块,如:头部、逻辑视屏描述块、图像控制扩充和尾记录,包含用于控制处理数据流或设置硬件参数的信息。成像块,如:图像描述符和纯文本扩充,包含用于在显示设备上成像的信息和数据。特殊用途块,如:注释扩充和应用扩充,包含那些既不用于处理数据流也不用于在显示设备上成象的信息。除了逻辑视屏描述块和全局色表之外,特殊用途块的作用域是整个数据流,而其他控制块的作用域是有限的,仅限于对他们后面的成象块起作用。特殊用途块不对任何控制块构成限制,它对于解码过程来说是透明的。成象块及扩充用于控制块及扩充的作用域限定。块的标记分为三段:除尾记录0x3b之外,0x00~0x7f用于成象块;0x80~0xf9用于控制块;0xfa~0xff用于特殊用途块。解码器通过识别块标记来处理块的作用域。

五、块尺寸

   一个块中的块尺寸字段用来记录块中所包含的字节数,不包括块尺寸字段本身和块结束符。它的设置便于跳过某个块,该尺寸设置后不能改变。数据块和子块的长度是可变的,以适应数据量的变化。

六、gif作为内嵌的协议

   作为一个内嵌的协议,gif属于某个更大的应用协议的一部分,在这个应用协议中gif用于成象。因此,应用协议可以将gif数据流定义在一个数据块中。当应用程序遇到一个gif类型的数据块时就调用gif解码器。使用gif扩展名来识别gif数据流的方法是一种较为有效的方法。

七、数据子块

   a. 数据子块是一些包含数据的单元。这些单元没有标签,被当作控制块的内容进行处理。数据子块中的第一个字节指示其后的数据长度(0~255),长度信息不包括这个长度字节。
   b. 必须的版本号:87a
   c. 句法

7 6 5 4 3 2 1 0 字段名 类型
+---------------+
0 | | 块尺寸 字节
+---------------+
1 | |
+- -+
2 | |
+- -+
3 | |
+- -+
| | 数据值 字节
. +- -+
. | |
. +- . . . . -+
. | |
+- -+
| |
+- -+
255 | |
+---------------+
d. 扩充和域:该类型的块总是作为其他更大块的一部分,它没有自己的作用域。
八、块终止符
a. 这是一个零长度的数据子块,用于说明前一个子块的结束。它只包含一个字节的块尺寸字段,其值为0,没有数据。
b. 必须的版本:87a
九、头部
a. 头部用于在上下文中识别gif 数据流。标记字段表明数据流的开始,版本字段用来标识一个解码器能够完整处理该数据流所需的功能集。此块是必须的,并且每个数据流只有一个头部。必须出现在数据流的开始。
b. 句法
7 6 5 4 3 2 1 0 字段名 类型
+---------------+
0 | | 标识符 3 字节
+- -+
1 | |
+- -+
2 | |
+---------------+
3 | | 版本 3 字节
+- -+
4 | |
+- -+
5 | |
+---------------+
i) 标识符 - 包含gif三个字符。
ii)版本 - 版本号为:87a或89a
iii) 扩充和域 - 该块的域为整个数据流。该块不能被任何扩充来改变。

十、逻辑视屏描述块

a. 逻辑视屏描述符包含用于定义显示设备的区域的参数。该块中的坐标以虚拟屏幕的左上角为基准,而不需要参考显示设备的绝对坐标。该块是必须的,并且每个数据流只能有一个逻辑视屏描述块。该块紧接着头部出现。
b. 语法
7 6 5 4 3 2 1 0 字段名 类型
+---------------+
0 | | 逻辑屏幕宽 Unsigned
+- -+
1 | |
+---------------+
2 | | 逻辑屏幕高 Unsigned
+- -+
3 | |
+---------------+
4 | | | | | <Packed Fields> See below
+---------------+
5 | | 背景色索引 Byte
+---------------+
6 | | 象素高宽比 Byte
+---------------+

<Packed Fields> = 全局色表标志 1 Bit
颜色方案 3 Bits
短标志 1 Bit
全局色表尺寸 3 Bits

   i) 全局色表标志 - 指示有没有全局色表,如果该标志位置1,则全局色表会紧接在该块之后出现。该位也用于解释是否选用背景颜色索引字段。若该位置1,则背景颜色索引字段的值将指向背景颜色表。
   ii) 色彩方案 - 提供给原始图像的每个颜色的位数减1。这个值代表图像中所使用的整个调色板的大小,而不是图像中所使用的颜色的数量。例如,若该字段的值为3,则图像中所使用的调色板的每个色值占4位。
   iii) 短标志 - 表明全局色表是否被排序。如果该位置1,则全局色表按照重要性递减的原则进行了排序。典型地,是按照颜色的使用频度进行递减排序,使用频度最高的颜色排在色表的最前面。这样便可帮助解码器选择最好的颜色子集来成象。
   iv) 全局色表的尺寸 - 如果全局色表标志位置1,则该字段的值记录全局色表中所占用的字节数。
   v) 背景颜色索引 - 为背景颜色指向全局色表。背景颜色是指那些没有背图像覆盖的视屏部分的颜色。若全局色表标志位置为0,则该字段也被值0,并且被忽略。
   vi) 象素高宽比 - 用于计算原图像中像素的近似高宽比。如果该字段的值为非0,则象素的高宽比由下面的公式计算。
高宽比 = (象素高宽比 + 15) / 64
该字段的取值范围从最宽的比值4:1到最高的比值1:4,递增的步幅为1/64。
取值: 0 - 没有比值
1~255 - 用于计算的值
c. 扩充和域。该块的作用域为整个数据流。它不能被任何扩充来改变。
十一、全局色表
a. 该块包含一个按照字节顺序表示红-绿-兰三元色的色表。全局色表用于那些没有局部色表的图像和纯文本扩充。在逻辑视屏描述块中的全局色表标志位置1时表示有全局色表。全局色表紧接在逻辑视屏描述块之后,占用的字节数为:
3*2^(全局色表尺寸+1)
b. 必须的版本:87a
c. 语法
7 6 5 4 3 2 1 0 字段名 类型
+===============+
0 | | Red 0 Byte
+- -+
1 | | Green 0 Byte
+- -+
2 | | Blue 0 Byte
+- -+
3 | | Red 1 Byte
+- -+
| | Green 1 Byte
+- -+
up | |
+- . . . . -+ ...
to | |
+- -+
| | Green 255 Byte
+- -+
767 | | Blue 255 Byte
+===============+
d.扩充和域:该块的作用域为整个数据流。它不能被任何扩充来改变。

十二、图像描述符

a. 数据流中的每一幅图像都由一个图像描述符、一个可选的局部色表和图像数据组成。每一幅图像必须在逻辑视屏描述块中所定义的逻辑视屏界限之内。图像描述符包含处理一个基于图像的表的必要参数。在这个块中给定的坐标是参照逻辑视屏的像素坐标。该块是一个成象块,在其前面可以选择加上一个或多个控制块,如:图像控制扩充,或者是后面接有局部色表;图像描述符后面总是图像数据。它是一幅图所必需的。一幅图像对应一个图像描述符。一个数据流中的图像数目不做限制。
b. 必须的版本号:87a
c. 语法
7 6 5 4 3 2 1 0 字段名 类型
+---------------+
0 | | 图象分隔符 Byte
+---------------+
1 | | 图象左坐标 Unsigned
+- -+
2 | |
+---------------+
3 | | 图象顶坐标 Unsigned
+- -+
4 | |
+---------------+
5 | | 图象宽度 Unsigned
+- -+
6 | |
+---------------+
7 | | 图象高度 Unsigned
+- -+
8 | |
+---------------+
9 | | | | | | <Packed Fields> See below
+---------------+
<Packed Fields> = 局部色表标志 1 Bit
隔行处理标志 1 Bit
短标志 1 Bit
保留 2 Bits
局部色表尺寸 3 Bits
i)图像分隔符 - 用于识别图像描述符的开始。取固定值0x2c。
d. 扩充和域:该块的域是基于表的图像。该块可以被图像控制扩充所改变。

十三、局部色表

a. 该块包含一个按照红-绿-兰三原色的顺序排列的色表。该表作用于紧跟其后的图像。当局不色表标志位置1时,该表出现,且其后紧跟图像的描述符,它所包含的字节数等于
3*2^(局部色表尺寸+1)
b. 必须的版本:87a
c. 语法
7 6 5 4 3 2 1 0 字段名 类型
+===============+
0 | | Red 0 Byte
+- -+
1 | | Green 0 Byte
+- -+
2 | | Blue 0 Byte
+- -+
3 | | Red 1 Byte
+- -+
| | Green 1 Byte
+- -+
up | |
+- . . . . -+ ...
to | |
+- -+
| | Green 255 Byte
+- -+
767 | | Blue 255 Byte
+===============+
d. 扩充及域:该块的域是紧跟其后的基于表的图像数据块。该块不能被任何扩充所改变。

十四、基于表的图像数据

a. 对一个基于表的图像数据由一系列子块组成,每个子块最多255
字节,包含一个为图中每个象素所指定的有效色表的索引。索引的顺序用LZW算法进行编码。
b. 必须的版本:87a
c. 语法
图像数据的格式如下图所示
7 6 5 4 3 2 1 0 字段名 类型
+---------------+
| | LZW 最小编码尺寸 Byte
+---------------+
+===============+
| |
/ / 图象数据 数据子块
| |
+===============+
i) LZW 最小编码尺寸:该字节用于决定在图像数据中用 LZW 编码最初的位数。
e. 扩充和域:该块没有域,它包括格栅数据。要改变基于表格的图像的扩充必须在相应的图像描述符之前出现。

十五、图像控制扩充

a. 图像控制扩充包含在处理一个成象块时所需的参数。扩充只包括一个数据子块。该块是可选的。通常只有一个图像控制扩充在成象块之前。这也是在一个数据流中对成象控制扩充的唯一限制。
b. 必须的版本:89a
c. 语法
7 6 5 4 3 2 1 0 字段名 类型
+---------------+
0 | | 扩充导入符 Byte
+---------------+
1 | | 图象控制标记 Byte
+---------------+
+---------------+
0 | | 块尺寸 Byte
+---------------+
1 | | | | | <Packed Fields> See below
+---------------+
2 | | 延长时间 Unsigned
+- -+
3 | |
+---------------+
4 | | 透明颜色索引 Byte
+---------------+
+---------------+
0 | | 块结束 Byte
+---------------+
<Packed Fields> = 保留 3 Bits
配置方法 3 Bits
用户输入标志 1 Bit
透明颜色标志 1 Bit
i) 扩充引入 - 用于识别一个扩充块的开始,该字段为固定值0x21。
ii)图像控制标号 - 识别当前块是否为图形控制扩充。该字段为固定值 0xF9。
iii) 块尺寸 - 块中所包含的字节数。从块尺寸字段开始到快结束符(不含结束符)。该字段包含固定值4。
iv) 配置方法 - 指示图像显示后的处理方法。
值: 0 - 无指定的配置,解码器不需要做任何处理。
1 - 不做配值。图像将被留在原位置。
2 - 恢复背景颜色。图像所占的区域必须备恢复为背景颜色。
3 - 恢复以前的颜色。解码器需要将图像区域恢复为原来成象的颜色。
4-7 - 未定义。
v)用户输入标志 - 说明在继续处理之前是否需要用户输入。可以和输入延时一起使用。
vi) 透明标志 - 表明在透明索引字段是否给定透明索引。
vii) 延时 - 如果不为0, 该字段指定以1/100秒为单位的时延数。
viii) 透明索引 - 如果遇到透明索引,则显示设备的相关象素不被改变,继续处理下一个象素。
ix) 块终止符 - 这个0长度字段标志着图像控制扩充得结束。
d. 扩充和域:该扩充的域是其后的成象块;在该块和它的作用块之间可以由其他扩充。该块可以改变图像描述块和纯文本扩充。
e. 建议:i)配置方法 - 恢复到原先的方法厂用于图像中的一些小区域;用该方法强制使解码器存储需要保留的图像区域,因此该方法要慎用。该方法并非为整个图像或大区域的图像所设置。
ii) 用户输入标志 - 当该标志被设置时,解码器会用(0x07)来激活声音来提醒用户输入数据。如果没有设定延时,则解码器会一直等待用户的输入。

十六、注释扩充

a. 注释扩充包含实际不属于gif数据流的文本信息。它适用于包括图像注释、描述或者任何其他非控制和非图像数据。注释扩充将被解码器忽略,或者被保留到以后处理。在任何情况下注释扩充也不能中断对数据流的处理。该块是可选的;在数据流中的出现量不加限制。
b. 必须的版本:89a
c. 语法
7 6 5 4 3 2 1 0 字段名 类型
+---------------+
0 | | 扩充导入符 Byte
+---------------+
1 | | 注释标记 Byte
+---------------+
+===============+
| |
N | | 注释数据 数据子块
| |
+===============+
+---------------+
0 | | 块结束符 Byte
+---------------+
i) 扩充导入符 - 标识扩充的开始。该字段为固定值0x21。
ii) 注释标号 - 标示某块为注释扩充。该段为固定值0xFE。
iii) 注释数据 - 按照子块顺序,每个注释最少1字节最多255字节。序列结尾用块结束符标识。
iv) 块结束符 - 这个零长度数据块用来标识注释扩充的结束。
d. 扩充和域:该块没有域,且不能被任何扩充修改。
e. 建议
i) 数据 - 该块为方便使用所设。它使用7位ASCII码字符集。不能用于存储控制信息。
ii) 位置 - 该块可以出现在数据流中的任何地方。建议该块尽量在数据流的开始或者结尾。

十七、纯文本扩充

a. 纯文本扩充包括纯文本数据和将数据显示为图像所必需的参数。文本数据将用7位可印刷ASCII码字符编码。文本数据用在块字段中定义的单元格字符元素来成象。每个字符用一个单元成象。为单色字符,用最合适的字型、字号。字符格包含单元的数量,剩余不足成为格子的部分要丢弃。编码器应精确测算,以避免剩余现象出现。该块使用全局色表。它可以被图形控制扩充来修改。该块为可选块。
b. 必须的版本:89a。
c. 语法
7 6 5 4 3 2 1 0 字段名 类型
+---------------+
0 | | 扩充导入符 Byte
+---------------+
1 | | 纯文本标记 Byte
+---------------+
+---------------+
0 | | 块尺寸 Byte
+---------------+
1 | | 文本格左坐标 Unsigned
+- -+
2 | |
+---------------+
3 | | 文本格顶坐标 Unsigned
+- -+
4 | |
+---------------+
5 | | 文本格宽度 Unsigned
+- -+
6 | |
+---------------+
7 | | 文本格高度 Unsigned
+- -+
8 | |
+---------------+
9 | | 字符单元宽度 Byte
+---------------+
10 | | 字符单元高度 Byte
+---------------+
11 | | 文本前景色索引 Byte
+---------------+
12 | | 文本背景色索引 Byte
+---------------+
+===============+
| |
N | | 纯文本数据 数据子块
| |
+===============+
+---------------+
0 | | 块结束符 Byte
+---------------+
i) 扩充导入符 - 标识一个扩充块的开始。取固定值0x21.
ii) 纯文本标记 - 标识当前块为原文扩充。取固定值0x01.
iii) 块尺寸 - 扩充中的字节数,取固定值12.
iv) 文本格左位置 - 逻辑视屏的左边,用象素表示的左边列数,
v) 文本格顶位置 - 逻辑视屏的上边,用象素表示的上边行数。
xii) 原文数据 - 子块序列,每个子块最少1字节最多255字节。该序列遇到块结束符时结束。
xiii) 块结束符 - 这个0长度数据块用来标志块结束。
d. 扩充和域:该块的域是包含其中的原文字数据。它可以被图像控制扩充来修改。
e. 建议
在原文扩充中的数据是提前格式化好的。对字型、字号的选择由解码器来定。如果遇到小于0x20 或者大于0xf7 的字符,解码器将按空格0x20来处理。为了最广泛地兼容,字符单元应该为8*8或8*16点阵。

十八、应用扩充

a. 应用扩充包含应用说明信息;它遵守如下所述的扩充块的语法,块标记为0xff.
b. 必须的版本:89a
c. 语法
7 6 5 4 3 2 1 0 字段名 类型
+---------------+
0 | | 扩充导入符 Byte
+---------------+
1 | | 扩充标记 Byte
+---------------+
+---------------+
0 | | 块尺寸 Byte
+---------------+
1 | |
+- -+
2 | |
+- -+
3 | | 应用标识符 8 Bytes
+- -+
4 | |
+- -+
5 | |
+- -+
6 | |
+- -+
7 | |
+- -+
8 | |
+---------------+
9 | |
+- -+
10 | | 应用证明码 3 Bytes
+- -+
11 | |
+---------------+
+===============+
| |
| | 应用数据 数据子块
| |
| |
+===============+
+---------------+
0 | | 块结束符 Byte
+---------------+
i) 扩充引入符 - 定义该块位扩充块。取固定值0x21.
ii) 应用扩充标记 - 标识该块为应用扩充块。取固定值0xFF.
iii) 块尺寸 - 指示该块中包含的字节数。取固定值11.
iv) 应用标识符 - 8格可印刷ASCII字符用来标识该应用所属的应用扩充。
v) 应用证明码 - 3格字节的序列用于证明应用标识符。一个应用程序可以一种算法来计算一个二进制码来唯一地识别这个应用是否数于这个应用扩充。
d. 扩充和域:该块没有域,且不能被其他扩充所修改。

十九、尾记录

a. 该块为一个单字段块,用来指示该数据流的结束。取固定值0x3b.
b. 必须的版本:87a。
c. 语法
7 6 5 4 3 2 1 0 字段名 类型
+---------------+
0 | | GIF 尾记录 Byte
+---------------+
d.扩充和域:该块没有域,它用于结束gif 数据流。它不能被任何扩充所修改。

附录A. 快速参照表.
块名称 必须项 标记 扩充 版本
应用扩充 可选 (*) 0xFF (255) 是 89a
注释扩充 可选 (*) 0xFE (254) 是 89a
全局色表 可选 (1) 无 否 87a
图像控制扩充 可选 (*) 0xF9 (249) 是 89a
头部 必须 (1) 无 否 N/A
图象描述符 可选 (*) 0x2C (044) 否 87a (89a)
局部色表 可选 (*) 无 否 87a
逻辑视屏描述块 必须 (1) 无 否 87a (89a)
纯文本扩充 可选 (*) 0x01 (001) 是 89a
尾记录 必须 (1) 0x3B (059) 否 87a
无标记块
头部 必须 (1) 无 否 N/A
逻辑视屏描述符 必须 (1) 无 否 87a (89a)
全局色表 可选 (1) 无 否 87a
局部色表 可选 (*) 无 否 87a
成象块
纯文本扩充 可选 (*) 0x01 (001) 是 89a
图像描述符 可选 (*) 0x2C (044) 否 87a (89a)
控制块
图象控制扩充 可选 (*) 0xF9 (249) 是 89a
特殊用途块
尾记录 必须 (1) 0x3B (059) 否 87a
注释扩充 可选 (*) 0xFE (254) 是 89a
应用扩充 可选 (*) 0xFF (255) 是 89a
图例: (1) 如果出现,最多发生一个
(*) 0个或者多个发生
(+) 一个或者多个发生
注 : 头部不受版本号的制约。
89a版的逻辑视屏描述块及图象描述符保留它们从87a版到89a版的语法,不过有的字段 在87a版是保留项,但是在89a版这为有用项。

附录B. GIF 语法.
   语法是用来表达序列的一种符号形式,并用这个表达序列中的一些对象来形成更大的对象。语法也用于表达在给定的位置出现对象的数目。在此给出的语法用来说明形成gif数据流的块序列,用一些规则列表来表达。下面列出用于gif语法的符号定义。
图例: <> 语法词
::= 符号定义
* 0个或更多的事件发生
+ 1个或更多的事件发生
| 替代元素
[] 可选元素
例子:
<GIF 数据流> ::= 头部 <逻辑视屏> <数据>* 尾记录
这个规则将<Gif 数据流>实体定义如下。它必须以头部开始,头部后面接一个逻辑视屏 实体,该实体药用其他规则来定义。最后,数据实体接结束符。数据实体后面的*表示数据实体可以在此位置出现0或多次。
语法
<Gif 数据流> ::= 头部 <逻辑视屏> <数据>* 尾记录
<逻辑视屏> ::= 逻辑视屏描述块 [全局色表]
<数据> ::= <成象块> |
<特殊用途块>
<成象块> ::= [图象控制扩充] <成象块>
<成象块> ::= <基于表的图象> |
纯文本扩充
<Table-Based Image> ::= 图象描述符 [局部色表] 图象数据
<特殊用途块> ::= 应用扩充 |
注释扩充

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理