Is there a Cocoa Touch way to convert colors from one color space to another?
At the end of this code:
UIColor *grey = [UIColor colorWithWhite: 0.5 alpha: 1.0];
CGColorRef greyRef = [grey CGColor];
int x = CGColorGetNumberOfComponents(greyRef);
...x
is 2.
The reason I need this is I'm trying to copy colors to a list of color components for CGGradientCreateWithColorComponents
, which needs all colors in a single colorspace. The problem is that grey is in the grayscale colorspace, rather than the RGB one. (The name escapes me at the moment, but it isn't important.)
CGGradientRef createGradient(NSInteger inCount, NSArray* inColors, CGFloat* inLocations) {
CGColorSpaceRef theColorspace = CGColorSpaceCreateDeviceRGB( );
size_t numberOfComponents = 4;
NSInteger colorSize = numberOfComponents * sizeof( CGFloat );
CGFloat *theComponents = malloc( inCount * colorSize );
CGFloat *temp = theComponents;
for ( NSInteger i = 0; i < inCount; i++ ) {
UIColor *theColor = [inColors objectAtIndex: i];
CGColorRef cgColor = [theColor CGColor];
const CGFloat *components = CGColorGetComponents( cgColor );
memmove( temp, components, colorSize );
temp += numberOfComponents;
}
CGGradientRef gradient = CGGradientCreateWithColorComponents( theColorspace,
theComponents, inLocations, inCount );
CGColorSpaceRelease( theColorspace );
free( theComponents );
return gradient;
}
I know I can look for colors in the greyscale color space and convert them. But that only solves one case. From looking at this question, I think HSB is handled as well. But I'd like to write some code here and never think about it again, which means supporting not just the color spaces that are there now but anything Apple could conceivably add in the future. Am I out of luck?
Another way to convert these is by drawing them into contexts and letting core graphics do the conversion for you. See my answer to this question:
Get RGB value from UIColor presets
For colors created using
[UIColor colorWithRed:green:blue:alpha:]
, you can useUIColor getRed:green:blue:alpha:
, described in UIColor Class Reference. It's part of iOS 5 and later.If the color was created with
colorWithWhite:alpha:
you can use thegetWhite:alpha:
instead, described in UIColor Class Reference.To determine which color space is being used, you can use
CGColorGetColorSpace([color colorSpace])
. But it's probably easier to just check the result of the method call, then fail over to the next attempt. Something like this:I don't know how to handle color constants such as
[UIColor lightGrayColor]
, other than drawing them to a temporary bitmap and detecting them. Some of these color constants are actually textures; your best bet is probably to avoid them.If you plan on doing this a lot, it's an appropriate use of a category:
I'm not sure how to automatically convert them, but to identify different color spaces you can get the
CGColorSpaceModel
from the color'sCGColorSpaceRef
:Then you can compare
colorSpaceModel
with the constants defined inCoreGraphics/CGColorSpace.h
. UIColor'sgetRed:green:blue:alpha
works forkCGColorSpaceModelRGB
, whereasgetWhite:alpha
works forkCGColorSpaceModelMonochrome
.Note that a
UIColor
that was created withcolorWithHue:saturation:brightness:alpha:
will actually be in the RGB color space.In swift 3 we can directly use
to get the color space and color space model from a
UIColor
.