Fix the macOS force decode colorspace does not match screen colorspace and cause copy

Fix the NSColor should still convert to sRGB for print...
This commit is contained in:
DreamPiggy 2023-07-13 20:52:35 +08:00
parent 67da434e79
commit 45b497c5f6
4 changed files with 38 additions and 12 deletions

View File

@ -72,7 +72,7 @@ static inline size_t SDByteAlign(size_t size, size_t alignment) {
/**
Return the shared device-dependent RGB color space. This follows The Get Rule.
Because it's shared, you should not retain or release this object.
Typically is sRGB, the color space defaults to rendering on Apple's devices.
Typically is sRGB for iOS, screen color space (like Color LCD) for macOS.
@return The device-dependent RGB color space
*/
@ -80,7 +80,7 @@ static inline size_t SDByteAlign(size_t size, size_t alignment) {
/**
From v5.17.0, this returns the byte alignment used for bytesPerRow(stride) **Preferred from current hardward && OS using runtime detection**
Typically is 64, the system page size.
Typically is 32, the 8 pixels bytesPerRow.
@note To calculate the bytesPerRow, use the formula `SDByteAlign(width * (bitsPerPixel / 8), alignment)`
*/
+ (size_t)preferredByteAlignment;

View File

@ -57,7 +57,7 @@ static inline CGRect SDCGRectFitWithScaleMode(CGRect rect, CGSize size, SDImageS
return rect;
}
static inline UIColor * SDGetColorFromGrayscale(Pixel_88 pixel, CGBitmapInfo bitmapInfo) {
static inline UIColor * SDGetColorFromGrayscale(Pixel_88 pixel, CGBitmapInfo bitmapInfo, CGColorSpaceRef cgColorSpace) {
// Get alpha info, byteOrder info
CGImageAlphaInfo alphaInfo = bitmapInfo & kCGBitmapAlphaInfoMask;
CGBitmapInfo byteOrderInfo = bitmapInfo & kCGBitmapByteOrderMask;
@ -135,11 +135,18 @@ static inline UIColor * SDGetColorFromGrayscale(Pixel_88 pixel, CGBitmapInfo bit
default:
break;
}
#if SD_MAC
// Mac supports ColorSync, to ensure the same bahvior, we convert color to sRGB
NSColorSpace *colorSpace = [[NSColorSpace alloc] initWithCGColorSpace:cgColorSpace];
CGFloat components[2] = {w, a};
NSColor *color = [NSColor colorWithColorSpace:colorSpace components:components count:2];
return [color colorUsingColorSpace:NSColorSpace.genericGamma22GrayColorSpace];
#else
return [UIColor colorWithWhite:w alpha:a];
#endif
}
static inline UIColor * SDGetColorFromRGBA(Pixel_8888 pixel, CGBitmapInfo bitmapInfo) {
static inline UIColor * SDGetColorFromRGBA(Pixel_8888 pixel, CGBitmapInfo bitmapInfo, CGColorSpaceRef cgColorSpace) {
// Get alpha info, byteOrder info
CGImageAlphaInfo alphaInfo = bitmapInfo & kCGBitmapAlphaInfoMask;
CGBitmapInfo byteOrderInfo = bitmapInfo & kCGBitmapByteOrderMask;
@ -150,8 +157,10 @@ static inline UIColor * SDGetColorFromRGBA(Pixel_8888 pixel, CGBitmapInfo bitmap
case kCGBitmapByteOrderDefault: {
byteOrderNormal = YES;
} break;
case kCGBitmapByteOrder16Little:
case kCGBitmapByteOrder32Little: {
} break;
case kCGBitmapByteOrder16Big:
case kCGBitmapByteOrder32Big: {
byteOrderNormal = YES;
} break;
@ -242,8 +251,15 @@ static inline UIColor * SDGetColorFromRGBA(Pixel_8888 pixel, CGBitmapInfo bitmap
default:
break;
}
#if SD_MAC
// Mac supports ColorSync, to ensure the same bahvior, we convert color to sRGB
NSColorSpace *colorSpace = [[NSColorSpace alloc] initWithCGColorSpace:cgColorSpace];
CGFloat components[4] = {r, g, b, a};
NSColor *color = [NSColor colorWithColorSpace:colorSpace components:components count:4];
return [color colorUsingColorSpace:NSColorSpace.sRGBColorSpace];
#else
return [UIColor colorWithRed:r green:g blue:b alpha:a];
#endif
}
#if SD_UIKIT || SD_MAC
@ -558,6 +574,9 @@ static inline CGImageRef _Nullable SDCreateCGImageFromCIImage(CIImage * _Nonnull
CGImageRelease(imageRef);
return nil;
}
// Get color space for transform
CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef);
// greyscale
if (components == 2) {
Pixel_88 pixel = {0};
@ -565,7 +584,7 @@ static inline CGImageRef _Nullable SDCreateCGImageFromCIImage(CIImage * _Nonnull
CFRelease(data);
CGImageRelease(imageRef);
// Convert to color
return SDGetColorFromGrayscale(pixel, bitmapInfo);
return SDGetColorFromGrayscale(pixel, bitmapInfo, colorSpace);
} else if (components == 3 || components == 4) {
// RGB/RGBA
Pixel_8888 pixel = {0};
@ -573,7 +592,7 @@ static inline CGImageRef _Nullable SDCreateCGImageFromCIImage(CIImage * _Nonnull
CFRelease(data);
CGImageRelease(imageRef);
// Convert to color
return SDGetColorFromRGBA(pixel, bitmapInfo);
return SDGetColorFromRGBA(pixel, bitmapInfo, colorSpace);
} else {
NSLog(@"Unsupported components: %zu", components);
CFRelease(data);
@ -637,6 +656,8 @@ static inline CGImageRef _Nullable SDCreateCGImageFromCIImage(CIImage * _Nonnull
// Convert to color
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
NSMutableArray<UIColor *> *colors = [NSMutableArray arrayWithCapacity:CGRectGetWidth(rect) * CGRectGetHeight(rect)];
// ColorSpace
CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef);
for (size_t index = start; index < end; index += components) {
if (index >= row * bytesPerRow + col * components) {
// Index beyond the end of current row, go next row
@ -648,14 +669,14 @@ static inline CGImageRef _Nullable SDCreateCGImageFromCIImage(CIImage * _Nonnull
UIColor *color;
if (components == 2) {
Pixel_88 pixel = {pixels[index], pixel[index+1]};
color = SDGetColorFromGrayscale(pixel, bitmapInfo);
color = SDGetColorFromGrayscale(pixel, bitmapInfo, colorSpace);
} else {
if (components == 3) {
Pixel_8888 pixel = {pixels[index], pixels[index+1], pixels[index+2], 0};
color = SDGetColorFromRGBA(pixel, bitmapInfo);
color = SDGetColorFromRGBA(pixel, bitmapInfo, colorSpace);
} else if (components == 4) {
Pixel_8888 pixel = {pixels[index], pixels[index+1], pixels[index+2], pixels[index+3]};
color = SDGetColorFromRGBA(pixel, bitmapInfo);
color = SDGetColorFromRGBA(pixel, bitmapInfo, colorSpace);
} else {
NSLog(@"Unsupported components: %zu", components);
}

View File

@ -478,6 +478,7 @@
#else
UIImage *image = [[UIImage alloc] initWithCGImage:cgImage scale:1 orientation:UIImageOrientationUp];
#endif
CGImageRelease(cgImage);
UIImage *newImage = [SDImageCoderHelper decodedImageWithImage:image policy:SDImageForceDecodePolicyAutomatic];
// Check policy works, since it's supported by CA hardware, which return the input image object, using pointer compare
XCTAssertTrue(image == newImage);
@ -515,6 +516,7 @@
#else
UIImage *image = [[UIImage alloc] initWithCGImage:cgImage scale:1 orientation:UIImageOrientationUp];
#endif
CGImageRelease(cgImage);
UIImage *newImage = [SDImageCoderHelper decodedImageWithImage:image policy:SDImageForceDecodePolicyAutomatic];
// Check policy works, since it's not supported by CA hardware, which return the different image object
XCTAssertFalse(image == newImage);

View File

@ -124,12 +124,15 @@
CGSize size = CGSizeMake(100, 100);
SDGraphicsImageRenderer *renderer = [[SDGraphicsImageRenderer alloc] initWithSize:size format:format];
UIColor *color = UIColor.redColor;
NSLog(@"Draw Color ColorSpace: %@", color.CGColor);
UIImage *image = [renderer imageWithActions:^(CGContextRef _Nonnull context) {
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, CGRectMake(0, 0, size.width, size.height));
}];
expect(image.scale).equal(format.scale);
expect([image sd_colorAtPoint:CGPointMake(50, 50)].sd_hexString).equal(color.sd_hexString);
UIColor *testColor = [image sd_colorAtPoint:CGPointMake(50, 50)];
NSLog(@"Draw Color ColorSpace: %@", testColor.CGColor);
expect(testColor.sd_hexString).equal(color.sd_hexString);
UIColor *grayscaleColor = UIColor.blackColor;
UIImage *grayscaleImage = [renderer imageWithActions:^(CGContextRef _Nonnull context) {