Instruments 9 min

How many colors can you actually tell apart?

The folklore answer is a sphere-packing estimate for one observer. The useful answer is a bracket, for your class count and your observers.

“How many distinguishable colors are there?” has a folklore answer — a number like ten million, arrived at by dividing the volume of a color solid by the volume of a just-noticeable difference. It is a fine piece of arithmetic and it answers almost no real question.

The real question is narrower and harder. You have twelve categories to encode. The result has to stay readable for people with protan and deutan color vision. What is the best minimum separation any palette could possibly achieve, and how close can a solver actually get?

Those are two different numbers, and having both is the point.

Why the folklore number does not transfer

The volume-ratio estimate assumes the space is uniformly packable, that a just-noticeable difference is a constant-sized ball everywhere, and that “distinguishable” means distinguishable by one observer under one light. None of those survive contact with the actual problem.

You are not packing the whole solid; you are picking twelve points that must be mutually separated. You are not one observer; you have declared a set of vision types, and a pair well separated for normal vision can collapse under deutan simulation. And the metric is not uniform — perceptual spaces are built to be roughly uniform and are only roughly so.

So the honest question is about your configuration, and it deserves a computed answer rather than a citation.

The ceiling: a covering argument

Here is the argument, which is short enough to state completely.

Sample the sRGB cube on a lattice. View every sampled point through each declared vision model, and define the distance between two colors as the minimum separation across all those views — the worst case, because a palette is only as good as its weakest observer.

Now suppose you could cover every sampled point with K balls of radius r in that metric. If K < N, then any N colors you choose must place two of them in the same ball, by pigeonhole. Two colors in one ball of radius r are at most 2r apart. Therefore no N-color palette can achieve a minimum pairwise separation greater than 2r.

Binary-search r for the tightest such statement the sample supports, and you have a ceiling: an upper bound on what is achievable, established by counting rather than by trying.

That is a genuinely different kind of claim from “the best palette we found scored 0.19.” It says the thing you are hoping for does not exist.

The floor: a witness

A ceiling alone is unsatisfying, because you do not know whether it is tight. A ceiling of 0.4 is useless if the best real palette scores 0.05 — all it tells you is that you have no idea.

So the tool also runs a maximin solver and returns the palette it found, along with its achieved minimum separation. That is a floor: a demonstration that at least this much is possible, backed by colors you can render.

The truth sits inside [floor, ceiling], and the tool reports the gap. A narrow gap means you know where you stand and further search is not worth much. A wide gap is honest uncertainty, and it points at which side needs work: a better solver, or a denser lattice for a tighter covering.

Reporting the interval instead of a single number is the whole design. A single number would have to be either a bound you cannot reach or a result you cannot justify.

What it says in practice

Run this for a realistic case — twelve classes, protan and deutan at full severity — and the ceiling comes down hard. Requiring a palette to survive two vision models simultaneously collapses the usable volume, because colors that separate cleanly for normal vision frequently converge under simulation. The worst-case metric is unforgiving by construction.

The consequence is a design conversation with actual content. If twelve classes cannot achieve the separation you need, no amount of palette tuning will fix it, and the ceiling proves that rather than suggesting it. The options that remain are structural: fewer categories, or a second visual channel — shape, position, texture, direct labeling — so color is not carrying the distinction alone.

That is the most useful thing this instrument does. It converts “our palette is not working” into “this is not a palette problem,” with an argument attached.

The limits, stated plainly

The ceiling depends on lattice density. The covering is built on a finite sample. 2r is exact for the sampled points; off-lattice colors are covered only up to the lattice’s slack. The step is reported alongside the bound because it is part of the claim, and a denser grid tightens it.

The floor is a found palette, not a proven optimum. It is whatever the seeded solver reached inside its budget. A wide gap may mean the ceiling is loose, or it may mean the solver is.

The threshold walk certifies feasibility, not impossibility. Given a required separation, the tool reports the largest class count at which the solver still met it. It stops at the first count that fails. That establishes feasibility up to that N; it is not a proof that N + 1 is impossible.

Vision models are models. Machado’s matrices are a well-founded parameterization of dichromacy, and real color vision deficiency varies between people. A certificate over these models is a statement about the models.

Each limit narrows the claim. What survives is still much more than the folklore number: a bracketed, configuration-specific answer whose assumptions are all written down, for a question people usually answer by feel.

Instruments in this post