Add SDScaledImageForScaleFactor, make the API more clear. Fix the scale factor option issue

This commit is contained in:
DreamPiggy 2018-04-08 00:06:11 +08:00
parent 7a84e59eb1
commit 1a3fb834a0
6 changed files with 88 additions and 47 deletions

View File

@ -485,7 +485,8 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
if (data) {
UIImage *image;
BOOL decodeFirstFrame = options & SDImageCacheDecodeFirstFrameOnly;
CGFloat scale = [context valueForKey:SDWebImageContextImageScaleFactor] ? [[context valueForKey:SDWebImageContextImageScaleFactor] doubleValue] : SDImageScaleForKey(key);
NSNumber *scaleValue = [context valueForKey:SDWebImageContextImageScaleFactor];
CGFloat scale = scaleValue.doubleValue >= 1 ? scaleValue.doubleValue : SDImageScaleFactorForKey(key);
if (!decodeFirstFrame) {
// check whether we should use `SDAnimatedImage`
if ([context valueForKey:SDWebImageContextAnimatedImageClass]) {
@ -499,7 +500,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
}
}
if (!image) {
image = [[SDWebImageCodersManager sharedManager] decodedImageWithData:data options:@{SDWebImageCoderDecodeFirstFrameOnly : @(decodeFirstFrame), SDWebImageContextImageScaleFactor : @(scale)}];
image = [[SDWebImageCodersManager sharedManager] decodedImageWithData:data options:@{SDWebImageCoderDecodeFirstFrameOnly : @(decodeFirstFrame), SDWebImageCoderDecodeScaleFactor : @(scale)}];
}
BOOL shouldDecode = YES;
if ([image conformsToProtocol:@protocol(SDAnimatedImage)]) {

View File

@ -15,6 +15,7 @@
#endif
#import "NSImage+Additions.h"
#import "UIImage+WebCache.h"
#import "SDWebImageDefine.h"
@interface SDWebImageCodersManager ()
@ -100,6 +101,13 @@
return nil;
}
BOOL decodeFirstFrame = [[options valueForKey:SDWebImageCoderDecodeFirstFrameOnly] boolValue];
CGFloat scale = 1;
if ([options valueForKey:SDWebImageCoderDecodeScaleFactor]) {
scale = [[options valueForKey:SDWebImageCoderDecodeScaleFactor] doubleValue];
if (scale < 1) {
scale = 1;
}
}
UIImage *image;
for (id<SDWebImageCoder> coder in self.coders) {
if ([coder canDecodeFromData:data]) {
@ -107,8 +115,15 @@
break;
}
}
if (decodeFirstFrame && image.images.count > 0) {
image = image.images.firstObject;
if (image) {
// Check static image
if (decodeFirstFrame && image.images.count > 0) {
image = image.images.firstObject;
}
// Check image scale
if (scale > 1 && scale != image.scale) {
image = SDScaledImageForScaleFactor(scale, image);
}
}
return image;

View File

@ -16,16 +16,19 @@ typedef NSMutableDictionary<SDWebImageContextOption, id> SDWebImageMutableContex
#pragma mark - Image scale
/**
Return the image scale from the specify key, supports file name and url key
Return the image scale factor for the specify key, supports file name and url key.
This is the built-in way to check the scale factor when we have no context about it. Because scale factor is not stored in image data (It's typically from filename).
However, you can also provide custom scale factor as well, see `SDWebImageContextImageScaleFactor`.
@param key The image cache key
@return The scale factor for image
*/
FOUNDATION_EXPORT CGFloat SDImageScaleForKey(NSString * _Nullable key);
FOUNDATION_EXPORT CGFloat SDImageScaleFactorForKey(NSString * _Nullable key);
/**
Scale the image with the scale factor from the specify key. If no need to scale, return the original image
This only works for `UIImage`(UIKit) or `NSImage`(AppKit).
Scale the image with the scale factor for the specify key. If no need to scale, return the original image.
This works for `UIImage`(UIKit) or `NSImage`(AppKit). And this function also preserve the associated value in `UIImage+WebCache`.
@note This is actually a convenience function, which firstlly call `SDImageScaleFactorForKey` and then call `SDScaledImageForScaleFactor`, kept for backward compatibility.
@param key The image cache key
@param image The image
@ -33,6 +36,16 @@ FOUNDATION_EXPORT CGFloat SDImageScaleForKey(NSString * _Nullable key);
*/
FOUNDATION_EXPORT UIImage * _Nullable SDScaledImageForKey(NSString * _Nullable key, UIImage * _Nullable image);
/**
Scale the image with the scale factor. If no need to scale, return the original image.
This works for `UIImage`(UIKit) or `NSImage`(AppKit). And this function also preserve the associated value in `UIImage+WebCache`.
@param scale The image scale factor
@param image The image
@return The scaled image
*/
FOUNDATION_EXPORT UIImage * _Nullable SDScaledImageForScaleFactor(CGFloat scale, UIImage * _Nullable image);
#pragma mark - WebCache Options
typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) {

View File

@ -16,7 +16,7 @@ static inline NSArray<NSNumber *> * _Nonnull SDImageScaleFactors() {
return @[@2, @3];
}
inline CGFloat SDImageScaleForKey(NSString * _Nullable key) {
inline CGFloat SDImageScaleFactorForKey(NSString * _Nullable key) {
CGFloat scale = 1;
if (!key) {
return scale;
@ -55,46 +55,56 @@ inline CGFloat SDImageScaleForKey(NSString * _Nullable key) {
return scale;
}
inline UIImage *SDScaledImageForKey(NSString * _Nullable key, UIImage * _Nullable image) {
inline UIImage * _Nullable SDScaledImageForKey(NSString * _Nullable key, UIImage * _Nullable image) {
if (!image) {
return nil;
}
CGFloat scale = SDImageScaleForKey(key);
if (scale > 1) {
UIImage *scaledImage;
if (image.sd_isAnimated) {
UIImage *animatedImage;
CGFloat scale = SDImageScaleFactorForKey(key);
return SDScaledImageForScaleFactor(scale, image);
}
inline UIImage * _Nullable SDScaledImageForScaleFactor(CGFloat scale, UIImage * _Nullable image) {
if (!image) {
return nil;
}
if (scale <= 1) {
return image;
}
if (scale == image.scale) {
return image;
}
UIImage *scaledImage;
if (image.sd_isAnimated) {
UIImage *animatedImage;
#if SD_UIKIT || SD_WATCH
// `UIAnimatedImage` images share the same size and scale.
NSMutableArray<UIImage *> *scaledImages = [NSMutableArray array];
for (UIImage *tempImage in image.images) {
UIImage *tempScaledImage = [[UIImage alloc] initWithCGImage:tempImage.CGImage scale:scale orientation:tempImage.imageOrientation];
[scaledImages addObject:tempScaledImage];
}
animatedImage = [UIImage animatedImageWithImages:scaledImages duration:image.duration];
animatedImage.sd_imageLoopCount = image.sd_imageLoopCount;
#else
// Animated GIF for `NSImage` need to grab `NSBitmapImageRep`
NSSize size = NSMakeSize(image.size.width / scale, image.size.height / scale);
animatedImage = [[NSImage alloc] initWithSize:size];
NSBitmapImageRep *bitmapImageRep = image.bitmapImageRep;
[animatedImage addRepresentation:bitmapImageRep];
#endif
scaledImage = animatedImage;
} else {
#if SD_UIKIT || SD_WATCH
scaledImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation];
#else
scaledImage = [[NSImage alloc] initWithCGImage:image.CGImage size:NSZeroSize];
#endif
// `UIAnimatedImage` images share the same size and scale.
NSMutableArray<UIImage *> *scaledImages = [NSMutableArray array];
for (UIImage *tempImage in image.images) {
UIImage *tempScaledImage = [[UIImage alloc] initWithCGImage:tempImage.CGImage scale:scale orientation:tempImage.imageOrientation];
[scaledImages addObject:tempScaledImage];
}
return scaledImage;
animatedImage = [UIImage animatedImageWithImages:scaledImages duration:image.duration];
animatedImage.sd_imageLoopCount = image.sd_imageLoopCount;
#else
// Animated GIF for `NSImage` need to grab `NSBitmapImageRep`
NSSize size = NSMakeSize(image.size.width / scale, image.size.height / scale);
animatedImage = [[NSImage alloc] initWithSize:size];
NSBitmapImageRep *bitmapImageRep = image.bitmapImageRep;
[animatedImage addRepresentation:bitmapImageRep];
#endif
scaledImage = animatedImage;
} else {
#if SD_UIKIT || SD_WATCH
scaledImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation];
#else
scaledImage = [[NSImage alloc] initWithCGImage:image.CGImage size:NSZeroSize];
#endif
}
return image;
scaledImage.sd_isIncremental = image.sd_isIncremental;
return scaledImage;
}
#pragma mark - Context option

View File

@ -364,7 +364,8 @@ didReceiveResponse:(NSURLResponse *)response
// check whether we should use `SDAnimatedImage`
UIImage *image;
BOOL decodeFirstFrame = self.options & SDWebImageDownloaderDecodeFirstFrameOnly;
CGFloat scale = [self.context valueForKey:SDWebImageContextImageScaleFactor] ? [[self.context valueForKey:SDWebImageContextImageScaleFactor] doubleValue] : SDImageScaleForKey(self.cacheKey);
NSNumber *scaleValue = [self.context valueForKey:SDWebImageContextImageScaleFactor];
CGFloat scale = scaleValue.doubleValue >= 1 ? scaleValue.doubleValue : SDImageScaleFactorForKey(self.cacheKey);
if (!decodeFirstFrame) {
// check whether we should use `SDAnimatedImage`
if ([self.context valueForKey:SDWebImageContextAnimatedImageClass]) {
@ -375,7 +376,7 @@ didReceiveResponse:(NSURLResponse *)response
}
}
if (!image) {
image = [self.progressiveCoder incrementalDecodedImageWithOptions:@{SDWebImageCoderDecodeFirstFrameOnly : @(decodeFirstFrame), SDWebImageContextImageScaleFactor : @(scale)}];
image = [self.progressiveCoder incrementalDecodedImageWithOptions:@{SDWebImageCoderDecodeFirstFrameOnly : @(decodeFirstFrame), SDWebImageCoderDecodeScaleFactor : @(scale)}];
}
if (image) {
BOOL shouldDecode = self.shouldDecompressImages;
@ -456,7 +457,8 @@ didReceiveResponse:(NSURLResponse *)response
// decode the image in coder queue
dispatch_async(self.coderQueue, ^{
BOOL decodeFirstFrame = self.options & SDWebImageDownloaderDecodeFirstFrameOnly;
CGFloat scale = [self.context valueForKey:SDWebImageContextImageScaleFactor] ? [[self.context valueForKey:SDWebImageContextImageScaleFactor] doubleValue] : SDImageScaleForKey(self.cacheKey);
NSNumber *scaleValue = [self.context valueForKey:SDWebImageContextImageScaleFactor];
CGFloat scale = scaleValue.doubleValue >= 1 ? scaleValue.doubleValue : SDImageScaleFactorForKey(self.cacheKey);
if (scale < 1) {
scale = 1;
}
@ -474,7 +476,7 @@ didReceiveResponse:(NSURLResponse *)response
}
}
if (!image) {
image = [[SDWebImageCodersManager sharedManager] decodedImageWithData:imageData options:@{SDWebImageCoderDecodeFirstFrameOnly : @(decodeFirstFrame), SDWebImageContextImageScaleFactor : @(scale)}];
image = [[SDWebImageCodersManager sharedManager] decodedImageWithData:imageData options:@{SDWebImageCoderDecodeFirstFrameOnly : @(decodeFirstFrame), SDWebImageCoderDecodeScaleFactor : @(scale)}];
}
BOOL shouldDecode = self.shouldDecompressImages;

View File

@ -25,7 +25,7 @@
* UIKit:
* Check the `images` array property
* AppKit:
* NSImage currently only support animated via GIF imageRep unlike UIImage. It will check all the imageRef
* NSImage currently only support animated via GIF imageRep unlike UIImage. It will check the imageRep's frame count.
*/
@property (nonatomic, assign, readonly) BOOL sd_isAnimated;