iOS 4种方法显示GIF

举报
福州司马懿 发表于 2021/11/19 04:51:40 2021/11/19
【摘要】 GIF作为一种淘汰的图像类型文件,和flash一样,直至现在依然存在于我们生活中的每一个角落。 有时候在iOS中使用GIF会比使用帧动画来的更加方便。 iOS中加载GIF的方法大致分为以下几类: (1)使用UIWebView播放GIF数据流。弊端是GIF图片只能播放一次(网上的很多博客都说可以播放,不知道是不是iOS版本的问题,还...

GIF作为一种淘汰的图像类型文件,和flash一样,直至现在依然存在于我们生活中的每一个角落。

有时候在iOS中使用GIF会比使用帧动画来的更加方便。

iOS中加载GIF的方法大致分为以下几类:

(1)使用UIWebView播放GIF数据流。弊端是GIF图片只能播放一次(网上的很多博客都说可以播放,不知道是不是iOS版本的问题,还是这可以播放指的就是1次)

(2)将GIF制作成一个本地网页,用UIVebView显示这个网页。弊端是GIF同样只能播放一次。

(2)预先将GIF中的图片提取出来,然后UIImageView每隔一定间隔显示一张图片。

(3)在运行时,通过代码提取GIF中的每一帧和间隔时间,通过帧动画CAKeyframeAnimation来播放。(该方法有点问题,每一帧的信息都能获取的到,但是动画无法播放,因此我还在调试,敬请期待)。


下面是实现以上技术的关键代码:

1、ViewController.m


  
  1. //
  2. // ViewController.m
  3. // GifDemo
  4. //
  5. // Created by 555chy on 6/17/16.
  6. // Copyright © 2016 555chy. All rights reserved.
  7. //
  8. #import "ViewController.h"
  9. //#import <MobileCoreServices/MobileCoreServices.h>
  10. #import "GifView.h"
  11. #define IMAGE_NAME @"resource/20140830549"
  12. #define IMAGE_TYPE @"gif"
  13. @interface ViewController () {
  14. CGRect contentRect;
  15. }
  16. @end
  17. @implementation ViewController
  18. CGRect screenRect;
  19. - (void)viewDidLoad {
  20. [super viewDidLoad];
  21. // Do any additional setup after loading the view, typically from a nib.
  22. self.navigationItem.title = @"chy龙神";
  23. [self getContentRect];
  24. /*
  25. extern const CFStringRef kUTTypeJPEG __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
  26. extern const CFStringRef kUTTypeJPEG2000 __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
  27. extern const CFStringRef kUTTypeTIFF __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
  28. extern const CFStringRef kUTTypePICT __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
  29. extern const CFStringRef kUTTypeGIF __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
  30. extern const CFStringRef kUTTypePNG __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
  31. extern const CFStringRef kUTTypeQuickTimeImage __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
  32. extern const CFStringRef kUTTypeAppleICNS __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
  33. extern const CFStringRef kUTTypeBMP __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
  34. extern const CFStringRef kUTTypeICO __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
  35. extern const CFStringRef kUTTypeRawImage __OSX_AVAILABLE_STARTING(__MAC_10_10,__IPHONE_8_0);
  36. extern const CFStringRef kUTTypeScalableVectorGraphics __OSX_AVAILABLE_STARTING(__MAC_10_10,__IPHONE_8_0);
  37. extern const CFStringRef kUTTypeLivePhoto __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_9_1);
  38. */
  39. [self loadGifInWebView1];
  40. [self loadGifInWebView2];
  41. [self loadGifInImageView];
  42. [self loadGifInGifView];
  43. }
  44. -(void)getContentRect {
  45. screenRect = [UIScreen mainScreen].bounds;
  46. contentRect = self.navigationController.navigationBar.frame;
  47. NSLog(@"navigationRect = (%f,%f) %f*%f", contentRect.origin.x, contentRect.origin.y, contentRect.size.width, contentRect.size.height);
  48. contentRect.origin.y = contentRect.size.height;
  49. contentRect.size.height = screenRect.size.height - contentRect.size.height;
  50. }
  51. //使用webview加载gif只能不放一轮,不能循环播放
  52. -(void)loadGifInWebView1 {
  53. NSString *path = [[NSBundle mainBundle] pathForResource:IMAGE_NAME ofType:IMAGE_TYPE];
  54. NSData *gifData = [NSData dataWithContentsOfFile:path];
  55. UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(contentRect.origin.x, contentRect.origin.y, contentRect.size.width/2, contentRect.size.height/2)];
  56. //禁止回弹
  57. webView.scrollView.bounces = NO;
  58. webView.scrollView.scrollEnabled = NO;
  59. webView.scalesPageToFit = YES;
  60. //设置透明背景(webview的默认背景上灰色的)
  61. webView.backgroundColor = [UIColor clearColor];
  62. webView.opaque = 0;
  63. //禁止交互
  64. webView.userInteractionEnabled = NO;
  65. [webView loadData:gifData MIMEType:@"image/gif" textEncodingName:@"UTF-8" baseURL:[NSURL fileURLWithPath:@""]];
  66. [self.view addSubview:webView];
  67. }
  68. -(void)loadGifInWebView2 {
  69. NSURL *resourceUrl = [NSBundle mainBundle].resourceURL;
  70. NSString *html = [NSString stringWithFormat:@"<html><body><img src=\"%@.%@\"></body></html>", IMAGE_NAME, IMAGE_TYPE];
  71. UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(contentRect.origin.x+contentRect.size.width/2, contentRect.origin.y, contentRect.size.width/2, contentRect.size.height/2)];
  72. [webView loadHTMLString:html baseURL:resourceUrl];
  73. [self.view addSubview:webView];
  74. }
  75. //普通的UIImage只能显示gif图片的第一帧
  76. -(void)loadGifInImageView {
  77. NSArray *gifImageNameArray = [[NSArray alloc] initWithObjects:@"1",@"5",@"10",@"16", nil];
  78. NSMutableArray *gifImageArray = [NSMutableArray array];
  79. for(int i=0; i<gifImageNameArray.count; i++) {
  80. NSString *name = [NSString stringWithFormat:@"resource/gif/%@", [gifImageNameArray objectAtIndex:i]];
  81. NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"jpg"];
  82. UIImage *image = [UIImage imageWithContentsOfFile:path];
  83. [gifImageArray addObject:image];
  84. }
  85. UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(contentRect.origin.x, contentRect.origin.y+contentRect.size.height/2, contentRect.size.width/2, contentRect.size.height/2)]; [self.view addSubview:imageView];
  86. imageView.animationImages = gifImageArray;
  87. //动画执行的总时长
  88. imageView.animationDuration = 4*0.15;
  89. //动画重复次数(0为重复播放)
  90. imageView.animationRepeatCount = 0;
  91. [imageView startAnimating];
  92. /*
  93. typedef NS_ENUM(NSInteger, UIViewContentMode) {
  94. UIViewContentModeScaleToFill,
  95. UIViewContentModeScaleAspectFit, // contents scaled to fit with fixed aspect. remainder is transparent
  96. UIViewContentModeScaleAspectFill, // contents scaled to fill with fixed aspect. some portion of content may be clipped.
  97. UIViewContentModeRedraw, // redraw on bounds change (calls -setNeedsDisplay)
  98. UIViewContentModeCenter, // contents remain same size. positioned adjusted.
  99. UIViewContentModeTop,
  100. UIViewContentModeBottom,
  101. UIViewContentModeLeft,
  102. UIViewContentModeRight,
  103. UIViewContentModeTopLeft,
  104. UIViewContentModeTopRight,
  105. UIViewContentModeBottomLeft,
  106. UIViewContentModeBottomRight,
  107. };
  108. */
  109. imageView.contentMode = UIViewContentModeScaleToFill;
  110. //imageView.contentMode = UIViewContentModeScaleAspectFit;
  111. //imageView.contentMode = UIViewContentModeScaleAspectFill;
  112. //imageView.contentScaleFactor = [UIScreen mainScreen].scale;
  113. //imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  114. imageView.backgroundColor = [UIColor yellowColor];
  115. [self.view addSubview:imageView];
  116. }
  117. -(void)loadGifInGifView {
  118. NSString *path = [[NSBundle mainBundle] pathForResource:IMAGE_NAME ofType:IMAGE_TYPE];
  119. GifView *gifView = [[GifView alloc] initWithFrame:CGRectMake(contentRect.origin.x+contentRect.size.width/2, contentRect.origin.y+contentRect.size.height/2, contentRect.size.width/2, contentRect.size.height/2) gifFileURL:[NSURL fileURLWithPath:path]];
  120. //[gifView startGif];
  121. [self.view addSubview:gifView];
  122. }
  123. - (void)didReceiveMemoryWarning {
  124. [super didReceiveMemoryWarning];
  125. // Dispose of any resources that can be recreated.
  126. }
  127. @end

2、GifView.h


  
  1. //
  2. // GifView.h
  3. // GifDemo
  4. //
  5. // Created by 555chy on 6/18/16.
  6. // Copyright © 2016 555chy. All rights reserved.
  7. //
  8. #import <UIKit/UIKit.h>
  9. #import <ImageIO/ImageIO.h>
  10. #import <QuartzCore/QuartzCore.h>
  11. @interface GifView : UIImageView
  12. -(id) initWithFrame:(CGRect)frame gifFileURL:(NSURL *)fileURL;
  13. -(BOOL) startGif;
  14. -(void) stopGif;
  15. @end

3、GifView.m


  
  1. //
  2. // GifView.m
  3. // GifDemo
  4. //
  5. // Created by 555chy on 6/18/16.
  6. // Copyright © 2016 555chy. All rights reserved.
  7. //
  8. #import "GifView.h"
  9. void getFrameInfo(CFURLRef url, NSMutableArray *frames, NSMutableArray *delayTimes, CGFloat *totalTime, CGFloat *gifWidth, CGFloat *gifHeight) {
  10. CGImageSourceRef gifSource = CGImageSourceCreateWithURL(url, NULL);
  11. size_t frameCount = CGImageSourceGetCount(gifSource);
  12. NSLog(@"gif frame count = %ld", frameCount);
  13. for(size_t i=0; i<frameCount; i++) {
  14. //get each frame
  15. CGImageRef frame = CGImageSourceCreateImageAtIndex(gifSource, i, NULL);
  16. //[frames addObject:(id)frame];
  17. //Cast of C pointer type 'CGImageRef' (aka 'struct CGImage *') to Objective-C pointer type 'id' requires a bridged cast
  18. [frames addObject:(id)CFBridgingRelease(frame)];
  19. //这边不需要手动释放了,因为CFBridgingRelease已经把管理权交给ARC了
  20. //CGImageRelease(frame);
  21. //get gif info with each frame
  22. //Cast of C pointer type 'CGImageRef' (aka 'struct CGImage *') to Objective-C pointer type 'id' requires a bridged cast
  23. //NSDictionary *dict = (NSDictionary*)CGImageSourceCopyPropertiesAtIndex(gifSource, i, NULL);
  24. NSDictionary *dict = (NSDictionary*)CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(gifSource, i, NULL));
  25. NSLog(@"kCGImagePropertyGIFDictionary %@", [dict valueForKey:(NSString*)kCGImagePropertyGIFDictionary]);
  26. //get gif size
  27. if(gifWidth != NULL && gifHeight != NULL) {
  28. *gifWidth = [[dict valueForKey:(NSString*)kCGImagePropertyPixelWidth] floatValue];
  29. *gifHeight = [[dict valueForKey:(NSString*)kCGImagePropertyPixelHeight] floatValue];
  30. NSLog(@"%ld. gif width*height = %f*%f", i, *gifWidth, *gifHeight);
  31. }
  32. //get gif property
  33. NSDictionary *gifPropertyDict = [dict valueForKey:(NSString*)kCGImagePropertyGIFDictionary];
  34. //kCGImagePropertyGifDictionary中kCGImagePropertyGIFDelayTime, kCGImagePropertyGIFUnclampedDelayTime的值是一样的
  35. id delayTimeObj = [gifPropertyDict valueForKey:(NSString*)kCGImagePropertyGIFDelayTime];
  36. NSLog(@"delayTimeObject = %@", delayTimeObj);
  37. [delayTimes addObject:delayTimeObj];
  38. id unclampedDelayTimeObj = [gifPropertyDict valueForKey:(NSString*)kCGImagePropertyGIFUnclampedDelayTime];
  39. NSLog(@"unclampedDelayTimeObj = %@", unclampedDelayTimeObj);
  40. //[delayTimes addObject:unclampedDelayTimeObj];
  41. if(totalTime) {
  42. *totalTime = *totalTime + [delayTimeObj floatValue];
  43. }
  44. }
  45. NSLog(@"totalTime = %f", *totalTime);
  46. CFRelease(gifSource);
  47. }
  48. @interface GifView() {
  49. NSMutableArray *_gifFrames;
  50. NSMutableArray * _gifFrameDelayTimes;
  51. CGFloat _gifTotalTime;
  52. CGFloat _gifWidth;
  53. CGFloat _gifHeight;
  54. }
  55. @end
  56. @implementation GifView
  57. - (id) initWithFrame:(CGRect)frame gifFileURL:(NSURL *)fileURL {
  58. self = [super initWithFrame:frame];
  59. if(self) {
  60. _gifFrames = [[NSMutableArray alloc] init];
  61. _gifFrameDelayTimes = [[NSMutableArray alloc] init];
  62. _gifWidth = 0;
  63. _gifHeight = 0;
  64. if(fileURL) {
  65. getFrameInfo((__bridge CFURLRef) fileURL, _gifFrames, _gifFrameDelayTimes, &_gifTotalTime, &_gifWidth, &_gifHeight);
  66. }
  67. }
  68. return self;
  69. }
  70. - (BOOL) startGif
  71. {
  72. CGFloat currentTime = 0;
  73. unsigned int count = (unsigned int)_gifFrameDelayTimes.count;
  74. NSLog(@"gif frame count = %u", count);
  75. if(count <= 0 || _gifTotalTime <= 0) {
  76. return NO;
  77. }
  78. CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];
  79. NSMutableArray *times = [NSMutableArray arrayWithCapacity:count];
  80. for(unsigned int i=0; i<count; i++) {
  81. [times addObject:[NSNumber numberWithFloat:(currentTime/_gifTotalTime)]];
  82. currentTime += [[_gifFrameDelayTimes objectAtIndex:i] floatValue];
  83. }
  84. [animation setKeyTimes:times];
  85. NSMutableArray *images = [NSMutableArray arrayWithCapacity:count];
  86. for(unsigned int i=0; i<count; i++) {
  87. NSString *path = [[NSBundle mainBundle] pathForResource:@"resource/gif/1" ofType:@"jpg"];
  88. UIImage *image = [UIImage imageWithContentsOfFile:path];
  89. [images addObject:image];
  90. //[images addObject:[_gifFrames objectAtIndex:i]];
  91. }
  92. [animation setValues: images];
  93. //[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
  94. animation.duration = _gifTotalTime;
  95. animation.delegate = self;
  96. /* The repeat count of the object. May be fractional. Defaults to 0. */
  97. animation.repeatCount = 5;
  98. [self.layer addAnimation:animation forKey:@"gifAnimation"];
  99. return YES;
  100. }
  101. - (void) stopGif {
  102. [self.layer removeAllAnimations];
  103. }
  104. - (void) animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
  105. self.layer.contents = nil;
  106. }
  107. //Only override drawRect: if you perform custom drawing. An empty implementation adversely affects performance during animation
  108. - (void) drawRect:(CGRect)rect {
  109. //Drawing code
  110. }
  111. @end


文章来源: blog.csdn.net,作者:福州-司马懿,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/chy555chy/article/details/51703446

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。