Gamma correction and color management
A value of 128 in an image file does not mean half the light. It means about 22%. That gap is gamma. Understanding it explains why downscaled photos get darker, why gradients have a muddy middle, and why the same file looks different on two screens.
Where gamma came from
A CRT tube was nonlinear: the brightness of the spot grew roughly as the voltage raised to a power of 2.2 to 2.5. Television signals were therefore encoded "in advance", raised to the inverse power, so that the screen would emit light proportionally.
CRTs are gone, but gamma stayed, because it turned out to be useful for a second reason. The eye is far more sensitive to differences in dark tones than in light ones. Gamma encoding spreads the 256 available 8-bit levels roughly evenly in perception: many steps in the shadows, fewer in the highlights. Linear 8-bit storage would show visible banding in dark areas and waste levels in bright ones.
The sRGB curve
sRGB does not use a pure power law but a curve made of a linear segment near black and a 2.4 power. Overall it resembles a 2.2 power:
| File value (0..255) | Light (linear) | Perceived lightness L* |
|---|---|---|
| 0 | 0% | 0 |
| 32 | 1.4% | 12.3 |
| 64 | 5.1% | 27.1 |
| 96 | 11.7% | 40.7 |
| 128 | 21.6% | 53.6 |
| 160 | 35.2% | 65.9 |
| 192 | 52.7% | 77.7 |
| 224 | 74.5% | 89.2 |
| 255 | 100% | 100 |
The table shows the point of the encoding: 128 is only 21.6% of the light, but to the eye (L* = 53.6) it is already about halfway from black to white. File values are closer to what we see than to how much light there is.
The most common mistake: computing on encoded values
Blending, blurring, resizing and transparency are operations on light. Done directly on sRGB values, they give wrong results:
- Averaging black and white. Arithmetically (0 + 255) / 2 = 128. But half the light is the value 188. A downscaled fine checkerboard, computed without linearization, comes out too dark.
- A red-to-green gradient. The midpoint computed on sRGB values is (128, 128, 0): a dark olive smudge. Computed in linear light it is (188, 188, 0), a bright yellow, which is what mixing two lights actually produces.
- Antialiasing and font edges look thinner or bolder depending on the background color.
The correct order is always the same: decode to linear light, do the operation, encode back. The same decoding is the first step of converting RGB to CIE XYZ.
Color management
Gamma is only one property of a device. Screens also differ in their primaries and white point, and a printer has a completely different gamut than a monitor. Color management makes the same color look the same across devices, as far as physics allows.
It works through ICC profiles. Every device or color space (sRGB, Adobe RGB, Display P3, a specific printer on a specific paper) has a profile that describes how its values relate to device-independent color. Conversion always goes through an intermediate space (the PCS, profile connection space), which is CIELAB or CIE XYZ with a D50 white:
When source colors do not fit in the destination gamut, the profile applies one of four rendering intents:
- perceptual: compresses the whole gamut, preserving the relations between colors; good for photographs,
- relative colorimetric: in-gamut colors stay unchanged, the rest are clipped to the gamut boundary; source white maps to paper white,
- saturation: keeps vividness at the cost of accuracy; for charts and graphics,
- absolute colorimetric: like relative, but without white point adaptation; for simulating paper on screen (proofing).
A screen profile only makes sense if the screen is calibrated. Calibrating with a colorimeter sets gamma, white point and brightness, then builds a profile describing how the screen actually reproduces color.