diff --git a/SDWebImage/Core/SDImageCacheDefine.m b/SDWebImage/Core/SDImageCacheDefine.m index 560a06eb..0a3afbe5 100644 --- a/SDWebImage/Core/SDImageCacheDefine.m +++ b/SDWebImage/Core/SDImageCacheDefine.m @@ -19,7 +19,16 @@ UIImage * _Nullable SDImageCacheDecodeImageData(NSData * _Nonnull imageData, NSS NSNumber *scaleValue = context[SDWebImageContextImageScaleFactor]; CGFloat scale = scaleValue.doubleValue >= 1 ? scaleValue.doubleValue : SDImageScaleFactorForKey(cacheKey); 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]; mutableCoderOptions[SDImageCoderDecodeFirstFrameOnly] = @(decodeFirstFrame); diff --git a/SDWebImage/Core/SDImageCoderHelper.h b/SDWebImage/Core/SDImageCoderHelper.h index dcf1da2b..9df53e0c 100644 --- a/SDWebImage/Core/SDImageCoderHelper.h +++ b/SDWebImage/Core/SDImageCoderHelper.h @@ -90,6 +90,12 @@ + (UIImage * _Nullable)decodedAndScaledDownImageWithImage:(UIImage * _Nullable)image limitBytes:(NSUInteger)bytes; #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. diff --git a/SDWebImage/Core/SDImageCoderHelper.m b/SDWebImage/Core/SDImageCoderHelper.m index 3cc0c7ea..9e92dd60 100644 --- a/SDWebImage/Core/SDImageCoderHelper.m +++ b/SDWebImage/Core/SDImageCoderHelper.m @@ -18,26 +18,15 @@ static const size_t kBytesPerPixel = 4; 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 * Suggested value for iPad1 and iPhone 3GS: 60. * Suggested value for iPad2 and iPhone 4: 120. * Suggested value for iPhone 3G and iPod 2 and earlier devices: 30. */ -static const CGFloat kDestImageSizeMB = 60.f; - -/* - * 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 CGFloat kDestImageLimitBytes = 60.f * kBytesPerMB; static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to overlap the seems where tiles meet. #endif @@ -311,13 +300,11 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over CGFloat destTotalPixels; CGFloat tileTotalPixels; - if (bytes > 0) { - destTotalPixels = bytes / kBytesPerPixel; - tileTotalPixels = destTotalPixels / 3; - } else { - destTotalPixels = kDestTotalPixels; - tileTotalPixels = kTileTotalPixels; + if (bytes == 0) { + bytes = kDestImageLimitBytes; } + destTotalPixels = bytes / kBytesPerPixel; + tileTotalPixels = destTotalPixels / 3; CGContextRef destContext; // 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 ++ (NSUInteger)defaultScaleDownLimitBytes { + return kDestImageLimitBytes; +} + ++ (void)setDefaultScaleDownLimitBytes:(NSUInteger)defaultScaleDownLimitBytes { + if (defaultScaleDownLimitBytes < kBytesPerMB) { + return; + } + kDestImageLimitBytes = defaultScaleDownLimitBytes; +} + // Convert an EXIF image orientation to an iOS one. + (UIImageOrientation)imageOrientationFromEXIFOrientation:(CGImagePropertyOrientation)exifOrientation { UIImageOrientation imageOrientation = UIImageOrientationUp; @@ -533,11 +531,10 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over return NO; } CGFloat destTotalPixels; - if (bytes > 0) { - destTotalPixels = bytes / kBytesPerPixel; - } else { - destTotalPixels = kDestTotalPixels; + if (bytes == 0) { + bytes = kDestImageLimitBytes; } + destTotalPixels = bytes / kBytesPerPixel; if (destTotalPixels <= kPixelsPerMB) { // Too small to scale down return NO; diff --git a/SDWebImage/Core/SDImageLoader.m b/SDWebImage/Core/SDImageLoader.m index aac7a93a..4c831c59 100644 --- a/SDWebImage/Core/SDImageLoader.m +++ b/SDWebImage/Core/SDImageLoader.m @@ -33,7 +33,16 @@ UIImage * _Nullable SDImageLoaderDecodeImageData(NSData * _Nonnull imageData, NS NSNumber *scaleValue = context[SDWebImageContextImageScaleFactor]; CGFloat scale = scaleValue.doubleValue >= 1 ? scaleValue.doubleValue : SDImageScaleFactorForKey(cacheKey); 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]; mutableCoderOptions[SDImageCoderDecodeFirstFrameOnly] = @(decodeFirstFrame); @@ -75,12 +84,7 @@ UIImage * _Nullable SDImageLoaderDecodeImageData(NSData * _Nonnull imageData, NS } if (shouldDecode) { - BOOL shouldScaleDown = SD_OPTIONS_CONTAINS(options, SDWebImageScaleDownLargeImages); - if (shouldScaleDown) { - image = [SDImageCoderHelper decodedAndScaledDownImageWithImage:image limitBytes:0]; - } else { - image = [SDImageCoderHelper decodedImageWithImage:image]; - } + image = [SDImageCoderHelper decodedImageWithImage:image]; } } @@ -104,7 +108,16 @@ UIImage * _Nullable SDImageLoaderDecodeProgressiveImageData(NSData * _Nonnull im NSNumber *scaleValue = context[SDWebImageContextImageScaleFactor]; CGFloat scale = scaleValue.doubleValue >= 1 ? scaleValue.doubleValue : SDImageScaleFactorForKey(cacheKey); 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]; mutableCoderOptions[SDImageCoderDecodeFirstFrameOnly] = @(decodeFirstFrame); diff --git a/SDWebImage/Core/SDWebImageDefine.h b/SDWebImage/Core/SDWebImageDefine.h index 03dd210c..549c1da7 100644 --- a/SDWebImage/Core/SDWebImageDefine.h +++ b/SDWebImage/Core/SDWebImageDefine.h @@ -122,9 +122,12 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) { SDWebImageAvoidAutoSetImage = 1 << 10, /** - * By default, images are decoded respecting their original size. On iOS, this flag will scale down the - * images to a size compatible with the constrained memory of devices. - * This flag take no effect if `SDWebImageAvoidDecodeImage` is set. And it will be ignored if `SDWebImageProgressiveLoad` is set. + * By default, images are decoded respecting their original size. + * 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. + * 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,