Goodnight Wiki / Color Science

Color Science

Most software gets color wrong, and for a reason that's almost too embarrassing to admit: we're still doing math in a color space designed for CRT monitors in the 1990s. The nonlinear transfer function baked into sRGB was a practical hack to match the voltage-brightness curve of cathode ray tubes, and it accidentally became the default for nearly all digital color processing. Blend green and magenta in sRGB and you get something dark and bluish. Blend them in linear light and you get something bright but hue-shifted. Neither matches human perception. We've known this for decades and mostly haven't fixed it.

Why sRGB Is Wrong (and Right)

Bjorn Ottosson's diagnosis is clean and damning: sRGB conflates reproduction of color with processing of color.1 The encoding was designed so that values could be sent directly to a CRT's electron gun, and modern displays maintain backward compatibility with it. For that purpose it works fine. The happy accident is that sRGB's gamma curve roughly correlates with human brightness perception, so 8-bit sRGB images look decent despite the limited precision. A linear encoding would need more bits to avoid banding in darks.

But when you do operations in sRGB — blending, blurring, resizing, alpha compositing — you're computing in a space that models neither physics nor perception. Linear blending of sRGB values darkens saturated colors because the nonlinear transfer function compresses high values. Blending white and blue shifts toward purple. These aren't subtle artifacts; they're visible in every gradient and every transparent layer on every website.

The fix for physics-based operations is simple: convert to linear before computing, convert back after. Every 3D renderer does this already — path tracing operates in linear space by necessity, because light transport equations assume linear superposition. The fact that Photoshop blends in sRGB by default, and CSS gradients render in sRGB by default, is a legacy bug that persists because backward compatibility matters more than correctness to the people who ship software.

The Perceptual Problem

Physics-correct is not perceptually correct. Linear blending gets the light transport right but doesn't preserve perceived hue, because human color vision is wildly nonlinear in ways that have nothing to do with display technology. Additive mixing of deep blue and white shifts toward purple — this is a real perceptual phenomenon, not a software bug. Red and green at equal physical intensity appear very different in brightness because our cone sensitivities are uneven.

This is where perceptual color spaces come in, and where things get genuinely interesting. The old standard CIELAB (1976) does a reasonable job of predicting lightness but has terrible hue linearity, especially in blue. Walk through CIELAB's gamut and "constant hue" curves through blue visibly bend toward purple. The IPT color space (1998) fixed hue linearity by optimizing against the Ebner-Fairchild experimental dataset, but its lightness predictions are off.

Bjorn Ottosson's Oklab (2020) is basically IPT done carefully: same simple architecture (3x3 matrix, cube root, 3x3 matrix) but with both matrices optimized simultaneously for hue linearity, lightness prediction, and chroma accuracy.2 Raph Levien's interactive review confirmed that Oklab's hue constancy is excellent and its lightness tracks CIELAB much more closely than IPT does. His scatterplots comparing lightness axes across color spaces are the most convincing evidence I've seen — Oklab correlates tightly with CIELAB L*, while IPT has substantial scatter.

Levien makes a subtle point that I think is underappreciated: the ideal transfer function depends on viewing conditions, and no single gamma curve is right for all situations.2 In standard dynamic range you can assume the viewer has adapted to a particular brightness. In HDR, you can't — the Barten model accounts for all possible adaptation states, and the SMPTE ST 2084 curve is the compromise. This is why ICtCp, the HDR color space, looks terrible for standard-range gradients: it spends too many code values in near-black regions that only matter under dark adaptation. A color space that's optimal for Netflix playback in a dark room is wrong for a web page viewed in daylight.

Color as Perception, Not Physics

The deepest weirdness in color science isn't about color spaces or transfer functions — it's that color perception is inherently constructed, and non-Euclidean to boot. Levien puts it memorably: fitting a perceptual color space is like flattening an orange peel. The ratio of distinguishable steps around a hue circle to those across through gray is greater than Euclidean geometry allows. No 3D coordinate system can make all perceptual distances equal. Every perceptual color space is a map projection with its own distortions.2

James Gurney's investigation of moonlight illustrates this from the opposite direction — through the physiology of low-light vision. Moonlight is spectrally almost identical to sunlight (slightly redder, actually), yet we see it as blue.3 This isn't a property of the light. It's a consequence of rod-cone interactions in the retina. At moonlight brightness levels, the rod cells — which are color-blind but sensitive to green wavelengths — are doing most of the work. Khan and Pattanaik hypothesized that rod signals leak through synaptic bridges into the blue-sensitive S-cone pathway, creating a phantom blue percept. The Purkinje shift compounds this: as light dims, peak sensitivity shifts from yellow-green (photopic, cone-driven) to blue-green (scotopic, rod-driven), making reds look black and greens look bright.

Every artist who has painted a moonlit scene is, whether they know it or not, translating a rod experience into a cone experience — creating something that looks "right" under gallery lighting for a scene where color receptors were barely functioning. Turner painted his nocturnes in muted grays with warm glows. Whistler used saturated blue-green. Maxfield Parrish painted moonlight with vivid reds and yellows that he almost certainly could not have seen. They're all "wrong" in different ways, and they're all achieving something a physically correct renderer cannot: evoking the feeling of moonlight, which is fundamentally a neurological state, not a spectral distribution.

This has practical implications for rendering. Any system that claims to handle nighttime scenes with physical accuracy is missing the point unless it also models the visual system's adaptation. The Purkinje shift alone means that a path-traced night scene viewed on a bright monitor will look wrong — the viewer's cones are fully engaged, but the scene should look like a rod-dominated experience. This is why film colorists grade night scenes blue: they're simulating a perceptual phenomenon that the physics-based pipeline can't produce on its own.

What Good Color Looks Like

The state of practical color is improving, even if slowly. CSS now supports oklch() and oklab() natively, letting web developers specify gradients and color manipulations in a perceptually uniform space. JPEG XL's XYB color space uses a cube-root-with-offset transfer function — GPU-friendly, smooth derivatives, perceptually reasonable — which suggests that the next generation of image codecs may finally move past sRGB processing.

But I think the most important insight from all this is that "correct" color has at least three meanings that don't coincide: physically correct (linear light transport), perceptually correct (Oklab-like uniform spaces), and aesthetically correct (the artist's judgment about what conveys the right feeling). A rendering pipeline needs all three at different stages. Physics for light transport. Perception for gradients, compositing, and color manipulation. Aesthetics for the final image. Collapsing all three into sRGB was always wrong — it just took us thirty years to care enough to fix it.

The Eye as Color Instrument

The handprint color science resource makes a point that rendering engineers routinely forget: the organ of vision is not the eye but the brain. The eye is an outpost of brain neurons that performs initial processing — luminance, contrast, movement — but color as we experience it is a "complex judgment experienced as a sensation." This isn't just philosophy; it has direct engineering consequences.4

The visible spectrum (effectively 400–700nm under normal conditions, though 380–900nm is possible under extreme brightness or dark adaptation) is bounded differently at each end and for different reasons. The infrared cutoff is gradual, limited by declining cone sensitivity. The ultraviolet cutoff is sharper — partly atmospheric filtering (ozone blocks below 320nm), partly the yellow tint of the adult lens that blocks below 500nm from reaching the retina. People who have had their lenses removed (aphakia) can see deep into the UV.

Most critically, light has no color. A monochromatic 600nm photon creates the sensation of "orange" in one context and can appear red, brown, or gray in another. Spectral colors in diagrams — including the chromaticity diagram that underpins all of colorimetry — are symbols for wavelengths, not representations of perception. This gap between spectral distribution and perceived color is where all the interesting problems in color science live, and it's why a perceptually uniform space like Oklab can never be derived from physics alone.4

Footnotes

  1. How software gets color wrong by Bjorn Ottosson — source

  2. An interactive review of Oklab by Raph Levien — source 2 3

  3. Is Moonlight Blue? by James Gurney — source

  4. Light and the Eye by handprint.com — source 2

Open in stacked reader →