转载自:http://www.cnblogs.com/smileEvday/archive/2013/03/28/Gif.html
三种方式显示GIF图片
播放gif图片通常会有四种方式
用UIWebView
NSString *path = [[NSBundle mainBundle] pathForResource:@"run" ofType:@"gif"];
NSData *gifData = [NSData dataWithContentsOfFile:path];
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 120, 100, 100)];
webView.backgroundColor = [UIColor <span style="font-family: Arial, Helvetica, sans-serif;">clearColor</span>];
webView.scalesPageToFit = YES;
[webView loadData:gifData MIMEType:@"image/gif" textEncodingName:nil baseURL:nil];
[self.view addSubview:webView];
要注意的点
这个webview可以设置透明: [webView setBackgroundColor:[UIColor clearColor]]; [webView setOpaque:NO];这样就不会出现白的底色,当然,前提是gif的每个桢图也是背景透明的。
webview需要将scrollview的滚动功能禁用,不然- -gif 是可以滚动的
优缺点
缺点: UIWebView的内存问题
优点: webview加载的gif会保持原有的桢速
用UIImageView的animationImages
UIImageView *gifImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 240, 100, 100)];
NSArray *gifArray = [NSArray arrayWithObjects:[UIImage imageNamed:@"1"],
[UIImage imageNamed:@"2"],
[UIImage imageNamed:@"3"],
nil];
gifImageView.animationImages = gifArray; //动画图片数组
gifImageView.animationDuration = 5; //执行一次完整动画所需的时长
gifImageView.animationRepeatCount = 999; //动画重复次数
[gifImageView startAnimating];
[self.view addSubview:gifImageView];
缺点
只能保持相同的帧速
用GifView
- (id)initWithFrame:(CGRect)frame data:(NSData *)_data{
self = [super initWithFrame:frame];
if (self) {
// 得到图片的一些属性 这个可有可无
gifProperties = [[NSDictionary dictionaryWithObject:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:0] forKey:(NSString *)kCGImagePropertyGIFLoopCount]
forKey:(NSString *)kCGImagePropertyGIFDictionary] retain];
// gif = CGImageSourceCreateWithURL((CFURLRef)[NSURL fileURLWithPath:_filePath], (CFDictionaryRef)gifProperties);
// 得到gif图片
gif = CGImageSourceCreateWithData((CFDataRef)_data, (CFDictionaryRef)gifProperties);
// 有多少张
count =CGImageSourceGetCount(gif);
timer = [NSTimer scheduledTimerWithTimeInterval:0.12 target:self selector:@selector(play) userInfo:nil repeats:YES];
[timer fire];
}
return self;
}
-(void)play
{
index ++;
index = index%count;
CGImageRef ref = CGImageSourceCreateImageAtIndex(gif, index, (CFDictionaryRef)gifProperties);
self.layer.contents = (id)ref;
CFRelease(ref);
}
缺点
只能保持相同的帧速
用ImageIO来处理
我们知道Gif是由一阵阵画面组成的,而且每一帧画面播放的时常可能会不相等,观察上面两个例子,发现他们都没有对Gif中每一帧的显示时常做处理,这样的结果就是整个Gif中每一帧画面都是以固定的速度向前播放,很显然这并不总会符合需求。
于是smileEvday写一个解析Gif的工具类,解决每一帧画面并遵循每一帧所对应的显示时间进行播放。
程序的思路如下:
1、首先使用ImageIO库中的CGImageSource加载Gif文件。
2、通过CGImageSource获取到Gif文件中的总的帧数,以及每一帧的显示时间。
/*
* @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];
}
CFRelease(dict);
}
if (gifSource) {
CFRelease(gifSource);
}
}
3、通过CAKeyframeAnimation来完成Gif动画的播放。
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"];