Polyatic Color Blindness Simulator
All tools

Color Blindness Simulator

See an image, a palette or your live camera through the common partial forms of color blindness — not only the complete ones.

1.00

Severity 1.00 models complete loss of the cone — dichromacy: protanopia, deuteranopia, tritanopia.

Colors · hex or CSS · up to 12

Safe palettes

Published palettes built with colour-blind viewers in mind. Pick one to load it into the grid and see how it holds up under each deficiency, then copy it for your code.

Okabe–Ito shown. Click a palette to load it into the grid.

Source: Okabe & Ito 2008, Color Universal Design; values as printed in Wong 2011, Nature Methods 8:441

Copy as
["#000000", "#E69F00", "#56B4E9", "#009E73", "#F0E442", "#0072B2", "#D55E00", "#CC79A7"]

Paste a whole stylesheet if you like — the tool extracts every #rrggbb and #rgb value it finds, keeps the first twelve, and drops duplicates. A red and a green that look distinct to you often collapse to one muddy tone under deuteranopia; this grid shows exactly when that happens.

Nothing leaves your browser. Every color is transformed with plain JavaScript on your device — no uploads and no server. The page keeps working with your network disconnected.

Offline later: once you have opened this page with a connection, it reopens and works with none — your browser keeps a copy. Not saved: the very first Polyatic page you ever open (open it again while online), and any page or link you have never opened.

Under each deficiency —

Close pairs

—

How this is measured. Each column's colors are compared after simulation with CIEDE2000 (ΔE00), the CIE's 2001 color-difference formula, on CIE L*a*b* under the D65 2° standard observer. Every pair closer than ΔE00 10 is named above, closest first. The little chips are the simulated pair; the hex beside them is the color you typed.

The 10 is our working convention, not a standard. There is no WCAG success criterion for palette separation, so nothing here passes or fails anything. CIEDE2000 was fitted to small differences — roughly ΔE00 1 is one just-noticeable difference between two large patches side by side under controlled light — so stretching it to “two chart swatches, glanced at, on different backgrounds” is an extrapolation we chose, at ten JNDs. Read a named pair as a prompt to look at the two chips yourself, not as a verdict on the palette.

Method & honest limits. The protan, deutan and tritan views use the peer-reviewed matrices of Machado, Oliveira & Fernandes (2009), “A Physiologically-based Model for Simulation of Color Vision Deficiency” (IEEE TVCG 15(6)) — the whole published severity ladder, 0.0 to 1.0 in steps of 0.1, so this page shows the partial -anomaly forms (protanomaly, deuteranomaly, tritanomaly) as well as the complete -opia ones at severity 1.0. A severity between two published steps is a linear interpolation of the two nearest matrices, the approximation the authors' own tutorial prescribes; nothing is fitted or eyeballed here, and no result is faked by fading the full-strength output back toward the original. Achromatopsia is a Rec.709 luminance grayscale at full strength and ignores the slider — achromatomaly, its partial form, is not modelled, because this model publishes no ladder for it. All transforms run in linear light — sRGB is decoded to linear RGB, the matrix is applied, values are clamped to the display gamut, then re-encoded — because color mixing is linear in light, not in gamma-encoded hex. This is an approximation of how a color-blind person perceives color, whether the partial or the complete form, and it is not a diagnosis and not medical advice; real vision varies between people, and no screen model replaces testing with color-blind users.

What color blindness actually is

Typical human color vision uses three types of cone cell, each most sensitive to a different band of light: L (long / red), M (medium / green) and S (short / blue). Color blindness is not seeing in black and white — it is usually one cone type being missing or shifted, which collapses part of the color space so that colors that used to be distinct now map to the same sensation. A missing cone is dichromacy; a cone that is present but whose peak sensitivity has slid toward its neighbor is anomalous trichromacy, and that is the partial form this tool's severity slider exists for.

How common is color blindness?

Congenital red-green color vision deficiency affects roughly 8% of men and under 1% of women of European ancestry, and the figures come from reviews you can check rather than from us. Jennifer Birch, Worldwide prevalence of red-green color deficiency, Journal of the Optical Society of America A 29(3), 313-320 (2012), doi:10.1364/JOSAA.29.000313, reports about 8% in men and about 0.4% in women in European Caucasian populations, and between 4% and 6.5% in men of Chinese and Japanese ethnicity. M. V. Simunovic, Colour vision deficiency, Eye 24(5), 747-755 (2010), doi:10.1038/eye.2009.251, gives as many as 8% of males and 0.5% of females. The sex difference is because the L and M cone opsin genes sit on the X chromosome, of which men have one copy. This page puts no number on how that total splits between the partial forms and the complete ones, because we have no source for that split we could cite here; what is not in dispute is that the partial forms are the more common ones.

What this tool shows — and what it does not

Three cone types, each across the full published severity range, plus achromatopsia at full strength. The severity slider is the difference between an -opia (the cone is gone) and an -anomaly (the cone is there but shifted) — and those -anomaly forms are the more common ones, which is why the slider sits next to the mode tabs rather than buried below the fold.

ConePartial
(severity 0.1–0.9)
Complete
(severity 1.0)
L (red)ProtanomalyProtanopia
M (green)DeuteranomalyDeuteranopia
S (blue)TritanomalyTritanopia
none (rods)not modelledAchromatopsia

Can I see my image under every type of color blindness at once?

Yes. In Image mode the original and all four simulations (protan, deutan, tritan and achromatopsia) are shown together in one grid, at whatever severity the slider is on, and they redraw as you drag it. Each panel is made by the same transform as the large view, so the grid and the large view never disagree. Click any panel to see it large, or use Download comparison sheet to save one labelled PNG of all five, each caption naming the form at the severity on screen, such as Deuteranomaly at severity 0.60; the achromatopsia caption says severity does not apply. Download PNG and Copy image still save only the one simulation you have selected.

Why it matters: a chart that survives deuteranopia can still fail under tritanopia, where blue and green merge instead of red and green. On the built-in sample, the green #2ca02c and the blue #1f77b4 bars stay about 50 ΔE00 apart for full protan and deutan viewers, but under full tritanopia they become two teals, #009b89 and #00868d, only 11.9 apart — barely past this page's “close” line of 10. Clicking through tabs one at a time, that is easy to miss; side by side it is not. The sheet is sized from your image — the 720×300 sample makes a 2288×928 PNG — so small detail in a screenshot stays legible.

Protan and deutan are the two red-green deficiencies and behave similarly, with one telling difference: a protanope also sees reds as darker (their missing cone was the one most sensitive to red light), while a deuteranope keeps roughly normal brightness. Tritan is a blue-yellow loss and is much rarer; unlike red-green it is not sex-linked. Achromatopsia is the absence of usable color vision altogether — everything arrives as shades of gray. The row that matters for honesty is the last one: achromatomaly — the partial form of achromatopsia — is not modelled here. The model behind this page publishes a severity ladder for the three cone-loss types and nothing else, so the achromatopsia column and tab are always full-strength grayscale and simply ignore the slider. Blending the grayscale back toward the original image would look like a partial form without being one, and it is exactly the shortcut Machado's paper was written to criticize.

Camera mode: the world through the same model, live

Camera mode runs the simulation on your camera instead of on a file. It asks for permission only when you press Camera (or Start camera) — never when the page loads, and not when a #camera link opens the tab. Each frame is decoded from sRGB to linear light, multiplied by the same published Machado matrix Image mode uses for the type and severity on screen, clamped and re-encoded; it runs as a small WebGL shader at up to 1280 px on the long edge, and where WebGL is missing it falls back to the Image-mode transform itself at up to 480 px. The page's test checks that a pixel of the processed camera frame matches Image mode's result for the same RGB value within 2 levels per channel.

What it is good for: checking things you cannot screenshot — a printed chart, a transit map on the wall, an LED status light, a paper form with red and green ticks, a warehouse colour code. Use the before/after slider to put the original and the simulation side by side in one view, then Freeze to hold the frame and click through Protan, Deutan and Tritan and drag severity on the very same picture. Save PNG downloads that frozen frame, fully simulated, at the processed resolution. Nothing is recorded, no video is kept, and no frame is sent anywhere; Stop, switching to another mode, or leaving the tab ends every camera track.

An honest limit: the camera is not your eye. Auto white balance, exposure and the sensor's own colour processing have already changed the colours before the model sees them, and a dim room adds noise that can look like colour. Treat the camera view as a quick field check; for a chart or a palette you made, the exact numbers in Palette mode are the measurement.

What the severity slider means

Severity 1.0 is the complete form: the cone is missing, and the result is dichromacy — protanopia, deuteranopia or tritanopia. Severity 0.0 is normal color vision; Machado et al. publish that step as the identity matrix, so the colors come back unchanged and the grid shows five identical swatches. Everything in between is anomalous trichromacy — protanomaly, deuteranomaly, tritanomaly. Moving the slider changes the swatch grid, the image canvas and the close-pairs measurement together and live, so what is measured is always what is on screen. Achromatopsia ignores the slider, because there is no published ladder for it.

Concretely, on the sample palette: the green #2ca02c and the orange #ff7f0e land 1.4 apart under full protanopia (severity 1.0) — #a39119 and #a59100, the same olive. Ease the slider back to 0.70 protanomaly and they separate to 12.2, already past this page's “close” line of 10; at 0.50 they are 21.5 apart, and at 0.30, 32.9 — two plainly different colors. That gradient is the whole argument for the control: a palette can be unusable at severity 1.0 and perfectly workable at 0.5, and a tool that only ever shows 1.0 cannot tell you where the line falls. Drag the slider yourself and watch the numbers under the grid move — they are recomputed at whatever severity is on screen, never at 1.0.

How the simulation is computed

Each pixel travels through the same short pipeline. Its sRGB channels (the 0–255 numbers behind the hex code) are first linearized — sRGB is gamma-encoded so its values are perceptually even rather than proportional to light, and cone responses are linear in light. The linear triple is then multiplied by a published 3×3 simulation matrix for the chosen deficiency, the result is clamped back into the [0,1] display gamut (a projection onto a reduced color space can otherwise land just outside it), and finally re-encoded to sRGB. Achromatopsia skips the matrix and instead computes Rec.709 luminance — 0.2126·R + 0.7152·G + 0.0722·B in linear light — so the gray it produces matches how bright each color truly is.

Two details matter for honesty. First, the matrices are copied verbatim from Machado, Oliveira & Fernandes (2009) — all thirty-three of them, three types by eleven severity steps, taken from Table 1 of the authors' own data page; they are not eyeballed or tuned here, and the partial forms are real published matrices rather than the full-strength result faded back toward the original. Where you pick a severity between two published steps, the two nearest matrices are linearly interpolated, which is the approximation the authors' tutorial itself recommends (“to compute the matrix for a case of severity 0.873, the matrices 0.8 and 0.9 can be interpolated with a weight of 0.73”). Second, doing the multiply in linear light rather than straight on the gamma-encoded hex is the step most web simulators skip — and skipping it visibly shifts hues and crushes midtones. You can verify the pure math yourself: the compute is exported as a Node module with committed golden-vector tests, including one that pins severity 1.0 to the values this page shipped before the slider existed and one that pins severity 0.0 to returning your color unchanged.

How close is too close?

Under the swatch grid the tool names the pairs that have moved close together. The distance is CIEDE2000 (written ΔE00), the CIE's 2001 color-difference formula, computed on CIE L*a*b* under the D65 2° standard observer — and computed after the simulation at the severity currently selected, so it measures the colors actually on screen rather than the ones you typed, and never quietly reports severity 1.0 while the grid shows something else. Every pair in a column is compared, so eight colors means 28 comparisons per column and 140 across the five columns.

The sample palette makes the point in three lines. In the original column its closest pair, #e2001a and #ff7f0e, sits 26.0 apart — comfortable. Switch to protanopia and #2ca02c and #ff7f0e land 1.4 apart: a green and an orange that have become the same olive. In full grayscale the red #e2001a and the blue #1f77b4 land 0.8 apart, because they were picked for hue and happen to share a luminance — the failure you would never catch by eye in the color version.

The threshold is a convention, and it is ours. This page names any pair under ΔE00 10. There is no WCAG success criterion for palette separation: the closest one, 1.4.11 Non-text Contrast, asks for a 3:1 luminance contrast ratio between a graphical object and what sits next to it, which is a different measurement answering a different question — it is not a rule that two categories in a legend must be a given ΔE00 apart. So nothing here passes or fails a standard, and this page does not award one. CIEDE2000 itself was fitted to small differences: roughly ΔE00 1 is one just-noticeable difference between two large patches shown side by side under controlled light. Ten of those is a deliberately generous line for swatches that are small, separated by whitespace and glanced at. Read a named pair as a prompt to look at the two chips yourself, not as a verdict on the palette.

Suggested fix: a replacement color for each close pair

Naming a clash is half the job; the other half used to be trial and error. For every flagged pair the tool now proposes one replacement, and it holds that color to a stricter test than the clash that triggered it: the new color must sit at least ΔE00 10 from every other color in the palette in all five columns — as typed, protan, deutan, tritan and grayscale — at severity 1.0 and at the severity on screen, and its WCAG contrast against the background you pick must stay on the same side of 3:1 (the Non-text Contrast line for chart marks) as the color it replaces. Among colors that pass, it picks the one nearest the original. The search is a fixed grid over OKLCH, tried in order: lightness alone in 0.01 steps; then lightness and chroma in 0.01 steps; then a hue shift of at most 30° in 5° steps (with lightness and chroma in 0.02 steps); and only then any hue, in 10° steps. Lightness goes first because every color-vision deficiency keeps it, hue last because it is what makes your red still read as your red. Colors outside sRGB are skipped, not clipped.

A worked example: chart red #d62728, green #2ca02c and blue #1f77b4. Under deuteranopia the red and green land 4.8 apart, and in grayscale the red and blue land 1.2 apart. The suggestion is #b00c16, a darker red 9.0 from the original, whose closest approach to anything in any column is 10.1 — one change clears both of the red's flags, and contrast on white rises from 5.0:1 to 7.2:1. The third flag, green and blue at 9.6 in grayscale, gets its own suggestion: the slightly lighter, softer green #5ba358. The honest limit: crowded palettes run out of lightness. With seven or eight colors the grayscale column alone needs seven gaps of about 10, and sometimes nothing within ΔE00 25 fits; the tool then says so and points you to a pattern, a marker shape or a direct label, which is the right fix anyway.

Share a palette as a link

The address bar follows the Colors box: type or paste a palette and the URL becomes /color-blindness-simulator/#palette=0072b2,e69f00,009e73&sev=100, and Copy link puts the full address on your clipboard. Whoever opens it — a colleague, a design review ticket, or an AI assistant answering “are these brand colors color-blind safe?” — lands on the same swatches with every column simulated and the close-pair verdicts already written out, without pressing anything. The rules are deliberately forgiving: 3- or 6-digit hex, the # optional (or written %23), commas between values, up to 12 colors, and an optional sev= from 0 to 100 (the slider moves in steps of 5, so 37 opens as 0.35). A value that is not a color is named under the box — #palette=zzz,00aa00 says it could not read “zzz” and shows the green alone — instead of being dropped silently.

As a worked example, the three Okabe–Ito colors in that link (blue #0072b2, orange #e69f00, bluish green #009e73) clear the ΔE00 10 line in every column; their tightest spot is orange against green in grayscale at 10.7. Swap in #palette=ff0000,00aa00 and the page flags the pair under deuteranopia at 2.6 apart. The colors live only in the part of the URL after #, which browsers never send to a server, so sharing a link shares the palette with its recipient and nobody else.

Colour-blind-friendly palettes to copy: where they come from and how they hold up

The Safe palettes picker in palette mode holds seven published palettes. Picking one puts it in the grid, so you judge it with the same ΔE00 line as your own colors, and Copy as gives it to you as a hex list, CSS custom properties (--okabe-ito-1…), a Python list you can pass to matplotlib (plt.rcParams['axes.prop_cycle'] = cycler(color=[…])), an R vector for scale_colour_manual(values = c(…)), or one hex per line to paste down an Excel column. Each one also opens from a link: #palette=okabe-ito, #palette=tol-muted, #palette=viridis-5.

  • Okabe–Ito (8 colors): Masataka Okabe and Kei Ito, Color Universal Design (2008), with the RGB values printed by Bang Wong, “Points of view: Color blindness”, Nature Methods 8, 441 (2011).
  • Tol bright (7), vibrant (7), muted (10, the last a pale grey Tol keeps for missing data) and high-contrast (5, including black and white): Paul Tol, Colour Schemes, SRON technical note SRON/EPS/TN/09-002, in the order of Tol’s own tol_colors module.
  • viridis and cividis at 5–9 stops: matplotlib’s _cm_listed.py, whose 256-entry tables these are sampled from. Stop k of n is entry min(255, ⌊k·256/(n−1)⌋), converted with round(v·255) per channel — the same entries colormaps['viridis'].resampled(n) picks, so five viridis stops are #440154 #3b528b #21918c #5ec962 #fde725 here and in Python.

“Designed for color-blind viewers” is not the same as “every pair is far apart”, and the grid shows where each one is thin. At severity 1.0, all 8 Okabe–Ito colors stay at least ΔE00 11 apart under protanopia, deuteranopia and tritanopia, but in grayscale 7 pairs fall under 10 — orange and sky blue are 0.6 apart — so it still needs a second cue if the chart may be printed in black and white. Tol high-contrast’s 5 colors clear the line in every column, grayscale included (closest 17.8). Tol bright has one tritan pair under the line (blue and green, 8.7). viridis and cividis are built to be read as an ordered ramp: at 5 stops both clear every column, but neighbouring stops close up as you add more — at 9 stops viridis’s two yellowest stops are 4.5 apart under protanopia — which is fine for a heat map and poor for telling 9 categories apart.

Make it readable: recolouring an image you cannot redraw

Simulation tells you a chart fails; it does not fix it. When you cannot go back to the source — a screenshot of someone else's dashboard, a scanned map, a slide from a deck — the Make it readable switch in Image mode daltonizes the picture for one type. Each pixel is simulated with the same Machado matrices as the rest of the page, the error (original minus simulation, the colour information that viewer loses) is computed in linear light, and that error is shifted into the channels the type still separates with the Fidaner et al. error-shift matrix: for protans the lost red signal goes into green and blue, for deutans the lost green signal into red and blue, for tritans the lost blue signal into red and green. Greys have no error, so they come back unchanged, and the strength slider scales how much of the shifted error is added. A worked example: matplotlib's default red #d62728 and green #2ca02c sit only 4.8 ΔE00 apart for a deuteranope — below the 10-unit line this page treats as "collapsing" — and after deutan recolouring at 100 % they become #fa2700 and #00a053, 13.0 apart under the same simulation (8.8 at 50 %). The honest costs: the recolouring changes how the image looks to everyone else (that red moves about 10 ΔE00, the green about 7), it is tuned for the one type you pick, saturated colours already at the edge of the sRGB gamut have little room to move and are clamped, and a photo can come out with odd casts. It is a reading aid, not a design fix: for anything you can still edit, direct labels, patterns or line styles and a real lightness gap work for every viewer at once and change nothing for anyone.

Designing so color-blind users aren't left out

The single most useful rule is never encode meaning with color alone (it is literally WCAG success criterion 1.4.1). Practical moves that survive every type above:

  • Add a second channel. Pair color with text labels, icons, shapes, or patterns — a dashed vs solid chart line reads even in full grayscale.
  • Lean on lightness. Color blindness largely preserves luminance contrast, so a clear light-vs-dark gap between two swatches keeps them apart when hue fails. Our contrast checker measures exactly that gap.
  • Prefer blue/orange over red/green. Blue and orange stay distinct under all the common red-green types; red and green are the classic trap.
  • Test the worst case, then the common case. Run your real screenshots and palettes through severity 1.0 here — if two things must be told apart and they merge, fix the design, not the simulator. Then walk the slider back through the partial forms to see how much of the range the problem actually covers.

Honest limits

This is a model, not a person. It renders one representative version of each deficiency at each severity step; actual color perception varies between individuals, shifts with lighting and adaptation, and two people given the same severity label on a clinical test will not see identically. The severity number here is the model's parameter, not a clinical grade, and there is no mapping on this page between it and an anomaloscope reading or any diagnostic scale. Achromatomaly is not modelled at all. The tool works in sRGB and treats wide-gamut (Display-P3) content as sRGB. It is not a diagnosis and not medical advice, for the partial forms every bit as much as the complete ones — if you want to know your own color vision, an eye-care professional administers proper tests (Ishihara plates, the Farnsworth-Munsell 100 hue). What it is good for is a fast, private check that your images and palettes still communicate across the range, not just at the worst case. Everything runs locally; nothing you load is uploaded.