Search code examples
phpcolorsrgbhsl

HSL to RGB conversion math


When converting from HSL to RGB the math involved seems relatively simple, especially when converting grayscale as the RGB values are the lightness multiplied by 255.

However take this hex #eeeeee. It's RGB value is rgb(238,238,238) and it's HSL representation is hsl(0.00, 0.00, 0.93).

Every reference to a conversion I have found simply does this:

// Hard coded values for brevity
$hue = 0.00;
$saturation = 0.00;
$lightness = 0.00;

if ($saturation == 0)
{
    $red = $green = $blue = $lightness;
}
else
{
    // Or run the math
}

$rgb = [round($red * 255), round($green * 255), round($blue * 255)];

In the case of #eeeeee we know the following

$red = $green = $blue = 0.93;

And all the RGB values === 238.

The math in all the conversions I have seen do not stack.

0.93 * 255 = 237.15

(as a note rgb(237,237,237) produces hex #ededed)

After rounding we are left with 237. So we change the result to use ciel. Well this works for this case but breaks a lot of other conversions.

There is a step in this conversion that I'm missing (and so it seems is the rest of the world). Does anyone have any idea how to accurately calculate the RGB values from HSL?


Solution

  • Based on the comment from @Lithis it became immediately clear that the problem is with the accuracy of HSL values. As was pointed out in the comment:

    238 / 255 = 0.9333333 recurring
    

    Increasing the floating point accuracy within the conversion creates the hex codes expected. So instead of:

    0.93 * 255 = 237.15
    

    We work with

    0.93333 * 255 = 237.99915
    

    Which is far more acceptable a result than 237.15