How to get color components of a CGColor correctly
Asked Answered
S

6

9

I have a UILabel with black color;

i am writing the following code to get black color's components.

UIColor *aColor = [aLabel.textColor retain];
const CGFloat* components = CGColorGetComponents(aColor.CGColor);
CGColorSpaceRef colorSpace=CGColorSpaceCreateDeviceRGB();

but always this is giving Green color components instead of black color components;

Is any one have idea about this?

Am i passing different color space?

:-( Please help me.

Shinar answered 11/11, 2010 at 14:51 Comment(0)
S
12

Most likely wrong colorspace. I guess the alpha component of the grayscale colorspace gets where you think the green component should be.
I use this function to create a string from UIColor, I only encounter RGB and Grayscale colorspaces, so I just interpret every color with less than 4 (R+G+B+A) components as grayscale.

if (CGColorGetNumberOfComponents(color.CGColor) < 4) {
    const CGFloat *components = CGColorGetComponents(color.CGColor);
    color = [UIColor colorWithRed:components[0] green:components[0] blue:components[0] alpha:components[1]];
}
if (CGColorSpaceGetModel(CGColorGetColorSpace(color.CGColor)) != kCGColorSpaceModelRGB) {
    NSLog(@"no rgb colorspace");
    // do seomthing
}
const CGFloat *components = CGColorGetComponents(color.CGColor);
NSString *colorAsString = [NSString stringWithFormat:@"%f,%f,%f,%f", components[0], components[1], components[2], components[3]];

of course this method is not save for all cases, you should adopt it to your requirements.

Selfidentity answered 11/11, 2010 at 15:18 Comment(3)
Hi fluchtpunkt! Thanks for your message! it helps me get some idea..can you tell me why it is giving r=0.000000 g=1.000000 b=0.000000 a=0.000000 when i am printing color components which are green color components even though i pass the black color. Thank you very muchShinar
I think the pointer that generated by CGColorGetComponents needs to be dealloced manually.Fecit
Nope. I was wrong. https://mcmap.net/q/331850/-where-is-the-memory-leakFecit
E
7

The reason you are seeing what looks like r=0, g=1, b=0, a=0 is because you are misinterpreting the values in the returned array as being in an RGB color model. UIColor uses monochrome colorspace for greyscale colors like black in this case.
What you are seeing is an array of 2 components from a monochrome color model. The first is gray level (0 for black) and the second is alpha (1 for opaque). The last two values your are looking at are off the end of the 2 element array and happen to be 0 in this case.

You'll notice if color is black and you try CGColorGetNumberOfComponents(color.CGColor), it returns 2. And if you try CGColorSpaceGetModel(CGColorGetColorSpace(color.CGColor)), it returns 0 which corresponds to kCGColorSpaceModelMonochrome (see the enum CGColorSpaceModel in CGColorSpace.h)

see CGColorSpace Reference

Eider answered 2/4, 2011 at 23:45 Comment(1)
thanks, now I got it. it doesn't hurt if they unify both grayscale and non-grayscale to 4 components, since grayscale can also be represented by RGB. I am surprised to find iOS has distinguished those two and not even document this :PInformed
S
2

I think this is a very nice way to get the rgb representation of any UIColor*, which already has a convenience method for retaining it´s components.

-(CGColorRef)CGColorRefFromUIColor:(UIColor*)newColor {
     CGFloat components[4] = {0.0,0.0,0.0,0.0};
     [newColor getRed:&components[0] green:&components[1] blue:&components[2]        alpha:&components[3]];
     CGColorRef newRGB = CGColorCreate(CGColorSpaceCreateDeviceRGB(), components);
     return newRGB;
}
Selfgoverned answered 28/11, 2011 at 17:0 Comment(1)
Beware! iOS5+ only. Also, you're not releasing the colorspace object you created.Aforementioned
D
1

One way to get RGB for these is by drawing the color into a graphics context and reading the color back out. See my answer to this question for example code:

Get RGB value from UIColor presets

Doralynne answered 15/1, 2011 at 15:25 Comment(0)
D
0

working exampel with UIColor: CALayer * btnLayer = [myLittleButton layer];

[layer setBackgroundColor:<#(CGColorRef)#>] becomes: [btnLayer setBorderColor:[[UIColor grayColor] CGColor]];

just make sure the buttons original colors doesnt cover the layer

Dashboard answered 15/3, 2013 at 14:1 Comment(0)
P
0
extension UIColor {

  func toRGB() -> UIColor? {
    guard let model = cgColor.colorSpace?.model else {
      return nil
    }
    
    let components = cgColor.components

    switch model {
    case .rgb:
      return UIColor(red: components?[0] ?? 0.0, green: components?[1] ?? 0.0, blue: components?[2] ?? 0.0, alpha: components?[3] ?? 0.0)
    case .monochrome:
      return UIColor(red: components?[0] ?? 0.0, green: components?[0] ?? 0.0, blue: components?[0] ?? 0.0, alpha: components?[1] ?? 0.0)
    default:
      return nil
    }
  }
}
Parrie answered 2/8, 2020 at 11:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.