Fix the iOS 15+ draw image blank because that CoreGraphics may not transcode on BGRX8888 pixel format context

This commit is contained in:
lizhuoli 2022-03-03 20:49:57 +08:00
parent 4589048fdd
commit 1b0fdd8cb6
1 changed files with 39 additions and 14 deletions

View File

@ -255,9 +255,19 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
// iOS prefer BGRA8888 (premultiplied) or BGRX8888 bitmapInfo for screen rendering, which is same as `UIGraphicsBeginImageContext()` or `- [CALayer drawInContext:]` // 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` // 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 // But since our build-in coders use this bitmapInfo, this can have a little performance benefit
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host; CGBitmapInfo bitmapInfo;
bitmapInfo |= hasAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst; CGContextRef context = NULL;
CGContextRef context = CGBitmapContextCreate(NULL, newWidth, newHeight, 8, 0, [self colorSpaceGetDeviceRGB], bitmapInfo); if (@available(iOS 15, tvOS 15, macOS 12, watchOS 8, *)) {
// Update for iOS 15: CoreGraphics's draw image will fail to transcode and draw some special CGImage on BGRX8888
// We prefer to use the input CGImaage's bitmap firstly, then fallback to BGRA. See #3330
bitmapInfo = CGImageGetBitmapInfo(cgImage);
context = CGBitmapContextCreate(NULL, newWidth, newHeight, 8, 0, [self colorSpaceGetDeviceRGB], bitmapInfo);
}
if (!context) {
bitmapInfo = kCGBitmapByteOrder32Host;
bitmapInfo |= hasAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst;
context = CGBitmapContextCreate(NULL, newWidth, newHeight, 8, 0, [self colorSpaceGetDeviceRGB], bitmapInfo);
}
if (!context) { if (!context) {
return NULL; return NULL;
} }
@ -358,7 +368,7 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
} }
destTotalPixels = bytes / kBytesPerPixel; destTotalPixels = bytes / kBytesPerPixel;
tileTotalPixels = destTotalPixels / 3; tileTotalPixels = destTotalPixels / 3;
CGContextRef destContext; 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];
@ -380,20 +390,35 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
// device color space // device color space
CGColorSpaceRef colorspaceRef = [self colorSpaceGetDeviceRGB]; CGColorSpaceRef colorspaceRef = [self colorSpaceGetDeviceRGB];
BOOL hasAlpha = [self CGImageContainsAlpha:sourceImageRef]; BOOL hasAlpha = [self CGImageContainsAlpha:sourceImageRef];
// iOS display alpha info (BGRA8888/BGRX8888)
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host;
bitmapInfo |= hasAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst;
// kCGImageAlphaNone is not supported in CGBitmapContextCreate. // kCGImageAlphaNone is not supported in CGBitmapContextCreate.
// Since the original image here has no alpha info, use kCGImageAlphaNoneSkipFirst // Since the original image here has no alpha info, use kCGImageAlphaNoneSkipFirst
// to create bitmap graphics contexts without alpha info. // to create bitmap graphics contexts without alpha info.
destContext = CGBitmapContextCreate(NULL, CGBitmapInfo bitmapInfo;
destResolution.width, if (@available(iOS 15, tvOS 15, macOS 12, watchOS 8, *)) {
destResolution.height, // Update for iOS 15: CoreGraphics's draw image will fail to transcode and draw some special CGImage on BGRX8888
kBitsPerComponent, // We prefer to use the input CGImaage's bitmap firstly, then fallback to BGRA. See #3330
0, bitmapInfo = CGImageGetBitmapInfo(sourceImageRef);
colorspaceRef, destContext = CGBitmapContextCreate(NULL,
bitmapInfo); destResolution.width,
destResolution.height,
kBitsPerComponent,
0,
colorspaceRef,
bitmapInfo);
}
if (!destContext) {
// iOS display alpha info (BGRA8888/BGRX8888)
bitmapInfo = kCGBitmapByteOrder32Host;
bitmapInfo |= hasAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst;
destContext = CGBitmapContextCreate(NULL,
destResolution.width,
destResolution.height,
kBitsPerComponent,
0,
colorspaceRef,
bitmapInfo);
}
if (destContext == NULL) { if (destContext == NULL) {
return image; return image;