How a colour becomes a number
Start with the question everybody actually asks. #ffffff is not a colour name — it is three bytes written in base 16, and they are the same three bytes a console sends to an RGB fixture. Once that lands, hex codes, DMX values and video code words stop being three separate subjects.
The direct answer
What #ffffff actually is
Three channels — red, green, blue — one byte each. A byte holds 0 to 255, and one byte is exactly two hexadecimal digits, which is the entire reason colours are written in base 16 rather than base 10: ff is unambiguous and two characters wide, where 255 is three characters and needs separators.
So #ff8800 is red 255, green 136, blue 0. Send those same three numbers down a lighting universe to an RGB fixture and you get the same instruction. A web colour and a DMX value are the same object arriving by different routes.
#fff is shorthand: each digit is doubled, so it expands to #ffffff. And #ffffff is every channel at maximum, which is why it is white — not because white is a colour, but because it is all three primaries at full.
Why 255 and not 100
Bit depth, again
Eight bits per channel gives 256 levels; three channels gives about 16.7 million combinations. That is 16.7 million codes, not 16.7 million distinguishable colours — the two are frequently confused in marketing.
Ten bits gives 1024 levels per channel and a bit over a billion codes. The reason to want that is not richer colour; it is gradients. A slow fade to black, a soft sky, a subtle wash across a large LED wall — these are where 256 steps become visible as bands, and where a large surface makes each step physically wide.
This is the same fact as bit depth in audio and 16-bit fixture control: resolution buys you steps small enough that nobody can see the join, and past that it buys storage.
The thing that surprises everyone
The numbers are not linear light
Half the code value is not half the light. Feed 128 out of 255 into a normal display and you get roughly 22% of the brightness of 255, not 50%.
That is deliberate. Human brightness perception is roughly logarithmic — we can distinguish far more steps in the dark than in the light, which is the dark adaptation story from the other side. If you spent 256 codes evenly on linear light, almost all of them would be wasted at the bright end where nobody can tell them apart, and the dark end would band horribly. So a transfer function is applied before storage that distributes the codes to match perception.
It is perceptual compression, and it is the only reason 8-bit video is watchable at all. It is also the source of a whole family of faults.
- Cross-fading in code values is wrong. Two layers at 50% do not sum to 100% of the light. Compositing, blending and dimming should happen in linear light and be re-encoded afterwards, which is exactly why a projector blend misbehaves in the overlap.
- An LED wall at 5% is where the steps live. Low code values are where the encoding has spent its resolution and the panel has spent its PWM range, and the two do not always agree.
- "Brightness" on a display is not one control. Backlight level, the transfer function and any picture processing are three different things, and only one of them is what you meant.
- HDR changes the transfer function, not just the peak. PQ and HLG are different curves designed for far larger ranges, so an HDR signal into an SDR display is not merely dim — it is decoded with the wrong function.
RGB is a recipe, not a colour
Which red is #ff0000?
The number says "the red primary, at full". It does not say what that primary is. Two displays with different red phosphors, different LEDs or different filters will both show you their maximum red, and those two reds will be visibly different colours.
A colour space is what closes that gap. It defines three things: the chromaticity of the primaries, the white point, and the transfer function. Given those, the same numbers mean the same colour on any display that honours them.
That is why a screenshot looks different on two monitors, why an LED wall needs calibration rather than just configuration, and why a camera, a media server and a wall all have to be told which space they are working in.
| Space | Where it lives | What to watch |
|---|---|---|
| sRGB | Computers, the web, most graphics and content produced on a laptop. | Effectively the same primaries as Rec.709 but a different transfer function definition. Close enough that people conflate them, and different enough to matter in a grade. |
| Rec.709 | HD broadcast and most show video. See BT.709. | The safe default for a show, and the one everything else gets converted into when nobody has agreed anything. |
| DCI-P3 | Cinema projection, and increasingly high-end displays. | Noticeably wider reds and greens than 709. Content mastered in P3 shown as 709 loses saturation; the reverse over-saturates. |
| Rec.2020 | UHD and HDR. See BT.2020. | Wider than any current display can actually reproduce, so it is a container rather than a description of a screen. |
| Rec.2100 | HDR transfer functions — PQ and HLG. See BT.2100. | PQ is absolute — a code means a specific brightness in nits. HLG is relative and degrades more gracefully on an SDR display. |
The compression nobody mentions
Chroma subsampling
The eye resolves far more spatial detail in brightness than in colour. Video exploits that: RGB is converted into one luma channel plus two colour-difference channels, and then the colour channels are stored at reduced resolution.
The notation counts samples in a four-pixel-wide block. 4:4:4 keeps full colour resolution. 4:2:2 halves it horizontally. 4:2:0 halves it horizontally and vertically — a quarter of the colour samples, and half the total data.
For camera footage of the real world this is nearly invisible and enormously useful. For anything with hard colour edges it is not: text, fine graphics, and keying. Coloured text over a contrasting background at 4:2:0 develops visible fringes, and a green-screen key at 4:2:0 has a quarter of the edge information a clean key needs.
luma
every pixel, always
Brightness detail is kept in full because that is what the eye actually resolves.
chroma
every pixel
Full colour resolution — what you need for graphics, text and keying.
The fault that catches everyone
Full range against limited range
Computer graphics use the whole byte: 0 is black, 255 is white. Broadcast video does not — it puts black at 16 and white at 235, leaving footroom below and headroom above for signals that overshoot.
Both conventions travel down the same cable in the same eight bits, and nothing in the picture announces which one it is. Get it wrong in one direction and blacks are crushed and whites clipped; get it wrong in the other and the image is washed out and grey with no true black.
This is the most common video fault on a show, it looks like a grading problem rather than a signalling one, and the fix is a setting rather than a colour correction. When a laptop looks washed out on a wall that was fine yesterday, check this before anything else.
The round trip
Light in, numbers, light out
Everything above is the middle of a journey that starts and ends in the physical world.
Capture. Photons land on photodiodes and accumulate charge — the image sensor story. That charge becomes a voltage, an analogue-to-digital converter turns it into numbers, and those numbers are linear light at that point. Then the Bayer mosaic is interpolated into full colour, a matrix converts the sensor's native primaries into a standard space, and a transfer function is applied. Only after all of that do you have the numbers a file contains.
Display. The reverse, and the last step is physical again. The transfer function is decoded, the values are mapped onto the display's actual primaries, and something emits light. On an LED wall a driver chip switches each LED fully on and fully off very quickly — the LED has no dimmer — and the ratio between on and off is the level. On a DLP projector, micromirrors flip. On an LCD panel, liquid crystal modulates a backlight.
Which is why an LED processor talks about grayscale bit depth and refresh rate in the same breath: grayscale is how many on/off ratios the driver can produce, and refresh is how fast it repeats the pattern. Both are invisible to an eye and entirely visible to a camera — see genlock and LED walls and flicker fusion.
- Check the levels before you check the colour. Full-versus-limited mismatch looks exactly like a bad grade and is fixed with a checkbox.
- Ask what space every hand-off is in. Camera, server, processor, wall. Each is a place the agreement can be silently dropped.
- 4:2:0 is for pictures of the world, not for graphics. If there is text, a key or a hard colour edge, get to 4:2:2 or better.
- A wall's calibration lives with the panels. Moving a wall between processors without carrying the calibration loses the thing the processor was bought for.
- 10-bit is about gradients, not saturation. If somebody wants "richer colour" the answer is usually the colour space, not the bit depth.
The hex, gamma, range and bandwidth calculations on this page are tested functions embedded verbatim from test/tools.test.mjs, the same as everything in the field tools. The colour-space documents are in the standards index with access links.
2 questions on the mechanism rather than the trivia. Nothing is scored and you can answer again — the explanation under a wrong answer is the point of it.
-
1Why is #808080 not half as bright as #ffffff on a normal display?
-
The half-integer is a rounding detail. The factor-of-two discrepancy is the transfer function.
-
Equal channels do give a neutral grey. The non-linearity is in the encoding, not the mixing.
-
It happens on a perfectly calibrated display. It is by design.
-
Right. The encoding spends more code values on dark tones where the eye is sensitive. 128 out of 255 lands around 22% of the light, not 50%.
-
-
2You are sending fine coloured text to an LED wall and it looks soft at the edges. Which is the most likely cause?
-
That shows as flicker or judder on movement, not softness on a static edge.
-
Right. Subsampling halves colour resolution horizontally and vertically. It is nearly invisible on camera footage and obvious on a sharp coloured edge, which is exactly what graphics and text are.
-
Low bit depth shows as banding in gradients, not soft edges on text.
-
A narrower gamut changes which colours are reachable, not how sharp an edge is.
-
Answers are kept in this browser on this device. Nothing is sent anywhere.
- What is a hex code?
- Why is 128 not half brightness?
- What is 4:2:0 costing me?
Where to go next
These pages are a chain rather than a library — the next one along usually answers the question this one raised.
Everything on this page, in the index
Each of these has its own entry with sources, ports, gotchas and an open gap where a field is missing.