iOS之UIImage的三中读取方法

来源:互联网 发布:软件系统安全架构 编辑:程序博客网 时间:2024/05/16 06:58

首先在项目中导入创建这个UIImage的分类


【UIImage+animatedGIF.h】

#import <UIKit/UIKit.h>/**        UIImage (animatedGIF)            This category adds class methods to `UIImage` to create an animated `UIImage` from an animated GIF.*/@interface UIImage (animatedGIF)/*        UIImage *animation = [UIImage animatedImageWithAnimatedGIFData:theData];        I interpret `theData` as a GIF.  I create an animated `UIImage` using the source images in the GIF.        The GIF stores a separate duration for each frame, in units of centiseconds (hundredths of a second).  However, a `UIImage` only has a single, total `duration` property, which is a floating-point number.        To handle this mismatch, I add each source image (from the GIF) to `animation` a varying number of times to match the ratios between the frame durations in the GIF.        For example, suppose the GIF contains three frames.  Frame 0 has duration 3.  Frame 1 has duration 9.  Frame 2 has duration 15.  I divide each duration by the greatest common denominator of all the durations, which is 3, and add each frame the resulting number of times.  Thus `animation` will contain frame 0 3/3 = 1 time, then frame 1 9/3 = 3 times, then frame 2 15/3 = 5 times.  I set `animation.duration` to (3+9+15)/100 = 0.27 seconds.*/+ (UIImage *)animatedImageWithAnimatedGIFData:(NSData *)theData;/*        UIImage *image = [UIImage animatedImageWithAnimatedGIFURL:theURL];        I interpret the contents of `theURL` as a GIF.  I create an animated `UIImage` using the source images in the GIF.        I operate exactly like `+[UIImage animatedImageWithAnimatedGIFData:]`, except that I read the data from `theURL`.  If `theURL` is not a `file:` URL, you probably want to call me on a background thread or GCD queue to avoid blocking the main thread.*/+ (UIImage *)animatedImageWithAnimatedGIFURL:(NSURL *)theURL;@end

【UIImage+animatedGIF.m】

#import "UIImage+animatedGIF.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 (animatedGIF)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) {                // Even though the GIF stores the delay as an integer number of centiseconds, ImageIO “helpfully” converts that to seconds for us.                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) {        // Note that after I process the first few elements of the vector, `gcd` will probably be smaller than any remaining element.  By passing the smaller value as the second argument to `pairGCD`, I avoid making it swap the arguments.        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));}@end


然后在UIViewController中使用


#import "ViewController.h"#import "UIImage+animatedGIF.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad {    [super viewDidLoad];    // Do any additional setup after loading the view, typically from a nib.        // 创建一个图片控件,UIImageView: 是用来显示图片的控件    UIImageView *image=[[UIImageView alloc]initWithFrame:CGRectMake(10, 20, 100, 20)];    // 给图片控件添加图片    [image setImage:[UIImage imageNamed:@"player1"]];    //把图片控件添加到我的视图上面去    [self.view addSubview:image];        //  UIImageView 使用的时候,总是会用到UIImage,//       就可以理解为,图片控件总是需要添加图片对象//     类似于,UILabel 总是需要用NSString 或者@"" 来添加字符    //    创建 UIImage 对象 尽量使用 imageNamed 方法创建图片对象//    原因:比较节省内存    //    1、 读取 图片路径//    2、把图片转成data//    3、用data 生成图片对象//    4、把图片对象加到图片控件上面        // 把Gif的图片路径读出来,也就是找到图片在哪儿    NSString *path=[[NSBundle mainBundle]pathForResource:@"FlagZombie" ofType:@"gif"];    // 把图片用图片路径读取出来,转成我们可以用的NSData    NSData *data=[NSData  dataWithContentsOfFile:path];        // 用图片数据,转成我们的图片对象,Gif 图片对象    UIImage *img=[UIImage animatedImageWithAnimatedGIFData:data];    //把图片设置到图片控件上面    [image setImage:img];            }- (void)didReceiveMemoryWarning {    [super didReceiveMemoryWarning];    // Dispose of any resources that can be recreated.}@end


0 0