SDWebImage (5.1.0)UIImage+GIF.h(
2019-08-26 本文已影响0人
charlotte2018
这个头文件就有一个方法,通过传入gif的data数据转化出一个image对象
+ (nullable UIImage *)sd_imageWithGIFData:(nullable NSData *)data {
if (!data) {
return nil;
}
return [[SDImageGIFCoder sharedCoder] decodedImageWithData:data options:0];
}
解析工作主要在SDImageGIFCoder
类中,所以主要看这个类,这个类继承自NSObject对象,然后实现了SDImageCoder.h
里的协议, SDImageCoder.h
里头都是协议
#import <Foundation/Foundation.h>
#import "SDImageCoder.h"
@interface SDImageGIFCoder : NSObject <SDProgressiveImageCoder, SDAnimatedImageCoder>
@property (nonatomic, class, readonly, nonnull) SDImageGIFCoder *sharedCoder;
@end
这个- (nullable UIImage *)decodedImageWithData:(nullable NSData *)data options:(nullable SDImageCoderOptions *)options;
方法是在@protocol SDImageCoder
协议里的,然而@protocol SDAnimatedImageCoder <SDImageCoder, SDAnimatedImageProvider>
所以也具备这个能力
iOS使用imageIO框架去实现data转化为Image,先了解GIF的几个概念:
- count (帧数)gif有多少帧
- frame(帧)一个gif可以认为是多个图片组成的动画。一帧就是其中的一张图片。
- duration (延迟时间) 每一帧播放的时间
- loopCount (播放次数)有些gif播放到一定次数就停止了,如果是0就是一直循环播放
- (UIImage *)decodedImageWithData:(NSData *)data options:(nullable SDImageCoderOptions *)options {
if (!data) {
return nil;
}
CGFloat scale = 1;
NSNumber *scaleFactor = options[SDImageCoderDecodeScaleFactor];
if (scaleFactor != nil) {
scale = MAX([scaleFactor doubleValue], 1);
}
#if SD_MAC
SDAnimatedImageRep *imageRep = [[SDAnimatedImageRep alloc] initWithData:data];
NSSize size = NSMakeSize(imageRep.pixelsWide / scale, imageRep.pixelsHigh / scale);
imageRep.size = size;
NSImage *animatedImage = [[NSImage alloc] initWithSize:size];
[animatedImage addRepresentation:imageRep];
return animatedImage;
#else
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
if (!source) {
return nil;
}
//gif有多少帧
size_t count = CGImageSourceGetCount(source);
UIImage *animatedImage;
BOOL decodeFirstFrame = [options[SDImageCoderDecodeFirstFrameOnly] boolValue];
if (decodeFirstFrame || count <= 1) {
animatedImage = [[UIImage alloc] initWithData:data scale:scale];
} else {
NSMutableArray<SDImageFrame *> *frames = [NSMutableArray array];
for (size_t i = 0; i < count; i++) {
CGImageRef imageRef = CGImageSourceCreateImageAtIndex(source, i, NULL);
if (!imageRef) {
continue;
}
//每一帧播放的时间
float duration = [self sd_frameDurationAtIndex:i source:source];
//一帧就是其中的一张图片。
UIImage *image = [[UIImage alloc] initWithCGImage:imageRef scale:scale orientation:UIImageOrientationUp];
CGImageRelease(imageRef);
//SDImageFrame中保存了每一帧的图片和播放的时间
SDImageFrame *frame = [SDImageFrame frameWithImage:image duration:duration];
[frames addObject:frame];
}
//有些gif播放到一定次数就停止了,如果是0就是一直循环播放
NSUInteger loopCount = [self sd_imageLoopCountWithSource:source];
//将帧数组传入SDImageCoderHelper生成animatedImage,通过遍历得到image数组和总的时间最后把
//animatedImage解析出来
//animatedImage = [UIImage animatedImageWithImages:animatedImages duration:totalDuration / 1000.f];
animatedImage = [SDImageCoderHelper animatedImageWithFrames:frames];
animatedImage.sd_imageLoopCount = loopCount;
}
animatedImage.sd_imageFormat = SDImageFormatGIF;
CFRelease(source);
return animatedImage;
#endif
}