• UIImage+PYJAnimatedGIF


    UIImage+PYJAnimatedGIF.h:

    #import <UIKit/UIKit.h>
    
    @interface UIImage (PYJAnimatedGIF)
    
    + (UIImage * _Nullable)animatedImageWithAnimatedGIFData:(NSData * _Nonnull)theData;
    
    + (UIImage * _Nullable)animatedImageWithAnimatedGIFURL:(NSURL * _Nonnull)theURL;
    
    + (UIImage * _Nullable)imageGIFWithName:(NSString * _Nonnull)theName;
    
    + (UIImage * _Nullable)imageGIFWithURL:(NSURL * _Nonnull)theURL;
    
    + (UIImage * _Nullable)imageGIFWithData:(NSData * _Nonnull)theData;
    
    @end

    UIImage+PYJAnimatedGIF.m:

    #import "UIImage+PYJAnimatedGIF.h"
    #import <ImageIO/ImageIO.h>
    
    #if __has_feature(objc_arc)
    #define toCF (__bridge CFTypeRef)
    #define fromCF (__bridge id)
    #else
    #define toCF (CFTypeRef)
    #define fromCF (id)
    #endif
    
    @implementation UIImage (PYJAnimatedGIF)
    
    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) {
                    delayCentiseconds = (int)lrint([number doubleValue] * 100);
                }
            }
            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) {
            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]);
        }
    }
    
    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(toCF url, NULL));
    }
    
    + (UIImage *)imageGIFWithName:(NSString *)theName {
        NSURL *url = [[NSBundle mainBundle] URLForResource:theName withExtension:@"gif"];
        return animatedImageWithAnimatedGIFReleasingImageSource(CGImageSourceCreateWithURL(toCF url, NULL));
    }
    
    + (UIImage *)imageGIFWithURL:(NSURL *)theURL {
        return animatedImageWithAnimatedGIFReleasingImageSource(CGImageSourceCreateWithURL(toCF theURL, NULL));
    }
    
    + (UIImage *)imageGIFWithData:(NSData *)theData {
        return animatedImageWithAnimatedGIFReleasingImageSource(CGImageSourceCreateWithData(toCF theData, NULL));
    }
    
    @end
  • 相关阅读:
    Emmet Documentation
    微软雅黑的Unicode码和英文名
    Eclipse让代码自动换行(WordWarp)
    如何更改MyEclipse代码自动换行的长度?
    PHP之道推荐使用PHP版本,数据库方式,以及虚拟机的创建程序
    ime-mode:disabled是什么?
    document.getElementsByClassName在ie8及其以下浏览器的兼容性问题
    Unobtrusive JavaScript 不唐突的JavaScript的七条准则
    详解 arguments, callee, caller, call, apply的区别
    怎样在谷歌浏览器上加载金山词霸的取词插件?
  • 原文地址:https://www.cnblogs.com/pengyunjing/p/6036205.html
Copyright © 2020-2023  润新知