Public Group

# Problem converting HSL to RGB [solved]

This topic is 4592 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

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 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 on other sites
Quote:
 Original post by Emmanuel DelogetHere 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 on other sites
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]

• 10
• 18
• 14
• 19
• 15