The iOS development implements a way to display gif images

  • 2020-05-13 03:19:15
  • OfStack

We know Gif consists of 1 of the picture, and each 1 frame play often could not equal, observe the above two examples, and found that they are not in Gif every frame display often do processing, the result is that every one in the whole Gif frame are fixed speed playback, obviously this is not always conform to the requirements.

Therefore, I wrote a tool class to parse Gif, solved every frame and played it according to the corresponding display time of every frame.

The idea of the program is as follows:

1. First use the CGImageSource files in the ImageIO library in the Gif files.

2. Get the total number of frames in the Gif file and the display time of each frame through CGImageSource.

3. Play Gif animation through CAKeyframeAnimation.

Here is the code that I wrote to parse and play Gif's utility class:


//
//  SvGifView.h
//  SvGifSample
//
//  Created by maple on 3/28/13.
//  Copyright (c) 2013 smileEvday. All rights reserved.
//
#import <UIKit/UIKit.h> @interface SvGifView : UIView
/*
 * @brief desingated initializer
 */
- (id)initWithCenter:(CGPoint)center fileURL:(NSURL*)fileURL; /*
 * @brief start Gif Animation
 */
- (void)startGif; /*
 * @brief stop Gif Animation
 */
- (void)stopGif; /*
 * @brief get frames image(CGImageRef) in Gif
 */
+ (NSArray*)framesInGif:(NSURL*)fileURL;
@end
//
//  SvGifView.m
//  SvGifSample
//
//  Created by maple on 3/28/13.
//  Copyright (c) 2013 smileEvday. All rights reserved.
// #import "SvGifView.h"
#import <ImageIO/ImageIO.h>
#import <QuartzCore/CoreAnimation.h> /*
 * @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 In the kCGImagePropertyGIFDelayTime . kCGImagePropertyGIFUnclampedDelayTime The value is 1 The sample of
        NSDictionary *gifDict = [dict valueForKey:(NSString*)kCGImagePropertyGIFDictionary];
        [delayTimes addObject:[gifDict valueForKey:(NSString*)kCGImagePropertyGIFDelayTime]];
       
        if (totalTime) {
            *totalTime = *totalTime + [[gifDict valueForKey:(NSString*)kCGImagePropertyGIFDelayTime] floatValue];
        }
    }
} @interface SvGifView() {
    NSMutableArray *_frames;
    NSMutableArray *_frameDelayTimes;
   
    CGFloat _totalTime;         // seconds
    CGFloat _width;
    CGFloat _height;
} @end @implementation SvGifView
- (id)initWithCenter:(CGPoint)center fileURL:(NSURL*)fileURL;
{
    self = [super initWithFrame:CGRectZero];
    if (self) {
       
        _frames = [[NSMutableArray alloc] init];
        _frameDelayTimes = [[NSMutableArray alloc] 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;
    }
   
    return self;
} + (NSArray*)framesInGif:(NSURL *)fileURL
{
    NSMutableArray *frames = [NSMutableArray arrayWithCapacity:3];
    NSMutableArray *delays = [NSMutableArray arrayWithCapacity:3];
   
    getFrameInfo((CFURLRef)fileURL, frames, delays, NULL, NULL, NULL);
   
    return frames;
} - (void)startGif
{
    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"];
} - (void)stopGif
{
    [self.layer removeAllAnimations];
} // remove contents when animation end
- (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


The code is short and relatively easy, so I won't explain 11. The original C function was mainly used to parse Gif. The reason for using the C function is that I have to return multiple messages, while Objective-c can only return one parameter. Besides, Objective-c and C languages can be easily mixed programming.

Two more ways to use UIImageView are introduced:

1. Play with UIWebView


    // Set the location and size
    CGRect frame = CGRectMake(50,50,0,0);
    frame.size = [UIImage imageNamed:@"guzhang.gif"].size;
    // read gif Image data
    NSData *gif = [NSData dataWithContentsOfFile: [[NSBundle mainBundle] pathForResource:@"guzhang" ofType:@"gif"]];
    // view generate
    UIWebView *webView = [[UIWebView alloc] initWithFrame:frame];
    webView.userInteractionEnabled = NO;// User non-interaction
    [webView loadData:gif MIMEType:@"image/gif" textEncodingName:nil baseURL:nil];
    [self.view addSubview:webView];
    [webView release];

2. Decompose the gif images into multiple png images and play them using UIImageView.
The code is as follows:


 UIImageView *gifImageView = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    NSArray *gifArray = [NSArray arrayWithObjects:[UIImage imageNamed:@"1"],
                                                  [UIImage imageNamed:@"2"],
                                                  [UIImage imageNamed:@"3"],
                                                  [UIImage imageNamed:@"4"],
                                                  [UIImage imageNamed:@"5"],
                                                  [UIImage imageNamed:@"6"],
                                                  [UIImage imageNamed:@"7"],
                                                  [UIImage imageNamed:@"8"],
                                                  [UIImage imageNamed:@"9"],
                                                  [UIImage imageNamed:@"10"],
                                                  [UIImage imageNamed:@"11"],
                                                  [UIImage imageNamed:@"12"],
                                                  [UIImage imageNamed:@"13"],
                                                  [UIImage imageNamed:@"14"],
                                                  [UIImage imageNamed:@"15"],
                                                  [UIImage imageNamed:@"16"],
                                                  [UIImage imageNamed:@"17"],
                                                  [UIImage imageNamed:@"18"],
                                                  [UIImage imageNamed:@"19"],
                                                  [UIImage imageNamed:@"20"],
                                                  [UIImage imageNamed:@"21"],
                                                  [UIImage imageNamed:@"22"],nil];
    gifImageView.animationImages = gifArray; // Animated image array
    gifImageView.animationDuration = 5; // perform 1 Length of time required for sub-complete animation
    gifImageView.animationRepeatCount = 1;  // Animation repetition
    [gifImageView startAnimating];
    [self.view addSubview:gifImageView];
    [gifImageView release];

Note: this method does not work if the time interval between frames is different for the gif animation.


Related articles: