前言
项目中有一个GIF图二次编辑的需求,这一功能我主要借助Glide库来实现,这里通过系列文章分享下实现过程和GIF相关的学习经验。
编解码器实现原理下其原理。
解码器
第一步创建了 GifHeaderParser
,用来解析GIF的头部数据,主要在 parseHeader()
方法内:
1 |
|
先后解析Header和Contents。
Header部分:
1 |
|
依次读取了文件头部的署名、GIF版本号,其中 readLSD()
读取逻辑屏幕标识符(LSD即Logical Screen Descriptor),readColorTable()
读取颜色列表。
1 |
|
这里源码的注释写的很详细,结合前面的GIF图文件结构就很容易理解了。再然后是Contents部分:
1 |
|
不断循环读取图像块数据,其中 readBitmap()
读取图像数据,readGraphicControlExt()
读取图像控制块数据,包括延迟时间、透明色索引等,readBlock()
读取块大小:
1 |
|
不过这里并没有直接读写Bitmap,而是用一个指针 bufferFrameStart
保存了每一帧的位置,真正的读写在读取Header数据后。我们在遍历每一帧的数据,这里是用一个指针指向当前要读的位置,advance()
方法实际上是在往前移动这一指针:
1 |
|
之后的 getNextFrame()
和 getNextDelay()
方法就是根据这一指针指向的位置,去获取图像和延迟时间:
1 |
|
最后是在 decodeBitmapData()
方法中用LZW算法来读取每一帧图像数据的,代码很多就不贴了。
编码器
首先是 start()
方法:
1 |
|
先写了入了header部分的的GIF 89a。之后再写入每一帧:
1 |
|
依次写入每一帧的数据,基本都是跟解码想对应的,除了writeLSD()
写入逻辑屏幕标识符,writePalette()
写入全局颜色表外,getImagePixels()
读取每一个像素点的颜色值,之后转换为565的格式保存;writeGraphicCtrlExt()
写入图像控制块(这其中要写入包括间隔时间delay等信息),最后在 writePixels()
方法中用LZW算法写入前面读取的图像数据。