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


      //
      // ViewController.m
      // GifDemo
      //
      // Created by 555chy on 6/17/16.
      // Copyright © 2016 555chy. All rights reserved.
      //
      #import "ViewController.h"
      //#import <MobileCoreServices/MobileCoreServices.h>
      #import "GifView.h"
      #define IMAGE_NAME @"resource/20140830549"
      #define IMAGE_TYPE @"gif"
      @interface ViewController () {
         CGRect contentRect;
      }
      @end
      @implementation ViewController
      CGRect screenRect;
      - (void)viewDidLoad {
          [super viewDidLoad];
         // Do any additional setup after loading the view, typically from a nib.
         self.navigationItem.title = @"chy龙神";
          [self getContentRect];
         /*
       extern const CFStringRef kUTTypeJPEG __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
       extern const CFStringRef kUTTypeJPEG2000 __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
       extern const CFStringRef kUTTypeTIFF __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
       extern const CFStringRef kUTTypePICT __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
       extern const CFStringRef kUTTypeGIF __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
       extern const CFStringRef kUTTypePNG __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
       extern const CFStringRef kUTTypeQuickTimeImage __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
       extern const CFStringRef kUTTypeAppleICNS __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
       extern const CFStringRef kUTTypeBMP __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
       extern const CFStringRef kUTTypeICO __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_3_0);
       extern const CFStringRef kUTTypeRawImage __OSX_AVAILABLE_STARTING(__MAC_10_10,__IPHONE_8_0);
       extern const CFStringRef kUTTypeScalableVectorGraphics __OSX_AVAILABLE_STARTING(__MAC_10_10,__IPHONE_8_0);
       extern const CFStringRef kUTTypeLivePhoto __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_9_1);
       */
          [self loadGifInWebView1];
          [self loadGifInWebView2];
          [self loadGifInImageView];
          [self loadGifInGifView];
      }
      -(void)getContentRect {
          screenRect = [UIScreen mainScreen].bounds;
          contentRect = self.navigationController.navigationBar.frame;
         NSLog(@"navigationRect = (%f,%f) %f*%f", contentRect.origin.x, contentRect.origin.y, contentRect.size.width, contentRect.size.height);
          contentRect.origin.y = contentRect.size.height;
          contentRect.size.height = screenRect.size.height - contentRect.size.height;
      }
      //使用webview加载gif只能不放一轮,不能循环播放
      -(void)loadGifInWebView1 {
         NSString *path = [[NSBundle mainBundle] pathForResource:IMAGE_NAME ofType:IMAGE_TYPE];
         NSData *gifData = [NSData dataWithContentsOfFile:path];
         UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(contentRect.origin.x, contentRect.origin.y, contentRect.size.width/2, contentRect.size.height/2)];
         //禁止回弹
          webView.scrollView.bounces = NO;
          webView.scrollView.scrollEnabled = NO;
          webView.scalesPageToFit = YES;
         //设置透明背景(webview的默认背景上灰色的)
          webView.backgroundColor = [UIColor clearColor];
          webView.opaque = 0;
         //禁止交互
          webView.userInteractionEnabled = NO;
          [webView loadData:gifData MIMEType:@"image/gif" textEncodingName:@"UTF-8" baseURL:[NSURL fileURLWithPath:@""]];
          [self.view addSubview:webView];
      }
      -(void)loadGifInWebView2 {
         NSURL *resourceUrl = [NSBundle mainBundle].resourceURL;
         NSString *html = [NSString stringWithFormat:@"<html><body><img src=\"%@.%@\"></body></html>", IMAGE_NAME, IMAGE_TYPE];
         UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(contentRect.origin.x+contentRect.size.width/2, contentRect.origin.y, contentRect.size.width/2, contentRect.size.height/2)];
          [webView loadHTMLString:html baseURL:resourceUrl];
          [self.view addSubview:webView];
      }
      //普通的UIImage只能显示gif图片的第一帧
      -(void)loadGifInImageView {
         NSArray *gifImageNameArray = [[NSArray alloc] initWithObjects:@"1",@"5",@"10",@"16", nil];
         NSMutableArray *gifImageArray = [NSMutableArray array];
         for(int i=0; i<gifImageNameArray.count; i++) {
             NSString *name = [NSString stringWithFormat:@"resource/gif/%@", [gifImageNameArray objectAtIndex:i]];
             NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"jpg"];
             UIImage *image = [UIImage imageWithContentsOfFile:path];
              [gifImageArray addObject:image];
          }
         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];
          imageView.animationImages = gifImageArray;
         //动画执行的总时长
          imageView.animationDuration = 4*0.15;
         //动画重复次数(0为重复播放)
          imageView.animationRepeatCount = 0;
          [imageView startAnimating];
         /*
       typedef NS_ENUM(NSInteger, UIViewContentMode) {
       UIViewContentModeScaleToFill,
       UIViewContentModeScaleAspectFit, // contents scaled to fit with fixed aspect. remainder is transparent
       UIViewContentModeScaleAspectFill, // contents scaled to fill with fixed aspect. some portion of content may be clipped.
       UIViewContentModeRedraw, // redraw on bounds change (calls -setNeedsDisplay)
       UIViewContentModeCenter, // contents remain same size. positioned adjusted.
       UIViewContentModeTop,
       UIViewContentModeBottom,
       UIViewContentModeLeft,
       UIViewContentModeRight,
       UIViewContentModeTopLeft,
       UIViewContentModeTopRight,
       UIViewContentModeBottomLeft,
       UIViewContentModeBottomRight,
       };
       */
          imageView.contentMode = UIViewContentModeScaleToFill;
         //imageView.contentMode = UIViewContentModeScaleAspectFit;
         //imageView.contentMode = UIViewContentModeScaleAspectFill;
         //imageView.contentScaleFactor = [UIScreen mainScreen].scale;
         //imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
          imageView.backgroundColor = [UIColor yellowColor];
          [self.view addSubview:imageView];
      }
      -(void)loadGifInGifView {
         NSString *path = [[NSBundle mainBundle] pathForResource:IMAGE_NAME ofType:IMAGE_TYPE];
          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]];
         //[gifView startGif];
          [self.view addSubview:gifView];
      }
      - (void)didReceiveMemoryWarning {
          [super didReceiveMemoryWarning];
         // Dispose of any resources that can be recreated.
      }
      @end
  
 

2、GifView.h


      //
      // GifView.h
      // GifDemo
      //
      // Created by 555chy on 6/18/16.
      // Copyright © 2016 555chy. All rights reserved.
      //
      #import <UIKit/UIKit.h>
      #import <ImageIO/ImageIO.h>
      #import <QuartzCore/QuartzCore.h>
      @interface GifView : UIImageView
      -(id) initWithFrame:(CGRect)frame gifFileURL:(NSURL *)fileURL;
      -(BOOL) startGif;
      -(void) stopGif;
      @end
  
 

3、GifView.m


      //
      // GifView.m
      // GifDemo
      //
      // Created by 555chy on 6/18/16.
      // Copyright © 2016 555chy. All rights reserved.
      //
      #import "GifView.h"
      void getFrameInfo(CFURLRef url, NSMutableArray *frames, NSMutableArray *delayTimes, CGFloat *totalTime, CGFloat *gifWidth, CGFloat *gifHeight) {
         CGImageSourceRef gifSource = CGImageSourceCreateWithURL(url, NULL);
          size_t frameCount = CGImageSourceGetCount(gifSource);
         NSLog(@"gif frame count = %ld", frameCount);
         for(size_t i=0; i<frameCount; i++) {
             //get each frame
             CGImageRef frame = CGImageSourceCreateImageAtIndex(gifSource, i, NULL);
             //[frames addObject:(id)frame];
             //Cast of C pointer type 'CGImageRef' (aka 'struct CGImage *') to Objective-C pointer type 'id' requires a bridged cast
              [frames addObject:(id)CFBridgingRelease(frame)];
             //这边不需要手动释放了,因为CFBridgingRelease已经把管理权交给ARC了
             //CGImageRelease(frame);
             //get gif info with each frame
             //Cast of C pointer type 'CGImageRef' (aka 'struct CGImage *') to Objective-C pointer type 'id' requires a bridged cast
             //NSDictionary *dict = (NSDictionary*)CGImageSourceCopyPropertiesAtIndex(gifSource, i, NULL);
             NSDictionary *dict = (NSDictionary*)CFBridgingRelease(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];
                 NSLog(@"%ld. gif width*height = %f*%f", i, *gifWidth, *gifHeight);
              }
             //get gif property
             NSDictionary *gifPropertyDict = [dict valueForKey:(NSString*)kCGImagePropertyGIFDictionary];
             //kCGImagePropertyGifDictionary中kCGImagePropertyGIFDelayTime, kCGImagePropertyGIFUnclampedDelayTime的值是一样的
             id delayTimeObj = [gifPropertyDict valueForKey:(NSString*)kCGImagePropertyGIFDelayTime];
             NSLog(@"delayTimeObject = %@", delayTimeObj);
              [delayTimes addObject:delayTimeObj];
             id unclampedDelayTimeObj = [gifPropertyDict valueForKey:(NSString*)kCGImagePropertyGIFUnclampedDelayTime];
             NSLog(@"unclampedDelayTimeObj = %@", unclampedDelayTimeObj);
             //[delayTimes addObject:unclampedDelayTimeObj];
             if(totalTime) {
                  *totalTime = *totalTime + [delayTimeObj floatValue];
              }
          }
         NSLog(@"totalTime = %f", *totalTime);
         CFRelease(gifSource);
      }
      @interface GifView() {
         NSMutableArray *_gifFrames;
         NSMutableArray * _gifFrameDelayTimes;
         CGFloat _gifTotalTime;
         CGFloat _gifWidth;
         CGFloat _gifHeight;
      }
      @end
      @implementation GifView
      - (id) initWithFrame:(CGRect)frame gifFileURL:(NSURL *)fileURL {
         self = [super initWithFrame:frame];
         if(self) {
              _gifFrames = [[NSMutableArray alloc] init];
              _gifFrameDelayTimes = [[NSMutableArray alloc] init];
              _gifWidth = 0;
              _gifHeight = 0;
             if(fileURL) {
                  getFrameInfo((__bridge CFURLRef) fileURL, _gifFrames, _gifFrameDelayTimes, &_gifTotalTime, &_gifWidth, &_gifHeight);
              }
          }
         return self;
      }
      - (BOOL) startGif
      {
         CGFloat currentTime = 0;
         unsigned int count = (unsigned int)_gifFrameDelayTimes.count;
         NSLog(@"gif frame count = %u", count);
         if(count <= 0 || _gifTotalTime <= 0) {
             return NO;
          }
         CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];
         NSMutableArray *times = [NSMutableArray arrayWithCapacity:count];
         for(unsigned int i=0; i<count; i++) {
              [times addObject:[NSNumber numberWithFloat:(currentTime/_gifTotalTime)]];
              currentTime += [[_gifFrameDelayTimes objectAtIndex:i] floatValue];
          }
          [animation setKeyTimes:times];
         NSMutableArray *images = [NSMutableArray arrayWithCapacity:count];
         for(unsigned int i=0; i<count; i++) {
             NSString *path = [[NSBundle mainBundle] pathForResource:@"resource/gif/1" ofType:@"jpg"];
             UIImage *image = [UIImage imageWithContentsOfFile:path];
              [images addObject:image];
             //[images addObject:[_gifFrames objectAtIndex:i]];
          }
          [animation setValues: images];
         //[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
          animation.duration = _gifTotalTime;
          animation.delegate = self;
         /* The repeat count of the object. May be fractional. Defaults to 0. */
          animation.repeatCount = 5;
          [self.layer addAnimation:animation forKey:@"gifAnimation"];
         return YES;
      }
      - (void) stopGif {
          [self.layer removeAllAnimations];
      }
      - (void) animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
         self.layer.contents = nil;
      }
      //Only override drawRect: if you perform custom drawing. An empty implementation adversely affects performance during animation
      - (void) drawRect:(CGRect)rect {
         //Drawing code
      }
      @end
  
 


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

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

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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