Bridge the exist options `SDWebImageScaleDownLargeImages`, to use the thumbnail decoding instead. Defaults use 60MB limit and thumbnail size is (3966, 3966)

This commit is contained in:
DreamPiggy 2020-01-05 22:20:37 +08:00
parent 19af6b76e6
commit 6bb8641783
5 changed files with 64 additions and 36 deletions

View File

@ -19,7 +19,16 @@ UIImage * _Nullable SDImageCacheDecodeImageData(NSData * _Nonnull imageData, NSS
NSNumber *scaleValue = context[SDWebImageContextImageScaleFactor]; NSNumber *scaleValue = context[SDWebImageContextImageScaleFactor];
CGFloat scale = scaleValue.doubleValue >= 1 ? scaleValue.doubleValue : SDImageScaleFactorForKey(cacheKey); CGFloat scale = scaleValue.doubleValue >= 1 ? scaleValue.doubleValue : SDImageScaleFactorForKey(cacheKey);
NSNumber *preserveAspectRatioValue = context[SDWebImageContextImagePreserveAspectRatio]; NSNumber *preserveAspectRatioValue = context[SDWebImageContextImagePreserveAspectRatio];
NSValue *thumbnailSizeValue = context[SDWebImageContextImageThumbnailPixelSize]; NSValue *thumbnailSizeValue;
BOOL shouldScaleDown = SD_OPTIONS_CONTAINS(options, SDWebImageScaleDownLargeImages);
if (shouldScaleDown) {
CGFloat thumbnailPixels = SDImageCoderHelper.defaultScaleDownLimitBytes / 4;
CGFloat dimension = ceil(sqrt(thumbnailPixels));
thumbnailSizeValue = @(CGSizeMake(dimension, dimension));
}
if (context[SDWebImageContextImageThumbnailPixelSize]) {
thumbnailSizeValue = context[SDWebImageContextImageThumbnailPixelSize];
}
SDImageCoderMutableOptions *mutableCoderOptions = [NSMutableDictionary dictionaryWithCapacity:2]; SDImageCoderMutableOptions *mutableCoderOptions = [NSMutableDictionary dictionaryWithCapacity:2];
mutableCoderOptions[SDImageCoderDecodeFirstFrameOnly] = @(decodeFirstFrame); mutableCoderOptions[SDImageCoderDecodeFirstFrameOnly] = @(decodeFirstFrame);

View File

@ -90,6 +90,12 @@
+ (UIImage * _Nullable)decodedAndScaledDownImageWithImage:(UIImage * _Nullable)image limitBytes:(NSUInteger)bytes; + (UIImage * _Nullable)decodedAndScaledDownImageWithImage:(UIImage * _Nullable)image limitBytes:(NSUInteger)bytes;
#if SD_UIKIT || SD_WATCH #if SD_UIKIT || SD_WATCH
/**
Control the default limit bytes to scale down larget images.
This value must be larger than or equal to 1MB. Defaults to 60MB.
*/
@property (class, readwrite) NSUInteger defaultScaleDownLimitBytes;
/** /**
Convert an EXIF image orientation to an iOS one. Convert an EXIF image orientation to an iOS one.

View File

@ -18,26 +18,15 @@
static const size_t kBytesPerPixel = 4; static const size_t kBytesPerPixel = 4;
static const size_t kBitsPerComponent = 8; static const size_t kBitsPerComponent = 8;
static const CGFloat kBytesPerMB = 1024.0f * 1024.0f;
static const CGFloat kPixelsPerMB = kBytesPerMB / kBytesPerPixel;
/* /*
* Defines the maximum size in MB of the decoded image when the flag `SDWebImageScaleDownLargeImages` is set * Defines the maximum size in MB of the decoded image when the flag `SDWebImageScaleDownLargeImages` is set
* Suggested value for iPad1 and iPhone 3GS: 60. * Suggested value for iPad1 and iPhone 3GS: 60.
* Suggested value for iPad2 and iPhone 4: 120. * Suggested value for iPad2 and iPhone 4: 120.
* Suggested value for iPhone 3G and iPod 2 and earlier devices: 30. * Suggested value for iPhone 3G and iPod 2 and earlier devices: 30.
*/ */
static const CGFloat kDestImageSizeMB = 60.f; static CGFloat kDestImageLimitBytes = 60.f * kBytesPerMB;
/*
* Defines the maximum size in MB of a tile used to decode image when the flag `SDWebImageScaleDownLargeImages` is set
* Suggested value for iPad1 and iPhone 3GS: 20.
* Suggested value for iPad2 and iPhone 4: 40.
* Suggested value for iPhone 3G and iPod 2 and earlier devices: 10.
*/
static const CGFloat kSourceImageTileSizeMB = 20.f;
static const CGFloat kBytesPerMB = 1024.0f * 1024.0f;
static const CGFloat kPixelsPerMB = kBytesPerMB / kBytesPerPixel;
static const CGFloat kDestTotalPixels = kDestImageSizeMB * kPixelsPerMB;
static const CGFloat kTileTotalPixels = kSourceImageTileSizeMB * kPixelsPerMB;
static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to overlap the seems where tiles meet. static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to overlap the seems where tiles meet.
#endif #endif
@ -311,13 +300,11 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
CGFloat destTotalPixels; CGFloat destTotalPixels;
CGFloat tileTotalPixels; CGFloat tileTotalPixels;
if (bytes > 0) { if (bytes == 0) {
destTotalPixels = bytes / kBytesPerPixel; bytes = kDestImageLimitBytes;
tileTotalPixels = destTotalPixels / 3;
} else {
destTotalPixels = kDestTotalPixels;
tileTotalPixels = kTileTotalPixels;
} }
destTotalPixels = bytes / kBytesPerPixel;
tileTotalPixels = destTotalPixels / 3;
CGContextRef destContext; CGContextRef destContext;
// autorelease the bitmap context and all vars to help system to free memory when there are memory warning. // autorelease the bitmap context and all vars to help system to free memory when there are memory warning.
@ -433,6 +420,17 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
} }
#if SD_UIKIT || SD_WATCH #if SD_UIKIT || SD_WATCH
+ (NSUInteger)defaultScaleDownLimitBytes {
return kDestImageLimitBytes;
}
+ (void)setDefaultScaleDownLimitBytes:(NSUInteger)defaultScaleDownLimitBytes {
if (defaultScaleDownLimitBytes < kBytesPerMB) {
return;
}
kDestImageLimitBytes = defaultScaleDownLimitBytes;
}
// Convert an EXIF image orientation to an iOS one. // Convert an EXIF image orientation to an iOS one.
+ (UIImageOrientation)imageOrientationFromEXIFOrientation:(CGImagePropertyOrientation)exifOrientation { + (UIImageOrientation)imageOrientationFromEXIFOrientation:(CGImagePropertyOrientation)exifOrientation {
UIImageOrientation imageOrientation = UIImageOrientationUp; UIImageOrientation imageOrientation = UIImageOrientationUp;
@ -533,11 +531,10 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
return NO; return NO;
} }
CGFloat destTotalPixels; CGFloat destTotalPixels;
if (bytes > 0) { if (bytes == 0) {
destTotalPixels = bytes / kBytesPerPixel; bytes = kDestImageLimitBytes;
} else {
destTotalPixels = kDestTotalPixels;
} }
destTotalPixels = bytes / kBytesPerPixel;
if (destTotalPixels <= kPixelsPerMB) { if (destTotalPixels <= kPixelsPerMB) {
// Too small to scale down // Too small to scale down
return NO; return NO;

View File

@ -33,7 +33,16 @@ UIImage * _Nullable SDImageLoaderDecodeImageData(NSData * _Nonnull imageData, NS
NSNumber *scaleValue = context[SDWebImageContextImageScaleFactor]; NSNumber *scaleValue = context[SDWebImageContextImageScaleFactor];
CGFloat scale = scaleValue.doubleValue >= 1 ? scaleValue.doubleValue : SDImageScaleFactorForKey(cacheKey); CGFloat scale = scaleValue.doubleValue >= 1 ? scaleValue.doubleValue : SDImageScaleFactorForKey(cacheKey);
NSNumber *preserveAspectRatioValue = context[SDWebImageContextImagePreserveAspectRatio]; NSNumber *preserveAspectRatioValue = context[SDWebImageContextImagePreserveAspectRatio];
NSValue *thumbnailSizeValue = context[SDWebImageContextImageThumbnailPixelSize]; NSValue *thumbnailSizeValue;
BOOL shouldScaleDown = SD_OPTIONS_CONTAINS(options, SDWebImageScaleDownLargeImages);
if (shouldScaleDown) {
CGFloat thumbnailPixels = SDImageCoderHelper.defaultScaleDownLimitBytes / 4;
CGFloat dimension = ceil(sqrt(thumbnailPixels));
thumbnailSizeValue = @(CGSizeMake(dimension, dimension));
}
if (context[SDWebImageContextImageThumbnailPixelSize]) {
thumbnailSizeValue = context[SDWebImageContextImageThumbnailPixelSize];
}
SDImageCoderMutableOptions *mutableCoderOptions = [NSMutableDictionary dictionaryWithCapacity:2]; SDImageCoderMutableOptions *mutableCoderOptions = [NSMutableDictionary dictionaryWithCapacity:2];
mutableCoderOptions[SDImageCoderDecodeFirstFrameOnly] = @(decodeFirstFrame); mutableCoderOptions[SDImageCoderDecodeFirstFrameOnly] = @(decodeFirstFrame);
@ -75,12 +84,7 @@ UIImage * _Nullable SDImageLoaderDecodeImageData(NSData * _Nonnull imageData, NS
} }
if (shouldDecode) { if (shouldDecode) {
BOOL shouldScaleDown = SD_OPTIONS_CONTAINS(options, SDWebImageScaleDownLargeImages); image = [SDImageCoderHelper decodedImageWithImage:image];
if (shouldScaleDown) {
image = [SDImageCoderHelper decodedAndScaledDownImageWithImage:image limitBytes:0];
} else {
image = [SDImageCoderHelper decodedImageWithImage:image];
}
} }
} }
@ -104,7 +108,16 @@ UIImage * _Nullable SDImageLoaderDecodeProgressiveImageData(NSData * _Nonnull im
NSNumber *scaleValue = context[SDWebImageContextImageScaleFactor]; NSNumber *scaleValue = context[SDWebImageContextImageScaleFactor];
CGFloat scale = scaleValue.doubleValue >= 1 ? scaleValue.doubleValue : SDImageScaleFactorForKey(cacheKey); CGFloat scale = scaleValue.doubleValue >= 1 ? scaleValue.doubleValue : SDImageScaleFactorForKey(cacheKey);
NSNumber *preserveAspectRatioValue = context[SDWebImageContextImagePreserveAspectRatio]; NSNumber *preserveAspectRatioValue = context[SDWebImageContextImagePreserveAspectRatio];
NSValue *thumbnailSizeValue = context[SDWebImageContextImageThumbnailPixelSize]; NSValue *thumbnailSizeValue;
BOOL shouldScaleDown = SD_OPTIONS_CONTAINS(options, SDWebImageScaleDownLargeImages);
if (shouldScaleDown) {
CGFloat thumbnailPixels = SDImageCoderHelper.defaultScaleDownLimitBytes / 4;
CGFloat dimension = ceil(sqrt(thumbnailPixels));
thumbnailSizeValue = @(CGSizeMake(dimension, dimension));
}
if (context[SDWebImageContextImageThumbnailPixelSize]) {
thumbnailSizeValue = context[SDWebImageContextImageThumbnailPixelSize];
}
SDImageCoderMutableOptions *mutableCoderOptions = [NSMutableDictionary dictionaryWithCapacity:2]; SDImageCoderMutableOptions *mutableCoderOptions = [NSMutableDictionary dictionaryWithCapacity:2];
mutableCoderOptions[SDImageCoderDecodeFirstFrameOnly] = @(decodeFirstFrame); mutableCoderOptions[SDImageCoderDecodeFirstFrameOnly] = @(decodeFirstFrame);

View File

@ -122,9 +122,12 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) {
SDWebImageAvoidAutoSetImage = 1 << 10, SDWebImageAvoidAutoSetImage = 1 << 10,
/** /**
* By default, images are decoded respecting their original size. On iOS, this flag will scale down the * By default, images are decoded respecting their original size.
* images to a size compatible with the constrained memory of devices. * On iOS/tvOS/watchOS, this flag will scale down the images to a size compatible with the constrained memory of devices. On macOS, this does nothing.
* This flag take no effect if `SDWebImageAvoidDecodeImage` is set. And it will be ignored if `SDWebImageProgressiveLoad` is set. * To control the limit bytes, check `SDImageCoderHelper.defaultScaleDownLimitBytes` (Defaults to 60MB)
* This will actually translate to use context option `.imageThumbnailPixelSize` from v5.5.0 (Defaults to (3966, 3966)). Previously does not.
* This flags effect the progressive and animated images as well from v5.5.0. Previously does not.
* @note If you need detail controls, it's better to use context option `imageThumbnailPixelSize` and `imagePreserveAspectRatio` instead.
*/ */
SDWebImageScaleDownLargeImages = 1 << 11, SDWebImageScaleDownLargeImages = 1 << 11,