Hacker News new | ask | show | jobs
by justinpombrio 3385 days ago
If you want to do something meaningful with colors, don't use RGB, and don't use HSL (which is based on RGB). These spaces are problematic. For instance, pure blue and pure green in RGB space have very different lightness. Here's a picture of the region of colors covered by RGB:

https://en.wikipedia.org/wiki/HSL_and_HSV#/media/File:Srgb-i...

If RGB space corresponded to what our eyes saw, that would be a perfect hexagon. It isn't. It's warped, and the warping isn't subtle.

Use CIELAB. CIELAB is designed to match what our eyes see.

https://en.wikipedia.org/wiki/Lab_color_space

In a little more detail, distances in the CIELAB colorspace approximate perceptual distance (how different two colors look). Distances in the RGB colorspace do not.

7 comments

RGB and HSL are related, but I wouldn't say HSL is based on RGB.

From a design point-of-view RGB actually has some problems, as it is difficult to manipulate in a reliable manner. However, from a data point-of-view if is useful because it can scale up or down depending on how much room you have to store information. Also, it relates to the way TV and many video standards transmit information.

In HSL, you have saturation and brighness, which can scale nicely depending on how much information you have, but hue is a a position on a circle, which is a different type of measurement.

Also, how exactly is lab color useful in web programming? How do you support it in CSS or HTML?

“HSL” is a trivial transformation of RGB. It’s what you get when you prop an RGB cube up on one corner, squish 6 of the other corners into the same plane, and then inflate it until it fills a cylinder shape. (Note that none of these steps make any reference to human perception.) Here’s my 2010 diagram showing that visually https://en.wikipedia.org/wiki/File:Hsl-and-hsv.svg

> Also, how exactly is lab color useful in web programming? How do you support it in CSS or HTML?

Implementing CIELAB in Javascript is straightforward. https://github.com/jrus/chromatist/blob/master/src/cielab.co...

You could alternately use a model like CIECAM02, but that gets a whole lot more complicated. https://github.com/jrus/chromatist/blob/master/src/ciecam.co...

I just wanted to say that the diagram of the transformation from RGB to the different color models is absolutely beautiful as well as informative. When I have a free day or two I am going to have to put together an animation for it where you can track a given color through the process. My favorite class in university was about color models, all the way from CIE 1931 to the various transformations on it to match human perception and driven by anatomical insights about the human eye. It's fascinating!
Just because something can be translated into something else doesn't mean that it is "based" on that thing.

Would you say celsius is "based" on fahrenheit? Or the other way around?

Is yiddish based on english?

Both RGB and HSL are based on the physics of color and perception. Just because it is trivial to transform one to the other doesn't mean anything.

> RGB and HSL are related, but I wouldn't say HSL is based on RGB.

HSL is explicitly defined as a transformation from RGB space, so each RGB triangle has a corresponding HSL space.

RGB is absolute garbage for doing anything other than displaying pixels. It's so bad, that the (piecewise) linear transformation to HSL is perceived by many to be good, when it's still equally terrible.

The main problem is that not all wavelengths of light contribute equally to perceived brightness in our color vision. Any color space that puts red, green, and blue on equal footing for a transformation is going to produce bad results. If you really want a linear transformation from RGB, you'll want to use something like luma instead (Y = .21R + .72G + .07B, according to Wikipedia)--you'll go from bad to acceptable, as luma is only a few percent off from the accurate results.

If you want to do color interpolation, you'll absolutely want to use CIELAB, which was explicitly designed for this purpose. Any good toolkit should provide CIELAB--d3 does, for example. If not, it's not hard to find snippets to do the conversion for you on places like stack overflow.

Note that “luma” (Y’, to avoid confusion please don’t call this Y) is based on a gamma-adjusted RGB space, and is therefore is not accurate for saturated colors.

To get a reasonably accurate correlate of lightness perception, you need to take your linear combination in a linear RGB space to get luminance (Y), and then afterward apply a non-linear correction to find lightness.

Plugging my side project a Munsell to sRGB converter.

https://github.com/germ/munsellScript/blob/master/README.md

It's useful because it gives a manipulatable version of the colour (lighten the value, shift the hue, etc) and then wing it back to hex. Integrates with keybinds and clipboard integration. Highlight, keybind, manipulate, keybind. Repeat as needed. There's a demo in the readme.

Amazing! I've been looking for a munsell colour space converter for weeks for my branding work. Thanks for posting this.
No worries, give her some use :)
See also http://www.hsluv.org for a perceptually uniform colour space based on CIELUV.
I'm not convinced. Picking one fresh-looking color, and sliding the "H" slider, I'm running into non-fresh (dull) looking colors. Or is that somehow supposed to happen?
In a sense, yes. The true "freshness" of a color is shown on the color picker as the distance from the center of the circle. This is equivalent to the chroma component of CIELUV, the color space that HSLuv is based on. The problem with that component is that the maximum chroma is different for different hues, so if you were to move the hue slider while keeping true chroma static, you would run into impossible colors (such as dark saturated yellow).

This is a fundamental trade-off. If you need true saturation, you can use CIELUV and deal with impossible colors. If you need a color space that doesn't have gaps, use HSLuv and deal with a suboptimal saturation. The strongest claim I can make about HSLuv's usefulness is that it is a better HSL.

Hope that helps.

EDIT: You gave an idea that it would be useful to show another slider on the picker called "C", showing the chroma component with gaps.

> You gave an idea that it would be useful to show another slider on the picker called "C", showing the chroma component with gaps.

Yes, that would be nice. But as I understand it, fixing C would cause the H slider to show gaps too (?) Also, if you show sliders for H, S, L and C, then I think it would not be clear from the interface which sliders are fixed.

Good points. Hmm. Needs more thought :)
What sort of computer are you viewing it on? On my mac and ipad the colours work very predictably, but on my work Linux box (which has absolutely no colour calibration) I see huge changes round the red and purple areas of the h slider.
I'm on Linux.
The article is about subjective design choices. Any color space is fine for that as it's only used to pick colors.

Generally, though, what to use working with colors greatly depends on what you are doing and I'm pretty sure most of the time where you think you need CIELAB, HSL with luma for Lightness would do just fine, heck, even jpeg's native YCbCr or RGB might do. It's just not a good advice to avoid RGB or HSL simply because it doesn't work well on rather rare occasions.

Well, for the most part, the color space we're accessing is the exact same, so you can always use whatever space you please. The biggest problem with things like RGB is that color selection ends up turning into a horrible mess of seemingly unrelated magic numbers.
Here's XSLT code that transforms RGB colour space into LCH (and vice versa), which is then used to colourise an arbitrary number of visually distinct and harmonious pie chart wedges:

http://stackoverflow.com/a/25481023/59087

The algorithm is straightforward, albeit verbose.

I'll add my shot at converting RGB to CIE (XY + brightness) I wrote for my command line controller for Hue lights:

https://github.com/TeMPOraL/hju/blob/39b0c2c27f5f076a93b360d...

(code in Common Lisp)

Hue documentation (available after registering with them) also has example algorithm in (AFAIR) Objective-C.

EDIT: replaced Github link with commit permalink, in case I change the file in the future.

The issue with CIELAB is that a* and b* are poor fits for most peoples' mental models of color. HCL still gives perceptual uniformity while also giving the knobs most people are interested in turning.
I built a CIELAB / HCL color-scheme designer prototype, because I wasn't able to find anything comparable. RGB-Based color pickers often make it easy to choose ugly colors. Even though it's unfinished, I think it's already useful. It also visualizes the CIEDE2000 perceived color-distance as a graph in realtime: https://fdietze.github.io/pigment