IOS中如何解析並顯示Gif

來源:互聯網
上載者:User

IOS中如何解析並顯示Gif

  聊天的時候我們經常用到很多搞笑的Gif表情,有時候千言萬語真的比不上一個Gif來的實在。以前一直以為想Gif作為一種常用格式,各大平台應該都會支援,知道前兩天項目中要載入一個Gif作為過渡動畫,我查了半天協助文檔,發現IOS中居然沒有現成的支援載入和播放Gif的類。

  於是上網簡單的搜了一下,發現兩個比較有有用的代碼。網址分別如下:

      三種方式顯示GIF圖片

  andrei512 / GIFLoader.h

  這兩種方法都是採用ImageIO庫,對Gif檔案進行解析,然後自己做動畫顯示,至此顯示Gif動畫的思路就已經比較明確了。

  我們知道Gif是由一陣陣畫面組成的,而且每一幀畫面播放的時常可能會不相等,觀察上面兩個例子,發現他們都沒有對Gif中每一幀的顯示時常做處理,這樣的結果就是整個Gif中每一幀畫面都是以固定的速度向前播放,很顯然這並不總會符合需求。

  於是自己寫一個解析Gif的工具類,解決每一幀畫面並遵循每一幀所對應的顯示時間進行播放。

  程式的思路如下:

  1、首先使用ImageIO庫中的CGImageSource家在Gif檔案。

  2、通過CGImageSource擷取到Gif檔案中的總的幀數,以及每一幀的顯示時間。

  3、通過CAKeyframeAnimation來完成Gif動畫的播放。

  下面直接上我寫的解析和播放Gif的工具類的代碼:

SvGifView

////  SvGifView.h//  SvGifSample////  Created by maple on 3/28/13.//  Copyright (c) 2013 smileEvday. All rights reserved.////  QQ: 1592232964#import <UIKit/UIKit.h>@interface SvGifView : UIView/* * @brief desingated initializer */- (id)initWithCenter:(CGPoint)center fileURL:(NSURL*)fileURL;/* * @brief start Gif Animation */- (void)startGif;/* * @brief stop Gif Animation */- (void)stopGif;/* * @brief get frames image(CGImageRef) in Gif */+ (NSArray*)framesInGif:(NSURL*)fileURL;@end
SvGifView.m

////  SvGifView.m//  SvGifSample////  Created by maple on 3/28/13.//  Copyright (c) 2013 smileEvday. All rights reserved.////  QQ: 1592232964#import "SvGifView.h"#import <ImageIO/ImageIO.h>#import <QuartzCore/CoreAnimation.h>/* * @brief resolving gif information */void getFrameInfo(CFURLRef url, NSMutableArray *frames, NSMutableArray *delayTimes, CGFloat *totalTime,CGFloat *gifWidth, CGFloat *gifHeight){    CGImageSourceRef gifSource = CGImageSourceCreateWithURL(url, NULL);        // get frame count    size_t frameCount = CGImageSourceGetCount(gifSource);    for (size_t i = 0; i < frameCount; ++i) {        // get each frame        CGImageRef frame = CGImageSourceCreateImageAtIndex(gifSource, i, NULL);        [frames addObject:(id)frame];        CGImageRelease(frame);                // get gif info with each frame        NSDictionary *dict = (NSDictionary*)CGImageSourceCopyPropertiesAtIndex(gifSource, i, NULL);        NSLog(@"kCGImagePropertyGIFDictionary %@", [dict valueForKey:(NSString*)kCGImagePropertyGIFDictionary]);                // get gif size        if (gifWidth != NULL && gifHeight != NULL) {            *gifWidth = [[dict valueForKey:(NSString*)kCGImagePropertyPixelWidth] floatValue];            *gifHeight = [[dict valueForKey:(NSString*)kCGImagePropertyPixelHeight] floatValue];        }                // kCGImagePropertyGIFDictionary中kCGImagePropertyGIFDelayTime,kCGImagePropertyGIFUnclampedDelayTime值是一樣的        NSDictionary *gifDict = [dict valueForKey:(NSString*)kCGImagePropertyGIFDictionary];        [delayTimes addObject:[gifDict valueForKey:(NSString*)kCGImagePropertyGIFDelayTime]];                if (totalTime) {            *totalTime = *totalTime + [[gifDict valueForKey:(NSString*)kCGImagePropertyGIFDelayTime] floatValue];        }    }}@interface SvGifView() {    NSMutableArray *_frames;    NSMutableArray *_frameDelayTimes;        CGFloat _totalTime;         // seconds    CGFloat _width;    CGFloat _height;}@end@implementation SvGifView- (id)initWithCenter:(CGPoint)center fileURL:(NSURL*)fileURL;{    self = [super initWithFrame:CGRectZero];    if (self) {                _frames = [[NSMutableArray alloc] init];        _frameDelayTimes = [[NSMutableArray alloc] init];                _width = 0;        _height = 0;                if (fileURL) {            getFrameInfo((CFURLRef)fileURL, _frames, _frameDelayTimes, &_totalTime, &_width, &_height);        }                self.frame = CGRectMake(0, 0, _width, _height);        self.center = center;    }        return self;}+ (NSArray*)framesInGif:(NSURL *)fileURL{    NSMutableArray *frames = [NSMutableArray arrayWithCapacity:3];    NSMutableArray *delays = [NSMutableArray arrayWithCapacity:3];        getFrameInfo((CFURLRef)fileURL, frames, delays, NULL, NULL, NULL);        return frames;}- (void)startGif{    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];        NSMutableArray *times = [NSMutableArray arrayWithCapacity:3];    CGFloat currentTime = 0;    int count = _frameDelayTimes.count;    for (int i = 0; i < count; ++i) {        [times addObject:[NSNumber numberWithFloat:(currentTime / _totalTime)]];        currentTime += [[_frameDelayTimes objectAtIndex:i] floatValue];    }    [animation setKeyTimes:times];        NSMutableArray *images = [NSMutableArray arrayWithCapacity:3];    for (int i = 0; i < count; ++i) {        [images addObject:[_frames objectAtIndex:i]];    }        [animation setValues:images];    [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];    animation.duration = _totalTime;    animation.delegate = self;    animation.repeatCount = 5;        [self.layer addAnimation:animation forKey:@"gifAnimation"];}- (void)stopGif{    [self.layer removeAllAnimations];}// remove contents when animation end- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{    self.layer.contents = nil;}// Only override drawRect: if you perform custom drawing.// An empty implementation adversely affects performance during animation.- (void)drawRect:(CGRect)rect{    // Drawing code}@end

  代碼很短也比較容易,就不一一解釋了。最開始的那個C函數主要就是用來解析Gif的,之所以用C函數是因為我要返回多個資訊,而Objective-c只能返回一個參數,而且Objective-c和C語言可以很方便的混合編程。

   測試程式Github地址:https://github.com/smileEvday/SvGifView/

  

 

 

 

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.