Case Study 2 — Why Your Screen Uses Three Colors: Basis, Span, and Independence in Computer Graphics

Field: computer graphics / digital imaging. Concepts used: subspace, span, linear independence, basis, coordinates. Big idea: every color your monitor shows is a unique linear combination of three independent, spanning primary colors — a textbook basis.

Three numbers for every color

Hold a magnifying glass to any LCD or OLED screen and you will see that each pixel is built from three tiny lights: one red, one green, one blue. By varying the brightness of these three primaries, the pixel can produce millions of distinct colors. A photo on your phone is, internally, a giant grid of triples — each pixel stored as $(r, g, b)$, three numbers between $0$ and $255$. White is $(255, 255, 255)$; pure red is $(255, 0, 0)$; a muddy teal might be $(0, 128, 255)$.

Why three numbers? Why not two, or seven? The answer is one of the cleanest real-world appearances of this chapter's ideas. The three primary colors form a basis of the space of displayable colors: they are linearly independent (no primary can be made from the other two) and they span the color space (every displayable color is reachable as a combination of them). Three is the magic number because the displayable color space has dimension 3 — and a basis of a 3-dimensional space needs exactly three vectors, as §6.10 explained.

Colors as vectors, mixing as linear combination

Treat each primary as a vector in a 3-dimensional "color space": $$\mathbf{R} = (1, 0, 0), \qquad \mathbf{G} = (0, 1, 0), \qquad \mathbf{B} = (0, 0, 1),$$ where the coordinates record (red light, green light, blue light) intensity, scaled to the range $[0, 1]$. Mixing colors is additive linear combination — exactly the operation this whole chapter is about. A color with red intensity $r$, green $g$, and blue $b$ is $$\mathbf{c} = r\,\mathbf{R} + g\,\mathbf{G} + b\,\mathbf{B}.$$ Yellow is red plus green, $\mathbf{R} + \mathbf{G} = (1, 1, 0)$. White is all three at full, $(1, 1, 1)$. A dim purple is $0.5\,\mathbf{R} + 0.5\,\mathbf{B} = (0.5, 0, 0.5)$. The space of all such combinations — the span of $\{\mathbf{R}, \mathbf{G}, \mathbf{B}\}$ — is the full color gamut the monitor can produce, and because three independent vectors span $\mathbb{R}^3$ (§6.5), that gamut is all of the (positive) color cube.

# RGB primaries as a basis of color space, and the coordinates of a target color.
import numpy as np
R = np.array([1, 0, 0]); G = np.array([0, 1, 0]); B = np.array([0, 0, 1])
M = np.column_stack([R, G, B]).astype(float)        # primaries as columns
print("rank =", np.linalg.matrix_rank(M),            # 3  -> spans 3D color space
      " det =", round(float(np.linalg.det(M)), 3))   # 1.0 -> independent (square, nonzero det)

teal = np.array([0.0, 0.5, 1.0])                     # the color we want to display
coords = np.linalg.solve(M, teal)                    # how much R, G, B to mix
print("mix recipe (r, g, b) =", coords)              # [0.  0.5 1. ]  -- unique!

The primaries have rank 3 and determinant 1, certifying both that they span the color space and that they are independent — a basis. Solving $M\mathbf{c} = \text{teal}$ returns the unique recipe $(0, 0.5, 1)$: no red, half green, full blue. That uniqueness is not a coincidence — it is the uniqueness-of-coordinates guarantee from §6.10, and it is essential. It means there is exactly one way for the hardware to produce a requested color; if recipes were not unique, the display logic would be ambiguous and the same stored pixel value could render as different colors.

The whole reason an image format like PNG or JPEG can store a color as just three numbers is that those three numbers are the coordinates of the color in the RGB basis. The basis is fixed and agreed upon, so three coordinates fully specify the color — exactly as a vector in $\mathbb{R}^3$ is fully specified by three coordinates once you fix a basis.

What goes wrong if the primaries are dependent

Now suppose a careless engineer designs a display with three sub-pixels colored red, green, and yellow — reasoning that yellow is a nice bright color worth having directly. The disaster is a linear-dependence disaster. Yellow is already red plus green: $$\mathbf{Y} = \mathbf{R} + \mathbf{G} = (1, 1, 0).$$ So the three "primaries" $\{\mathbf{R}, \mathbf{G}, \mathbf{Y}\}$ are linearly dependent — the third is a combination of the first two, hence redundant (§6.5). Their span is not all of color space; it is only the 2-dimensional plane spanned by red and green. Every color this display can make has its blue coordinate equal to zero. The display can never produce blue. No mixture of red, green, and yellow contains any blue light, because none of the three primaries does.

# A broken "basis": red, green, and yellow (= red + green) are dependent.
import numpy as np
R = np.array([1, 0, 0]); G = np.array([0, 1, 0]); Y = R + G   # yellow = R + G
M_bad = np.column_stack([R, G, Y]).astype(float)
print("rank =", np.linalg.matrix_rank(M_bad),               # 2 -- NOT 3!
      " det =", round(float(np.linalg.det(M_bad)), 3))       # 0.0 -- dependent

# Try to display pure blue (0,0,1) with these three primaries:
blue = np.array([0.0, 0.0, 1.0])
c, *_ = np.linalg.lstsq(M_bad, blue, rcond=None)
print("best mix for blue =", np.round(c, 3),                 # [0. 0. 0.]
      " -> produces", np.round(M_bad @ c, 3),                # [0. 0. 0.]  (black!)
      " matches blue?", np.allclose(M_bad @ c, blue))        # False

The broken set has rank 2 and determinant 0 — the unmistakable signature of dependence (§6.5, §6.13 of the exercises). When we ask the least-squares solver for the closest mix to pure blue, it returns $(0, 0, 0)$ — black — because blue is simply unreachable, and the nearest reachable color is the origin. A whole region of the visible spectrum has been lost, all because the three chosen primaries failed to be independent. The fix is the same lesson as the data-science case study, in reverse: choose primaries that are independent and spanning — a genuine basis — so that the gamut is the full space and every color has a unique recipe.

Beyond RGB: choosing a basis to suit the task

The choice of red, green, and blue is not the only basis for color, and graphics professionals switch bases constantly — which is precisely the change-of-basis idea that Chapter 16 develops. The same color (the same vector in color space) gets different coordinates in different bases, just as the vector $(5, -2, 4)$ had coordinates $(5, -7, 6)$ in the climbing basis of §6.10 but coordinates $(5, -2, 4)$ in the standard one.

  • CMY (cyan, magenta, yellow) is the basis used in printing, because printers work by subtracting light from white paper rather than adding it. Cyan, magenta, and yellow are independent and span the printable gamut — a different basis of (roughly) the same space.
  • HSV (hue, saturation, value) re-coordinatizes color in a way that matches human intuition — "make it more saturated" is one coordinate — but it describes the same underlying 3-dimensional color space.
  • YCbCr, used in JPEG and video compression, separates brightness from color so the eye-insensitive color channels can be compressed harder. It is literally a change of basis applied to the RGB vector, performed by a $3 \times 3$ matrix — and that matrix is invertible precisely because both the old and new primaries are independent, spanning sets.

Every one of these is a basis of the same 3-dimensional color space, related to the others by an invertible $3 \times 3$ matrix (a change of basis). The invertibility is guaranteed by independence: a set of three independent vectors in $\mathbb{R}^3$ assembles into a matrix of rank 3, which is invertible (Chapter 9). The fact that color needs three coordinates — no more, no less — is the statement that color space has dimension 3, traceable to the three types of cone cell in the human eye. Dimension, basis, span, independence: the abstract machinery of this chapter is, quite literally, painted onto every screen you own.