跪拜 Guibai
← All articles
Rust · WebAssembly · Color Space · YCbCr · Chroma Subsampling · Green Screen Keying · JPEG · Nalgebra

YCbCr Is a 3×3 Matrix That Halves Your Photo Size Without You Noticing

By 花褪残红青杏小 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

YCbCr is the invisible substrate under every compressed image and video stream a developer encounters. Knowing it as a 3×3 matrix plus an offset — rather than a black-box library call — explains why brightness adjustments clip in RGB, why chroma subsampling artifacts appear at keying edges, and when to demand 4:4:4 assets for post-production pipelines.

Summary

RGB encodes every pixel as three numbers that all carry brightness, so adjusting exposure or compressing color inevitably distorts the image. YCbCr replaces that with one luminance channel (Y) and two color-difference channels (Cb, Cr) via a fixed 3×3 matrix defined by BT.601. The Y channel is exactly the grayscale image from Section 1 of this series; the chroma channels are just scaled versions of B−Y and R−Y, offset by 128 to fit into a u8.

Once separated, the engineering payoff is immediate. Setting Cb and Cr to 128 produces a perfect grayscale image. Averaging chroma across 2×2 blocks — 4:2:0 subsampling — cuts total data in half with no visible difference, which is why every JPEG and video codec defaults to it. Adjusting only Y brightens an image without the color shift that RGB multiplication causes when channels clip at 255. And measuring Euclidean distance on the Cb-Cr plane, ignoring Y entirely, gives a green-screen keyer that handles shadows and wrinkles with a single threshold.

The inverse transform needs no memorized constants: `try_inverse()` on the forward matrix produces the textbook coefficients 1.402 and 1.772. PCA from the previous chapter also finds a grayscale axis, but YCbCr won because its axes are fixed — zero per-image overhead, universally recognized by every codec.

Takeaways
Discarding chroma (Cb=Cr=128) produces a recognizable grayscale image; discarding luminance (Y=constant) produces an unrecognizable color blob, even though both discard the same amount of data.
The Y channel is exactly the BT.601 grayscale image: Y = 0.299R + 0.587G + 0.114B.
4:2:0 chroma subsampling averages Cb and Cr over 2×2 blocks, halving total data from 3n to 1.5n with no visible difference.
Multiplying only Y adjusts brightness without color shift; multiplying RGB channels together causes clipping that distorts hue in highlights.
Green-screen keying on the Cb-Cr plane ignores luminance entirely, so shadows and wrinkles on the backdrop cluster at the same chroma point and key cleanly with one distance threshold.
The inverse YCbCr-to-RGB matrix can be computed with `try_inverse()` rather than memorizing constants like 1.402 and 1.772.
Mixing BT.601 and BT.709 coefficients causes a greenish-dark color shift; JPEG uses BT.601, HDTV uses BT.709.
Chroma subsampling must happen at the end of a pipeline — keying or grading 4:2:0 assets produces edge artifacts and color bleeding.
Conclusions

YCbCr and PCA both find a grayscale axis, but YCbCr won because its fixed, human-chosen constants eliminate per-image overhead and guarantee universal decoder compatibility.

The ±128 offset on Cb and Cr is a mechanical detail that causes catastrophic fluorescent output when missed, yet it's purely a storage convention to fit signed values into unsigned bytes.

Real JPEG stores subsampled chroma as a physically smaller image and interpolates on decode; the visual result is identical to the block-average-then-spread-back approach shown here, but the memory savings are real only in the former.

Chroma subsampling is lossy compression that exploits human physiology, not math — the eye's poor color spatial resolution is the only reason 4:2:0 works.

Concepts & terms
YCbCr
A color space that separates a pixel into one luminance channel (Y) and two chrominance channels (Cb, Cr). Defined by a fixed 3×3 matrix (BT.601 for JPEG) plus an offset of 128 on the chroma channels to fit signed values into unsigned bytes.
4:2:0 chroma subsampling
A compression technique that keeps luminance at full resolution but averages chrominance over 2×2 pixel blocks, reducing total data by half. The default for JPEG, H.264, and phone cameras. Named for the ratio of luma samples to chroma samples per 2×2 block.
BT.601 vs BT.709
Two standards defining the RGB-to-YCbCr matrix coefficients. BT.601 (0.299, 0.587, 0.114) is used for SD video and JPEG. BT.709 (0.2126, 0.7152, 0.0722) is used for HD video and HDTV. Mixing them during encode and decode causes a greenish color shift.
Chroma keying on Cb-Cr plane
A green-screen technique that ignores luminance (Y) and measures Euclidean distance between a pixel's (Cb, Cr) and a target key color's (Cb, Cr). Because shadows and wrinkles change Y but barely shift Cb/Cr, a single distance threshold keys the entire backdrop cleanly.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗