iOS开发中实现显示gif图片的方法
我们知道Gif是由一阵阵画面组成的,而且每一帧画面播放的时常可能会不相等,观察上面两个例子,发现他们都没有对Gif中每一帧的显示时常做处理,这样的结果就是整个Gif中每一帧画面都是以固定的速度向前播放,很显然这并不总会符合需求。
于是自己写一个解析Gif的工具类,解决每一帧画面并遵循每一帧所对应的显示时间进行播放。
程序的思路如下:
1、首先使用ImageIO库中的CGImageSource家在Gif文件。
2、通过CGImageSource获取到Gif文件中的总的帧数,以及每一帧的显示时间。
3、通过CAKeyframeAnimation来完成Gif动画的播放。
下面直接上我写的解析和播放Gif的工具类的代码:
// // SvGifView.h // SvGifSample // // Createdbymapleon3/28/13. // Copyright(c)2013smileEvday.Allrightsreserved. //
#import<UIKit/UIKit.h>
@interfaceSvGifView:UIView
/* *@briefdesingatedinitializer */ -(id)initWithCenter:(CGPoint)centerfileURL:(NSURL*)fileURL;
/* *@briefstartGifAnimation */ -(void)startGif;
/* *@briefstopGifAnimation */ -(void)stopGif;
/* *@briefgetframesimage(CGImageRef)inGif */ +(NSArray*)framesInGif:(NSURL*)fileURL;
@end
// // SvGifView.m // SvGifSample // // Createdbymapleon3/28/13. // Copyright(c)2013smileEvday.Allrightsreserved. //
#import"SvGifView.h" #import<ImageIO/ImageIO.h> #import<QuartzCore/CoreAnimation.h>
/* *@briefresolvinggifinformation */ voidgetFrameInfo(CFURLRefurl,NSMutableArray*frames,NSMutableArray*delayTimes,CGFloat*totalTime,CGFloat*gifWidth,CGFloat*gifHeight) { CGImageSourceRefgifSource=CGImageSourceCreateWithURL(url,NULL); //getframecount size_tframeCount=CGImageSourceGetCount(gifSource); for(size_ti=0;i<frameCount;++i){ //geteachframe CGImageRefframe=CGImageSourceCreateImageAtIndex(gifSource,i,NULL); [framesaddObject:(id)frame]; CGImageRelease(frame); //getgifinfowitheachframe NSDictionary*dict=(NSDictionary*)CGImageSourceCopyPropertiesAtIndex(gifSource,i,NULL); NSLog(@"kCGImagePropertyGIFDictionary%@",[dictvalueForKey:(NSString*)kCGImagePropertyGIFDictionary]); //getgifsize if(gifWidth!=NULL&&gifHeight!=NULL){ *gifWidth=[[dictvalueForKey:(NSString*)kCGImagePropertyPixelWidth]floatValue]; *gifHeight=[[dictvalueForKey:(NSString*)kCGImagePropertyPixelHeight]floatValue]; } //kCGImagePropertyGIFDictionary中kCGImagePropertyGIFDelayTime,kCGImagePropertyGIFUnclampedDelayTime值是一样的 NSDictionary*gifDict=[dictvalueForKey:(NSString*)kCGImagePropertyGIFDictionary]; [delayTimesaddObject:[gifDictvalueForKey:(NSString*)kCGImagePropertyGIFDelayTime]]; if(totalTime){ *totalTime=*totalTime+[[gifDictvalueForKey:(NSString*)kCGImagePropertyGIFDelayTime]floatValue]; } } }
@interfaceSvGifView(){ NSMutableArray*_frames; NSMutableArray*_frameDelayTimes; CGFloat_totalTime; //seconds CGFloat_width; CGFloat_height; }
@end
@implementationSvGifView
-(id)initWithCenter:(CGPoint)centerfileURL:(NSURL*)fileURL; { self=[superinitWithFrame:CGRectZero]; if(self){ _frames=[[NSMutableArrayalloc]init]; _frameDelayTimes=[[NSMutableArrayalloc]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; } returnself; }
+(NSArray*)framesInGif:(NSURL*)fileURL { NSMutableArray*frames=[NSMutableArrayarrayWithCapacity:3]; NSMutableArray*delays=[NSMutableArrayarrayWithCapacity:3]; getFrameInfo((CFURLRef)fileURL,frames,delays,NULL,NULL,NULL); returnframes; }
-(void)startGif { CAKeyframeAnimation*animation=[CAKeyframeAnimationanimationWithKeyPath:@"contents"]; NSMutableArray*times=[NSMutableArrayarrayWithCapacity:3]; CGFloatcurrentTime=0; intcount=_frameDelayTimes.count; for(inti=0;i<count;++i){ [timesaddObject:[NSNumbernumberWithFloat:(currentTime/_totalTime)]]; currentTime+=[[_frameDelayTimesobjectAtIndex:i]floatValue]; } [animationsetKeyTimes:times]; NSMutableArray*images=[NSMutableArrayarrayWithCapacity:3]; for(inti=0;i<count;++i){ [imagesaddObject:[_framesobjectAtIndex:i]]; } [animationsetValues:images]; [animationsetTimingFunction:[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionLinear]]; animation.duration=_totalTime; animation.delegate=self; animation.repeatCount=5; [self.layeraddAnimation:animationforKey:@"gifAnimation"]; }
-(void)stopGif { [self.layerremoveAllAnimations]; }
//removecontentswhenanimationend -(void)animationDidStop:(CAAnimation*)animfinished:(BOOL)flag { self.layer.contents=nil; }
//OnlyoverridedrawRect:ifyouperformcustomdrawing. //Anemptyimplementationadverselyaffectsperformanceduringanimation. -(void)drawRect:(CGRect)rect { //Drawingcode }
@end