Merge pull request #3355 from dreampiggy/feature_support_uiimage_preparefordisplay

Support using iOS 15 UIImage new API imageByPreparingForDisplay for faster force decoding
This commit is contained in:
DreamPiggy 2022-06-20 17:17:10 +08:00 committed by GitHub
commit 8743cdd633
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 53 additions and 26 deletions

View File

@ -330,6 +330,19 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
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;
if (!imageRef) {
return image;
@ -355,27 +368,24 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
return image;
}
if (![self shouldScaleDownImage:image limitBytes:bytes]) {
return [self decodedImageWithImage:image];
}
CGFloat destTotalPixels;
CGFloat tileTotalPixels;
if (bytes == 0) {
bytes = kDestImageLimitBytes;
bytes = [self defaultScaleDownLimitBytes];
}
bytes = MAX(bytes, kBytesPerPixel);
destTotalPixels = bytes / kBytesPerPixel;
tileTotalPixels = destTotalPixels / 3;
CGContextRef destContext = NULL;
// 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];
@autoreleasepool {
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.
@ -385,6 +395,27 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
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;
// 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];
@autoreleasepool {
// device color space
CGColorSpaceRef colorspaceRef = [self colorSpaceGetDeviceRGB];
BOOL hasAlpha = [self CGImageContainsAlpha:sourceImageRef];
@ -592,14 +623,10 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
return YES;
}
+ (BOOL)shouldScaleDownImage:(nonnull UIImage *)image limitBytes:(NSUInteger)bytes {
+ (BOOL)shouldScaleDownImagePixelSize:(CGSize)sourceResolution limitBytes:(NSUInteger)bytes {
BOOL shouldScaleDown = YES;
CGImageRef sourceImageRef = image.CGImage;
CGSize sourceResolution = CGSizeZero;
sourceResolution.width = CGImageGetWidth(sourceImageRef);
sourceResolution.height = CGImageGetHeight(sourceImageRef);
float sourceTotalPixels = sourceResolution.width * sourceResolution.height;
CGFloat sourceTotalPixels = sourceResolution.width * sourceResolution.height;
if (sourceTotalPixels <= 0) {
return NO;
}
@ -609,7 +636,7 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
}
bytes = MAX(bytes, kBytesPerPixel);
destTotalPixels = bytes / kBytesPerPixel;
float imageScale = destTotalPixels / sourceTotalPixels;
CGFloat imageScale = destTotalPixels / sourceTotalPixels;
if (imageScale < 1) {
shouldScaleDown = YES;
} else {