控件中国网现已改版,您看到的是老版本网站的镜像,系统正在为您跳转到新网站首页,请稍候.......
中国最专业的商业控件资讯网产品咨询电话:023-67870900 023-67871946
产品咨询EMAIL:SALES@COMPONENTCN.COM

iOS由ImageIO.framework实现gif的系统解码

作者:未知 出处:cnblog 2013年09月26日 阅读:

首先先简单介绍一下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;


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

热推产品

  • ActiveReport... 强大的.NET报表设计、浏览、打印、转换控件,可以同时用于WindowsForms谀坔攀戀Forms平台下......
  • AnyChart AnyChart使你可以创建出绚丽的交互式的Flash和HTML5的图表和仪表控件。可以用于仪表盘的创......
首页 | 新闻中心 | 产品中心 | 技术文档 | 友情连接 | 关于磐岩 | 技术支持中心 | 联系我们 | 帮助中心 Copyright-2006 ComponentCN.com all rights reserved.重庆磐岩科技有限公司(控件中国网) 版权所有 电话:023 - 67870900 传真:023 - 67870270 产品咨询:sales@componentcn.com 渝ICP备12000264号 法律顾问:元炳律师事务所 重庆市江北区塔坪36号维丰创意绿苑A座28-5 邮编:400020
在线客服
在线客服系统
在线客服
在线客服系统