The HTML5 Chromaticity Plotter

Accessing image data via javascript and plotting it on an xy diagram. All in the comfort of your own browser!

No browser drag & drop support! Sorry.
Drag & Drop Your Own Image Here!

How it works

This is a demonstration of accessing RGB image data via the HTML5 canvas. Everything happens on the client side — in the browser. It requires no round trip to the server. The ability to manipulate images with javascript on the client side is exciting and opens a lot of possibilities. It does, however, require a modern browser to work. It should work in recent versions of Chrome, Safari, and Firefox. I didn't test it in Internet Explorer, but I expect it will work with the latest version or two.

To access the data, the image must be drawn into a canvas element. This element does not need to be part of the DOM tree, you can make one in javascript with: document.createElement('canvas'); and it will remain invisible to the user, but you can still draw to it. Once the canvas contains the image, the data can be read with javascript's getImageData() function.

To make the xy diagram you need to step through each pixel and convert from RGB to XYZ and then to xyY. These points are then plotted on a new canvas element with the coordinates x & y (scaled so the diagram is a reasonable size) and with the color of the original pixel from the image.

A few notes

The data from the canvas arrives as a one-dimensional buffer of RGBa values rather than a more convenient matrix where each element represents a single RGB pixel. This is very efficient, but it makes a little extra work for us. The first element in the buffer is the red value of the first pixel followed by the green, and then the blue, and finally the alpha value. The next pixel begins at the fifth element. If you are looking for a specific pixel at image coordinates (x, y), it's red value will be found at:
(x + y * image.width) * 4.

In every browser I tested, by the time the image is drawn to the canvas it has been converted to sRGB. You can see this quite clearly with the included image that covers the sRGB gamut almost perfectly. This is reasonable behavior for a web browser and is in line with the canvas specification. But it means we can't upload a ProPhotoRGB image and marvel at the vastness of its gamut or easily compare images from different color spaces. Sadly, this limits this particular tool to a novelty and simple demonstration, but it doesn't mean that client side image manipulations don't have a lot of interesting potential.

Be aware that the chromaticity diagram is a two-dimensional representation of three-dimensional data. Many different colors can have the same xy coordinates. I've made no attempt to influence the order in which they are drawn on the canvas. It's possible that the amazing color you are looking for on the diagram was drawn underneath its darker cousin. Also, many dark colors that look black or near-black are numerically very saturated and will be plotted at the edge of the RGB gamut. A color such as RGB[3, 0, 0] looks black but is actually pure dark red and will sit at the same xy coordinate as the red primary of the space. This is especially noticeable in the image that loads with this post where the dark colors seem to create an outline around the triangle-shaped sRGB gamut. It may be helpful to cull these values before plotting.

If you really want to figure it out, take a look at the source — specifically the colorplot.js file. It's not very complicated and I've tried to annotate it with helpful comments.


This font is Kulturista Web by Suitcase Type Foundry, served from Typekit.

Javascript, css, and html were hand-coded in BBedit on a Mac by Mark Meyer with the help of Safari's developer tools. Some of the grunt work under the hood has been made easier by jQuery.

The color checker image is from BabelColor who makes some really cool color analysis software.

If you like nerdy web experiments, you might also like this scrolling version of an historic chess game.

Never tested on animals or Internet Explorer.

Mark Meyer • Anchorage, Alaska@markmeyerphoto