Why do Saturation and Luminance go all the way to 240, but Hue goes only to 239? And why 239 anyway?


If you open the common Color Picker dialog, the custom color picker lets you specify the color in one of three ways.

  • Graphically, by clicking a color in the rainbow and using the slider to change the brightness.
  • Numerically by specifying Hue, Saturation, and Luminance.
  • Numerically by specifying Red, Green, and Blue.

Let's look at the Red, Green, and Blue values first. Theoretically, color channels are expressed as floating point values between 0.0 and 1.0 (inclusive). In Windows, it is common to change the scale to integers 0 to 255 (inclusive), since that corresponds to the color values in a 24-bit color space. This is the color space you've probably spent a good amount of time dealing with, since it corresponds to the RGB macro in wingdi.h, the COLORREF data type, and the way colors are typically expressed in CSS: #RRGGBB.

The Hue, Saturation, and Luminance is a bit tricker. The theoretical range for Hue is an angle, normalized to be greater than or equal to 0° and strictly less than 360°. The upper value of the range is not reached because Hue is cyclical, so a value of 360° is equivalent to 0°. On the other hand, Saturation and Luminance are floating point values between 0.0 and 1.0 (inclusive).

In Windows, the Hue, Saturation, and Luminance ranges are rescaled so that they go from 0 to 240. Hue is endpoint-exclusive (because 360° = 0°) whereas Saturation and Luminance are endpoint-inclusive (because 1.0 is achievable).

Okay, but why rescaled to 240? Why not rescale to 255?

The Hue value works out best when the range can be equally divided into 12 segments, because the important points of the Hue occur every 30°. The highest multiple of 12 that is still less than 256 is 252, but 240 makes for prettier values.

RGB Name 240-based 252-based
FF0000 red 0 0
FF8000 orange 20 21
FFFF00 yellow 40 42
80FF00 chartreuse 60 63
00FF00 green 80 84
00FF80 spring green 100 105
00FFFF cyan 120 126
0080FF dodger blue 140 147
0000FF blue 160 168
8000FF electric indigo 180 189
FF00FF fuchsia 200 210
FF0080 deep pink 220 231

(Color names taken from Colblindor.)

Saturation and Luminance could have gone up to 255, but I guess they used 240 out of solidarity. The original code was written in the 1980's for a now-defunct program called Chart, and it has been carried forward ever since.

Comments (34)
  1. Joshua says:

    Yeah, and the math is wrong forever. Take a color, convert to HSL, add 20 to hue, and convert back. It's brightness changed. I tried repeatedly to find the correct math only to learn in the end what they say about RGB only having 55% of the gamut true. Still looking for an approximate solution to correct L to make white colors compatible with black. The logarithmic curve involved in L makes it really hard.

  2. Alex says:

    @Joshua:  You'll find the LAB color space much more useful for that.  I assume you are attempting to find a "brightness" value that is representative of how the human eye sees color.  The L value in HSL is pretty useless for that, as full blue (0,0,255) is shown as having an L of 1.0 but is quite dark.  You can convert from RGB to XYZ, and then XYZ to LAB.  The Lab "L" value is a much truer representation of "brightness".

  3. Ben Voigt says:

    @Alex: (0,0,255) is 100% saturation, 50% luminosity.  L=1.0 implies white no matter what H and S values are.

  4. Karellen says:

    Alternatively, RGB are all in the range [0, 255] (or [0.0, 1.0], depending on scaling), whereas H is in the range [0, 240) (or [0, 360) ) and SL are in the range [0, 240] (or [0.0, 1.0] ).

    en.wikipedia.org/.../Interval_(mathematics)

  5. Alex says:

    @Ben Sorry, you're right.  But the problem is that red (255,0,0), green (0,255,0) and blue (0,0,255) all have L=50%, even though to the eye green is much brighter than blue or red.

    If you are trying to write code that determines whether the given color is "dark" or "bright" so it can decide whether to display text on top of it in black or white, you need to use LAB color space.

  6. boogaloo says:

    @Alex: They shouldn't have L=50% because it _should_ be calculated like en.wikipedia.org/.../Relative_luminance anyway.

  7. Alice Rae says:

    Ha, I always was curious about this! This kind of post is what I love about your blog, Raymond--explanations behind all the little Windows quirks I've seen over the past 20 years.

  8. Alex says:

    @boogaloo Well, the "L" component (something labeled B for Brightness) in HSL is not relative luminance, it is just luminance with each color treated the same.

    This is why we have LAB and XYZ :)

  9. Jonathan says:

    Presumably, Hue was scaled to 240 so it would fit into 1 byte - it made a difference in the 1980's. The later-developed CSS HSL color standard uses the much more logical ([0..359], [0-100%], [0-100%]).

    It's probably a coincidence, but Ars Technica just published an article about the crazy CSS color names: arstechnica.com/.../tomato-versus-ff6347-the-tragicomic-history-of-css-color-names

  10. And then you get S-52, which stores all the colours in CIE 1931 XYZ format.  You have to apply matrix transformations to get something you can use for displaying on an RGB device.

  11. 12BitSlab says:

    Since I am color blind, my personal go to authority is one of 2 things:

    1) Crayola -- they've been doing it forever.

    2) Mrs. 12BitSlab.  Sometimes I will put some clothes on (sans matching colors) and she will look at me and say something along the lines of, "Are you going to wear that?"

  12. Antonio 'Grijan' says:

    @Alex: for those uses, a weighted average is enough. In the research done while developing the NTSC color television standard (which for compatibility reasons added a color subcarrier on top of a black and white signal, and thus needed to establish a correspondence between them), they decided to define Y (luminance) as 0.33*R + 0.55*G + 0.11*B (note that this assumes green is perceived brighter than red, and red than blue). and I find that a quite sensible choice. Next time, apply that formula to your RGB value, and compare to 128. If you need to make integer arithmetic, take into account that 0.11 = 1/9, so 0.55*G = 5 * (G / 9).

    Basing a luminance-correct HSL system on that formula is much more complicated, and maybe isn't worth the effort.

  13. Dan says:

    The nice thing about 240 is that it's the largest “highly composite number” that fits in a single byte.  Divisible by 2, 3, 4, 5, 6, 8, 10, 12, 15, 16, 20, 24, 30, 40, 48, 60, 80, and 120.

  14. Dave says:

    240, well, it's one brighter, isn't it? It's not 239. You see, most blokes, you know, will be displaying at 239. You're on 239 here, all the way up, all the way up, all the way up, you're on 239 on your colour picker. Where can you go from there? Where? Nowhere. Exactly. What we do is, if we need that extra push over the cliff, you know what we do? Put it up to 240.

  15. Falcon says:

    @Dave:

    So, why not just make 239 the top number and make that a little brighter?

  16. Yuri Khan says:

    @Antonio ‘Grijan’

    The comparison should be to somewhere around 186, because gamma.

    http://www.4p8.com/.../gamma.html

  17. Gabe says:

    Am I the only one who finds it amusing that the color picker has remained virtually unchanged since the 1980's? It even retains the anachronistic "Color|Solid" caption on the preview box from when dithering was the norm.

    And this quote from the MSDN page is precious: "The actual number of colors displayed is determined by the display driver. For example, a VGA driver displays 48 colors, and a monochrome display driver displays only 16."

    According to Wikipedia (en.wikipedia.org/.../Microsoft_Chart) Chart actually predates Windows, being the charting program to accompany Excel's DOS-based precursor, Multiplan.

  18. jk says:

    I'd always heard it as Hue, Saturation and Lightness

  19. ender says:

    @Falcon:

    Look up "This is Spinal Tap".

  20. laonianren says:

    @ender:

    Look up "This is Spinal Tap".

  21. DebugErr says:

    Thanks, that adds some logic to the color picker dialog... I never really liked that dialog anyway.

    I remember that up to some Windows version (I think I saw it in Windows 2000 the last time), if you had specific font / metric settings of the user interface, you could only enter 2 numbers into the textboxes, because the last didn't fit in anymore, and the textboxes were somehow not limited to 3 characters inside it, but more to the width of the entered text. It sounds so weird, I wouldn't believe it myself anymore, but I'm sure I tried to enter 255 every so often into the R, G or B fields, and only 25 was possible...

  22. Falcon says:

    @ender:

    My comment was a continuation of Dave's joke.

  23. DWalker says:

    Looking at some of those links:  Color is hard on computers.

  24. Jeff says:

    This made too much sense. I was expecting a more convoluted reason.

  25. Deltics says:

    @DWalker - yep.  Computers had it much easier back in the days of black & white.

  26. Steinar H. Gunderson says:

    DWalker: Color is hard, period.

    Currently the closest model we have to human color vision is CIECAM02. Look up the Wikipedia article and marvel at the complexity. :-)

  27. DWalker says:

    I loved Falcon's comment to Dave's comment!  

  28. mikeb says:

    Just as good was laonianren's comment to ender.

  29. Katie says:

    @Dan, the highly composite thing is what stuck out to me. If I had actually thought about the problem I would have decided divisibility by 6 was the key factor. But when I saw 240 my thought was basically "that number has a ton of factors - I bet it has to do with that" and went on to read the explanation.

  30. Andreas Rejbrand says:

    I have too found it somewhat strange/amusing that the Windows Colour Picker hasn't changed for ages.

  31. Aaron says:

    Am I allowed to say on this blog that the Mac color picker has always been far better than Windows'? The Windows one has barely changed since Windows 98 (I think the "Color|Solid" stuff was implemented later), while the Mac one, even in Mac OS 9, had a much nicer range of preset colors and a more logical HSL color selector.

    This is a problem Microsoft tends to have in all its software - most features are kept nicely polished from one version to the next, but some bits are just left to age ungracefully, retaining the same antiquated UI and limited options (and sometimes even bugs) version after version.

  32. Andreas Rejbrand says:

    @Aaron: As far as I know, the Windows Colour Picker hasn't changed at all since (at least) Windows 95. I don't know about Windows 3.1.

    [I think it dates back to Windows 3.1. But there's a fancy new color picker that nobody uses. -Raymond]
  33. ender says:

    [I think it dates back to Windows 3.1. But there's a fancy new color picker that nobody uses. -Raymond]

    Looks similar to the colour picker in Windows 10 for high contrast theme colours (which is pretty much completely useless, because it only lets you choose between around 20 predefined colours and doesn't even have an option for choosing a custom colour).

  34. BenTen says:

    @ender

    At least it follows Windows Ten theme in general: From bad to broken.

Comments are closed.

Skip to main content