Last active
September 3, 2020 23:25
-
-
Save sandymc/7382989 to your computer and use it in GitHub Desktop.
This code snippet shows how to convert an image buffer between color spaces (e.g., transform from ProPhoto to sRGB or whatever) using Apple's new (and entirely undocumented) ColorSyncTransformConvert function. Firstly, a transform is created, then that transform is used to convert an image buffer.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const void *keys[] = {kColorSyncProfile, kColorSyncRenderingIntent, kColorSyncTransformTag}; | |
const void *srcVals[] = {[srcProfile ref], kColorSyncRenderingIntentUseProfileHeader, kColorSyncTransformDeviceToPCS}; | |
const void *dstVals[] = {[destProfile ref], kColorSyncRenderingIntentUseProfileHeader, kColorSyncTransformPCSToDevice}; | |
CFDictionaryRef srcDict = CFDictionaryCreate ( | |
NULL, | |
(const void **)keys, | |
(const void **)srcVals, | |
3, | |
&kCFTypeDictionaryKeyCallBacks, | |
&kCFTypeDictionaryValueCallBacks); | |
CFDictionaryRef dstDict = CFDictionaryCreate ( | |
NULL, | |
(const void **)keys, | |
(const void **)dstVals, | |
3, | |
&kCFTypeDictionaryKeyCallBacks, | |
&kCFTypeDictionaryValueCallBacks); | |
const void* arrayVals[] = {srcDict, dstDict, NULL}; | |
CFArrayRef profileSequence = CFArrayCreate(NULL, (const void **)arrayVals, 2, &kCFTypeArrayCallBacks); | |
transform = ColorSyncTransformCreate (profileSequence, NULL); | |
if (srcDict) CFRelease (srcDict); | |
if (dstDict) CFRelease (dstDict); | |
if (profileSequence) CFRelease (profileSequence); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Notes to the code: | |
1. This is designed to work on buffers that are either 32 bit float or 16 bit uint; RGBA packed | |
2. [srcProfile ref] and [destProfile ref] return ColorSyncProfileRefs | |
3. srcProfile is the existing color profile; destProfile is what you want | |
3. transform is a ColorSyncTransformRef, and must be released when done | |
5. This example operates in place; there's no documentation to suggest whether in-place operation is actually supported. But then, there's no documentation at all. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void* dst; | |
void* scr; | |
ColorSyncDataDepth depth; | |
ColorSyncDataLayout layout; | |
size_t bytesPerRow; | |
if (_imageBuf.isFloat) { | |
scr = [_imageBuf bufferFloatForRow:0 col:0]; | |
dst = scr; | |
depth = kColorSync32BitFloat; | |
layout = kColorSyncAlphaLast; | |
bytesPerRow = _imageBuf.imageWidth*4*sizeof(float); | |
} | |
else { | |
scr = [_imageBuf bufferU16ForRow:0 col:0]; | |
dst = scr; | |
depth = kColorSync16BitInteger; | |
layout = kColorSyncAlphaLast; | |
bytesPerRow = _imageBuf.imageWidth*4*sizeof(uint16); | |
} | |
bool result = ColorSyncTransformConvert ( | |
transform, // transform - transform to be used for converting color | |
_imageBuf.imageWidth, // width - width of the image in pixels | |
_imageBuf.imageHeight, // height - height of the image in pixels | |
dst, // dst - a pointer to the destination where the results will be written. | |
depth, // dstDepth - describes the bit depth and type of the destination color components | |
layout, // dstFormat - describes the format and byte packing of the destination pixels | |
bytesPerRow, // dstBytesPerRow - number of bytes in the row of data | |
scr, // src - a pointer to the data to be converted. | |
depth, // srcDepth - describes the bit depth and type of the source color components | |
layout, // srcFormat - describes the format and byte packing of the source pixels | |
bytesPerRow, // srcBytesPerRow - number of bytes in the row of data | |
nil); // CFDictionaryRef options | |
if (!result) { | |
NSLog(@"%s error in ColorSyncTransformConvert", __PRETTY_FUNCTION__); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I think you are almost always better off using vImageConvert_AnyToAny with a CGColorConversionInfoRef these days.