This commit is contained in:
DreamPiggy 2022-06-20 17:33:00 +08:00
commit 3746c5d4c6
3 changed files with 75 additions and 31 deletions

View File

@ -179,6 +179,17 @@ typedef NS_OPTIONS(NSUInteger, SDImageCacheOptions) {
toDisk:(BOOL)toDisk toDisk:(BOOL)toDisk
completion:(nullable SDWebImageNoParamsBlock)completionBlock; completion:(nullable SDWebImageNoParamsBlock)completionBlock;
/**
* Asynchronously store an image data into disk cache at the given key.
*
* @param imageData The image data to store
* @param key The unique image cache key, usually it's image absolute URL
* @param completionBlock A block executed after the operation is finished
*/
- (void)storeImageData:(nullable NSData *)imageData
forKey:(nullable NSString *)key
completion:(nullable SDWebImageNoParamsBlock)completionBlock;
/** /**
* Asynchronously store an image into memory and disk cache at the given key. * Asynchronously store an image into memory and disk cache at the given key.
* *
@ -198,7 +209,7 @@ typedef NS_OPTIONS(NSUInteger, SDImageCacheOptions) {
completion:(nullable SDWebImageNoParamsBlock)completionBlock; completion:(nullable SDWebImageNoParamsBlock)completionBlock;
/** /**
* Synchronously store image into memory cache at the given key. * Synchronously store an image into memory cache at the given key.
* *
* @param image The image to store * @param image The image to store
* @param key The unique image cache key, usually it's image absolute URL * @param key The unique image cache key, usually it's image absolute URL
@ -207,7 +218,7 @@ typedef NS_OPTIONS(NSUInteger, SDImageCacheOptions) {
forKey:(nullable NSString *)key; forKey:(nullable NSString *)key;
/** /**
* Synchronously store image data into disk cache at the given key. * Synchronously store an image data into disk cache at the given key.
* *
* @param imageData The image data to store * @param imageData The image data to store
* @param key The unique image cache key, usually it's image absolute URL * @param key The unique image cache key, usually it's image absolute URL

View File

@ -168,6 +168,12 @@ static NSString * _defaultDiskCacheDirectory;
[self storeImage:image imageData:nil forKey:key toDisk:toDisk completion:completionBlock]; [self storeImage:image imageData:nil forKey:key toDisk:toDisk completion:completionBlock];
} }
- (void)storeImageData:(nullable NSData *)imageData
forKey:(nullable NSString *)key
completion:(nullable SDWebImageNoParamsBlock)completionBlock {
[self storeImage:nil imageData:imageData forKey:key toDisk:YES completion:completionBlock];
}
- (void)storeImage:(nullable UIImage *)image - (void)storeImage:(nullable UIImage *)image
imageData:(nullable NSData *)imageData imageData:(nullable NSData *)imageData
forKey:(nullable NSString *)key forKey:(nullable NSString *)key
@ -182,14 +188,14 @@ static NSString * _defaultDiskCacheDirectory;
toMemory:(BOOL)toMemory toMemory:(BOOL)toMemory
toDisk:(BOOL)toDisk toDisk:(BOOL)toDisk
completion:(nullable SDWebImageNoParamsBlock)completionBlock { completion:(nullable SDWebImageNoParamsBlock)completionBlock {
if (!image || !key) { if ((!image && !imageData) || !key) {
if (completionBlock) { if (completionBlock) {
completionBlock(); completionBlock();
} }
return; return;
} }
// if memory cache is enabled // if memory cache is enabled
if (toMemory && self.config.shouldCacheImagesInMemory) { if (image && toMemory && self.config.shouldCacheImagesInMemory) {
NSUInteger cost = image.sd_memoryCost; NSUInteger cost = image.sd_memoryCost;
[self.memoryCache setObject:image forKey:key cost:cost]; [self.memoryCache setObject:image forKey:key cost:cost];
} }
@ -234,7 +240,7 @@ static NSString * _defaultDiskCacheDirectory;
} }
- (void)_archivedDataWithImage:(UIImage *)image forKey:(NSString *)key { - (void)_archivedDataWithImage:(UIImage *)image forKey:(NSString *)key {
if (!image) { if (!image || !key) {
return; return;
} }
// Check extended data // Check extended data

View File

@ -330,6 +330,19 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
return image; return image;
} }
#if SD_UIKIT
// See: https://developer.apple.com/documentation/uikit/uiimage/3750834-imagebypreparingfordisplay
// Need CGImage-based
if (@available(iOS 15, tvOS 15, *)) {
UIImage *decodedImage = [image imageByPreparingForDisplay];
if (decodedImage) {
SDImageCopyAssociatedObject(image, decodedImage);
decodedImage.sd_isDecoded = YES;
return decodedImage;
}
}
#endif
CGImageRef imageRef = image.CGImage; CGImageRef imageRef = image.CGImage;
if (!imageRef) { if (!imageRef) {
return image; return image;
@ -355,36 +368,54 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
return image; return image;
} }
if (![self shouldScaleDownImage:image limitBytes:bytes]) {
return [self decodedImageWithImage:image];
}
CGFloat destTotalPixels; CGFloat destTotalPixels;
CGFloat tileTotalPixels; CGFloat tileTotalPixels;
if (bytes == 0) { if (bytes == 0) {
bytes = kDestImageLimitBytes; bytes = [self defaultScaleDownLimitBytes];
} }
bytes = MAX(bytes, kBytesPerPixel);
destTotalPixels = bytes / kBytesPerPixel; destTotalPixels = bytes / kBytesPerPixel;
tileTotalPixels = destTotalPixels / 3; tileTotalPixels = destTotalPixels / 3;
CGImageRef sourceImageRef = image.CGImage;
CGSize sourceResolution = CGSizeZero;
sourceResolution.width = CGImageGetWidth(sourceImageRef);
sourceResolution.height = CGImageGetHeight(sourceImageRef);
if (![self shouldScaleDownImagePixelSize:sourceResolution limitBytes:bytes]) {
return [self decodedImageWithImage:image];
}
CGFloat sourceTotalPixels = sourceResolution.width * sourceResolution.height;
// Determine the scale ratio to apply to the input image
// that results in an output image of the defined size.
// see kDestImageSizeMB, and how it relates to destTotalPixels.
CGFloat imageScale = sqrt(destTotalPixels / sourceTotalPixels);
CGSize destResolution = CGSizeZero;
destResolution.width = MAX(1, (int)(sourceResolution.width * imageScale));
destResolution.height = MAX(1, (int)(sourceResolution.height * imageScale));
#if SD_UIKIT
// See: https://developer.apple.com/documentation/uikit/uiimage/3750835-imagebypreparingthumbnailofsize
// Need CGImage-based
if (@available(iOS 15, tvOS 15, *)) {
// Calculate thumbnail point size
CGFloat scale = image.scale ?: 1;
CGSize thumbnailSize = CGSizeMake(destResolution.width / scale, destResolution.height / scale);
UIImage *decodedImage = [image imageByPreparingThumbnailOfSize:thumbnailSize];
if (decodedImage) {
SDImageCopyAssociatedObject(image, decodedImage);
decodedImage.sd_isDecoded = YES;
return decodedImage;
}
}
#endif
CGContextRef destContext = NULL; CGContextRef destContext = NULL;
// 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.
// on iOS7, do not forget to call [[SDImageCache sharedImageCache] clearMemory]; // on iOS7, do not forget to call [[SDImageCache sharedImageCache] clearMemory];
@autoreleasepool { @autoreleasepool {
CGImageRef sourceImageRef = image.CGImage;
CGSize sourceResolution = CGSizeZero;
sourceResolution.width = CGImageGetWidth(sourceImageRef);
sourceResolution.height = CGImageGetHeight(sourceImageRef);
CGFloat sourceTotalPixels = sourceResolution.width * sourceResolution.height;
// Determine the scale ratio to apply to the input image
// that results in an output image of the defined size.
// see kDestImageSizeMB, and how it relates to destTotalPixels.
CGFloat imageScale = sqrt(destTotalPixels / sourceTotalPixels);
CGSize destResolution = CGSizeZero;
destResolution.width = MAX(1, (int)(sourceResolution.width * imageScale));
destResolution.height = MAX(1, (int)(sourceResolution.height * imageScale));
// device color space // device color space
CGColorSpaceRef colorspaceRef = [self colorSpaceGetDeviceRGB]; CGColorSpaceRef colorspaceRef = [self colorSpaceGetDeviceRGB];
BOOL hasAlpha = [self CGImageContainsAlpha:sourceImageRef]; BOOL hasAlpha = [self CGImageContainsAlpha:sourceImageRef];
@ -592,14 +623,10 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
return YES; return YES;
} }
+ (BOOL)shouldScaleDownImage:(nonnull UIImage *)image limitBytes:(NSUInteger)bytes { + (BOOL)shouldScaleDownImagePixelSize:(CGSize)sourceResolution limitBytes:(NSUInteger)bytes {
BOOL shouldScaleDown = YES; BOOL shouldScaleDown = YES;
CGImageRef sourceImageRef = image.CGImage; CGFloat sourceTotalPixels = sourceResolution.width * sourceResolution.height;
CGSize sourceResolution = CGSizeZero;
sourceResolution.width = CGImageGetWidth(sourceImageRef);
sourceResolution.height = CGImageGetHeight(sourceImageRef);
float sourceTotalPixels = sourceResolution.width * sourceResolution.height;
if (sourceTotalPixels <= 0) { if (sourceTotalPixels <= 0) {
return NO; return NO;
} }
@ -609,7 +636,7 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
} }
bytes = MAX(bytes, kBytesPerPixel); bytes = MAX(bytes, kBytesPerPixel);
destTotalPixels = bytes / kBytesPerPixel; destTotalPixels = bytes / kBytesPerPixel;
float imageScale = destTotalPixels / sourceTotalPixels; CGFloat imageScale = destTotalPixels / sourceTotalPixels;
if (imageScale < 1) { if (imageScale < 1) {
shouldScaleDown = YES; shouldScaleDown = YES;
} else { } else {