HTML 5 Canvas Tutorial – Converting Images to Grayscale

HTML 5 and the Canvas tag has brought a whole world of possibilities when it comes to image manipulation. This tutorial will demonstrate one of those possibilities that is particularly powerful – getting raw image data and transforming it.

We’ve done a conversion to grayscale tutorial before using C# and this tutorial will look fairly similar to an approach outlined in that article.

Grayscale Example

There actually isn’t too much code, so I’m going to just throw the entire contents here and explain what’s going on after.

// Create an image object.     
var image = new Image();

// Can’t do anything until the image loads.
// Hook its onload event before setting the src property.
image.onload = function() {

   // Create a canvas.
   var canvas = document.createElement(‘canvas’);
   
   // Get the drawing context.
   var ctx = canvas.getContext(‘2d’);
   
   // Get the width/height of the image and set
   // the canvas to the same size.
   var width = image.width;
   var height = image.height;
   
   canvas.width = width;
   canvas.height = height;
   
   // Draw the image to the canvas.
   ctx.drawImage(image, 0, 0);
   
   // Get the image data from the canvas, which now
   // contains the contents of the image.
   var imageData = ctx.getImageData(0, 0, width, height);
   
   // The actual RGBA values are stored in the data property.
   var pixelData = imageData.data;
   
   // 4 bytes per pixels – RGBA
   var bytesPerPixel = 4;
   
   // Loop through every pixel – this could be slow for huge images.
   for(var y = 0; y < height; y++) {
      for(var x = 0; x < width; x++) {
         // Get the index of the first byte of the pixel.
         var startIdx = (y * bytesPerPixel * width) + (x * bytesPerPixel);
         
         // Get the RGB values.
         var red = pixelData[startIdx];
         var green = pixelData[startIdx + 1];
         var blue = pixelData[startIdx + 2];
         
         // Convert to grayscale.  An explanation of the ratios
         // can be found here: http://en.wikipedia.org/wiki/Grayscale
         var grayScale = (red * 0.3) + (green * 0.59) + (blue * .11);  
         
         // Set each RGB value to the same grayscale value.
         pixelData[startIdx] = grayScale;
         pixelData[startIdx + 1] = grayScale;
         pixelData[startIdx + 2] = grayScale;
      }
   }
   
   // Draw the converted image data back to the canvas.
   ctx.putImageData(imageData, 0, 0);
};

// Load an image to convert.
image.src = "myImage.png";

The first thing we need is an image to convert. There are multiple ways to get image objects, but this is one of the easiest. I hook the image’s onload event and then set the source to a URL. It’s important to note here that you can’t convert images that aren’t hosted on the same domain – the canvas is said to be tainted by a cross domain image and therefore getImageData and putImageData no longer work.

Since we can’t get information directly from an image, we have to draw it to a canvas first. I simply create a canvas the same size as the image and paint the image to it.

The conversion process is actually pretty simple. We just need to loop through every pixel, convert it to grayscale, and draw the new image back to the canvas. The conversion equation, (red * 0.3) + (green * 0.59) + (blue * 0.11), does a better job than just taking the average of the three values. You can read a little bit more about those values on Wikipedia’s Grayscale page.

After we’ve converted every pixel, we just call putImageData to draw the converted image back to the canvas. And that’s all there is to it – you now have a black and white version of your picture.

This is a pretty basic example of using an image’s raw data, but you can begin to see the power developers now have. If you’ve got any questions, feel free to leave them below.

Want to learn more about the HTML 5 Canvas? Check out these great books:

Leave a Reply

Your email address will not be published. Required fields are marked *