首先先简单介绍一下gif的几个算是术语吧:

frame(帧):一个gif可以简单认为是多张image组成的动画,一帧就是其中一张图片image.

frameCount(帧数): 就是一个gif有多少帧

loopCount(播放次数):有些gif播放到一定次数就停止了,如果为0就代表gif一直循环播放。

delayTime(延迟时间):每一帧播放的时间,也就是说这帧显示到delayTime就转到下一帧。

所以gif播放主要就是把每一帧image解析出来,然后每一帧显示它对应的delaytime,然后再显示下一张。如此循环下去。

下面是纯粹实现由系统提供的解码:

-(void)decodeWithFilePath:(NSString *)filePath

{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^() { NSData *data = [NSData dataWithContentsOfFile:self.path]; [self decodeWithData:data]; }); } -(void)decodeWithData:(NSData *)data
{
CGImageSourceRef src = CGImageSourceCreateWithData((CFDataRef) data, NULL);
if (src)
{
//获取gif的帧数
NSUInteger frameCount = CGImageSourceGetCount(src);
//获取GfiImage的基本数据
NSDictionary *gifProperties = (NSDictionary *) CGImageSourceCopyProperties(src, NULL);
if(gifProperties)
{
//由GfiImage的基本数据获取gif数据
NSDictionary *gifDictionary =[gifProperties objectForKey:(NSString*)kCGImagePropertyGIFDictionary];
//获取gif的播放次数
NSUInteger loopCount = [[gifDictionary objectForKey:(NSString*)kCGImagePropertyGIFLoopCount] integerValue];
for (NSUInteger i = ; i < frameCount; i++)
{
//得到每一帧的CGImage
CGImageRef img = CGImageSourceCreateImageAtIndex(src, (size_t) i, NULL);
if (img)
{
//把CGImage转化为UIImage
UIImage *frameImage = [UIImage imageWithCGImage:img];
//获取每一帧的图片信息
NSDictionary *frameProperties = (NSDictionary *) CGImageSourceCopyPropertiesAtIndex(src, (size_t) i, NULL);
if (frameProperties)
{
//由每一帧的图片信息获取gif信息
NSDictionary *frameDictionary = [frameProperties objectForKey:(NSString*)kCGImagePropertyGIFDictionary];
//取出每一帧的delaytime
CGFloat delayTime = [[frameDictionary objectForKey:(NSString*)kCGImagePropertyGIFDelayTime] floatValue];
//TODO 这里可以实现边解码边回调播放或者把每一帧image和delayTime存储起来
CFRelease(frameProperties);
}
CGImageRelease(img);
}
}
CFRelease(gifProperties);
}
CFRelease(src);
}
}

上面我们可以看到系统解码已经把每一帧的image和delayTime解析出来,并且能知道gif一共的帧数和播放次数。所以我们实现gif播放就是启动一个timer,可以以一个适当的时间运行,如果发现time激活的时间间隔大于这一帧的delayTime,就把image换成下一帧。如此循环,当然,如果loopCount大于0,并且播放次数大于loopCount,就把timer停止就行了。这样是可以实现变解码边播放的,并且都是调用系统解码,效率也不错。

因项目需要,模仿了SDWebImage实现了一个UIImageView的category,只需要提供一个路径就能实现gif的边解码边播放,而不用考虑timer或者其他处理事件,并且因为是category,所以不直接用UIImageView即可。插一句,SDWebImage这个开源库的封转方法是蛮值得学习的。

@interface UIImageView(GifImageView)<GifPlayerDelegate>

- (void)setGifFilePath:(NSString*)filePath;
- (void)setGifFilePath:(NSString*)filePath placeholderImage:(UIImage *)placeholder;
- (void)setGifFilePath:(NSString*)filePath placeholderImage:(UIImage *)placeholder failure:(GifPlayerError)error; - (void)setGifUrlString:(NSString*)urlString;
- (void)setGifUrlString:(NSString*)urlString placeholderImage:(UIImage *)placeholder;
- (void)setGifUrlString:(NSString*)urlString placeholderImage:(UIImage *)placeholder failure:(GifPlayerError)error; -(void)gifPasue;
-(void)gifResume;
-(void)gifStop;

仅供参考。代码整理一下再贴出来。

iOS由ImageIO.framework实现gif的系统解码的更多相关文章

  1. iOS使用Security.framework进行RSA 加密解密签名和验证签名

    iOS 上 Security.framework为我们提供了安全方面相关的api: Security框架提供的RSA在iOS上使用的一些小结 支持的RSA keySize 大小有:512,768,10 ...

  2. iOS 神秘而又强大的传感器系统 (附demo)

    iOS中的各种传感器: 随着科技的发展,机器感知人的行为!Goole的无人驾驶汽车到李彦宏的无人驾汽车,都带入了各种计算及传感. 为了研究自然现象和制造劳动工具,人类必须了解外界的各类信息.了解外界信 ...

  3. iOS开发-动态和静态FrameWork

    开发中我们会使用到第三方的SDK,有的时候也会将整个系统的公用的功能的抽象出来成为FrameWork,我们只需要暴露对外的接口,使用者只需要调用接口,对于内部实现的过程不需要维护,可以以库的形式进行封 ...

  4. IOS: 使用imageIO获取和修改图片的exif信息

    使用imageIO获取和修改图片的exif信息 一幅图片除了包含我们能看见的像素信息,背后还包含了拍摄时间,光圈大小,曝光等信息.UIImage类将这些细节信息都隐藏了起来,只提供我们关心的图片尺寸, ...

  5. iOS Core Telephony Framework

    Core Telephony Framework(核心通讯框架) 概述: 这个库的前缀为CT(Core Telephony),主要用来获得用户通讯相关信息,我们可以使用这些信息来定义外部接口以便自己使 ...

  6. Unity3D研究院之IOS全自动编辑framework、plist、oc代码

    Unity打IOS时会先生成一个Xcode工程,如果你需要增加一些第三方的framework那么需要手动一条一条的添加,这太烦了..而且可能你还需要修改Plist文件,甚至还可能要修改unity自动生 ...

  7. iOS中 MediaPlayer framework实现视频播放 韩俊强的博客

    iOS开发中播放音乐可以使用MPMusicPlayerController类来实现,播放视频可以使用MPMoviePlayerController和MPMoviePlayerViewControlle ...

  8. iOS XCode7制作.Framework动态库和.a静态库的总结

    一.开发SDK时的支持情况: OC语言制作动态库时,支持iOS8+:OC语言制作静态库,支持iOS7+. Swift语言制作动态库时,支持iOS8+;Swift不支持静态库. 对于SDK来说,支持情况 ...

  9. ios svn无法连接xp或者win7系统svn的解决方法

    找到服务器svn的安装目录,或者直接查找httpd.conf,找到端口号,复制到ios系统的svn端口号,就ok了,如图 这是其他人的解决方法 Subversion有两种不同的配置方式,一种基于它自带 ...

随机推荐

  1. 第17章 中介者模式(Mediator Pattern)

    原文 第17章 中介者模式(Mediator Pattern) 中介者模式  概述:   在软件开发中,我们有时会碰上许多对象互相联系互相交互的情况,对象之间存在复杂的引用关系,当需求更改时,对系统进 ...

  2. Cocos2d-X采用CCScrollView创建滚动视图

    CCScrollView滚动视图可以让游戏有效果,并能够通过滚动视图切换游戏场景,滚动视图通常用来选择在游戏中的级别 实例1:使用CCScrollView创建一个简单的滚动视图 首先创建一个Scrol ...

  3. WCF中的数据契约(DataContract)

    服务契约定义了远程访问对象和可供调用的方法,数据契约则是服务端和客户端之间要传送的自定义数据类型. 一旦声明一个类型为DataContract,那么该类型就可以被序列化在服务端和客户端之间传送,如下所 ...

  4. SP服务商收益究竟有多大?

    揭秘spspsp服务商怎样盈利?代办sp服务商又称持增值电信----移动网信息服务许可证信息提供商,sp主要业务有短信彩信(手机报.短信群发.客服系统).WAP.彩铃.IVR.百宝箱.JAVA游戏.B ...

  5. vSphere HA状况:未知配置错误解决的方法

    问题:vSphere HA配置出现未知错误,导致打不开主机上的虚拟机电源,vmware client连接vcenter后,主机显示警报信息,例如以下: 解决:例如以下图,选中有问题的物理主机,然后又一 ...

  6. .net mvc mssql easyui treegrid 及时 编辑 ,支持拖拽

    这里提到了,1个问题,怎么扩展 Easyui 参见: http://blog.csdn.net/chenkai6529/article/details/17528833 @{ ViewBag.Titl ...

  7. A WebBrowser Toy

    原文:A WebBrowser Toy 记得上大学时,某老师为了防止学生上课不听讲,只准学生在课堂上看他放映的PPT,不准学生拷贝,而考试的内容恰恰是PPT上的内容,于是一个同学来找我,我就用VB写了 ...

  8. JS 数组array方法push, pop, unshift, shift, slice,splice,contact, join, sort

    Array:数组对象用来在单独的变量名中存储一系列的值   定义数组:         1. var arrayObj = new Array();         2. var arrayObj = ...

  9. phpstorm集成phpunit

    1.下载phpunit.phar,将该文件放到某个工程中 2.File > Settings > Languages & Frameworks > PHP > PHPU ...

  10. 用erlang写的kmp算法

    Knuth-Morris-Pratt 字符串查找算法,简称为 "KMP算法",常用于在一个文本串S内查找一个模式串P 的出现位置,这个算法由Donald Knuth.Vaughan ...