diff --git a/SDWebImage/SDAnimatedImage.h b/SDWebImage/SDAnimatedImage.h index 006ee14f..968b47e9 100644 --- a/SDWebImage/SDAnimatedImage.h +++ b/SDWebImage/SDAnimatedImage.h @@ -7,51 +7,25 @@ */ #import "SDWebImageCompat.h" -#import "NSData+ImageContentType.h" +#import "SDWebImageCoder.h" -@protocol SDWebImageAnimatedCoder; -@protocol SDAnimatedImage + +/** + This is the protocol for SDAnimatedImage class only but not for SDWebImageAnimatedCoder. If you want to provide a custom animated image class with full advanced function, you can conform to this instead of the base protocol. + */ +@protocol SDAnimatedImage @required /** - The original animated image data for current image. If current image is not an animated format, return nil. - We may use this method to grab back the original image data if need, such as NSCoding or compare. + Initializes the image with an animated coder. You can use the coder to decode the image frame later. + @note Normally we use `initWithData:scale:` to create custom animated image class. However, for progressive image decoding, we will use this instead. - @return The animated image data + @param animatedCoder An animated coder which conform `SDWebImageAnimatedCoder` protocol + @param scale The scale factor to assume when interpreting the image data. Applying a scale factor of 1.0 results in an image whose size matches the pixel-based dimensions of the image. Applying a different scale factor changes the size of the image as reported by the `size` property. + @return An initialized object */ -- (nullable NSData *)animatedImageData; +- (nullable instancetype)initWithAnimatedCoder:(nonnull id)animatedCoder scale:(CGFloat)scale; -/** - Total animated frame count. - It the frame count is less than 1, then the methods below will be ignored. - - @return Total animated frame count. - */ -- (NSUInteger)animatedImageFrameCount; -/** - Animation loop count, 0 means infinite looping. - - @return Animation loop count - */ -- (NSUInteger)animatedImageLoopCount; -/** - Returns the frame image from a specified index. - @note The index maybe randomly if one image was set to different imageViews, keep it re-entrant. (It's not recommend to store the images into array because it's memory consuming) - - @param index Frame index (zero based). - @return Frame's image - */ -- (nullable UIImage *)animatedImageFrameAtIndex:(NSUInteger)index; -/** - Returns the frames's duration from a specified index. - @note The index maybe randomly if one image was set to different imageViews, keep it re-entrant. (It's recommend to store the durations into array because it's not memory-consuming) - - @param index Frame index (zero based). - @return Frame's duration - */ -- (NSTimeInterval)animatedImageDurationAtIndex:(NSUInteger)index; - -// These methods are for SDAnimatedImage class only but not for SDWebImageAnimatedCoder. @optional /** Pre-load all animated image frame into memory. Then later frame image request can directly return the frame for index without decoding. @@ -71,16 +45,6 @@ */ - (BOOL)isAllFramesLoaded; -/** - Initializes the image with an animated coder. You can use the coder to decode the image frame later. - @note Normally we use `initWithData:scale:` to create custom animated image class. So you can implement your custom class without our built-in coder. - - @param animatedCoder An animated coder which conform `SDWebImageAnimatedCoder` protocol - @param scale The scale factor to assume when interpreting the image data. Applying a scale factor of 1.0 results in an image whose size matches the pixel-based dimensions of the image. Applying a different scale factor changes the size of the image as reported by the `size` property. - @return An initialized object - */ -- (nullable instancetype)initWithAnimatedCoder:(nonnull id)animatedCoder scale:(CGFloat)scale; - @end @interface SDAnimatedImage : UIImage diff --git a/SDWebImage/SDAnimatedImage.m b/SDWebImage/SDAnimatedImage.m index 9ffb2b92..a6d4b8bf 100644 --- a/SDWebImage/SDAnimatedImage.m +++ b/SDWebImage/SDAnimatedImage.m @@ -282,9 +282,6 @@ static NSArray *SDBundlePreferredScales() { if (!data || data.length == 0) { return nil; } - if (scale <= 0) { - scale = 1; - } data = [data copy]; // avoid mutable data id animatedCoder = nil; for (idcoder in [SDWebImageCodersManager sharedManager].coders) { @@ -298,24 +295,7 @@ static NSArray *SDBundlePreferredScales() { if (!animatedCoder) { return nil; } - UIImage *image = [animatedCoder animatedImageFrameAtIndex:0]; - if (!image) { - return nil; - } -#if SD_MAC - self = [super initWithCGImage:image.CGImage size:NSZeroSize]; -#else - self = [super initWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation]; -#endif - if (self) { - _coder = animatedCoder; -#if SD_MAC - _scale = scale; -#endif - SDImageFormat format = [NSData sd_imageFormatForImageData:data]; - _animatedImageFormat = format; - } - return self; + return [self initWithAnimatedCoder:animatedCoder scale:scale]; } - (instancetype)initWithAnimatedCoder:(id)animatedCoder scale:(CGFloat)scale { diff --git a/SDWebImage/SDWebImageCoder.h b/SDWebImage/SDWebImageCoder.h index 0dcaf874..1afe6757 100644 --- a/SDWebImage/SDWebImageCoder.h +++ b/SDWebImage/SDWebImageCoder.h @@ -9,7 +9,6 @@ #import #import "SDWebImageCompat.h" #import "NSData+ImageContentType.h" -#import "SDAnimatedImage.h" typedef NSString * SDWebImageCoderOption NS_STRING_ENUM; typedef NSDictionary SDWebImageCoderOptions; @@ -118,11 +117,56 @@ FOUNDATION_EXPORT SDWebImageCoderOption _Nonnull const SDWebImageCoderEncodeComp @end +/** + This is the animated image protocol to provide the basic function for animated image rendering. It's adopted by `SDAnimatedImage` and `SDWebImageAnimatedCoder` + */ +@protocol SDAnimatedImageProvider + +@required +/** + The original animated image data for current image. If current image is not an animated format, return nil. + We may use this method to grab back the original image data if need, such as NSCoding or compare. + + @return The animated image data + */ +- (nullable NSData *)animatedImageData; + +/** + Total animated frame count. + It the frame count is less than 1, then the methods below will be ignored. + + @return Total animated frame count. + */ +- (NSUInteger)animatedImageFrameCount; +/** + Animation loop count, 0 means infinite looping. + + @return Animation loop count + */ +- (NSUInteger)animatedImageLoopCount; +/** + Returns the frame image from a specified index. + @note The index maybe randomly if one image was set to different imageViews, keep it re-entrant. (It's not recommend to store the images into array because it's memory consuming) + + @param index Frame index (zero based). + @return Frame's image + */ +- (nullable UIImage *)animatedImageFrameAtIndex:(NSUInteger)index; +/** + Returns the frames's duration from a specified index. + @note The index maybe randomly if one image was set to different imageViews, keep it re-entrant. (It's recommend to store the durations into array because it's not memory-consuming) + + @param index Frame index (zero based). + @return Frame's duration + */ +- (NSTimeInterval)animatedImageDurationAtIndex:(NSUInteger)index; + +@end /** This is the animated image coder protocol for custom animated image class like `SDAnimatedImage`. Through it inherit from `SDWebImageCoder`. We currentlly only use the method `canDecodeFromData:` to detect the proper coder for specify animated image format. */ -@protocol SDWebImageAnimatedCoder +@protocol SDWebImageAnimatedCoder @required /** diff --git a/SDWebImage/SDWebImageDefine.h b/SDWebImage/SDWebImageDefine.h index ae5dfd0d..604e0cd9 100644 --- a/SDWebImage/SDWebImageDefine.h +++ b/SDWebImage/SDWebImageDefine.h @@ -50,7 +50,7 @@ FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextCustom FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextCustomTransformer; /** - A Class object which the instance is a `UIImage/NSImage` subclass and adopt `SDAnimatedImage` protocol. We will call `initWithData:scale:` to create the instance (or `initWithAnimatedCoder:sclae` when using progressive download) . If the instance create failed, fallback to normal `UIImage/NSImage`. + A Class object which the instance is a `UIImage/NSImage` subclass and adopt `SDAnimatedImage` protocol. We will call `initWithData:scale:` to create the instance (or `initWithAnimatedCoder:scale` when using progressive download) . If the instance create failed, fallback to normal `UIImage/NSImage`. This can be used to improve animated images rendering performance (especially memory usage on big animated images) with `SDAnimatedImageView` (Class). */ FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextAnimatedImageClass; diff --git a/SDWebImage/SDWebImageDownloaderOperation.m b/SDWebImage/SDWebImageDownloaderOperation.m index d0f36d7c..0d755b44 100644 --- a/SDWebImage/SDWebImageDownloaderOperation.m +++ b/SDWebImage/SDWebImageDownloaderOperation.m @@ -365,7 +365,7 @@ didReceiveResponse:(NSURLResponse *)response UIImage *image; if ([self.context valueForKey:SDWebImageContextAnimatedImageClass]) { Class animatedImageClass = [self.context valueForKey:SDWebImageContextAnimatedImageClass]; - if ([animatedImageClass isSubclassOfClass:[UIImage class]] && [animatedImageClass conformsToProtocol:@protocol(SDAnimatedImage)] && [animatedImageClass instancesRespondToSelector:@selector(initWithAnimatedCoder:scale:)] && [self.progressiveCoder conformsToProtocol:@protocol(SDWebImageAnimatedCoder)]) { + if ([animatedImageClass isSubclassOfClass:[UIImage class]] && [animatedImageClass conformsToProtocol:@protocol(SDAnimatedImage)] && [self.progressiveCoder conformsToProtocol:@protocol(SDWebImageAnimatedCoder)]) { CGFloat scale = SDImageScaleForKey(self.cacheKey); image = [[animatedImageClass alloc] initWithAnimatedCoder:(id)self.progressiveCoder scale:scale]; }