iOS由ImageIO.framework实现gif的系统解码
2015-11-16 15:29
267 查看
http://www.cnblogs.com/vicstudio/p/3339944.html
首先先简单介绍一下gif的几个算是术语吧:
frame(帧):一个gif可以简单认为是多张image组成的动画,一帧就是其中一张图片image.
frameCount(帧数): 就是一个gif有多少帧
loopCount(播放次数):有些gif播放到一定次数就停止了,如果为0就代表gif一直循环播放。
delayTime(延迟时间):每一帧播放的时间,也就是说这帧显示到delayTime就转到下一帧。
所以gif播放主要就是把每一帧image解析出来,然后每一帧显示它对应的delaytime,然后再显示下一张。如此循环下去。
下面是纯粹实现由系统提供的解码:
上面我们可以看到系统解码已经把每一帧的image和delayTime解析出来,并且能知道gif一共的帧数和播放次数。所以我们实现gif播放就是启动一个timer,可以以一个适当的时间运行,如果发现time激活的时间间隔大于这一帧的delayTime,就把image换成下一帧。如此循环,当然,如果loopCount大于0,并且播放次数大于loopCount,就把timer停止就行了。这样是可以实现变解码边播放的,并且都是调用系统解码,效率也不错。
因项目需要,模仿了SDWebImage实现了一个UIImageView的category,只需要提供一个路径就能实现gif的边解码边播放,而不用考虑timer或者其他处理事件,并且因为是category,所以不直接用UIImageView即可。插一句,SDWebImage这个开源库的封转方法是蛮值得学习的。
仅供参考。
iOS由ImageIO.framework实现gif的系统解码
首先先简单介绍一下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, 0), ^() { 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 = 0; 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:GIF图片的预览以及生成
- iOS定位和地理坐标类型解释
- iOS 设置Button的 初始选中状态
- 仿ios日期选择控件
- iOS LBS相关: 定位和中国特色的位置偏移纠正
- iOS9 获取通讯录信息
- (iOS)控制器的生命周期
- iOS学习之屏蔽SSL认证
- iOS中GIF的制作的简单版本记录 详解
- iOS容易造成循环引用的三种场景,就在你我身边!
- IOS修改webView背景透明以及IOS调用前台js的方法
- iOS开发 - TargetAction
- iOS 中正则表达式的运用
- iOS开发—音乐的播放
- iOS判断机型
- 芒果iOS开发之内存管理二
- iOS学习笔记40-GCD定时器的实现
- 转 WWDC 2013 Session笔记 - iOS7中的ViewController切换
- iOS 设计模式——单例模式
- iOS相机与相册的调用常用代码