ios播放gif图片
2015-03-01 14:11
453 查看
以前一直听说ios不可以播放gif图片。也没取看看。其实想想有啥不能播放的。只是没有提供现成的api而已。最近看看资料以及别人的例子了解了一下实现原理 特记录一下:
gif 其实本来就是一系列的图片的集合 可以通过 imageIO 获取到图片数组。然后动画播放就ok了;先看一下 简单的例子:
一个简单的播放gif的例子就出来了。不过毫无疑问。这么写有很大的问题。原因在于gif 每一桢之间的间隔时间是可以设置的。甚至可以不同。所以需要做些处理
有个人的实现原理是这样的:取出gif图片所有桢的时间。 取这些时间的最大公约数 作为显示的的桢的时间。 然后根据新的桢的间隔时间取对应的图片。 这样处理显示的帧数大于等于原始帧数。 如果原始桢的间隔时间太奇葩。 会导致大量的图片是重复的。不过正常使用还是很不错的。
下面是 从code4app上下载的别人的代码 地址已经不记得了。删除了其他的部分 只留下了跟播放动画相关的地方 贴出来参考:
另外也可以通过动画来播放。这样可能不会像上面出现特殊情况下大量重复的桢。不过现实中gif间隔一般都是固定的。所以上面就够用了。
gif 其实本来就是一系列的图片的集合 可以通过 imageIO 获取到图片数组。然后动画播放就ok了;先看一下 简单的例子:
NSURL *url = [[NSBundle mainBundle] URLForResource:@"pika.gif" withExtension:nil]; CGImageSourceRef csf = CGImageSourceCreateWithURL((__bridge CFTypeRef) url, NULL); size_t const count = CGImageSourceGetCount(csf); UIImage *frames[count]; CGImageRef images[count]; for (size_t i = 0; i < count; ++i) { images[i] = CGImageSourceCreateImageAtIndex(csf, i, NULL); UIImage *image =[[UIImage alloc] initWithCGImage:images[i]]; frames[i] = image; CFRelease(images[i]); } UIImage *const animation = [UIImage animatedImageWithImages:[NSArray arrayWithObjects:frames count:count] duration:0.1]; [view2 setImage:animation]; NSLog(@"xxxx%zu",count); CFRelease(csf);
一个简单的播放gif的例子就出来了。不过毫无疑问。这么写有很大的问题。原因在于gif 每一桢之间的间隔时间是可以设置的。甚至可以不同。所以需要做些处理
有个人的实现原理是这样的:取出gif图片所有桢的时间。 取这些时间的最大公约数 作为显示的的桢的时间。 然后根据新的桢的间隔时间取对应的图片。 这样处理显示的帧数大于等于原始帧数。 如果原始桢的间隔时间太奇葩。 会导致大量的图片是重复的。不过正常使用还是很不错的。
下面是 从code4app上下载的别人的代码 地址已经不记得了。删除了其他的部分 只留下了跟播放动画相关的地方 贴出来参考:
// // ViewController.m // test4 // // Created by Aurora_sgbh on 15-2-6. // Copyright (c) 2015年 Aurora_sgbh. All rights reserved. // #if __has_feature(objc_arc) #define toCF (__bridge CFTypeRef) #define fromCF (__bridge id) #else #define toCF (CFTypeRef) #define fromCF (id) #endif #import "ViewController.h" #import <ImageIO/ImageIO.h> #pragma mark - UIImage Animated GIF @implementation UIImage (animatedGIF) static int delayCentisecondsForImageAtIndex(CGImageSourceRef const source, size_t const i) { int delayCentiseconds = 1; CFDictionaryRef const properties = CGImageSourceCopyPropertiesAtIndex(source, i, NULL); if (properties) { CFDictionaryRef const gifProperties = CFDictionaryGetValue(properties, kCGImagePropertyGIFDictionary); if (gifProperties) { NSNumber *number = fromCF CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFUnclampedDelayTime); if (number == NULL || [number doubleValue] == 0) { number = fromCF CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFDelayTime); } if ([number doubleValue] > 0) { // Even though the GIF stores the delay as an integer number of centiseconds, ImageIO “helpfully” converts that to seconds for us. delayCentiseconds = (int)lrint([number doubleValue] * 100); NSLog(@"看看时间%d",delayCentiseconds); } } CFRelease(properties); } return delayCentiseconds; } static void createImagesAndDelays(CGImageSourceRef source, size_t count, CGImageRef imagesOut[count], int delayCentisecondsOut[count]) { for (size_t i = 0; i < count; ++i) { imagesOut[i] = CGImageSourceCreateImageAtIndex(source, i, NULL); delayCentisecondsOut[i] = delayCentisecondsForImageAtIndex(source, i); } } static int sum(size_t const count, int const *const values) { int theSum = 0; for (size_t i = 0; i < count; ++i) { theSum += values[i]; } return theSum; } //最大公约数 static int pairGCD(int a, int b) { if (a < b) return pairGCD(b, a); while (true) { int const r = a % b; if (r == 0) return b; a = b; b = r; } } static int vectorGCD(size_t const count, int const *const values) { int gcd = values[0]; for (size_t i = 1; i < count; ++i) { // Note that after I process the first few elements of the vector, `gcd` will probably be smaller than any remaining element. By passing the smaller value as the second argument to `pairGCD`, I avoid making it swap the arguments. gcd = pairGCD(values[i], gcd); } return gcd; } static NSArray *frameArray(size_t const count, CGImageRef const images[count], int const delayCentiseconds[count], int const totalDurationCentiseconds) { int const gcd = vectorGCD(count, delayCentiseconds); size_t const frameCount = totalDurationCentiseconds / gcd; UIImage *frames[frameCount]; for (size_t i = 0, f = 0; i < count; ++i) { UIImage *const frame = [UIImage imageWithCGImage:images[i]]; for (size_t j = delayCentiseconds[i] / gcd; j > 0; --j) { frames[f++] = frame; } } return [NSArray arrayWithObjects:frames count:frameCount]; } static void releaseImages(size_t const count, CGImageRef const images[count]) { for (size_t i = 0; i < count; ++i) { CGImageRelease(images[i]); } } //xxx static UIImage *animatedImageWithAnimatedGIFImageSource(CGImageSourceRef const source) { size_t const count = CGImageSourceGetCount(source); CGImageRef images[count]; int delayCentiseconds[count]; // in centiseconds createImagesAndDelays(source, count, images, delayCentiseconds); int const totalDurationCentiseconds = sum(count, delayCentiseconds); NSArray *const frames = frameArray(count, images, delayCentiseconds, totalDurationCentiseconds); UIImage *const animation = [UIImage animatedImageWithImages:frames duration:(NSTimeInterval)totalDurationCentiseconds / 100.0]; releaseImages(count, images); return animation; } static UIImage *animatedImageWithAnimatedGIFReleasingImageSource(CGImageSourceRef CF_RELEASES_ARGUMENT source) { if (source) { UIImage *const image = animatedImageWithAnimatedGIFImageSource(source); CFRelease(source); return image; } else { return nil; } } + (UIImage *)animatedImageWithAnimatedGIFData:(NSData *)data { return animatedImageWithAnimatedGIFReleasingImageSource(CGImageSourceCreateWithData(toCF data, NULL)); } + (UIImage *)animatedImageWithAnimatedGIFURL:(NSURL *)url { return animatedImageWithAnimatedGIFReleasingImageSource(CGImageSourceCreateWithURL((__bridge CFTypeRef) url, NULL)); } @end @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; UIImageView *view =[[UIImageView alloc]initWithFrame:CGRectMake(50, 50, 100, 100)]; [view setImage:[UIImage animatedImageWithAnimatedGIFURL:[[NSBundle mainBundle] URLForResource:@"3.gif" withExtension:nil]]]; //mytest // UIImageView *view2 =[[UIImageView alloc]initWithFrame:CGRectMake(50, 250, 100, 100)]; // [view2 setBackgroundColor:[UIColor redColor]]; // NSURL *url = [[NSBundle mainBundle] URLForResource:@"pika.gif" withExtension:nil]; // CGImageSourceRef csf = CGImageSourceCreateWithURL((__bridge CFTypeRef) url, NULL); // size_t const count = CGImageSourceGetCount(csf); // UIImage *frames[count]; // CGImageRef images[count]; // for (size_t i = 0; i < count; ++i) { // images[i] = CGImageSourceCreateImageAtIndex(csf, i, NULL); // UIImage *image =[[UIImage alloc] initWithCGImage:images[i]]; // frames[i] = image; // CFRelease(images[i]); // } // // UIImage *const animation = [UIImage animatedImageWithImages:[NSArray arrayWithObjects:frames count:count] duration:0.1]; // // [view2 setImage:animation]; // NSLog(@"xxxx%zu",count); // CFRelease(csf); // [self.view addSubview:view2]; [self.view addSubview:view]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
另外也可以通过动画来播放。这样可能不会像上面出现特殊情况下大量重复的桢。不过现实中gif间隔一般都是固定的。所以上面就够用了。
相关文章推荐
- IOS 播放动态Gif图片
- IOS 播放动态Gif图片
- iOS 中播放gif图片
- 《iOS开发之美》节选: 如何在iOS中播放gif 动画图片?
- iOS gif 图片播放实现方法 (image 扩展方案)
- iOS 播放gif图片
- IOS播放GIF图片
- 如何在iOS中播放gif 动画图片?
- ios播放gif图片
- 【代码笔记】iOS-gif图片播放
- 【代码笔记】iOS-gif图片播放
- iOS 播放.GIF图片
- iOS 播放GIF动态图片!!!!!
- iOS开发之旋转动画及GIF格式图片的播放
- IOS 播放动态Gif图片
- IOS:如何使用多张图片合成GIF
- IOS锁屏状态播放音乐时显示专辑信息和图片
- iOS 播放gif 动画
- java图片处理——多张图片合成一张Gif图片并播放或Gif拆分成多张图片
- Android播放GIF图片