首先先簡單介紹一下gif的幾個算是術語吧:async
frame(幀):一個gif能夠簡單認爲是多張image組成的動畫,一幀就是其中一張圖片image.oop
frameCount(幀數): 就是一個gif有多少幀學習
loopCount(播放次數):有些gif播放到必定次數就中止了,若是爲0就表明gif一直循環播放。動畫
delayTime(延遲時間):每一幀播放的時間,也就是說這幀顯示到delayTime就轉到下一幀。url
因此gif播放主要就是把每一幀image解析出來,而後每一幀顯示它對應的delaytime,而後再顯示下一張。如此循環下去。spa
下面是純粹實現由系統提供的解碼:code
-(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中止就好了。這樣是能夠實現變解碼邊播放的,而且都是調用系統解碼,效率也不錯。blog
因項目須要,模仿了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;
僅供參考。代碼整理一下再貼出來。圖片