Sign in to follow this  
DeadXorAlive

Problem converting HSL to RGB [solved]

Recommended Posts

DeadXorAlive    535
I have some problems converting RGB values to HSL (using C++ with SDL) which I just can't seem to solve. I managed to get the HSL value of a given RGB, but the other way around gives me screwed up values. I read a wiki, some tutorial, and this, so the approach seems fine as far as I can tell. I'm guessing it has something to do with the conversion from int to doubles and back, I wouldn't know. I really like this Hue-Saturation-Lightness thing, if anybody is willing to help out you will be my hero. Here is my code, a bit much, in case:
//Not working conversion from HSL to RGB. HSL_Color is struct like a SDL_Color.
SDL_Color HSLtoRGB(const HSL_Color& HSL)
{
    double r, g, b, h, s, l;
    double temp1, temp2, tempr, tempg, tempb;
    
    //Scale each value to 0.0 - 1.0, from type int:
    h = HSL.h / 360.0;  //Hue is represented as a range of 360 degrees
    s = HSL.s / 256.0;  //Saturation 
    l = HSL.l / 256.0;  //Lightness
    
    if (s == 0)         //Saturation of 0 means a shade of grey
    {
    	r = g = b = l;
    }
    else                //
    {
        if (l < 0.5)
            temp2 = l * (1.0 + s);
        else
            temp2 = (l + s) - (l * s);
        
        temp1 = 2.0 * l - temp2;
        tempr = h + 1.0 / 3.0;
        if (tempr > 1.0)
            tempr-= 1.0;
        tempg = h;
        tempb = h - 1.0 / 3.0;
        if (tempb < 0) 
            tempb += 1.0; 
        
        // Calculate red value:     
        if (6.0 * tempr < 1.0)
        {
            r = temp1 + (temp2 - temp1) * 6.0 * tempr;
        }
        else if (2.0 * tempr < 1.0)
        {
            r = temp2;
        }
        else if (3.0 * tempr < 2.0)
        {
            r = temp1 + (temp2 - temp1) * ((2.0 / 3.0) - tempr) * 6.0;
        }
        else
        {
            r = temp1;
        }

        // Calculate green value       
        if (6.0 * tempg < 1.0)
        {
            g = temp1 + (temp2 - temp1) * 6.0 * tempg;
        }
        else if (2.0 * tempg < 1.0)
        {
            g = temp2;
        }
        else if (3.0 * tempg < 2.0)
        {
            g = temp1 + (temp2 - temp1) * ((2.0 / 3.0) - tempg) * 6.0;
        }
        else
        {
            g = temp1; 
        }

        // Calculate blue value    
        if (6.0 * tempb < 1.0)
        {
            b = temp1 + (temp2 - temp1) * 6.0 * tempb;
        }
        else if (2.0 * tempb < 1.0)
        {
            b = temp2;
        }
        else if (3.0 * tempr < 2.0)
        {
            b = temp1 + (temp2 - temp1) * ((2.0 / 3.0) - tempb) * 6.0;
        }
        else
        {
            g = temp1; 
        }
    }

    SDL_Color TempColor;
    TempColor.r = int(r * 256.0);
    TempColor.g = int(g * 256.0);
    TempColor.b = int(b * 256.0);
    TempColor.unused = HSL.unused;
    
    return TempColor;
}

[Edited by - DeadXorAlive on October 24, 2005 7:28:14 AM]

Share this post


Link to post
Share on other sites
I fed your routine with these:

HSL(0,256,128)
HSL(120,256,192)
HSL(240,256,64)

And it gave me

RGB(256,0,0)
RGB(128,256,128)
RGB(0,0,128)

Which are the expected values - if the Wikipedia article is right (and it seems to be right).

I guess you have to make sure that
  1. your hue is really an angle in [0,360[ (most of the time we use the range [0,256[)
  2. verify that your saturation and luminance values are in the range [0,256[


I didn't had a careful look to the code, so maybe it contains a small error, but if this is correct and if your code is only a copy of this code (as it seems), then you shouldn't have any problem.

Here is another reference about HSL/RGB conversion. I find the code simpler to read. This is the routine I used in numerous (professionnal, photo-oriented) projects, and as far as I can tell it works well ;)

HTH,

Share this post


Link to post
Share on other sites
LessBread    1415
Quote:
Original post by Emmanuel Deloget
Here is another reference about HSL/RGB conversion. I find the code simpler to read. This is the routine I used in numerous (professionnal, photo-oriented) projects, and as far as I can tell it works well ;)


Um, yeah, Paul Bourke ain't no slouch to say the least. Check out his section on surfaces. Wow.

Share this post


Link to post
Share on other sites
DeadXorAlive    535
Emmanuel Deloget, thank you so much for helping me out and providing extra noteworthy material.

You are right, the routine was fine. The problem turned out, I believe, to be a fencepost error in combination with the 8 bit integers that SDL_Color uses to store the RGB values. A quick test with normal ints showed me this.

Now, you really saved me a lot of time and frustration.

EDIT: The algorithm Deloget mentioned doesn't give exactly the same results as the wiki, but is good anyway. I think that's just a different way of mapping the saturation, I have yet to draw some examples with it to visualize it. Although probably unnecessary, I mentioned this just in case anybody would use this information, as to avoid confusion.

[Edited by - DeadXorAlive on October 24, 2005 11:26:05 AM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this