2

I want to get the individual values from a UIColor. Unsure how to do it?

Andrew
  • 15,935
  • 28
  • 121
  • 203

3 Answers3

8
static void RGBtoHSV( float r, float g, float b, float *h, float *s, float *v )
{
    float min, max, delta;
    min = MIN( r, MIN( g, b ));
    max = MAX( r, MAX( g, b ));
    *v = max;               // v
    delta = max - min;
    if( max != 0 )
        *s = delta / max;       // s
    else {
        // r = g = b = 0        // s = 0, v is undefined
        *s = 0;
        *h = -1;
        return;
    }
    if( r == max )
        *h = ( g - b ) / delta;     // between yellow & magenta
    else if( g == max )
        *h = 2 + ( b - r ) / delta; // between cyan & yellow
    else
        *h = 4 + ( r - g ) / delta; // between magenta & cyan
    *h *= 60;               // degrees
    if( *h < 0 )
        *h += 360;
}

static void HSVtoRGB( float *r, float *g, float *b, float h, float s, float v )
{
    int i;
    float f, p, q, t;
    if( s == 0 ) {
        // achromatic (grey)
        *r = *g = *b = v;
        return;
    }
    h /= 60;            // sector 0 to 5
    i = floor( h );
    f = h - i;          // factorial part of h
    p = v * ( 1 - s );
    q = v * ( 1 - s * f );
    t = v * ( 1 - s * ( 1 - f ) );
    switch( i ) {
        case 0:
            *r = v;
            *g = t;
            *b = p;
            break;
        case 1:
            *r = q;
            *g = v;
            *b = p;
            break;
        case 2:
            *r = p;
            *g = v;
            *b = t;
            break;
        case 3:
            *r = p;
            *g = q;
            *b = v;
            break;
        case 4:
            *r = t;
            *g = p;
            *b = v;
            break;
        default:        // case 5:
            *r = v;
            *g = p;
            *b = q;
            break;
    }
}

...

CGFloat r, g, b, a, h, s, v;

const CGFloat *comp = CGColorGetComponents([myUIColor CGColor]);

r = comp[0];
g = comp[1];
b = comp[2];
a = comp[3];

RGBtoHSV(r, g, b, &h, &s, &v);

The code above assumes the UIColor is setup in the RGB space (which is typical). If the color is in another color space it will crash and / or have undefined behavior.

iOS 5.0 has - (BOOL)getHue:(CGFloat *)hue saturation:(CGFloat *)saturation brightness:(CGFloat *)brightness alpha:(CGFloat *)alpha which does all this work for you. But it's not available yet.

Dustin
  • 1,030
  • 11
  • 15
  • 4
    This answer is technically correct, but needs an extra line to make it work with Apple's libraries. At the end of RGB2HSV, add the line: "*h /= 360.0;" -- because Apple specifies H in 0.0..1.0, rather than the Photoshop way which is 0..360 – Adam Jan 15 '12 at 22:06
  • You should respectively calculate sector this way: `if (h == 1.0) h = 0.0; else h *= 6.0` (instead of dividing by 60) in hsv2rgb() if your H value is in [0.0 ... 1.0] – kervich Dec 07 '12 at 13:41
1

At the bottom of Dustin's algorithm, he mentions all UIColor objects in iOS 5 and later now have

getHue:saturation:brightness:alpha:

This makes it very easy to get the values from a color. This is definitely the easiest solution now, and most everyone is on iOS 5.

karlbecker_com
  • 969
  • 1
  • 10
  • 16
  • But for those people who aren't on iOS 5 (yes they still exist), using this method will result in a very timely crash. – n_b Feb 18 '13 at 23:50
  • Absolutely - I meant my comment for people who are targeting modern iOS builds. If you can let go of iOS 4 users, it's definitely worth it in maintenance headaches since so many things changed (for the better) in iOS 5. – karlbecker_com Feb 19 '13 at 03:38
1

There's a function called HSL2RGB() in the GLPaint sample code from Apple that'll do what you want. A comment above the function points you to Wikipedia for an explanation of the code, which may help you understand what's going on.

Caleb
  • 124,013
  • 19
  • 183
  • 272