本文在对GIF文件结构学习之后,在iOS平台上进行一些应用。
最近在开发的项目中,有一个需求如下:对GIF文件进行调速。
- 最开始由于项目中存在多种素材(视频、图片组、GIF以及Live Photo)转为GIF的需求,使用的是开源的FFmpeg来进行格式的转换来最终生成GIF。此方法需要额外导入FFmpeg库,造成安装包大小的增大,同时FFmpeg更多的是注重于各种格式图像素材的转换,而非对各种素材进行调速等处理(虽然也能很容易达到,但是极其耗时)。
- 之后技术实现换为FFmpeg负责格式的转换,而对GIF文件数据流进行直接操作覆写达到调速功能。(虽然最终整体换为iOS平台的ImageIO框架,但是还是有必要记录一下该思路的)。
实现思路
通过上一篇文章的学习,我们可以知道,对于GIF调速,本质上就是修改GIF中每张图片的持续时间,该持续时间存储在图形控制扩展的第4、5字节中,所以我们只需直接修改对应位置的数据即可,同时为了保证速度,我们可以对GIF中其余控制块与数据块进行跳过处理。
方法入口
首先我们提供两种修改方式:(1)直接修改持续时间;(2)在原有基础上按倍数修改持续时间
1 | typedef enum : NSUInteger { |
1 | /** |
辅助方法
在处理数据过程中,我们需要一些辅助方法:
获取某字节数据的十六位表达
1 | ///获取对应data的数据 |
具体实现
判断文件是否存在
我们首先需要判断指定的文件是否存在:
1 | //判断文件是否存在 |
判断文件是否可以正常打开
1 | NSFileHandle *fileHandle = [NSFileHandle fileHandleForUpdatingAtPath:gifFilePath]; |
判断指定文件是否为GIF文件
对于GIF文件的判断,我们可以从GIF文件结构入手,GIF文件开头为GIF三个字符:
1 | ///检查是否为GIF |
判断是否有全局颜色列表
1 | /读取是否含有全局颜色列表 |
循环处理控制块与数据块
1 | while (YES) { |
处理控制块
其中标识为0x21为控制块
1 | ///处理可能为标识块的数据 |
处理图形控制扩展
1 | ///处理可能为图形控制拓展 |
在图形控制扩展中,我们可以直接修改读取到的持续时间:
1 | ///调速 |
处理注释扩展
1 | ///处理注释拓展 |
处理图形文本扩展
1 | ///处理可能为图形文本拓展 |
处理应用持续扩展
1 | ///处理可能为应用程序扩展 |
处理数据块
数据块的长度在每个数据块第一个字节指明了,在数据块组结束时,末尾会有一个长度为0x00的数据块为结束标志。
1 | ///跳过数据块 |
以上就是iOS对于GIF文件数据流直接处理达到调速功能,Demo地址下Valhalla/Valhalla/ImageAndGraphics/GIFSpeed文件夹