I have a CGImage in CMYK color space (i.e. CGColorSpaceGetModel returns kCGColorSpaceModelCMYK when queried via CGImageGetColorSpace).
However, when I try saving it via CGImageDestination, it gets converted to RGBColorSpace. I've tried to set the correct disctionary values, but to no avail. How do I know this? When I open the saved image with Preview, the General Info Tab tells me 'ColorModel:RGB' and 'Profile Name: Generic RGB Profile'. If I open the saved file with CGImageSource and read out the properties, I get the same results (RGB color model, Generic RGB Profile).
Now, before I lose my last hair (singular), my question is: is this intentional? Is ImageIO not capable of saving images in any format other than RGB? Just for kicks, I tried the same with a L*a*b color space, and had the same result.
Here's my save code:
BOOL saveImage(CGImageRef theImage, NSURL *fileDestination, NSString *theUTI)
{
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithURL((__bridge CFURLRef)fileDestination, (__bridge CFStringRef) theUTI, 1, nil);
// now assemble the dictionary for saving
NSMutableDictionary *theDict = nil;
theDict = [[NSMutableDictionary alloc] initWithCapacity:10];
[theDict setObject:[NSNumber numberWithFloat:hdpi] forKey: (id) kCGImagePropertyDPIHeight];
[theDict setObject:[NSNumber numberWithFloat:vdpi] forKey: (id) kCGImagePropertyDPIWidth];
}
// now make sure that we have the correct color space in the dictionary
NSString *colorModel = nil;
CGColorSpaceRef theColorSpace = CGImageGetColorSpace(theImage);
CGColorSpaceModel theModel = CGColorSpaceGetModel(theColorSpace);
switch (theModel) {
case kCGColorSpaceModelRGB:
colorModel = kCGImagePropertyColorModelRGB;
break;
case kCGColorSpaceModelLab:
colorModel = kCGImagePropertyColorModelLab;
break;
case kCGColorSpaceModelCMYK:
colorModel = kCGImagePropertyColorModelCMYK;
break;
default:
colorModel = kCGImagePropertyColorModelRGB;
break;
}
[theDict setObject:colorModel forKey:(id) kCGImagePropertyColorModel];
// Add the image to the destination, characterizing the image with
// the properties dictionary.
CGImageDestinationAddImage(imageDestination, theImage, (__bridge CFDictionaryRef) theDict); //properties);
BOOL success = (CGImageDestinationFinalize(imageDestination) != 0);
CFRelease(imageDestination);
return success;
}
There must be something obvious I'm overlooking. Do I have to set some kCFSuperSecretProperty to get this to work? Or does ImageIO simply not save as CMYK?
Oh, I'm on OSX 10.7 (Lion) if that is a factor,
Ok, I bit the bullet and used an incident to get Apple's Engineering help. Here's their reply:
The answer has two parts:
1) ImageIO will preserve CMYK and Lab color space if the file format for the destination supports that color space. Currently, image formats that support CMYK are TIFF, PSD, JPEG and JPEG 2000. If the destination file format does not support the current color space, ImageIO will convert to Standard RGB profile. This happens, for example, if you intend to save a CMYK image to PNG or BMP file format
2) ImageIO does not support saving CMYK or Lab to JPEG 2000, even though the specifications state that the file format supports CMYK and Lab. Apple Engineering acknowledges that this currently is a shortcoming of ImageIO. This may be changed in the future.
So, the code above is correct. You will have to filter your file destination types (UTI) yourself or warn the user that a conversion is imminent. In the future, when Apple adds CMYK and Lab support to JPEG 2000, you'll have to change the filter function, but the code can remain the same.