From 3929f2cd2a354f2fc23b1be819c73451f9ed35e5 Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Sun, 15 Dec 2019 20:44:32 +0800 Subject: [PATCH] Replace the background decode core function CGImageCreateDecoded with UIGraphicsRenderer, this one should use the perferred format --- SDWebImage/Core/SDImageCoderHelper.m | 35 ++++++++++++++++------------ 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/SDWebImage/Core/SDImageCoderHelper.m b/SDWebImage/Core/SDImageCoderHelper.m index 3cc0c7ea..1a3391e1 100644 --- a/SDWebImage/Core/SDImageCoderHelper.m +++ b/SDWebImage/Core/SDImageCoderHelper.m @@ -12,6 +12,7 @@ #import "NSData+ImageContentType.h" #import "SDAnimatedImageRep.h" #import "UIImage+ForceDecode.h" +#import "SDGraphicsImageRenderer.h" #import "SDAssociatedObject.h" #if SD_UIKIT || SD_WATCH @@ -257,22 +258,26 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over } BOOL hasAlpha = [self CGImageContainsAlpha:cgImage]; - // iOS prefer BGRA8888 (premultiplied) or BGRX8888 bitmapInfo for screen rendering, which is same as `UIGraphicsBeginImageContext()` or `- [CALayer drawInContext:]` - // Though you can use any supported bitmapInfo (see: https://developer.apple.com/library/content/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_context/dq_context.html#//apple_ref/doc/uid/TP30001066-CH203-BCIBHHBB ) and let Core Graphics reorder it when you call `CGContextDrawImage` - // But since our build-in coders use this bitmapInfo, this can have a little performance benefit - CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host; - bitmapInfo |= hasAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst; - CGContextRef context = CGBitmapContextCreate(NULL, newWidth, newHeight, 8, 0, [self colorSpaceGetDeviceRGB], bitmapInfo); - if (!context) { - return NULL; - } - // Apply transform - CGAffineTransform transform = SDCGContextTransformFromOrientation(orientation, CGSizeMake(newWidth, newHeight)); - CGContextConcatCTM(context, transform); - CGContextDrawImage(context, CGRectMake(0, 0, width, height), cgImage); // The rect is bounding box of CGImage, don't swap width & height - CGImageRef newImageRef = CGBitmapContextCreateImage(context); - CGContextRelease(context); + // Using UIGraphicsRenderer on supported platforms, and use the main screeen's perferred format (like Wide Color) + SDGraphicsImageRendererFormat *format = [SDGraphicsImageRendererFormat preferredFormat]; + format.scale = 1; // use pixel instead of point + format.opaque = !hasAlpha; + SDGraphicsImageRenderer *renderer = [[SDGraphicsImageRenderer alloc] initWithSize:CGSizeMake(newWidth, newHeight) format:format]; + UIImage *newImage = [renderer imageWithActions:^(CGContextRef _Nonnull context) { + // Apply transform + CGAffineTransform transform = SDCGContextTransformFromOrientation(orientation, CGSizeMake(newWidth, newHeight)); + CGContextConcatCTM(context, transform); +#if SD_MAC + UIImage *drawImage = [[UIImage alloc] initWithCGImage:cgImage scale:1 orientation:kCGImagePropertyOrientationUp]; +#else + UIImage *drawImage = [[UIImage alloc] initWithCGImage:cgImage scale:1 orientation:UIImageOrientationUp]; +#endif + [drawImage drawInRect:CGRectMake(0, 0, width, height)]; // The rect is bounding box of CGImage, don't swap width & height + }]; + CGImageRef newImageRef = newImage.CGImage; + // Retain the CGImage because this temp `newImage` will release after function return + CGImageRetain(newImageRef); return newImageRef; }