Thanks for sharing that code. That Swift code wouldn't compile for me. I'm using Objective-C in my project but your Swift code doesn't appear like it would produce anything different than the code I'm experimenting with now (unless I'm missing something?):
CGImageRef doConvertCMYKCGImageToRGB (CGImageRef sourceImage)
{
size_t sourceBitsPerComponent = CGImageGetBitsPerComponent(sourceImage);
size_t sourceBitsPerPixel = CGImageGetBitsPerPixel(sourceImage);
CGColorSpaceRef sourceColorSpace = CGImageGetColorSpace(sourceImage);
CGBitmapInfo sourceBitmapInfo = CGImageGetBitmapInfo(sourceImage);
CGColorRenderingIntent sourceRenderingIntent = CGImageGetRenderingIntent(sourceImage);
const CGFloat *sourceDecode = CGImageGetDecode(sourceImage);
vImage_CGImageFormat cmykFormat = {
.bitsPerComponent = (uint32_t)sourceBitsPerComponent, // 8
.bitsPerPixel = (uint32_t)sourceBitsPerPixel, // 32
.colorSpace = sourceColorSpace, // (kCGColorSpaceICCBased; kCGColorSpaceModelCMYK; Generic CMYK Profile)
.bitmapInfo = sourceBitmapInfo, // kCGBitmapByteOrderDefault
.renderingIntent = sourceRenderingIntent, // kCGRenderingIntentDefault
.version = 0,
.decode = sourceDecode
};
vImage_CGImageFormat rgbFormat = {
.bitsPerComponent = 8,
.bitsPerPixel = 24,
.colorSpace = CGColorSpaceCreateDeviceRGB(),
.bitmapInfo = (CGBitmapInfo)kCGImageAlphaNone,
.renderingIntent = kCGRenderingIntentDefault
};
/*
Also tried:
vImage_CGImageFormat rgbFormat = {
.bitsPerComponent = 8,
.bitsPerPixel = 32,
.colorSpace = CGColorSpaceCreateDeviceRGB(),
.bitmapInfo = (CGBitmapInfo)kCGImageAlphaNoneSkipLast | kCGBitmapByteOrderDefault,
.renderingIntent = kCGRenderingIntentDefault
};*/
// Initialize source buffer
vImage_Buffer sourceBuffer;
// You are responsible for releasing the memory pointed to by buf->data back to the system using free().
vImage_Error error = vImageBuffer_InitWithCGImage(
&sourceBuffer, &cmykFormat, NULL, sourceImage, kvImageNoFlags);
if (error != kvImageNoError)
{
os_log_error(OS_LOG_DEFAULT,"Error initializing source buffer: %ld", error);
return NULL;
}
// Initialize destination buffer..
// You are responsible for releasing the memory pointed to by buf->data back to
// the system when you are done with it using free(). If no such allocation is desired, pass
// * kvImageNoAllocate in the flags to cause buf->data to be set to NULL and the preferred alignment
// * to be returned from the left hand side of the function.
vImage_Buffer destBuffer;
error = vImageBuffer_Init(&destBuffer, sourceBuffer.height, sourceBuffer.width, rgbFormat.bitsPerPixel, kvImageNoFlags);
if (error != kvImageNoError)
{
os_log_error(OS_LOG_DEFAULT,"Error initializing destination buffer: %ld", error);
free(sourceBuffer.data);
return NULL;
}
// Create a converter
vImageConverterRef cmykToRGBConverter = vImageConverter_CreateWithCGImageFormat(&cmykFormat, &rgbFormat, NULL, kvImageNoFlags, &error);
if (cmykToRGBConverter == NULL)
{
os_log_error(OS_LOG_DEFAULT,"Error creating vImage converter: %ld", error);
free(destBuffer.data); // Free destBuffer.data.
free(sourceBuffer.data); // Free sourceBuffer.data.
return NULL;
}
// Perform the conversion
error = vImageConvert_AnyToAny(cmykToRGBConverter, &sourceBuffer, &destBuffer, NULL, kvImageNoFlags);
CGImageRef rgbResult = NULL;
if (error == kvImageNoError)
{
// Create RGB result image
rgbResult = vImageCreateCGImageFromBuffer(&destBuffer, &rgbFormat, NULL, NULL, kvImageNoFlags, &error);
}
else
{
os_log_error(OS_LOG_DEFAULT,"Error converting image: %ld", error);
}
// Create CMYK image (not needed)...
//CGImageRef cmykImage = vImageCreateCGImageFromBuffer(&sourceBuffer, &cmykFormat, NULL, NULL, kvImageNoFlags, &error);
// Clean up
vImageConverter_Release(cmykToRGBConverter);
free(destBuffer.data); // Free destBuffer.data
free(sourceBuffer.data); // Free destBuffer.data
return rgbResult;
}
Using that with image I provided in my feedback as sourceImage produces a black box (same when I pass the image data I provided in my feedback directly to higher level APIs like NSBitmapImageRep).