The Visual Gamut Boundary

Generate the points and draw the image

color space: 

sampling increment:  nm (smaller values make everything run slower)


inner arrows: 10°
outer arrows: 45°
↺: reset

Redraw the image

saturate  1.2

scale canvas: 
scale dots: 


List the points



list | select all | clear | (high numbers of points may slow the browser)


λ 400 500 600 700 800 nm x y z

What does the Lab visual gamut look like? How is the xy chromaticity diagram generated? The visual gamut boundary may be delineated by passing square wave pulses through the CIE XYZ color matching functions. Something like mapping the edges of a nebula by shooting photon torpedoes at it. For details, please see Computing XYZ From Spectral Data and About the Lab Gamut at

Start with the 1931 2° CIE Standard Colorimetric Observer Data (“Full set of 1nm data,” all_1nm_data.xls) at the Rochester Institute of Technology. The color matching functions are lookup tables, x, y, and z for each sampled wavelength λ. They start like this and go to 830 nm. Graphed, they look like the figure on the right.

 λ	     x		     y		     z
360	0.0001299	3.917E-06	0.0006061
361	0.000145847	4.393581E-06	0.0006808792
362	0.0001638021	4.929604E-06	0.0007651456

Then generate X, Y, and Z for each pulse as follows. xλ, yλ, and zλ are the values of the color matching functions at the specified wavelength. Pλ is the spectral power at the specified wavelength, which for a square wave is either 0 or 1. Instead of using Δλ, I normalized the output by dividing by the sum of the function values at all the wavelengths in use, accounting for the sampling increment and interpolated values.


Finally, convert the XYZ values to another color space such as Lab or xyY if desired, and graph them in three dimensions. Simple!

The script above graphs the visual gamut boundary in the Lab, Lu′v′, xyY, or XYZ color space. A sampling increment of 1 nm uses all the values in the color matching functions; smaller increments are interpolated. Smaller increments mean more points (~ inverse square) and a smoother outline, at the expense of slower rendering. Scaling the dots is less resource-intensive. A solid outline can make an attractive image, but gaps between the points make the contours easier to see.


The dots are colored using an RGB matrix based on primaries at the very corners of the xy chromaticity diagram, a slightly larger space than Wide Gamut RGB. This minimizes the artifacts seen when using smaller RGB spaces; there is still a hint of a streak running from the blue corner to the top. The colors may be further saturated to suit your taste.

Generating the points can take a relatively long time; redrawing them by rotating the axes, or scaling the canvas and/or the dots, runs much faster. The values are normalized to 0-100 and drawn at their actual pixel positions in space. Scaling and fitting the canvas zooms in on the figure.

Lab points with 0-1 RGB values may be incorporated into the kind of X3DOM files generated by viewgam, part of ArgyllCMS. Turn them into something like this:

<transform translation="39.24 29.70 17.24"> 
      <material diffusecolor="0.281 0.094 0.000"></material>

Side note, the inclusive a and b values for the Lab visual gamut are -165 to +145 and -145 to +146.

To answer the questions posed above:
1. The Lab visual gamut looks like a psychedelic liver.
2. The xyY and Lu′v′ chromaticity diagrams may be generated by drawing the relevant color spaces and resetting the rotation.