Skip to content

ONE MORE COLOUR · the measured result

How many colours
can you promise?

Not “how many look different to you”. How many stay clearly apart for typical vision, for each of the three kinds of colour blindness, and on a black-and-white screen — all at the same time. The field’s answer has always been a shrug: somewhere around eight, stop. This page publishes the number, the choice it depends on, and the proof.

colours

asking the engine…

engine loading…

Every figure on this page is computed in your browser, right now, by the same src/color/ modules the game ships. Nothing below is typed in by hand. Reload and the numbers are recomputed; change the controls and they change with you.

01

The guarantee

Here it is in plain English. This is the whole promise, and it is the sentence every number on this page is measured against.

Every two colours in the set stay clearly apart for someone with typical vision, for each of the three kinds of colour blindness, and on a black-and-white screen — all at the same time, not one at a time.

checking that quote against the engine…

The words that carry the weight are all at the same time. It is easy to find colours that survive one condition. It is easy to find colours that survive another. Finding colours that survive all five simultaneously is a different, and much harder, promise — and it is the promise that runs out.

The same thing, formally

score(a, b) = min over c in {normal, protan, deutan, tritan, grey} of ΔE′CAM16-UCS( simc(a), simc(b) )
conforming(P, Δ) ⇔ for all a ≠ b in P: score(a, b) ≥ Δ

What “all five” does not cover

The word carrying the weight in that promise is all, and a word like that is only honest with its edge drawn. It means these five conditions and nothing else. The three colour-blindness rows are the complete dichromacies — a whole cone class missing. Anomalous trichromacy, where the cone is present but its sensitivity is shifted, is a different thing and it is not modelled here at all.

What the threshold means, in plain words

Distance is measured in CAM16-UCS, a space built so that equal numeric steps are meant to be equally visible steps [1]. The scale has a natural top and bottom: black to white.

Δ is not a tuning knob. The temptation in a project like this is to hit a nice round number of colours by quietly lowering the threshold. So the deliverable here is not one N: it is the whole curve N*(Δ), published in section 3, with the game picking one point on it. If Δ ever moves, every number here moves with it, and this page says so out loud.

The choice inside the number: which CAM16-UCS

There is a second thing a threshold in this metric depends on, and stating it is the difference between a result and a claim. Li et al. 2017 publish three scalings of the same space in the same paper [1], differing in one constant — KL, which stretches or squashes the lightness axis before the distance is taken. LCD is fitted to large colour differences, SCD to small ones, and UCS across the whole range.

They are not interchangeable here, because the ceiling this page publishes is essentially a length divided by Δ — and KL is exactly the constant that sets that length. So the same one-line argument gives a different answer under each. All three are computed below, live, by machinery this page first checks against the shipped engine:

02

Colour blindness is not a filter you bolt on

The common mental model is that colour blindness dims colours a bit, so a palette that looks bold enough will be fine. That model is wrong in a specific and destructive way: dichromacy projects colour onto a lower-dimensional space. Whole families of very different colours land on the same point. Not similar. The same.

Pick any two colours and watch what each observer condition does to the gap between them. The number under each pair is the real ΔE′ the engine computes, and the score for the pair is the smallest of the five — because the promise has to hold under all of them at once.

Read this before you trust a swatch

The little colour squares are not the simulated colours. The numbers are. A dichromat’s version of a colour is very often outside anything an sRGB screen can physically show — about a quarter of all colours under protanopia. There is no pixel for it. So every simulated square on this page is the closest colour the screen can show, a stand-in, while every ΔE′ is computed from the real thing.

That is not a small caveat, so the page measures it for you instead of asking you to take it on faith. The table below has a column called picture off by: it is the distance, in the same units as everything else, between the square you are looking at and the value the number came from. Small means the picture is a good likeness. Large means look at the number, not the square.

measuring…

Why this kills the naive approach

A designer checking their work in a colour-blindness simulator is checking one condition, usually deuteranopia, usually by eye. The pairs that kill a palette are rarely the ones that look risky. In section 5, across every published palette measured, the pair that sets the score is chosen by the same condition every single time — and it is the one almost nobody designs for: plain greyscale.

03

The curve: N*(Δ)

The deliverable is not one number. It is the largest conforming palette size at every threshold on the published range. Two things are plotted, and they are different objects: an upper bound that no palette anywhere can beat, and a construction that the shipped search actually built.

Read the columns carefully

04

Why the ceiling is a proof and not a failed search

Most “we could not find more than N” results are search results. This one is not. The upper bound needs no search at all, and here is the whole argument in four steps a non-mathematician can follow.

Step 1 — greyscale collapses everything onto one line

The grey condition takes a colour to its relative luminance and paints that back as a neutral. There are only 256 neutral 8-bit colours, #000000 to #ffffff. So the whole 16.7-million-colour sRGB cube lands on 256 points. Millions of colours in; 256 out. Here are colours that are wildly different, and the single grey they all become:

Step 2 — two colours on the same grey are the same colour, to the checker

If two palette colours land on the same grey, their distance under the grey condition is exactly 0. The score is a minimum over the five conditions, so their score is 0 too, however brilliant they look in colour. A conforming palette of N colours therefore needs N different greys, every pair at least Δ apart.

Step 3 — that is a one-dimensional packing problem, and it is exact

Points on a line, pick as many as you can with a minimum gap. Greedy from the dark end is optimal, and it is exact — not an approximation, not a sample — because those 256 greys are the entire set of reachable values, not a grid drawn through a continuum. The engine checks the one property that makes greedy provably optimal here (distance strictly increasing as you move away along the axis) at load time, over every pair on the axis, rather than assuming it.

Step 4 — the ruler

Here is the whole argument as one picture, and it is the only picture on this page you really need. The strip is all 256 greys — the entire image of the sRGB cube under the grey condition. The marks are where the packing puts the colours. The brackets carry the real distance between neighbours. The number left over at the top is why there is no room for one more.

The grey ruler

Every position, every bracket and the verdict above are recomputed from the engine on each step of this slider. The picture is not an illustration of the result; it is the result, drawn.

What the engine actually does when the game asks for one more

The game walks down this curve and asks the engine for one more colour until it says no. There are two ways to say no and they are not the same claim, so the engine names which one it is making rather than leaving a reader to infer it: refusalKind: "search" means a real search ran and came back empty, and refusalKind: "bound" means nothing was tried, because nothing could work. Here is what the shipped function returns at the wall, asked exactly the way the game asks it:

The obvious attack, closed

CAM16 needs a stated viewing condition, and picking a flattering one would be exactly the quiet tuning this project exists not to do. So the packing is recomputed here across a 64-fold range of adapting luminance, from a very dim room to a bright one. If the ceiling moved with the room, it would be an artefact of our choices. It does not move.

Computed live, in this page, by rebuilding the CAM16 viewing conditions at each LA and re-running the packing from scratch.

What this does and does not establish

05

The published palettes, measured

These are the good ones — the sets a careful person reaches for. Measured against this guarantee, here is how they do. Read the framing paragraph under the table before you draw a conclusion from it.

This is a finding, not a takedown

These palettes were built to keep a different promise, and they keep it. Okabe–Ito set out to make figures readable for colourblind readers in print and on screen. Paul Tol’s sets are built for scientific plots. ColorBrewer is built for maps. Not one of them ever claimed that every pair would survive protanopia and deuteranopia and tritanopia and greyscale simultaneously at a stated numeric threshold. That is a strictly harder promise, and it is the one measured here.

The right way to read the table: under normal vision every one of these palettes is comfortably separated — that column is what they were designed for and they deliver it. The all-five column is a different question. And the answer to that question is remarkably consistent about which condition does the killing.

There is one more honest point in the table, and it matters: a published palette does pass. Look at the small ones. When a designer keeps the count low enough, the harder promise is kept without anyone having set out to keep it. The wall this project measures is not a claim that published work is careless. It is a claim about how many.

06

The ordering trap

The guarantee preserves distance. It does not preserve direction. Two colours can sit a comfortable distance apart under all five conditions while their hue order, their warmth, and their similarity ranking are completely different for a dichromat. This has a consequence that no colourblind mode can fix.

6.1 A gradient, and what a dichromat gets

Colour-ordering puzzle games — the genre where you drag tiles into their correct place in a gradient — are built on ranking, not identity. Here is a gradient of exactly that kind. Row one is what a trichromat sees. Row two is the same row simulated under deuteranopia. Row three is the same as row two, with two tiles swapped into the wrong places.

The number that matters is the last one: how much this observer’s percept changes when the puzzle is wrong. If swapping two tiles moves what they receive by less than the smallest visible step, then the solved board and the broken board are the same thing to them. The player is not being asked to see something. They are being asked to guess.

Measured on the exact projection, not on the squares above — for the same reason section 2 gives. On “blue → purple” under deuteranopia the two answers are far enough apart to move this demo’s own verdict from one band to the next, so it is not a distinction without a difference.

This is not fixable by choosing better colours, because the defect is in the verb. A game built on “put these in order” is closed to a dichromat however the palette is chosen. A game built on “is this the same as that” is not. That is why the game this page belongs to has five verbs and every one of them is an identity judgement.

The two games this is really about, and exactly how far we are entitled to go

The genre described above is I Love Hue and Blendoku, and honesty requires being precise about which parts of that are measured and which are quoted.

  • Measured here, by us: the demonstration above. A gradient, simulated with the shipped CVD model, with the ordering collapsing. That is a claim about the verb — arrived at from the model, not from playing anything.
  • Not measured here: either shipping app. There is no official web build of either, and neither is installable on the machine this was built on. Where this project needed a playable comparison it built documented reconstructions of the two loops and compared against those, and every published comparison says so. This page makes no claim about the difficulty or quality of either product.
  • Quoted, with attribution: Blendoku’s own developer, Rod Green of Lonely Few, writing about the colourblind mode he shipped: “there could still be cases where you’re unable to distinguish all the colors in a level regardless of how much you color shift.” (Guest post via Evolve PR, 27 June 2013.) That is a developer describing the exact hole this page measures, in his own product, in writing, before anybody outside had to.
  • Also quoted: this project’s research file on I Love Hue records that it found no colourblind mode in either I Love Hue title, and that the App Store accessibility panel for both reads “The developer has not yet indicated which accessibility features this app supports.”

None of that makes either game bad. Both are well made and enormously popular. It makes them structurally closed to a set of players — and that is a different, more specific, and more useful thing to say.

6.2 Category collapse — the sharper version of the same problem

It goes further than order. A conforming palette keeps every pair far apart, and the same palette can still lose its categorical structure entirely. Below, the hue angle of each palette colour is plotted under each condition. Under typical vision they spread out. Under each dichromacy they fall into clusters — and colour working memory leans on exactly that categorical structure [9].

Clustering rule, stated so you can check it: a colour counts as chromatic if its CAM16 colourfulness M exceeds 5 (below that a colour has no meaningful hue), and two chromatic colours are in the same hue cluster if their CAM16 hue angles are within 30°, wrapping around the circle. Change the rule and the counts change; the collapse does not.

What survives: telling them apart. What does not: which ones feel like they belong together. A design that leans on “the warm ones mean X” is leaning on something the guarantee never promised.

07

The negative control

A checker that passes everything is worthless, however green its output. So the engine ships a family of deliberately broken twins: same size, same lightness spread, same “looks like a real palette”, one defect each. The same checker that clears the real palette must reject them, and name the pair and the condition that did it.

A real palette and its twin, side by side

Look at the two rows before you look at the verdicts. They are equally plausible. Both have a sensible lightness spread, both would pass a glance, and one of them would ship. The difference is not visible in the swatches — it is visible in the measurement, which is the entire point of having one.

08

Citations

One invented citation destroys the credibility of every correct one beside it. Everything below was read first-hand during this build. Where a source did not say what was hoped, that is recorded rather than papered over.

  1. Li, C., Li, Z., Wang, Z., Xu, Y., Luo, M. R., Cui, G., Melgosa, M., Brill, M. H. & Pointer, M. (2017). “Comprehensive color solutions: CAM16, CAT16, and CAM16-UCS.” Color Research & Application 42(6), 703–718. doi:10.1002/col.22131 The distance of record. Every ΔE′ on this page is Euclidean distance in CAM16-UCS, with KL = 1.
  2. Brettel, H., Viénot, F. & Mollon, J. D. (1997). “Computerized simulation of color appearance for dichromats.” Journal of the Optical Society of America A 14(10), 2647–2655. doi:10.1364/JOSAA.14.002647 The dichromacy model implemented here — the full two-half-plane projection, not the single-matrix shortcut.
  3. Viénot, F., Brettel, H. & Mollon, J. D. (1999). “Digital video colourmaps for checking the legibility of displays by dichromats.” Color Research & Application 24(4), 243–252. Implemented as a cross-check only. It is a single-plane approximation valid for protan and deutan; the engine refuses to use it for tritan, because doing so is a known error.
  4. Machado, G. M., Oliveira, M. M. & Fernandes, L. A. F. (2009). “A physiologically-based model for simulation of color vision deficiency.” IEEE Transactions on Visualization and Computer Graphics 15(6), 1291–1298. Second cross-check model. Matrices transcribed from the authors’ own published tables at inf.ufrgs.br/~oliveira.
  5. Smith, V. C. & Pokorny, J. (1975). “Spectral sensitivity of the foveal cone photopigments between 400 and 500 nm.” Vision Research 15(2), 161–171. The cone fundamentals the Brettel implementation uses, with the Judd–Vos modified colour matching functions tabulated by the Colour & Vision Research Laboratory (cvrl.org).
  6. IEC 61966-2-1:1999. Multimedia systems and equipment — Colour measurement and management — Part 2-1: Default RGB colour space — sRGB. Transfer function, primaries, and the 64-lux reference viewing environment that fixes the CAM16 adapting luminance.
  7. W3C. Web Content Accessibility Guidelines (WCAG) 2.2, W3C Recommendation, 12 December 2024. w3.org/TR/WCAG22 Definition of relative luminance — the 0.2126 / 0.7152 / 0.0722 coefficients the grey condition uses.
  8. Somers, A. (Myndex Technologies). APCA — Advanced Perceptual Contrast Algorithm, algorithm revision SA98G (“0.98G-4g”), revision date 3 July 2022. Reference implementation apca-w3 0.1.9 — github.com/Myndex/apca-w3, read here from two independent copies (the git tree and the pinned npm tarball) which agree character for character. Provenance, corrected. This is not a W3C publication and there is no such thing as a “W3C Beta 0.1.9” — apca-w3 is a package name and 0.1.9 is that package’s version. APCA is independent work by its author, who is a W3C Invited Expert; it appeared in WCAG 3 working drafts as exploratory content and was removed from the July 2023 draft, and the current WCAG 3 editor’s draft says the contrast algorithm for WCAG 3 is still undetermined. So it is cited here as a stable, versioned, public algorithm that reproduces its own published reference values to the bit, and as nothing more. Chosen over WCAG 2.x ratios for text on coloured tiles because WCAG 2’s ratio is a known-poor predictor at mid lightness, which is exactly where a chromatic palette lives — and WCAG 2.2 ratios are computed and reported alongside so nobody has to take the choice on faith. And one thing it is not: a second safeguard. APCA is a luminance-only model, and the grey observer condition is luminance too — so the contrast rule and the greyscale clause are the same physical quantity asked two different questions (can this text be read on that tile versus are these two tiles apart), not two independent lines of defence. Passing both is one safeguard measured twice.
  9. Bae, G.-Y., Olkkonen, M., Allred, S. R. & Flombaum, J. I. (2015). “Why some colors appear more memorable than others: A model combining categories and particulars in color working memory.” Journal of Experimental Psychology: General 144(4), 744–763. Quoted for one thing only, verbatim from the abstract: “responses drawn from working memory are significantly biased away from category boundaries and toward category centers.” This is why section 6.2’s category collapse is a real cost and not a curiosity.
  10. Luck, S. J. & Vogel, E. K. (1997). “The capacity of visual working memory for features and conjunctions.” Nature 390, 279–281. About four colours held at once. Cited for scale: the wall this page measures is above what a person comfortably holds anyway.
  11. Okabe, M. & Ito, K. (2008). Color Universal Design (CUD): How to make figures and presentations that are friendly to colorblind people. J*FLY, jfly.uni-koeln.de/color Provenance note, because it matters. That page presents the palette as an image, not as numbers — we fetched it and confirmed the hex values are not in its text. The eight sRGB values measured in section 5 are the ones distributed as the "Okabe-Ito" palette in R’s grDevices (src/library/grDevices/R/colorstuff.R), where they are attributed to “Masataka Okabe & Kei Ito” with a link to the J*FLY page. R’s table carries a ninth entry, gray = #999999, which is R’s own addition and is not measured here.
  12. Brewer, C. A. & Harrower, M. ColorBrewer 2.0, colorbrewer2.org; scheme definitions read from colorbrewer2.org/export/colorbrewer.json. See also Harrower, M. & Brewer, C. A. (2003). “ColorBrewer.org: An online tool for selecting colour schemes for maps.” The Cartographic Journal 40(1), 27–37. Dark2 and Set2 are read from that JSON export as RGB triples and converted to hex. The export does not carry a colourblind-safe flag, so no claim about ColorBrewer’s own safety marking is made from it here.
  13. Tol, P. Colour Schemes (Paul Tol’s Notes), SRON personal pages, sronpersonalpages.nl/~pault The bright, high-contrast, vibrant, muted, medium-contrast and light qualitative schemes, read from that page during this build. The page as fetched carries update dates but no technical-note number, so none is cited.
  14. Ottosson, B. (2020). A perceptual color space for image processing (OKLab). bottosson.github.io/posts/oklab Implemented as a cross-check only. Agreement between the two rankings is evidence the implementation is sane; CAM16-UCS is the number of record.
  15. CIE 159:2004, A colour appearance model for colour management systems: CIECAM02. Source of the convention LA = LW × Yb/100, carried into CAM16 unchanged. Section 9 records how getting this wrong once moved our numbers.
  16. Mahy, M., Van Eycken, L. & Oosterlinck, A. (1994). “Evaluation of uniform color spaces developed after the adoption of CIELAB and CIELUV.” Color Research & Application 19(2), 105–121. doi:10.1111/j.1520-6378.1994.tb00070.x Cited for exactly one figure and no more: the widely-used ≈ 2.3 ΔE per just-noticeable difference, which in that paper is a mean discrimination-ellipse radius in CIELAB, reported with a coefficient of variation of roughly 57 % — an average of something that varies by about half its own size across the space. Section 1 uses it once, hedged, and only as a divisor: Δ over 2.3, printed live, rather than the folk version that multiplies Δ by one. Two caveats travel with it and are printed there: it is a CIELAB figure being borrowed for a CAM16-UCS scale, and it is an average, not a constant.
  17. Birch, J. (2012). “Worldwide prevalence of red-green color deficiency.” Journal of the Optical Society of America A 29(3), 313–320. doi:10.1364/JOSAA.29.000313 Cited in section 1 for the size of the population this page draws a boundary through, and for nothing else. Its abstract, read first-hand, reports inherited red-green deficiency at about 8 % of European Caucasian men and about 0.4 % of women, and between 4 % and 6.5 % of men of Chinese and Japanese ethnicity. What we wanted from it and did not take: the abstract does not split anomalous trichromacy from dichromacy — that split is in the paper’s Table 4, which we did not read — so no such figure is published here, and section 1 says so instead of rounding one up from memory.
09

What is proved, what is not, and what moved

Proved

Searched hard and not found — which is a different thing

Simulated, and therefore not a claim about any real person

This is the one that cannot be closed in software, so it is declared rather than solved. Every dichromatic figure on this page is produced by Brettel, Viénot & Mollon 1997 [2], a published model of dichromatic appearance. It is a model.

Things this page says that we could not reproduce

What moved during the build

How to check any of it yourself

Open the console on this page. The whole computed dataset is on window.__explainer — every table, every measurement, with the engine’s own objects attached. Or run the engine directly: it is ESM with zero dependencies, and the same files run in Node and in the browser with no build step.