Chroma Subsampling Lab

Compare how video codecs preserve luma detail while reducing chroma resolution.

Loading interactive simulation...

why codecs throw away color first 🖖

Human vision resolves brightness detail more sharply than color detail, so codecs keep full luma (Y) resolution and share chroma (Cb/Cr) samples across neighboring pixels. 4:4:4 stores full color detail, 4:2:2 halves horizontal chroma resolution, and 4:2:0 halves chroma both horizontally and vertically. The bandwidth saving is real: 4:2:0 uses about half the raw sample data of 4:4:4, but sharp colored text and alternating color patterns reveal the loss first.

what the three numbers mean 🖖

The ratio is a recipe for a block that is 4 pixels wide and 2 rows tall. The first number (4) is the block width; the second counts the color samples in the top row; the third says how many change in the bottom row. So 4:2:2 takes 2 color samples per row, while 4:2:0 takes 2 in the top row and reuses them below (0 new), sharing one color across a 2×2 square. Luma is always sampled at every pixel.

your grandparents' TV already did this 🖖

Chroma subsampling is not a digital invention. When NTSC color television launched in 1953, engineers gave the brightness signal about 4.2 MHz of bandwidth but squeezed the two color channels into roughly 1.3 MHz and 0.5 MHz — the narrow "Q" channel exploited the eye's especially poor resolution for blue-violet color detail. Analog color TV was quietly throwing away chroma resolution decades before JPEG or H.264 formalized the idea.

ONE STAGE OF A CHAIN — WHAT ARRIVES, WHAT LEAVES, WHAT BREAKS DOWNSTREAM

Where This Sits In The Encoding Pipeline

A video encoder is not one algorithm but eight stages in a fixed order, and the order is not arbitrary: each stage exists because the one before it made its job possible. This tool models one of them. The chain below links to the other seven.

Chroma Subsampling Lab — discards most of the colour resolution while leaving brightness untouched

What arrives
Full-resolution luma and chroma — one colour sample per pixel, written 4:4:4.
What leaves
Luma at full resolution, chroma at a quarter of the samples in 4:2:0.
What the next stage assumes
Everything downstream handles four times less chroma data, and the decoder will interpolate the discarded samples back.
What goes wrong here
A saturated edge — red text on black is the standard case — has its colour smeared across the block, because that edge lives in the chroma channel where the samples were removed. Luma survives intact, so the picture looks sharp and the colour looks wrong.

Problem solved in full

  1. Bytes per pixel for 4:4:4, 4:2:2 and 4:2:0 from the sample counts 6 steps

    Derive the bytes per pixel for 4:4:4, 4:2:2 and 4:2:0 from the sample counts, then find out how much bandwidth 4:2:0 is really saving.

    1. Count the samples in a 2×2 block. The notation names how many chroma samples accompany four luma ones in the top and bottom rows, so the ratio is a count and not a fraction.

    2. The other two modes drop chroma horizontally, then vertically as well. Each halving removes two of the twelve samples in the block.

    3. Multiply by the pixel count for the frame size, and take the ratio for the saving. 4:2:0 is exactly half of 4:4:4 by construction, not by measurement.

    4. Look at where the samples went. Luma is untouched in every mode — the colour-difference channels are the only ones being thinned, and the human eye resolves them at roughly half the acuity.

    5. Scale the same 1.5 bytes per pixel to a real frame at a real rate.

    6. That is why the failure mode is specific rather than general: the loss is entirely in the two channels that carry no luminance detail.

    Answer

    Half, and it is still 746 Mbit/s for uncompressed 1080p30. That number is the point of the exercise. Chroma subsampling is the cheapest compression there is — no transform, no entropy coder, no decision to make — and after halving the data the stream is still far too big for any network anybody has at home, which is why every codec that ships starts after this step rather than instead of it. The reason it costs so little visually is in the Y equation: luma is sampled at every pixel and only Cb and Cr are thinned, so edges, texture and detail are untouched. What breaks is anything whose information lives in colour alone — red text on a grey background, a saturated logo, a chroma-key edge — which is why 4:2:0 is invisible on foliage and disastrous on a slide deck.

References (1)

Example problems

  • Color bars - Eight bars across 64 pixels, so each one is eight wide, and 4:2:0 averages chroma in 2×2 blocks. No block ever straddles a bar edge, so every block it averages is already one flat colour: the three panels come out pixel for pixel identical while the frame falls from 9,216 bytes to 4,608. The 50.0% saving costs nothing at all on this picture.
  • Hue gradient - Smooth hue gradient: 4:2:0 and 4:2:2 look nearly identical — natural scenes hide chroma artifacts well
  • Colored text - Red letters on white, and this is the picture that actually breaks. Every stroke edge is a red-to-white chroma jump, 4:2:0 averages it across a 2×2 block, and the edges bleed while the luma stays perfectly sharp. 4:2:2 lands between the two because it averages horizontally only. It saves the same 4,608 bytes as the colour bars, which lose nothing. The picture decides the cost, not the ratio.
  • Checker stress - The name promises stress and the panels come out identical. Its squares are 2×2 red and cyan, and 4:2:0 averages chroma over 2×2 on the same grid, so every group it touches is already one colour. Fine detail is not what subsampling punishes. Detail that falls out of step with the chroma grid is, which is what the coloured text shows and this does not.