1

I am wondering if there is single one matched HSL color for a given RGB color?

Based on existing formula converting RGB to HSL, it is yes.

However, I want to know if my assertion above is true?

1
  • Do you mean having a 1-1 correspondence between the two color formats? Commented May 15, 2017 at 11:50

3 Answers 3

1

Relying solely on common sense:

RGB is defined by

  • Red ranges from 0 to 255 (256 options)

  • Green ranges from 0 to 255 (256 options)

  • Blue ranges from 0 to 255 (256 options)

Total number of RGB options = 256*256*256 = 16,777,216

HSL is defined by:

  • Hue - ranges from 0 to 359 (360 options)

  • Saturation - ranges from 0 to 100 (101 options)

  • Lightness(luminosity) - ranges from 0 to 100 (101 options)

Total number of HSL options = 360*101*101 = 3,672,360

My guess here is that since the total number of RGB colors is much higher than that of HSL colors, it's impossible to have 1 - 1 correspondence between the formats.

Will a convertor convert every RGB value to an HSL value - absolutely - it will round off to the closest value it can assign.

2
  • 1
    Hi Spasimir, I have been so bold to correct your math ;)
    – Vincent
    Commented May 16, 2017 at 8:47
  • 1
    Aren't HSL values in decimal? Assuming they are, would the answer still stand? I mainly wanna know, for example if rgb(198, 26, 78) = hsl(341.9, 76.8, 43.9) can I hope to increase the lightness to exact 50 (from 43.9) and still be able to recreate the same RGB values by adjusting either hue or saturation or both? Commented Nov 22, 2020 at 0:04
1
+50

Generally, yes

HSL is a polar(ish), or more accurately hexagon, transformation of the standard RGB color space as such each value only corresponds to one possible RGB triplet. This is however what would happen if we assume the numbers are numbers in the mathematical sense.

Implementation Details Matter

However, the individual implementation details of each software do matter. It may be that if you convert this into integer to integer, float to integer processing. That a individual colors drop out on account of rounding or implementation mistakes.

This may or may not matter to you. As it applies to every implementation of everything on a computer. Personally I never think of color as byte sized values. Instead i just think of each channel as it would be a floating point number from 0 to unbounded whit 1 being maximum display value. Why? Because this works if my channel depth is suddenly 12 bit or 16 or float or whatever. I can just normalize it. So i Personally do not care, if the details become a limit i just upgrade my processing to higher bit order.

0

Tested it out programmatically. It seems there is indeed one-to-one relation.

At least for complex colors (e.g. 198, 26, 78), and not colors like (128, 128, 128)

I personally wanted to know, for example if in rgb(198, 26, 78) = hsl(341.9, 76.8, 43.9) I could set the lightness to exact 50 (from 43.9) and still be able to recreate the same RGB values by adjusting either hue or saturation or both. It seems not. However if I relaxed the RGB values to be ~10 away from the original I could find a few corresponding HSL values.

Code (NodeJS):

const R = 198;
const G = 26;
const B = 78;

const step = 0.001;

const hslValues = new Set;
for (let h = 0; h < 1; h += step) {
  for (let s = 0; s < 1; s += step) {
    for (let l = 0; l < 1; l += step) {
      const [r, g, b] = hslToRgb(h, s, l)
      if (R === r && G === g && B === b) {
        hslValues.add(`${h}, ${s}, ${l}`);
        // console.log(`${hslValues.size} HSL values found for given RGB`);
      }
    }
  }
}
console.log(`${hslValues.size} HSL values found for given RGB`);
console.log(hslValues);

function hslToRgb(h, s, l) {
  /* https://stackoverflow.com/questions/2353211/hsl-to-rgb-color-conversion */
  var r, g, b;

  if (s == 0) {
    r = g = b = l; // achromatic
  } else {
    var hue2rgb = function hue2rgb(p, q, t) {
      if (t < 0) t += 1;
      if (t > 1) t -= 1;
      if (t < 1 / 6) return p + (q - p) * 6 * t;
      if (t < 1 / 2) return q;
      if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
      return p;
    }

    var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
    var p = 2 * l - q;
    r = hue2rgb(p, q, h + 1 / 3);
    g = hue2rgb(p, q, h);
    b = hue2rgb(p, q, h - 1 / 3);
  }

  return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}
2
  • I guess for the relation to work with neutral colors like RGB(128,128,128) (in other words colors with saturation = 0), you would have to allow hue to be null. That way you could set up your code to work backwards as well.
    – Wolff
    Commented Nov 22, 2020 at 1:05
  • 1
    Besides that, it's pretty obvious that you can't just change lightness to some other value and expect to be able to find a set of hue/saturation that will yield the same RGB values. In your example you only change lightness a little bit so if you allow the RGB values to differ about 10 you succeed. But if you change lightness more you have to allow for a greater difference in RGB values. So the idea doesn't work.
    – Wolff
    Commented Nov 22, 2020 at 1:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.