Count pixels by color in the browser using JavaScript and the HTML 5 Canvas Element
I recently wrote a small Python script that accepted an image file and returned the count of pixels per a unique color. The script worked great for my use case (making 8-bit pixel art), and it has saved me a lot of time.
Unfortunately, the command line interface makes it difficult for others to use. I wanted to make the application more accessible for those who aren’t command line savvy nor want to download Python and my script. The best alternative: running the pixel counter in the browser. Thus Canvas Pixel Color Counter was born!
Canvas Pixel Color Counter
Canvas Pixel Color Counter accepts an image and displays the total number of pixels per a color within the image.
I wrote the web app in plain ole JavaScript, CSS and HTML. It was a good exercise to use vanilla JS over a framework, and this project was the first time I needed to write a web worker.
The application was designed with small 16×16 or 32×32 images in mind, but will work for larger images as well. (Be prepared to scroll a lot!)
Canvas’ ImageData Object
The main star of the application is the ImageData
object of the canvas
. This object facilitates pixel manipulation by storing the canvas’ pixel data.
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
ImageData
has three properties: height
, width
, and data
. data
is an Uint8ClampedArray
containing the RGBA values of each pixel within the canvas.
Each pixel represents 4 bytes of data within the Uint8ClampedArray
. The Red, Green, Blue and Alpha values are one byte each and appear in the array in that order.
To get the RGBA value of each pixel in the image requires a little math:
for(let index = 0; index < imageData.data.length; index += 4) {
const rgba = [imageData.data[index],
imageData.data[index + 1],
imageData.data[index + 2],
(imageData.data[index + 3] / 255));
// do something
}
Each pixel is a clump of 4 elements in the array. In a 2×2 image of 4 pixels, the data array will contain 16 elements. The first 4 elements would represent the pixel in the top right, the next four elements would represent the pixel in the top left, the following 4 elements represent the pixel on the bottom right and finally, the last 4 elements would represent the pixel in the bottom left.
If you wanted the RGBA value of a specific row/column or x/y coordinate in the image you could use the following equation:
const redIndex = y * (width * 4) + x * 4;
const blueIndex = redIndex + 1;
const greenIndex = redIndex + 2;
const alphaIndex = redIndex + 3;
const rgba = [imageData.data[redIndex],
imageData.data[blueIndex],
imageData.data[greenIndex],
(imageData.data[alphaIndex] / 255));
Putting the Pixel Counter to Work
I have used the Canvas Pixel Color Counter for a few projects already. Here’s a sneak peak of one I currently have in progress: 8-Bit Boo from Super Mario Bros. 3!
The code for this project is available for viewing on GitHub!