Gamma

A pixel stored as 128 does not emit half the light of one stored as 255. It emits about a fifth. It does look roughly half as bright, and that gap between the light and the look is the whole subject. The value is not a quantity of light, it is a code for one, and the two are related by a curve. Everything that goes wrong here comes from doing arithmetic on the code as though it were the light. The curve itself is not the mistake, and this page shows why keeping it is the right decision.

New to how colour is stored? Start here

A grey pixel is one number, usually from 0 to 255. It is easy to assume that number is an amount of light, so that 128 emits half of what 255 does. It does not.

The number is a code, and a curve turns it into an amount of light. The curve exists because human vision is far more sensitive to differences among dark tones than bright ones, so spacing the codes evenly in light would waste most of them. Spacing them evenly to the eye means the arithmetic you would naturally do on them is measuring the wrong thing.

A grid of dots on a clock

A screen is a grid of coloured dots, redrawn from top to bottom on a fixed beat. Everything drawn on it is a decision about which dots and what colour, made before the beat arrives.

The clock is the part that makes this hard. It does not wait, and it does not care whether the drawing was finished, so a picture that took too long is shown half-done. Most of the machines in this topic exist because of that deadline rather than because of the picture.

The machine for this idea on its own is Eight Sprites, if you would rather press it than read about it.

The numbers are not light

1 Black and white, and the two different answers to what lies halfway between

Two colours, and the two answers to what lies halfway between them. One averages the stored numbers. The other converts both to the light they stand for, averages that, and converts back. Move either slider: the gap between the middle two swatches is the error.

first
averaging the bytes
averaging the light
second

2 The same comparison across other pairs, and across all thirty-three thousand of them

The same comparison on other pairs. The error is largest where the two values are furthest apart and vanishes when they are the same, which is why blending similar colours looks fine and blending opposite ones does not.

Two ways to average
pairbytesaveraging bytesaveraging lighterror

3 What eight bits of linear light would look like instead, which is why the curve is kept

Why the curve is worth keeping. If those eight bits held linear light instead, the codes would not be evenly spaced to the eye: the darkest ones would be far apart and the bright ones wastefully close together.

Perceptual size of a linear code step
linear codesapparent jump

These ran in this browser when the page loaded. Each claim, whether it held, and the number behind it.

Each claim, whether it held, and the values behind it
claimheldmeasured
the transfer function round-trips on all 256 codesyesencode(decode(v)) returns v for every 8-bit value; 0 failures
the straight segment and the power segment meet, which is why those constants are not roundyesat the breakpoint the linear branch gives 0.00313080 and the power branch 0.00313081, a step of 2.3e-9
the midpoint of black and white is 188, not 128yesaveraging the bytes gives 128; averaging the light they stand for and encoding the result gives 188
128 carries about a fifth of white's light, while looking about half as brightyesbyte 128 is 21.6% of the light that 255 is, though it looks about half as bright: L* 53.6 of 100. The light and the look are different quantities, and the curve exists to hold them apart
averaging encoded values is too dark on every pair, and never once too lightyes32,896 pairs swept: 32,585 too dark, 0 too light, 311 exactly equal; worst error 60.0 codes at (0, 255). Compared before rounding, because 1 pair rounds a genuine tie the other way
eight bits of linear light would band badly, which is why the curve is thereyesthe step from the darkest linear code to the next is 12.7 sRGB codes wide, so the shadows would move in visible jumps; sRGB's own steps are about one code each, by design
the encoding is not the mistake, and this page does not call it oneyesthe curve is roughly perceptually uniform and is a good use of eight bits; what is wrong is arithmetic performed on encoded values, which is a different claim and the only one made here
1996 is the proposal and 1999 is the standardyessRGB version 1.10 is dated 5 November 1996; IEC 61966-2-1 followed in October 1999, and the era spans both

What is real here, and what is not

Gamma is not a mistake, and calling it one is the usual error

The curve is often explained as a leftover from cathode ray tubes that we are stuck with, which suggests the fix is to abolish it. It is roughly perceptually uniform, so eight bits of it look smooth where eight bits of linear light would band visibly in the shadows. The third panel computes exactly that. The encoding is a good decision; arithmetic performed on encoded values is the mistake, and they are different claims.

The swatches are shown in your browser's colour handling, not a controlled one

The greys here are painted as sRGB and rendered by whatever display and settings you have. The relationship between the two midpoints is arithmetic and holds regardless, but if your screen is set to something other than a standard gamma the visual gap will not match the numbers exactly. The numbers are the claim.

The comparison is made before rounding, and one pair needs that

Averaging is compared as exact values rather than as rounded bytes. At the pair 9 and 10 the true midpoint is exactly 9.5, and in floating point it arrives fractionally below, so the two rounded answers differ by one code in the direction the rule says is impossible. That is a rounding tie, not a counterexample, and comparing the exact quantities is the honest way to state the rule.

Real colour work has more in it than one curve

This page treats a pixel as one grey number. Actual colour management involves three primaries whose coordinates matter, a white point, viewing conditions, and spaces that are not sRGB at all. The gamma error shown here is real and is the one people meet first, but a page that showed only this would leave the impression that colour is a single curve.

1996 and 1999 are both here on purpose

The sRGB proposal is dated 5 November 1996 and IEC 61966-2-1 standardised it in October 1999. The era covers both. The roster previously carried month 10, which is the standard's date rather than the proposal's, and the entry now says which is which.

Which of these sources were actually read

The IEC standard is sold rather than published, so what was fetched is its shop entry and not its text. That is fine for this page: the transfer function used here is from the 1996 sRGB proposal, which IS archived, and the two agree. The IEC citation is present because the standard is where the curve became official, not because anything here was taken from it.

Sources