Okay, Color Spaces
Colors⦠in⦠spaaaaaaace
What is a âcolor space?â
Well first you take some colors.
redyellowblue
And then you arrange them, however you like, into some kind of space:
The space has coordinates. In the little toy color space we've just defined, red is at , yellow is at , and blue is at . Thatâs a color space!
You might ask: what kind of color might we find at the origin: ? Right now, itâs undefined, but we could put anything there: black, gray, brown, heck â even hotpink if we wanted.
Which brings us to the first point: color spaces are all constructs. People just make them up! Useful ones are constructed in order to do useful things, but thereâs no, like, One True Fundamental Color Space.
(as handed down from Newton and Goethe).
When I was a kid, various art teachers taught me about The Color Wheel with its Three Primary Colors and its Three Secondary Colors and while that wheel did help me make greenish paint when the classroom only had yellow and blue, it also gave me some wrong ideas about color.
You see, just like the food pyramid, the RYB color wheel is made up. Itâs a conceptual model, invented by people, who invented it by arranging a set of things into an abstract, hierarchical geometry, as a problem-solving tool. The RYB color wheel was developed in order to give artists and eight-year-olds a (rough) way to (loosely) predict what might happen when they mixed certain pigments. But colors â like tastes, touches, and smells â donât have any kind of innate geometric relationship to each other. When we arrange colors around a wheel, or set them into any other space: we did that.
All of this is to say: color spaces canât really be ârightâ (or âwrong.â) They can only be useful.
CIE XYZ: a very useful color space
The toy color space that I constructed at the beginning of this post is useless. It doesn't help us do anything.
What might a useful color space do? Well, just like the RYB color wheel, maybe it could help us predict how different colors will mix.
And lo, in 1931, an international team of experts got together in England and laid out a color space that does exactly that1. They used science and math. They called themselves the International Commission on Illumination (aka le Commission Internationale de l'Ãclairage, aka the CIE), and they called their color space CIE XYZ.
Here are three colors plotted in CIE XYZ: a red, a green, and a blue.
The first thing you might notice is, it's 3D! Turns out, most useful color spaces have at least three dimensions, although in order to visualize various things, people will often flatten 3D spaces into 2D.
Now, CIE XYZ isnât limited to three colors. In fact, it contains all of the colors2.
So letâs fill our visualization out a bit. The red, green, and blue that that I plotted above happen to be the three primary colors that define the P3 color gamut. Hereâs the rest of the P3 gamut, plotted in CIE XYZ:
Sweep the âcross section â slider to get a sense of how colors are distributed in the solidâs interior.
Unlike our toy color space, which defined three discrete colors, CIE XYZ is continuous. I could pick any point in the CIE XYZ space and get a unique color. Thatâs cool, but itâs still not useful. Whatâs useful about CIE XYZ is the way it helps people solve the related problems of predicting mixes and creating matches of arbitrary colors.
CIE XYZ is built out of three functions. Those functions take some wavelength of light as input, and give , , and as output. This means you can sample some real-world light with a spectrometer, do some math, and get an , a , and a , which locate that lightâs color within the CIE XYZ space.
Letâs say Iâve got a pair of spotlights:
color(xyz-d65 0.40 0.25 0.05)(red)color(xyz-d65 0.30 0.50 0.10)(green)
What color will I see if I shine them both, full-blast, at the same spot? CIE XYZ lets me predict the result. The space has been structured in just such a way that all I have to do is add up the s, s, and s:
color(xyz-d65 0.70 0.75 0.15) (yellow!)
By slicing a lilâ parallelogram out of the CIE XYZ space â with one corner at black, two corners at the locations of our two spotlights, and the last corner at the location of their full-blast mix â I can predict what any combination of these two lights, at any intensity level, is going to look like.
Left: simulated spotlights. Right: the white circle shows the location of the mixed color within CIE XYZ.
With a little matrix algebra, I can go the other way: CIE XYZ lets me take a color and figure out whether-and-how I can replicate it by mixing another set of colored lights. This is extremely useful! Once I know the CIE XYZ coordinates of the subpixels that make up a physical pixel on a display, I can calculate how to mix them to precisely replicate all kinds of colors. With CIE XYZ, I can dial up, say, color(xyz-d65 0.12 0.07 0.31) on wildly different displays and get consistent results.
CIE XYZ turns color mixing problems and color matching problems into math problems. This has proven so useful that every modern color space is defined in terms of CIE XYZ. When we say that a system is âcolor managedâ what weâre saying is: itâs built on top of CIE XYZ.
So! CIE XYZ! Itâs useful! But itâs not useful for everything.
Perceptual uniformity (is hard)
Predicting mixes was one thing I learned in art class. Another? Creating even gradients.
When youâre learning a new medium or technique â crosshatching, watercolors, whatever â this is the 101 lesson; itâs like playing scales in music. Practicing gradients gives you a facility with the tools and teaches you how to judge and create even intervals of color.
CIE XYZ is very bad at this. If we draw a straight line through the CIE XYZ space and mark that line at evenly-spaced intervals, sampling at each mark, we get bad gradients. Like this lopsided grayscale:
CIE XYZ gradient Something better, for comparison
CIE XYZ hangs out in the light-gray zone forever, and then gets very dark very fast â that last step is a doozy.
All CIE XYZ transitions from lighter colors to darker colors suffer from this problem3.
Yellow yellow yellow yellow, yellowish-gray⦠mauve⦠purple! This one has the same number of yellows and purples, and puts the middle color in the middle.
Transitions between light colors and dark colors arenât the only problem. Gradients between different hues can look lopsided, too.4.
I can barely tell the difference between the first two swatches. But things are getting green quickly, over on the right. Better.
My favorite perceptual problem with CIE XYZ is that transitions between blue and gray get weirdly purple in the middle:
True blue, all the way through.
Color nerds call color spaces that are good at creating even gradients âperceptually uniform.â Meaning, the distance between any two colors in the space corresponds to âhow differentâ they look, to people. There are all sorts of reasons folks might want a color space like this.
- Maybe theyâre making a data visualization and want to use color differences to communicate value differences.
- Maybe theyâre making image-editing software, and want modifications to feel consistent and intuitive.5
- Maybe theyâre storing colors digitally, and want to store as many perceptually-different colors in as few bits as possible.
- Maybe theyâre trying to measure color contrast in order to ensure accessibility.
- Maybe theyâre trying to render a nice, even-looking gradient as a design element.
For these tasks (and more!), a perceptually-uniform color space is the right tool for the job.
As discussed, CIE XYZ ainât it.
(sRGB, the webâs dominant, default color space, was constructed in order to model a typical 1990s cathode-ray tube display; sRGB also ainât it.6)
The first attempt at âitâ (a perceptually-uniform color space) was made by Albert Munsell, who described his space in 1905 (charmingly, as a âCOLOR TREEâ) and published an âAtlasâ to it in 1913.
The central âtrunkâ of Munsellâs TREE goes from black at the bottom, through grey in the middle, to white at the top. The middle expands outwards into a rainbow of âbranchesâ, with each angle around the trunk representing a particular hue. Each branch starts off desaturated near the middle, and gets more and more saturated the further out it goes.
Left: A wood engraving illustrating Munsellâs COLOR TREE from A Grammar of Color by T. M. Cleland, 1921. Right: An excellent cutaway visualization of the Munsell Renotation Data by the stellar Wikipedian, Mike Horvath, aka Datumizer
Whereas every color theorist before Albert Munsell (and many, after him) worked from the âframe inâ, trying to cram all visible colors into a regular shape like a wheel or a sphere or whatever, Munsell instead worked from the âcontent outâ, trying to create even intervals between adjacent colors and letting each âbranchâ extend as far as it could before he reached some limit of saturation. The resulting solid resembles a lumpy, lopsided spinning top.
Albertâs COLOR TREE was immediately recognized as useful, and is in fact still used. But as time passed, problems accumulated:
- It was based on his own personal judgements rather than scientific experiments, and it showed.
- (Just like our toy color space!) the COLOR TREE is discrete, and only specifies the positions of a few hundred individual colors.
- Those colors didnât cover anything close to the range of colors that people can actually see.
In the decades that followed, people tried to solve all of these problems, both iterating on Munsellâs tree and creating wholly new continuous color spaces that attempted to be perceptually uniform. Arguably, the most significant of those spaces was constructed by the CIE, in 1976: CIELAB. (Ever heard of âLab colorâ? This is that.)
CIELAB is a relatively simple mathematical transform of CIE XYZ, making it easy to implement in âcolor managedâ digital contexts. But â tragically! â CIELAB isnât exactly perceptually uniform. Worse, the more experiments people did, the clearer it became that no three-dimensional space could ever be perceptually uniform; three dimensions just cannot capture all of the weird and wonderful ways that our eyes and brains process color comparisons. As anyone who has entered a Turrell or debated The Dress can tell you, color perception is wild. When trying to predict how people are going to perceive the difference between two colors, we need to account for way more than three variables. For instance:
- How large are the color samples? Where are they in the subjectâs field of vision?
- How long have they been there? What other colors were there recently?
- Crucially, what other colors surround the samples?
- Whatâs the ambient background lighting like?
(Iâm not even going to mention the ways in which we âreadâ scenes within semantic and cultural contexts, which also matter.)
So, after 1976, people started developing more-and-more complicated models that attempted to account for more-and-more of this complexity. Weâve spent fifty years coming up with these things. Many of the resulting color models are considered too complex for most practical applications, and yet none of them is considered perfect.
I am fascinated that the CIE knocked predicting color mixes and matches out of the park in 1931, and yet here we are, almost a hundred years later, still trying to solve the problem of predicting color differences. Our mastery of mixing and matching makes us very good at capturing and replicating colors. But, because we canât predict differences well, weâre still bad at automating all sorts of other color tasks, which remain as much art as science.
One thing thatâs absolutely clear is that the problem of perceptual uniformity is never going to be solved with a plain-Jane three-dimensional color space. But! The entire universe of digital imaging is rooted in such spaces, because itâs all built on top of CIE XYZ.
So â what is someone who wants a perceptually-uniform space in a digital context supposed to do these days?
Oklab: itâs okay!
Until a few years ago, the best tool for these sorts of jobs was still CIELAB. So I was excited when CIELAB-for-the-web was first proposed in 2016. And then I waited for five years, until it finally shipped.
While I was waiting, in December of 2020, a guy named Björn Ottosson wrote a blog post. In it, he introduced a brand-new three-dimensional color space that heâd been working on: Oklab.
In an over-simplified nutshell, hereâs how Björn came up with Oklab:
- He picked a couple of best-in-class color models7.
- After choosing a set of values representing ânormalâ viewing conditions, he used those models to generate a set of color comparison data.
- He transformed CIE XYZ in a mathematically clean/easy way to approximately fit all of that color comparison data pretty well.
Et voila: Oklab. Hereâs what it looks like:
The P3 gamut, plotted in the Oklab color space.
Is it perfect? No, it is not. But is it mathematically and computationally simple? Yes! And does it perform better at most tasks requiring perceptual uniformity than all of the other simple, three-dimensional color spaces? Sure seems like it!
What happened next was astonishing: the web platform rapidly adopted Oklab. Oklab went from a blog post to shipping in Safari in fifteen months! Wild!
So, Oklab: if you want perceptual ~uniformity, itâll do.
OKLCH, because Munsell was a good API designer
What do Oklabâs , , and parameters actually mean?
- is lightness. This represents how light or dark a color looks. goes from zero to one.
- is âgreeness-to-rednessâ with gray at zero. Itâs theoretically unbounded but in practice it goes from around -0.4 to +0.4.
- is âblueness-to-yellownessâ with gray at zero. Same-same with the practical approximate -0.4 to +0.4 range.
So, in Oklab, blueviolet is oklab(53.38% 0.1303 -0.2137): medium lightness, somewhat red, and rather blue.
Are you thinking what I'm thinking? and are weird.
Munsellâs COLOR TREE has much nicer dimensions:
- Lightness: height up the tree; black to white.
- Hue: angle around the trunk; just like the color wheels of my youth.
- Chroma: how far away from the trunk are we? Gray in the middle and more saturated the further away we get.
These three dimensions seem to express ways that our brains actually process color. When comparing one color to another on the same branch of Munsellâs COLOR TREE, it feels like only one thing has changed: chroma. Likewise when we go up and down the tree, or around it â both lightness and hue feel like independent variables. Whereas when we change, say, the of an Oklab color, it feels like weâre changing two things â both the hue and the chroma â simultaneously. Itâs not easy to predict how changing or is going to look.
Thankfully â turns out! â Oklab was explicitly designed so that movement up/down, in/out, and around the axis works exactly like navigating Munsellâs COLOR TREE. Each type of movement changes just one, psychologically-independent thing: the lightness, chroma, or hue of the color. In order to navigate Oklab like this, we need to use a polar coordinate system, instead of a rectangular one. When we do, we refer to the space by another name: OKLCH8.
Same same;
oklab(53.38% 0.1303 -0.2137) =
oklch(53.38% 0.2503 301.4deg).
I should note that OKLCH was not the first color space to adopt Munsellâs lightness-chroma-hue âAPIâ;Â even CIELAB had a polar version that worked like this, called LCH. But OKLCH does appear to be one of the best.
Both OKLCH and Oklab have their uses. Gradients in polar spaces work differently than gradients in rectangular spaces. Theyâre not better or worse, mind you â just different.
In a rectangular space, a gradient between two colors that lie on opposite sides of the space gets gray in the middle:
In a polar space, instead of drawing a straight line through the space to get from one color to the other, we orbit the origin, creating a half-rainbow of evenly-separated hues.
Some tasks (like measuring color difference) are simpler in rectangular spaces. But whenever we want to change the hue or chroma of a color independently â say, when we want to turn a colorâs saturation up a notch, or theme and scheme with code â only a perceptually ~uniform, polar space will do. Right now, on the web: that means OKLCH.
So!
What have we learned?
- Color spaces are constructs, which arrange colors into some coordinate-based space.
- Colors donât have any kind of innate spatial relationship to each other, but arranging them in various ways can be useful.
- CIE XYZ is an extremely useful color space, because it turns color mixing problems and color matching problems into math problems.
- All âcolor managedâ digital imaging is based on CIE XYZ.
- Measuring how weâll perceive the difference between two colors is a whole other kettle of fish; predicting differences remains an unsolved problem.
- Solving that problem â by constructing a model with perfect âperceptual uniformityâ â is going to require more than three variables, but oops! We built all digital imaging on top of CIE XYZ, a three-dimensional space.
- Oklab tries to resolve this by making many assumptions and simplifications, in order to model everything weâve learned about perceptual uniformity in a simple three-dimensional space.
- Oklab is pretty good!
- People tend to think about color in terms of three variables: lightness, chroma, and hue.
- Oklab does a good job of isolating these variables, but in order to use them, we have to navigate it using polar coordinates instead of rectangular ones. When we navigate Oklab this way, we call it OKLCH.
Time to play
Enough reading! Go! Explore!
- Evil Martiansâ OKLCH color picker is fantastic.
- I couldnât have written this post without Color.js. Itâs doing all of the color math in the interactive visualizations, and I had multiple color notebooks open at all times, while writing.
- Speaking of the interactive illustrations, if you want to visualize other gamuts in other color spaces, the ColorAide Interactive 3D Color Space Models demo by Isaac Muse and Hueplot by Alexey Ardov have you covered.
- For a different entry point into understanding color spaces in general and CIE XYZ in particular, check out Bartosz Ciechanowskiâs Color Spaces. Itâs chock full of interactives.
- I know I linked to it earlier, but Björn Ottossonâs original Oklab blog post is very good.
Okay, bye! ð