最近想了解下 iOS 实现 GIF 是如何实现的,看到有一个轮子的实现是通过 Image I/O framework 来实现的,接读了下文档。
Image I/O Programming Guide
Image I/O framework 提供了两个类型来对图片进行操作: (CGImageSourceRef) 负责对图片的读操作 (CGImageDestinationRef) 负责对图片的写操作。
支持格式
framework 支持大多数流行的图片格式,如果想知道所有支持的格式可以通过下列的方式获得所有支持的格式的列表:
CFArrayRef mySourceTypes = CGImageSourceCopyTypeIdentifiers();`
CFShow(mySourceTypes); // print all the supported types
CFArrayRef myDestinationTypes = CGImageDestinationCopyTypeIdentifiers();`
CFShow(myDestinationTypes); // print all the supported types
Image Source
创建一个 CGImageSource 对象, 然后通过指定 index 和 options 去获取图片.前者是因为它是支持多图的; 后者可以通过设置属性(键值对)来完成类似创建缩略图和使用缓存的功能.通过 CGImageSourceGetCount可以获取当前 image source 所有的图片数量.
有些 image source 是包含缩略图的; 如果没有缩略图, 可以指定缩略图的最大尺寸和变化来生成它.
持续加载图片
如果图片太大或者图片需要下载, 可以使用 incremental image source, 这样就可以边加载边显示图片.大致需要按下面几步来实现
- 创建一个对应图片数据的 CFData 对象
- 通过 CGImageSourceCreateIncremental创建一个 incremental image source 对象
- 把图片数据赋值给 CFData 对象
- 调用 CGImageSourceUpdateData 指定是需要整个图片还是只是需要部分图片数据. 任何情况下, 数据参数必须包含所有累积至该点的图像文件的数据(?.
- 如果已经累积了足够的数据, 通过 CGImageSourceCreateImageAtIndex 创建图片, 并开始 绘制这部分图片, 然后释放掉内存.
- 通过调用 CGImageSourceGetStatusAtIndex来检查是否完成加载所有数据.
- 如果已经完成加载, 返回 skCGImageStatusComplete
- 如果未完成加载, 重复 3&4 步, 直到完成
- 释放 incremental image source
显示图片的属性
通过 CGImageSourceCopyPropertiesAtIndex 来获得图片资源里的图片所包含的所有属性的字典.
创建 image source, 从 CGImageSourceCopyPropertiesAtIndex 返回的 CFDictionary 对象. 该对象就是包含图片属性的键值对.
Image Destinations
image destinations 抽象了数据写操作并通过 raw buffer 减少了管理数据的需求.可以展示一张或多张图片, 并可以通过属性的方式显示为多个图片存储缩略图. 可以通过 URL, CFData object, or Quartz data consumer 创建 image destination, 设置图片数据和属性. 完成操作之后需要调用 CGImageDestinationFinalize.
设置 Image Destination 的属性
Image destination 通过 CGImageDestinationSetProperties 来设置键值对属性(CFDictionaryRef . 设置属性是可选的, 可以设置 关键字或饱和度, 曝光率或者其他想保存的值.
Image I/O 定义了大量的键来指定比较重要的值, 详情参考CGImageProperties Reference. 一般需要的图片信息都已包括.
在 Image Destination 上添加图片
先通过以下方法创建 Image Destination CGImageDestinationCreateWithURL
,CGImageDestinationCreateWithData
, or CGImageDestinationCreateWithDataConsumer. 这里需要指定 UTI 或者类似的常量.
通过 CGImageDestinationAddImage
或 CGImageDestinationAddImageFromSource 两个方法向 image destination 添加图片; 如果图片格式允许多图,可以持续添加.
完成添加之后,调用 CGImageDestinationFinalize 来标记添加图片介绍, 结束之后就无法继续添加图片了.