Created
December 9, 2017 12:58
-
-
Save daoseng33/839a6d48b22df9e42461405f26c0fa9a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// UIImage+GIF.h | |
// LBGIFImage | |
// | |
// Created by Laurin Brandner on 06.01.12. | |
// Copyright (c) 2012 __MyCompanyName__. All rights reserved. | |
// | |
#import <UIKit/UIKit.h> | |
@interface UIImage (GIF) | |
+ (UIImage *)sd_animatedGIFNamed:(NSString *)name; | |
+ (UIImage *)sd_animatedGIFWithData:(NSData *)data; | |
- (UIImage *)sd_animatedImageByScalingAndCroppingToSize:(CGSize)size; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// UIImage+GIF.m | |
// LBGIFImage | |
// | |
// Created by Laurin Brandner on 06.01.12. | |
// Copyright (c) 2012 __MyCompanyName__. All rights reserved. | |
// | |
#import "UIImage+GIF.h" | |
#import <ImageIO/ImageIO.h> | |
@implementation UIImage (GIF) | |
+ (UIImage *)sd_animatedGIFWithData:(NSData *)data { | |
if (!data) { | |
return nil; | |
} | |
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL); | |
size_t count = CGImageSourceGetCount(source); | |
UIImage *animatedImage; | |
if (count <= 1) { | |
animatedImage = [[UIImage alloc] initWithData:data]; | |
} | |
else { | |
NSMutableArray *images = [NSMutableArray array]; | |
NSTimeInterval duration = 0.0f; | |
for (size_t i = 0; i < count; i++) { | |
CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL); | |
if (!image) { | |
continue; | |
} | |
duration += [self sd_frameDurationAtIndex:i source:source]; | |
[images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]]; | |
CGImageRelease(image); | |
} | |
if (!duration) { | |
duration = (1.0f / 10.0f) * count; | |
} | |
animatedImage = [UIImage animatedImageWithImages:images duration:duration]; | |
} | |
CFRelease(source); | |
return animatedImage; | |
} | |
+ (float)sd_frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source { | |
float frameDuration = 0.1f; | |
CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil); | |
NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties; | |
NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary]; | |
NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime]; | |
if (delayTimeUnclampedProp) { | |
frameDuration = [delayTimeUnclampedProp floatValue]; | |
} | |
else { | |
NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime]; | |
if (delayTimeProp) { | |
frameDuration = [delayTimeProp floatValue]; | |
} | |
} | |
// Many annoying ads specify a 0 duration to make an image flash as quickly as possible. | |
// We follow Firefox's behavior and use a duration of 100 ms for any frames that specify | |
// a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082> | |
// for more information. | |
if (frameDuration < 0.011f) { | |
frameDuration = 0.100f; | |
} | |
CFRelease(cfFrameProperties); | |
return frameDuration; | |
} | |
+ (UIImage *)sd_animatedGIFNamed:(NSString *)name { | |
CGFloat scale = [UIScreen mainScreen].scale; | |
if (scale > 1.0f) { | |
NSString *retinaPath = [[NSBundle mainBundle] pathForResource:[name stringByAppendingString:@"@2x"] ofType:@"gif"]; | |
NSData *data = [NSData dataWithContentsOfFile:retinaPath]; | |
if (data) { | |
return [UIImage sd_animatedGIFWithData:data]; | |
} | |
NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"]; | |
data = [NSData dataWithContentsOfFile:path]; | |
if (data) { | |
return [UIImage sd_animatedGIFWithData:data]; | |
} | |
return [UIImage imageNamed:name]; | |
} | |
else { | |
NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"]; | |
NSData *data = [NSData dataWithContentsOfFile:path]; | |
if (data) { | |
return [UIImage sd_animatedGIFWithData:data]; | |
} | |
return [UIImage imageNamed:name]; | |
} | |
} | |
- (UIImage *)sd_animatedImageByScalingAndCroppingToSize:(CGSize)size { | |
if (CGSizeEqualToSize(self.size, size) || CGSizeEqualToSize(size, CGSizeZero)) { | |
return self; | |
} | |
CGSize scaledSize = size; | |
CGPoint thumbnailPoint = CGPointZero; | |
CGFloat widthFactor = size.width / self.size.width; | |
CGFloat heightFactor = size.height / self.size.height; | |
CGFloat scaleFactor = (widthFactor > heightFactor) ? widthFactor : heightFactor; | |
scaledSize.width = self.size.width * scaleFactor; | |
scaledSize.height = self.size.height * scaleFactor; | |
if (widthFactor > heightFactor) { | |
thumbnailPoint.y = (size.height - scaledSize.height) * 0.5; | |
} | |
else if (widthFactor < heightFactor) { | |
thumbnailPoint.x = (size.width - scaledSize.width) * 0.5; | |
} | |
NSMutableArray *scaledImages = [NSMutableArray array]; | |
for (UIImage *image in self.images) { | |
UIGraphicsBeginImageContextWithOptions(size, NO, 0.0); | |
[image drawInRect:CGRectMake(thumbnailPoint.x, thumbnailPoint.y, scaledSize.width, scaledSize.height)]; | |
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); | |
[scaledImages addObject:newImage]; | |
UIGraphicsEndImageContext(); | |
} | |
return [UIImage animatedImageWithImages:scaledImages duration:self.duration]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment