Color Math: Inside Photoshop Gradients
Before we begin
There’s a vast amount of writing on “how color works,” by far more qualified people than me. In this article, we’ll limit ourselves to just the knowledge needed to follow this series.
If you want to go deeper, I highly recommend these resources:
- Charles Poynton — imaging and color scientist
- Björn Ottosson — software engineer who invented the math behind the Oklab color space
Throughout the article, I’ll include links — mostly to Wikipedia — for those who want to explore further.
Color is harder than it looks
Take two colors and build a transition between them. The simplest approach is linear interpolation: split into R, G, B and compute an intermediate value for each channel.
Where t ∈ [0, 1] is the position in the transition: t = 0 is the start color, t = 1 is the end.
Seems straightforward? Here are four interpolation methods that Photoshop offers for the exact same gradient:
All four gradients look noticeably different. You might assume it’s because of different interpolation formulas — but the main reason is something else: the interpolation happens in different color spaces.
Gamma, sRGB, and optical illusions
sRGB — a color space “for the eyes”
When we pick a color in Photoshop, set RGB in CSS, or save a PNG — we’re working in sRGB.
It’s a color encoding standard that defines how numbers (R, G, B ∈ [0, 255]) map to visible colors.
Here’s a riddle for you: Why is the value 128 not half the brightness of 255?
The answer lies in the sensitivity of human vision. Our eyes are far more sensitive to dark tones than to light ones. In other words, you can distinguish more dark shades from each other than light shades of the same range.
This leads us to the answer — 128 is not half the brightness because the relationship is intentionally nonlinear, reflecting the sensitivity of human vision to avoid banding (colors of different brightness merge into one and form a “flat step”).
sRGB encodes values nonlinearly, allocating more brightness levels to dark tones.
But this raises even more questions: if sRGB encodes and compresses, what exactly does it encode and what does it compress?
Linear-light — the physical space of light
Linear-light RGB is the uncompressed physical light space, where each channel is expressed as a value from 0 to 1.
Here, 0.5 is exactly half the physical brightness.
This is what sRGB compresses using gamma correction — a transfer function.
Linear RGB to sRGB conversion
The gamma function is applied per-channel and is fully reversible, allowing conversion between the two color spaces.
sRGB to Linear RGB conversion
Why this matters for gradients
The “Classic” method in Photoshop interpolates in sRGB. The Linear method interpolates in linear-light RGB. Same interpolation formula, same RGB channels, but visually different results:
- In sRGB, the midpoint (128, 128, 128) → brightness ≈ 21%.
- In linear-light, the midpoint (0.5, 0.5, 0.5) → sRGB ≈ (184, 184, 184) → brightness = 50%.
You might notice that sRGB interpolation looks “uniform” — and that’s precisely because of what we described above: your eyes are far more sensitive to dark tones than light ones.
Oklab — a perceptual space
Neither sRGB nor linear RGB are perceptually uniform. The same numerical distance between two colors can be perceived as large or small, depending on hue and brightness.
In 2020, Björn Ottosson developed the Oklab color space with three components:
- L — lightness,
- a — green-to-red axis,
- b — blue-to-yellow axis.
Oklab’s main advantage is that interpolation in this space is close to perceptually uniform, and intuitively feels more accurate and true to life.
The examples clearly show that sRGB interpolation looks “muddy” at transition boundaries, where Oklab produces vibrant, saturated colors.
Mathematically, converting between sRGB and Oklab is more involved, as it requires two intermediate color spaces: linear RGB (which we covered above) and LMS.
LMS describes the response of three types of color receptors in the eye (cones in the retina):
- L — Long wavelength (red, peak ~564 nm)
- M — Medium wavelength (green, peak ~534 nm)
- S — Short wavelength (blue, peak ~420 nm)
Oklab builds its color space starting from how the eye physically perceives color. The cube root in the conversion formulas (see below) models the nonlinear receptor response — it’s analogous to gamma, but for the biological system.
sRGB to Oklab conversion
-
sRGB → linear RGB (formula above)
-
linear RGB → LMS
- Cube root
- LMS’ → Oklab:
Oklab to sRGB conversion
- Oklab → LMS
- Cube
- LMS → linear RGB
- linear RGB → sRGB (formula above)
Cubic curves and smooth transitions
We’ve figured out which space to interpolate in. Now let’s figure out how — what shape the transition curve can take.
So far, we’ve been looking at linear interpolation — a straight line from V0 to V1. At the halfway point (t = 0.5), we get exactly the average of the two values. No bends, no surprises.
In practice, gradients use a blend of linear interpolation and easing functions. And as easing functions, cubic curves are used. We’ll mainly be interested in the Hermite cubic spline and the Bézier cubic curve.
Both Hermite and Bézier describe the same math — constructing S-shaped curves. They differ only in parameterization and how the computation is done.
The Hermite cubic spline is defined by endpoint values V0, V1 and tangents T0, T1. The tangent controls the speed and direction at which the curve enters or leaves a point.
- Large tangent -> steep entry/exit
- Zero -> horizontal
- Negative (with positive ΔV) -> the curve initially goes “the wrong way.”
The contribution of each component can be written as a building block (basis function):
The final interpolation formula is the sum of the basis functions multiplied by the curve’s values:
Where do tangents come from
The Hermite formula takes four parameters: endpoint values (V0, V1) and tangents (T0, T1). Values are the colors of our color stops — straightforward. But the tangents need to come from somewhere.
For a two-stop gradient there’s a single segment, and both stops are endpoints. An endpoint stop has a neighbor on only one side, so the tangent is determined by that single segment — the curve smoothly rises (or falls) from V0 to V1:
With three or more stops, interior stops appear — those between the first and last. Each interior stop has two neighboring segments: the left one (from the previous stop) and the right one (to the next). The tangent at that point must account for both.
Some interpolation methods use the Catmull-Rom tangent formula — the average direction between the left and right segments:
If the red channel was rising on the left segment (100 → 200) and continues rising on the right (200 → 250) — the tangent is positive, and the curve passes smoothly through the stop. If it was rising on the left (100 → 200) but falls on the right (200 → 50) — the tangent is close to zero, and the curve slows down and reverses.
Concordant, discordant, and overshoot
For each channel at each interior stop, the question arises: which way does the tangent point relative to the next segment?
Concordant: the tangent points in the same direction as the segment. The channel was rising and continues to rise, or was falling and continues to fall. The curve passes smoothly through the stop without exceeding the values at its endpoints.
Discordant: the tangent points in the opposite direction from the segment. The channel was rising but now falls — yet the tangent’s momentum keeps pulling it up. The curve is forced to go “the wrong way” first, then reverse. This overshoot means the curve exceeds the boundary values at the segment’s endpoints.
Flat: the channel doesn’t change across the segment (ΔV ≈ 0), but the tangent is nonzero because the neighboring segment has a slope. The curve “bulges” above or below the flat value.
The chart below shows three Hermite curves on a single segment. Gray lines mark the endpoint value boundaries:
Overshoot isn’t a bug — it’s a mathematical property of cubic curves with Catmull-Rom tangents. Different interpolation methods in Photoshop handle overshoot in different ways — and this is one of the key differences between them.
Bézier cubic curves
Beyond Hermite, cubic curves can also be defined through control points — these are Bézier curves. Instead of endpoint values and tangents, there are four control points (P0, P1, P2, P3). The curve passes through the first and last points, while the two middle ones “pull” it toward them, shaping the bend.
Any Bézier curve can be converted to an equivalent Hermite spline and vice versa — it’s the same math, just written differently. We’ll cover Bézier in detail in the article on the Smooth method — the only Photoshop method that uses this form.
Midpoint as center of gravity
Between every two neighboring stops in Photoshop, there’s a small diamond — the midpoint. By default, it sits in the middle (50%), but you can drag it closer to either stop.
The midpoint shifts the gradient’s center of gravity, making it pass through the segment’s central color faster (values < 50%) or slower (values > 50%). The start and end colors of the segment stay the same — only its center shifts, the point where the main transition happens.
- Midpoint 50% — everything is smooth, the color midpoint is at the center of the segment.
- Midpoint 5% — by just 5% of the way, the color is nearly halfway from V0 to V1. The transition happens rapidly at the start, and the remaining 95% gently coasts to V1.
- Midpoint 95% — the opposite. Nearly the entire segment gently builds toward the transition, then snaps to V1.
Technically, this is implemented by remapping the pixel’s position within the segment:
u∈ [0, 1]— normalized pixel position within the segmentm∈ [0, 1]— midpoint positionφ∈ [0, 1]— remapped position for interpolation.
The midpoint remapping is always applied before interpolation — both cubic and linear. Hermite interpolation and Bézier work with the remapped position φ(u), not the original u. That’s why the midpoint affects all interpolation methods equally.
The gradient pipeline
Let’s sum up. Every interpolation method in Photoshop goes through the same stages:
- Convert stops to the interpolation color space
- Compute tangents
- Cubic interpolation with midpoint adjustment
- Post-processing (overshoot handling)
- Convert back to sRGB
| Step | Classic | Linear | Perceptual | Smooth |
|---|---|---|---|---|
| Color space | ??? | ??? | ??? | ??? |
| Curve | ??? | ??? | ??? | ??? |
| Tangent | ??? | ??? | ??? | ??? |
| Post-processing | ??? | ??? | ??? | ??? |
We’ll fill in every cell of this table in the following articles.
What’s next
In the next article, we’ll break down the simplest known interpolation method — Classic, and find out what tricks Adobe’s engineers came up with to tame those ever-escaping curves.