Proper way to convert CGColors between colorspaces

cgcolorspace, colors, core-graphics, ios, macos

Solution

Apple added this API in iOS 9 and macOS 10.11:

- ObjC: `CGColorCreateCopyByMatchingToColorSpace`

- Swift: `CGColor.converted(to:intent:options:)`

Problem

There are several questions out there that ask about converting colors between colorspaces on Apple platforms. Unfortunately, the answers quite often involve `NSColor` or `UIColor` -- non portable Objective-C classes that cannot be interchangeably used on OS X and iOS. So I'd like to ask a very specific thing that I'm sure there must be a good answer to out there. I simply cannot believe that Apple would not foresee the need for this. How does one convert `CGColor` from one colorspace (for example, monochrome) to another one (for example, RGB) in a generic way, supporting all `CGColorSpace` types, while using solely the portable Core Graphics functions? Some context. I need to multiply the value provided by an online service with a value stored in `UIColor`. Correct way to extract the RGB components prior to iOS5, which finally introduced the method `-[UIColor getRed:green:blue:alpha:]`, is to use `CGColorGetComponents()`. I then multiply this color with the color fetched from the online service. This fails in case `+[UIColor grayColor]` was used to generate the `UIColor`. Meaning, I need to convert the color from the greyscale colorspace into RGB. In this case, it's easy. What about some other colorspace being provided? Or what if in a theoretical future scenario I just want to process a single pixel's color? There is a suggestion somewhere that I paint a pixel into a bitmap context and then read this pixel. That's insane, and I hope it isn't the only way to do this. Obviously the drawing method can figure out how to perform the conversion; how can we leverage this without creating a bitmap context solely to draw a pixel in it? Additional research: - This article on color conversion, aside from `UIColor`'s undocumented/private method `-styleString`, more interestingly mentions also undocumented `CGColorTransform`s. - ColorCG.cpp from WebKit suggests there is a header named `CoreGraphics/CGColorTransform.h`. Unfortunately, this header does not exist, at least not on Mountain Lion. Why would Apple hide these APIs? - The only other sensible resource I found mentioning `CGColorTransform`s is FreeQuartz, a free/open source reimplementation of Core Graphics. Filed a radar with Apple, #12141580, to open up and document `CGColorTransform`. I'm not holding my breath, though, so if there are other sensible suggestions, I'm all ears.

Original source