Fix the WebP encoding which loss the image's input color space

Should prefer to use input color space and only use device RGB as fallback
This commit is contained in:
DreamPiggy 2023-11-08 17:42:18 +08:00
parent a47710f9f2
commit 8113caf1b7
7 changed files with 8 additions and 2 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 246 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 979 KiB

View File

@ -883,14 +883,20 @@ WEBP_CSP_MODE ConvertCSPMode(CGBitmapInfo bitmapInfo) {
} }
uint8_t *rgba = NULL; // RGBA Buffer managed by CFData, don't call `free` on it, instead call `CFRelease` on `dataRef` uint8_t *rgba = NULL; // RGBA Buffer managed by CFData, don't call `free` on it, instead call `CFRelease` on `dataRef`
// We could not assume that input CGImage's color mode is always RGB888/RGBA8888. Convert all other cases to target color mode using vImage // We must prefer the input CGImage's color space, which may contains ICC profile
CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef);
if (!colorSpace) {
colorSpace = [SDImageCoderHelper colorSpaceGetDeviceRGB];
}
vImage_CGImageFormat destFormat = { vImage_CGImageFormat destFormat = {
.bitsPerComponent = 8, .bitsPerComponent = 8,
.bitsPerPixel = hasAlpha ? 32 : 24, .bitsPerPixel = hasAlpha ? 32 : 24,
.colorSpace = [SDImageCoderHelper colorSpaceGetDeviceRGB], .colorSpace = colorSpace,
.bitmapInfo = hasAlpha ? kCGImageAlphaLast | kCGBitmapByteOrderDefault : kCGImageAlphaNone | kCGBitmapByteOrderDefault // RGB888/RGBA8888 (Non-premultiplied to works for libwebp) .bitmapInfo = hasAlpha ? kCGImageAlphaLast | kCGBitmapByteOrderDefault : kCGImageAlphaNone | kCGBitmapByteOrderDefault // RGB888/RGBA8888 (Non-premultiplied to works for libwebp)
}; };
vImage_Buffer dest; vImage_Buffer dest;
// We could not assume that input CGImage's color mode is always RGB888/RGBA8888. Convert all other cases to target color mode using vImage
// But vImageBuffer_InitWithCGImage will do convert automatically (unless you use `kvImageNoAllocate`), so no need to call `vImageConvert` by ourselves
vImage_Error error = vImageBuffer_InitWithCGImage(&dest, &destFormat, NULL, imageRef, kvImageNoFlags); vImage_Error error = vImageBuffer_InitWithCGImage(&dest, &destFormat, NULL, imageRef, kvImageNoFlags);
if (error != kvImageNoError) { if (error != kvImageNoError) {
return nil; return nil;