JavaScript Make Image Greyscale

grayscale.js

Copyright, © James Padolsey

Grayscale.js is an experimental attempt to emulate Microsoft’s proprietary ‘grayscale‘ filter (available in most IE versions).

This started out as a little experiment and eventually turned into quite an endeavor. The task was simple enough; to emulate Internet Explorer’s ‘grayscale‘ filter in all non-IE browsers. The solution, much to my initial surprise, is not as tricky as you would think.

The ‘grayscale‘ filter in IE can be applied to any element and visually transforms the element itself into grayscale. You can apply the filter using one line of messy proprietary CSS:

This can also be defined in your StyleSheet:

As shown, getting this to work in IE is a piece of cake; other browsers, however, require much more attention!

There are two things to consider; images and everything else. “Everything else” is quite simple; loop through all elements within the document and look for colour properties such as backgroundColor and color, then convert their RGB values to grayscale. There are a few ways of doing this; note that we’re not talking about desaturating a photo; grayscaling is slightly different (as I understand it):

So, each element with a colour property has it converted to grayscale; the original colour is stored somewhere for resetting purposes.

Whether our image can be converted to grayscale depends on two things; the browser in question must support the HTML5 canvas element and its getImageData method and the image must be hosted on the same domain; externally hosted images cannot be passed into getImageData regardless of whether it’s supported. Google Chrome and Safari (<4) don’t support getImageData so we’re stuck there, but, on other browsers that support the canvas element grayscaling images can be achieved!

The only way to do this is to “manually” traverse all pixels of the image in question and apply the same RGBtoGrayscale function as we did for the CSS colour properties. This can really eat up the browser; even speedy JavaScript engines can suffer considerably with large images.

For the reason mentioned above it makes sense to add a prepare function to run before anything actually needs to be grayscaled – this function can use the classic zero-timeout recursion technique so as not to lock up the browser. If only small images need to be converted then you can avoid using ‘prepare’ and go straight ahead with the brute-force conversion.

Why, oh why?

You may wonder what the point is in grayscaling anything… Well, for one; eliminating colour detracts focus from the user therefore leaving their attention open for other focus-grabbing items on your website; e.g. a lightbox. Forum software such as vBulletin makes it so that the page goes entirely grayscale when you click logout; this brings up a confirm box which is quickly and easily identifiable since it’s the one of the only things with colour left on the screen.

The real reason behind this whole grayscaling obsession is that I was curious about whether it’d be possible to achieve; I knew about the filter in IE and wondered if other browsers could be made to emulate this handy effect. I know the effect itself might be considered out-of-date but I really don’t care; I was only interested in getting it to work.

Demo

For those blood-thirsty demo hunters lurking around I’ve created a demo page which shows the functionality as described in this post. Remember, it won’t work properly in Safari (<4) or Chrome (and probably some old version (pre v.2) of FF); also remember it’s just an experiment!

The DEMO: /demos/grayscale/

Usage

To grayscale an element you need to call grayscale() with that element passed as a reference, e.g.

To reset an element (back to its original colourful state) you must call grayscale.reset() and pass whatever elements you want reset:

The prepare function, as discussed earlier, should be called when there’s a large image to process or even if there are several smaller images. Be aware that larger images will take quite a while to process (just a 300×300 PNG takes about 3 seconds in prepare mode).

for the jQuery rookie guy, this prepares the image in a blog-post, activates grayscale on hover (and removes it afterwards). Check your selectors first.

Reference: grayscale.js

Leave a Reply

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

CAPTCHA