Friday, September 10th, 2010

HTML5 Canvas Image Effects: Black & White

Category: Canvas

Marco Lisci has written a tutorial on creating a black and white image effect using the Canvas tag.

The heart of his tutorial is using getImageData() and looping through the red, green, blue, and alpha values of each pixel to change it’s luminance:

So, what can we use to make an image black and white? The luminance. The luminance is how much a color is luminous to the human eye and it’s used to measure the clipping white in video editing systems, for example. In video editing system a white color that “break” the screen is a white that is too white to be represented on a common TV.

This is important because by calculating the average number between red, green and blue values we could obtain a value for every pixel that represent a static mathematical representation of the color luminance.

But there’s a problem, an human eye see colors dynamically. For example, if we take similar shades of blue and green, our eyes will detect the green color more luminous than the blue. In our algorithm we could use the static average formula, but our image will be too flat, and we’ll lose a lot of color depth.

So, let’s introduce the luminance formula: red x 0.3 + green x 0.59 + blue x 0.11.

This formula calculates the luminance of a color as it’s perceived by the human eye, so the green channel has more importance than the red and the blue. In our Javascript code we calculate for every pixel the grayscale number, by using exactly this formula. Then we assign this value to the red, green and blue channels of our pixel. By doing this for every pixel we are able to get a black and white version of our original image. There are obviously other more complex methods to calculate the correct grayscale value, but they could be too heavy to be used in an HTML5 canvas element, and we can say that for an everyday use, the luminance algorithm is good.

Resulting in code that looks as follows:

< view plain text >
  1. var imgd = context.getImageData(0, 0, 500, 300);
  2. var pix =;
  3. for (var i = 0, n = pix.length; i < n; i += 4) {
  4.   var grayscale = pix[i] * .3 + pix[i+1] * .59 + pix[i+2] * .11;
  5.   pix[i] = grayscale;       // red
  6.   pix[i+1] = grayscale;  // green
  7.   pix[i+2] = grayscale;  // blue
  8.   // alpha
  9. }
  10. context.putImageData(imgd, 0, 0);

It would be cool to see this combined as a kind of filter that can be applied to do black and white roll-over effects of elements, similar to what you can do with SVG filters.

[via Mark Mildner]

Posted by Brad Neuberg at 5:30 am

3 rating from 3 votes


Comments feed TrackBack URI

Just use Pixastic – – which does all sorts of fantastic filters with Canvas

Comment by sos — September 10, 2010

@sos, I was going to suggest the exact same thing ;-)

Comment by RoryH — September 13, 2010

Using perceptive factors for color luminance is not bad, but unfortunately, the brightness of color is much more complicated than that. See the following w3 document for the calculation of relative luminance

Comment by fforw — September 13, 2010

Fun with HTML5 Canvas Effects

Comment by julianstricker — September 14, 2010

Leave a comment

You must be logged in to post a comment.