Merge branch 'master' of https://github.com/SDWebImage/SDWebImage
This commit is contained in:
commit
3746c5d4c6
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue