您的位置:首页 > 移动开发 > Android开发

Android中Gif图片显示(一)-GIF图片的信息分析

2014-06-10 23:36 411 查看
那什么是GIF图片?

GIF(Graphics Interchange Format)是CompuServe公司开发的图像文件存储格式,1987年开发的GIF文件格式版本号是GIF87a,1989年进行了扩充,扩充后的版本号定义为GIF89a。

GIF文件由文件头,描述块,彩色表,数据块,扩展块和结束符构成,GIF87a和GIF89a的区别在于:后者较前者增加了扩展块,从功能上看即提供了对透明色和多帧动画的支持。GIF89a支持多帧动画。

那为什么Android不能播放由多帧动画组成的GIF图片?

Android支持多帧动画,如在Android的项目中的drawable目录下面添加xml文件,语法如下图:

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/f1" android:duration="300" />
<item android:drawable="@drawable/f2" android:duration="300" />
<item android:drawable="@drawable/f3" android:duration="300" />
<item android:drawable="@drawable/f4" android:duration="300" />
</animation-list>


在文件中可以设置多个图片,也可以指定显示各个图片之间的间隔。
但是Android不能显示GIF的动画,因为GIF文件是一个文件,GIF的所有动画的帧和它们之间的时间间隔都存储在这个文件的数据中,所以需要对GIF文件进行解码才能显示在Android的收件上面。

GIF图片的信息是如何组成的呢,请看下图:



GIF文件由三部分组成:文件头,GIF数据流,文件结尾。

文件头和文件结尾两部分比较好容易区分,那先看这两部分。

文件头:GIF署名用来确认一个文件是否是GIF格式的文件,这一部分由三个字节组成:"GIF"(如果前三个字符不是“GIF”,那就不是GIF图片);文件版本号也是由三个字节组成,可以为"87a"或"89a"。

文件结尾:文件终结器(Trailer),这一部分只有一个值为0x3B的字节,标识一个GIF文件结束。

GIF数据流:那个从第七个字节开始到倒数第二个字节都是GIF数据流的内容。

GIF数据流的第一部分-逻辑屏幕标识符(Logical Screen Descriptor)



前两个字节是GIF图像显示区域的屏幕宽度(用像素表示),三四字节是GIF图像显示区域的屏幕高度(用像素表示)。

第五个字节的具体说明如下图:

m - 全局颜色列表标志(Global Color Table Flag),当置位时表示有全局颜色列表,pixel值有意义。

cr - 颜色深度(Color ResoluTion),cr+1确定图像的颜色深度。

s - 分类标志(Sort Flag),如果置位表示全局颜色列表分类排列。

pixel - 全局颜色列表大小,pixel+1确定颜色列表的索引数(2的pixel+1次方)。

全局颜色列表(Global Color Table)

全局颜色列表必须紧跟在逻辑屏幕标识符后面,每个颜色列表索引条目由三个字节组成,按R、G、B的顺序排列。

图像标识符(Image Descriptor)



一个GIF文件内可以包含多幅图像,一幅图像结束之后紧接着下是一幅图像的标识符。

Image Separator 固定为0x2C(ASCII码中代表“,”,第一个字节的值为“0X2C”)。

Image Left position + Image Top position 表示Image Descriptor 后面跟的一幅图像(块)起始点相对(逻辑)屏幕原点(令其为最左上角点)的位移。

Image Width + Image Depth 表示Image Descriptor 后面跟的一幅图像(块)的实际宽和高,不应该超过Logical Screen Width 和Logical Screen Depth的大小。

以上四项信息在显示多帧图像(动画)时尤其要注意,因为每帧更新的区域有可能都不一样#。

Local Color Table Flag 局部颜色表标志,为1时表示Image Descriptor后面跟的是下幅图像所用的颜色表,此时Global Color Table(全局颜色表)无效。

Note:对于GIF中的一幅图像,可能只有全局颜色表(如静态图像,GIF87a图像和大部分多帧动画),可能没有全局颜色表而每幅图像有各自的局部颜色表(GIF电影片断动画较常见),可能两种颜色表都有(即为上面考虑的情况),也可能两种颜色表都没有(此种情况要用系统颜色表,本文不作考虑)。

Interlace Flag 交错显示标志,为1时表示图像数据是以隔行方式存放的。最初GIF标准设置此标志的目的是考虑到通信设备间传输速度不理想情况下,用这种方式存放和显示图像,就可以在图像显示完成之前看到这幅图像的概貌,慢慢的变清晰,而不觉得显示时间过长。具体扫描行顺序参见GIF89a标准【1】。作为单机显示系统来讲,可以采取逐次行显示方式,也可以采取逐次全屏显示方式(此时将看不到交错效果),依据显示系统的刷新显示性能,解码程序设计者可以选择权衡的。

Sort Flag  与Global Color Table中Sort Flag含义相同。

Reserved  保留。

Local Color Table Size 局部颜色表大小,计算方法与Global Color Table中的方法一致。

顺便说一下扩展的部分:

Extension Introducer 扩展导入符,固定为0x21(ASCII码中代表“!”)。

Application Label 应用扩展块标签,值为0x00~0xFF。

Block Terminator 固定为0x00。

Application Extension结构:



 Block Size  表示Application Data 的大小。

Application Information 为11Bytes的应用程序信息,包含制作GIF文件的应用程序的相关信息。前8字节为应用程序标示符(程序名称),后3字节为应用程序识别码。

Application Data 为Block Size 字节的数据。

Graphic Control Extension 结构:



Block Size 的值应该固定为0x04,即块数据大小为4Bytes。

Display Method 一般值为1,即不作其他特殊处理。其他值处理方式参见GIF89a【1】

User Input Flag 用户输入标志,为1时表示处理完该图像域后等待用户的输入后才开始下一图像域的处理。

Delay Time  表示处理完该图像域到开始处理下一个图像域的延迟时间,单位是1/100秒。注意1秒等于1000毫秒,用java计算间隔时候记得乘以10.

l Note:如果同时出现User Input Flag 置位和Delay Time不为0的情况下,则在      Delay Time定时到之前有用户输入,或者没有用户输入而Delay Time定时到这两种情况下,都会触发下一图像域的处理。

Transparent Color Flag 表示透明颜色索引标志,该标志置位表示透明颜色索引有效。

Transparent Color Index 表示透明颜色索引,在透明颜色索引有效情况下,解码所得颜色索引与该索引值相等时,数据将不作处理(不更新对应像素)。

l Note:什么是透明?透明一般用在多帧图像显示中,例如计划对第一幅图像的一小块区域做更新,而实际上第二幅图像的Image Descriptor指定的区域要比预期的大。对于编码器而言,这多余位置的数据就相当于编码成了透明色索引,解码器解码时就知道这些数据可以不处理,从效果上看就像那些像素是“透明”的,没有破坏第一幅图像的对应区域。如果没有考虑透明处理,那么相应区域就将被刷新为索引色(一般是黑色),这是我们不希望看到的。

某位技术大牛曾经说过:“你认识得越深,你做得越好”。

我会在第二篇博客中把GIF的代码分享给大家。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息