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 = ;
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] == ) {
number = fromCF CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFDelayTime);
}
if ([number doubleValue] > ) {
delayCentiseconds = (int)lrint([number doubleValue] * );
}
}
CFRelease(properties);
}
return delayCentiseconds;
} static void createImagesAndDelays(CGImageSourceRef source, size_t count, CGImageRef imagesOut[count], int delayCentisecondsOut[count]) {
for (size_t i = ; 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 = ;
for (size_t i = ; 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 == )
return b;
a = b;
b = r;
}
} static int vectorGCD(size_t const count, int const *const values) {
int gcd = values[];
for (size_t i = ; 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 = , f = ; i < count; ++i) {
UIImage *const frame = [UIImage imageWithCGImage:images[i]];
for (size_t j = delayCentiseconds[i] / gcd; j > ; --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 = ; 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

UIImage+PYJAnimatedGIF的更多相关文章

  1. SDWebImage源码解读 之 UIImage+GIF

    第二篇 前言 本篇是和GIF相关的一个UIImage的分类.主要提供了三个方法: + (UIImage *)sd_animatedGIFNamed:(NSString *)name ----- 根据名 ...

  2. 聊天气泡 button backgroundImage uiimage 拉伸 stretchableImageWithLeftCapWidth: 方法的使用

    - (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCap ...

  3. github源码学习之UIImage+YYWebImage

    UIImage+YYWebImage是YYWebImage(https://github.com/ibireme/YYWebImage)中的一个分类,这个分类封装了一些image常用的变化方法,非常值 ...

  4. 第3月30天 UIImage imageWithContentsOfFile卡顿 Can't add self as subview MPMoviePlayerControlle rcrash

    1. UIImage imageWithContentsOfFile卡顿 [[UIImage alloc] initWithContentsOfFile 卡顿 2.uitableview scroll ...

  5. 使用libjpeg.framework压缩UIImage

    +(void)writeFile:(NSString *)filePath withQuality:(int)quality { //初始化图片参数 UIImage *image=[UIImage i ...

  6. iOS开发之功能模块--长方形UIImage截取中间最大正方形区域

    这里直接用CoreGraphics的一些处理图片的方法,本身不难,但是有些时候用的不多,就会遗忘掉使用方法的细节.下面就直接展示关键源码,以便下次重复需求,就可以立马找回. 该方法中在UIImage的 ...

  7. iOS 分析一个支持GIF的UIImage扩展:SwiftGIF

    Github:https://github.com/bahlo/SwiftGif 这个extension代码不多,主要通过Apple的ImageIO框架进行解析GIF. 整个扩展最核心还是下面的函数, ...

  8. UIImage加载本地图片的两种方式

    UIImage加载图片方式一般有两种: (1)imagedNamed初始化:默认加载图片成功后会内存中缓存图片,这个方法用一个指定的名字在系统缓存中查找并返回一个图片对象.如果缓存中没有找到相应的图片 ...

  9. uiimage 上传 数据库

    之前我所接触的上传图片都是直接与服务器交互的,即 app端要做的就是上传到服务器 现在这个项目却是app先上传到"数据库",由"数据库"传到服务端 下面说主题 ...

随机推荐

  1. 【Flask】Flask Restful api

    ### 安装: Flask-Restful需要在Flask 0.8以上的版本,在Python2.6或者Python3.3上运行.通过pip install flask-restful即可安装. ### ...

  2. nginx 第一天

    来公司第一天先装了一下nginx 第一步:  先装brew /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/ ...

  3. C++结构体定义和C的区别

    对于C来说,struct定义的结构体不是一种数据类型,所以每次声明的时候需要加上struct让编译器知道这是结构体,为了不每次都加上struct关键字,可以在定义结构体的时候加上typedef关键字: ...

  4. 初涉Rx套餐 之RxBinding(让你的事件流程更清晰)

    转载请注明出处:王亟亟的大牛之路 最近下班回家都在WOW,周末就爆肝,感觉人都要GO DIE了,昨天下午看了看RxBinding相关的功能感觉还是蛮强大的,所提供的API也是相当丰富(基本Rx套餐都是 ...

  5. truncate delete 与 drop的区别

    一张表几亿条数据.根据task_id删除几千万. delete删除后查询,发现查询速度还是没有变快.explain查看 rows并没有发生变化.查询速度肯定也不会变化.原因? truncate del ...

  6. 编写第一个Shell脚本【TLCL】

    怎样编写一个 Shell 脚本 编写一个脚本 使脚本文件可执行 把脚本放到Shell能够找到的地方 脚本文件格式 #!/bin/bash # This is our first script. ech ...

  7. scala mapPartitionsWithIndex函数的使用

    var rdd1=sc.makeRDD(Array((1,"A"),(2,"B"),(3,"C"),(4,"D")),2 ...

  8. hdu 5776 sum 前缀和

    sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submi ...

  9. SQLite 插入大量数据慢的解决方法

    sqlite 插入数据很慢的原因:sqlite在没有显式使用事务的时候会为每条insert都使用事务操作,而sqlite数据库是以文件的形式存在磁盘中,就相当于每次访问时都要打开一次文件,如果对数据进 ...

  10. tensorflow conv2d的padding解释以及参数解释

    1.padding的方式: 说明: 1.摘录自http://stackoverflow.com/questions/37674306/what-is-the-difference-between-sa ...