美文网首页
iOS:研究下gif图的实现

iOS:研究下gif图的实现

作者: 爱笑的猫mi | 来源:发表于2019-08-09 13:27 被阅读0次

    1.简单描述

    在现在比较流行的App中,gif动画其实已经成为了核心的功能点,不管是刷新加载时候放上App独有的gif图,还是各种动效使用。尤其是段视频,电商等较为娱乐与金钱结合的App。这里简单描述下实现方式。

    gif动画是iOS开发中很常用的一个功能,有的是为了显示加载视频的过程,更多的是为了显示一个结果状态(动画更直观)。

    那么如何执行gif动画,方法有很多。(这里只写一下方法三,前两种之前都用过)

    方法一使用UIWebView来显示;

    方法二使用UIImageView的帧动画显示;

    方法三使用SDWebImage这个三方框架来显示。

    2.简单使用

    1、显示gif动画(三方框架SDWebImage的UIImage+GIF分类)

    #import "UIImage+GIF.h"
    #import "SDWebImageGIFCoder.h"
    #import "NSImage+WebCache.h"
    
    @implementation UIImage (GIF)
    
    + (UIImage *)sd_animatedGIFWithData:(NSData *)data {
        if (!data) {
            return nil;
        }
        return [[SDWebImageGIFCoder sharedCoder] decodedImageWithData:data];
    }
    
    - (BOOL)isGIF {
        return (self.images != nil);
    }
    
    @end
    
    //使用
    NSData *gifData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"live_sign" ofType:@"gif"]];
    UIImage  *signSuccessGifImg = [UIImage sd_animatedGIFWithData:gifData];
    self.imageView.image = signSuccessGifImg;
    

    2、获取gif动画时长

    //获取gif图片的总时长
    - (NSTimeInterval)durationForGifData:(NSData *)data{
        
        //将GIF图片转换成对应的图片源
        CGImageSourceRef gifSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
        
        //获取其中图片源个数,即由多少帧图片组成
        size_t frameCout = CGImageSourceGetCount(gifSource);
    
        //定义数组存储拆分出来的图片
        NSMutableArray* frames = [[NSMutableArray alloc] init];
        NSTimeInterval totalDuration = 0;
        for (size_t i=0; i<frameCout; i++) {
    
            //从GIF图片中取出源图片
            CGImageRef imageRef = CGImageSourceCreateImageAtIndex(gifSource, i, NULL);
    
            //将图片源转换成UIimageView能使用的图片源
            UIImage* imageName = [UIImage imageWithCGImage:imageRef];
    
            //将图片加入数组中
            [frames addObject:imageName];
            NSTimeInterval duration = [self gifImageDeleyTime:gifSource index:i];
            totalDuration += duration;
            CGImageRelease(imageRef);
        }
        
        //获取循环次数
        NSInteger loopCount;//循环次数
        CFDictionaryRef properties = CGImageSourceCopyProperties(gifSource, NULL);
        if (properties) {
            CFDictionaryRef gif = CFDictionaryGetValue(properties, kCGImagePropertyGIFDictionary);
            if (gif) {
                CFTypeRef loop = CFDictionaryGetValue(gif, kCGImagePropertyGIFLoopCount);
                if (loop) {
                    //如果loop == NULL,表示不循环播放,当loopCount  == 0时,表示无限循环;
                    CFNumberGetValue(loop, kCFNumberNSIntegerType, &loopCount);
                };
            }
        }
        CFRelease(gifSource);
        return totalDuration;
    }
    
    //获取GIF图片每帧的时长
    - (NSTimeInterval)gifImageDeleyTime:(CGImageSourceRef)imageSource index:(NSInteger)index {
        NSTimeInterval duration = 0;
        CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, index, NULL);
        if (imageProperties) {
            CFDictionaryRef gifProperties;
            BOOL result = CFDictionaryGetValueIfPresent(imageProperties, kCGImagePropertyGIFDictionary, (const void **)&gifProperties);
            if (result) {
                const void *durationValue;
                if (CFDictionaryGetValueIfPresent(gifProperties, kCGImagePropertyGIFUnclampedDelayTime, &durationValue)) {
                    duration = [(__bridge NSNumber *)durationValue doubleValue];
                    if (duration < 0) {
                        if (CFDictionaryGetValueIfPresent(gifProperties, kCGImagePropertyGIFDelayTime, &durationValue)) {
                            duration = [(__bridge NSNumber *)durationValue doubleValue];
                        }
                    }
                }
            }
        }
        
        return duration;
    }
    

    3、获取gif动画执行次数

    //获取gif图片的循环次数
    -(NSInteger)repeatCountForGifData:(NSData *)data{
        
        //将GIF图片转换成对应的图片源
        CGImageSourceRef gifSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
        
        //获取循环次数
        NSInteger loopCount = 0;//循环次数
        CFDictionaryRef properties = CGImageSourceCopyProperties(gifSource, NULL);
        if (properties) {
            CFDictionaryRef gif = CFDictionaryGetValue(properties, kCGImagePropertyGIFDictionary);
            if (gif) {
                CFTypeRef loop = CFDictionaryGetValue(gif, kCGImagePropertyGIFLoopCount);
                if (loop) {
                    //如果loop == NULL,表示不循环播放,当loopCount  == 0时,表示无限循环;
                    CFNumberGetValue(loop, kCFNumberNSIntegerType, &loopCount);
                };
            }
        }
        CFRelease(gifSource);
        
        return loopCount;
    }
    

    三.创建分类

    import "UIImageView+GIFProperty.h"

    #import <UIKit/UIKit.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface UIImageView (GIFProperty)
    -(NSTimeInterval)durationForGifData:(NSData *)data;//获取gif动画总时长
    -(NSInteger)repeatCountForGifData:(NSData *)data;  //获取gif动画循环总次数 0:表示无限循环
    @end
    
    NS_ASSUME_NONNULL_END
    
    
    #import "UIImageView+GIFProperty.h"
    
    @implementation UIImageView (GIFProperty)
    
    //获取gif图片的总时长
    - (NSTimeInterval)durationForGifData:(NSData *)data{
        
        //将GIF图片转换成对应的图片源
        CGImageSourceRef gifSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
        
        //获取其中图片源个数,即由多少帧图片组成
        size_t frameCout = CGImageSourceGetCount(gifSource);
    
        //定义数组存储拆分出来的图片
        NSMutableArray* frames = [[NSMutableArray alloc] init];
        NSTimeInterval totalDuration = 0;
        for (size_t i=0; i<frameCout; i++) {
    
            //从GIF图片中取出源图片
            CGImageRef imageRef = CGImageSourceCreateImageAtIndex(gifSource, i, NULL);
    
            //将图片源转换成UIimageView能使用的图片源
            UIImage* imageName = [UIImage imageWithCGImage:imageRef];
    
            //将图片加入数组中
            [frames addObject:imageName];
            NSTimeInterval duration = [self gifImageDeleyTime:gifSource index:i];
            totalDuration += duration;
            CGImageRelease(imageRef);
        }
        
        //获取循环次数
        NSInteger loopCount;//循环次数
        CFDictionaryRef properties = CGImageSourceCopyProperties(gifSource, NULL);
        if (properties) {
            CFDictionaryRef gif = CFDictionaryGetValue(properties, kCGImagePropertyGIFDictionary);
            if (gif) {
                CFTypeRef loop = CFDictionaryGetValue(gif, kCGImagePropertyGIFLoopCount);
                if (loop) {
                    //如果loop == NULL,表示不循环播放,当loopCount  == 0时,表示无限循环;
                    CFNumberGetValue(loop, kCFNumberNSIntegerType, &loopCount);
                };
            }
        }
        CFRelease(gifSource);
        return totalDuration;
    }
    //获取gif图片的循环次数
    -(NSInteger)repeatCountForGifData:(NSData *)data{
        
        //将GIF图片转换成对应的图片源
        CGImageSourceRef gifSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
        
        //获取循环次数
        NSInteger loopCount = 0;//循环次数
        CFDictionaryRef properties = CGImageSourceCopyProperties(gifSource, NULL);
        if (properties) {
            CFDictionaryRef gif = CFDictionaryGetValue(properties, kCGImagePropertyGIFDictionary);
            if (gif) {
                CFTypeRef loop = CFDictionaryGetValue(gif, kCGImagePropertyGIFLoopCount);
                if (loop) {
                    //如果loop == NULL,表示不循环播放,当loopCount  == 0时,表示无限循环;
                    CFNumberGetValue(loop, kCFNumberNSIntegerType, &loopCount);
                };
            }
        }
        CFRelease(gifSource);
        
        return loopCount;
    }
    
    
    //获取GIF图片每帧的时长
    - (NSTimeInterval)gifImageDeleyTime:(CGImageSourceRef)imageSource index:(NSInteger)index {
        NSTimeInterval duration = 0;
        CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, index, NULL);
        if (imageProperties) {
            CFDictionaryRef gifProperties;
            BOOL result = CFDictionaryGetValueIfPresent(imageProperties, kCGImagePropertyGIFDictionary, (const void **)&gifProperties);
            if (result) {
                const void *durationValue;
                if (CFDictionaryGetValueIfPresent(gifProperties, kCGImagePropertyGIFUnclampedDelayTime, &durationValue)) {
                    duration = [(__bridge NSNumber *)durationValue doubleValue];
                    if (duration < 0) {
                        if (CFDictionaryGetValueIfPresent(gifProperties, kCGImagePropertyGIFDelayTime, &durationValue)) {
                            duration = [(__bridge NSNumber *)durationValue doubleValue];
                        }
                    }
                }
            }
        }
        
        return duration;
    }
    
    @end
    
    

    相关文章

      网友评论

          本文标题:iOS:研究下gif图的实现

          本文链接:https://www.haomeiwen.com/subject/dhacjctx.html