Convert a CGColorRef to another CGColorSpaceRef

It is not documented and officially there is no way to convert a CGColor from a CGColorSpaceRef to another. Therefore, if you have two colors from a different colorspace, you’re kind of stuck. Unless you go ColorTransform, but then you’re on your own (undocumented CoreGraphics exports, which means some Reverse Engineering and assembly to do – I’ll go there for you if I feel like it someday).

The problem is more common than it seems: [UIColor whiteColor] gets you a color in the white colorspace, while [UIColor greenColor] gets you one in… the RGB colorspace. Now if you try to create a CGGradientRef from those two, you’ll have a problem. CGGradientRef does not convert any of those two to its own CGColorSpaceRef.

The only way I’ve found to do that is to use an undocumented method: styleString. It returns a parse-able NSString* that can be used to create a RGB based UIColor.

Here’s some code in an easy-to-use category to you code-lubbers:

 
 
@interface UIColor (colorSpaceConversionCategory)
// Transfer the UIColor to another UIColor that is guaranteed to be in the RGB
// colorspace.
- (UIColor*)rgbColor;
@end
 
@interface UIColor (UIColorUndocumentedCategory)
// Undocumented API. Remove the warning from the code below.
- (id)styleString;
@end
 
@implementation UIColor (colorSpaceConversionCategory)
- (UIColor*)rgbColor
{
  // Call to undocumented method.
  NSString*style = [self styleString];
 
  // Remove the "rgb(" prefix and the ")" suffix.
  style = [[style substringToIndex:style.length - 1] substringFromIndex:4];
  // Split the components.
  NSArray* rgb = [style componentsSeparatedByString:@","]; 
 
  CGFloat red   = [[rgb objectAtIndex:0] floatValue] / 255.0f;
  CGFloat green = [[rgb objectAtIndex:1] floatValue] / 255.0f; 
  CGFloat blue  = [[rgb objectAtIndex:2] floatValue] / 255.0f;
  CGFloat alpha = CGColorGetAlpha([self CGColor]);
 
  return [UIColor colorWithRed:red 
                         green:green 
                          blue:blue
                         alpha:alpha];
}
@end

There you go. This code is ugly as hell but works. Now calling [[UIColor whiteColor] rgbColor] returns a color in the RGB colorspace. Whatever the source colorspace.

This might not work in future versions of the SDK. I’ll post back if it changes.

/poltras

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • LinkedIn
  • Print
  • Reddit
  • StumbleUpon
  • Technorati
  • TwitThis
  • Wikio

Comments (3)

Benoit CerrinaApril 19th, 2009 at 9:27 am

you want to add an autorelease to the returned color.

PoltrasApril 19th, 2009 at 4:06 pm

@Benoit: no. [UIColor colorWithRed:green:blue:alpha:] returns an autoreleased UIColor object already.

Benoit CerrinaApril 19th, 2009 at 8:36 pm

Please ignore my previous comment code is good as is no need for an autorelease, the method
+(UIColor) colorWitRed: green: blue: alpha:
already returns an autoreleased object

Leave a comment

Your comment