2

I've googled for ages and can't find a way to do this. Anybody got an idea? There is an NSColor way of doing it for mac, but nothing for iPhone that I can see. The idea in my app is that the user types in a HEX code (which i have managed to get into RGB) and it's changed into HSB.

Ideas?

Andrew
  • 15,935
  • 28
  • 121
  • 203
  • Why doesn't NSColor work on iPhone? Just use UIColor. – Matt Ball Apr 08 '11 at 02:42
  • I think there is such a method in PaintGL sample application. – nacho4d Apr 08 '11 at 03:12
  • Nope, it was the opposite HSB to RGB. Posted anyway ;) – nacho4d Apr 08 '11 at 03:16
  • possible duplicate of [Objective-C RGB to HSB](http://stackoverflow.com/questions/2591013/objective-c-rgb-to-hsb). Also. [How do I convert an RGB color or Hex into HSB?](http://stackoverflow.com/questions/5575080/how-do-i-convert-an-rgb-color-or-hex-into-hsb) and several others. – Caleb Apr 08 '11 at 03:27

2 Answers2

5

It just takes a little bit of math. The following code is just the important parts of the custom class I created for conversion. The "HSBColor" class stores just the hue, saturation, and brightness and I provide functions to get the components of it or a UIColor if I need to actually use it for something in the system.

Note: This code will not work as is unless you define an HSBColor class with hue, brightness, and saturation properties.

+(void)max:(int*)max andMin:(int*)min ofArray:(float[])array
{
    *min=0;
    *max=0;
    for(int i=1; i<3; i++)
    {
        if(array[i] > array[*max])
            *max=i;
        if(array[i] < array[*min])
            *min=i;
    }
}

+(HSBColor*)colorWithRed:(float)red Green:(float)green Blue:(float)blue
{
    HSBColor* toReturn = [[[HSBColor alloc] init] autorelease];

    float colorArray[3];
    colorArray[0] = red; 
    colorArray[1] = green; 
    colorArray[2] = blue;
    //NSLog(@"RGB: %f %f %f",colorArray[0],colorArray[1],colorArray[2]);
    int max;
    int min;
    [self max:&max andMin:&min ofArray:colorArray];

    if(max==min)
    {
        toReturn.hue=0;
        toReturn.saturation=0;
        toReturn.brightness=colorArray[0];
    }
    else
    {
        toReturn.brightness=colorArray[max];

        toReturn.saturation=(colorArray[max]-colorArray[min])/(colorArray[max]);

        if(max==0) // Red
            toReturn.hue = (colorArray[1]-colorArray[2])/(colorArray[max]-colorArray[min])*60/360;
        else if(max==1) // Green
            toReturn.hue = (2.0 + (colorArray[2]-colorArray[0])/(colorArray[max]-colorArray[min]))*60/360;
        else // Blue
            toReturn.hue = (4.0 + (colorArray[0]-colorArray[1])/(colorArray[max]-colorArray[min]))*60/360;
    }
    return toReturn;
}

+(HSBColor*)colorWithSystemColor:(UIColor*)color
{

    const CGFloat* components = CGColorGetComponents(color.CGColor);

    return [self colorWithRed:components[0] Green:components[1] Blue:components[2]];
}
drewag
  • 93,393
  • 28
  • 139
  • 128
  • Thanks for this. I've never used something with a + on the start, and dropping that into my code causes an 'Expected ) before HSBColor' error on the '(HSBColor*)' line. How do i set this up? And how do i pass a series of values into it? – Andrew Apr 08 '11 at 02:53
  • 1
    Sorry, HSBColor is a class I defined. You can't just drop in the code because you have not defined the HSBColor class yourself. I pasted this code in here to show the calculations of the brightness (toReturn.brightness), saturation (toReturn.saturation), and hue (toReturn.hue). You should use those calculations however they are most useful to you. Defining a function with a plus sign makes it a static function which means you can call it directly on the class instead of an instance of the class. – drewag Apr 08 '11 at 03:06
  • I got it. This helped a great deal. Thank you very much. – Andrew Apr 08 '11 at 03:21
2

In case you need it:

Convert HSV to RGB (From GLPaint sample application AppController.m)

//FUNCTIONS:
/*
   HSL2RGB Converts hue, saturation, luminance values to the equivalent red, green and blue values.
   For details on this conversion, see Fundamentals of Interactive Computer Graphics by Foley and van Dam (1982, Addison and Wesley)
   You can also find HSL to RGB conversion algorithms by searching the Internet.
   See also http://en.wikipedia.org/wiki/HSV_color_space for a theoretical explanation
 */
static void HSL2RGB(float h, float s, float l, float* outR, float* outG, float* outB)
{
    float           temp1,
                    temp2;
    float           temp[3];
    int             i;

    // Check for saturation. If there isn't any just return the luminance value for each, which results in gray.
    if(s == 0.0) {
        if(outR)
            *outR = l;
        if(outG)
            *outG = l;
        if(outB)
            *outB = l;
        return;
    }

    // Test for luminance and compute temporary values based on luminance and saturation 
    if(l < 0.5)
        temp2 = l * (1.0 + s);
    else
        temp2 = l + s - l * s;
        temp1 = 2.0 * l - temp2;

    // Compute intermediate values based on hue
    temp[0] = h + 1.0 / 3.0;
    temp[1] = h;
    temp[2] = h - 1.0 / 3.0;

    for(i = 0; i < 3; ++i) {

        // Adjust the range
        if(temp[i] < 0.0)
            temp[i] += 1.0;
        if(temp[i] > 1.0)
            temp[i] -= 1.0;


        if(6.0 * temp[i] < 1.0)
            temp[i] = temp1 + (temp2 - temp1) * 6.0 * temp[i];
        else {
            if(2.0 * temp[i] < 1.0)
                temp[i] = temp2;
            else {
                if(3.0 * temp[i] < 2.0)
                    temp[i] = temp1 + (temp2 - temp1) * ((2.0 / 3.0) - temp[i]) * 6.0;
                else
                    temp[i] = temp1;
            }
        }
    }

    // Assign temporary values to R, G, B
    if(outR)
        *outR = temp[0];
    if(outG)
        *outG = temp[1];
    if(outB)
        *outB = temp[2];
}
nacho4d
  • 43,720
  • 45
  • 157
  • 240