Subscribe to our RSS

Convert Images to Grayscale

Tags: , , ,

Convert Images to Grayscale

Read this tutorial to find out how to desaturate an image (convert color images to grayscale) using JavaScript. A cross-browser code sample is supplied.
Recently we published a tutorial explaining how to rotate images using JavaScript. To continue this series of tutorials on image manipulation using JavaScript, we would like to explain how to change color images to grayscale using JavaScript.

This is a relatively simple task, but there are two methods (one method for Internet Explorer and one method for all other browsers).

Canvas Method

As you probably know, screen color consists of 3 components: red, green and blue. Each component or color (for example, red) has a value from 0 to 255. The value 0 indicates there is no red color and the value 255 would be the brightest possible red color. To convert a color to grayscale you just need to calculate the average for all three components. This can be done using the simple formula below:

{code type=php}
grayscalecolor = (red + green + blue) / 3;
{/code}

All modern browsers support the CANVAS tag which is allowed access to the image’s pixels. The code below will go through each pixel in the image and replace the color values with an average value. Here is the code:

{code type=php}
var canvas = document.createElement(’canvas’);
var canvasContext = canvas.getContext(’2d’);

var imgW = imgObj.width;
var imgH = imgObj.height;
canvas.width = imgW;
canvas.height = imgH;

canvasContext.drawImage(imgObj, 0, 0);
var imgPixels = canvasContext.getImageData(0, 0, imgW, imgH);

for(var y = 0; y < imgPixels.height; y++){
for(var x = 0; x < imgPixels.width; x++){
var i = (y * 4) * imgPixels.width + x * 4;
var avg = (imgPixels.data[i] + imgPixels.data[i + 1] + imgPixels.data[i + 2]) / 3;
imgPixels.data[i] = avg;
imgPixels.data[i + 1] = avg;
imgPixels.data[i + 2] = avg;
}
}

canvasContext.putImageData(imgPixels, 0, 0, 0, 0, imgPixels.width, imgPixels.height);
return canvas.toDataURL();
{/code}

From the above code sample, you see that we created a canvas, loaded the image into it, and then changed the color values of each pixel in the image to an average value. After that we simply replaced the SRC of our image to the image changed in the canvas.

Using the same method you can also flip images using JavaScript. (We will create a tutorial for this in the future).

MSIE (Internet Explorer) method

Microsoft Internet Explorer does not support the CANVAS tag, but Microsoft does provide image manipulation through filters. The filter to use for converting images to grayscale is the filter named DXImageTransform.Microsoft.BasicImage. Therefore, we simply apply this filter to our image, and it will work in all versions of MSIE (starting from version 6).

{code type=php}
imgObj.style.filter = ‘progid:DXImageTransform.Microsoft.BasicImage(grayScale=1)’;
{/code}

That’s it ;) Click the Demo to see it in action.

Evangun

January 23, 2010

Thank you, it works great.
However, in order to be able to apply grayscale on resized images, you would rather detect their size this way :

imgObj2 = new Image;
imgObj2.src = imgObj.src;
var imgW = imgObj2.width;
var imgH = imgObj2.height;

instead of

var imgW = imgObj.width;
var imgH = imgObj.height;

Cheers

ajaxBlender.com

February 1, 2010

Evangun,

Yes, your method will work as well and thank you for sharing it. I am sure some users will find this to better suit their needs. However, I should note that the method we used has been tested and works in all browsers. So, if anyone prefers this alternative method, we suggest they be sure to test it for full browser compatibility.

Alex

Chris

February 15, 2010

This is great. I’d like to turn all images with a certain class grey, and while adapting your demo if I change:

var imgObj = document.getElementById(’image’);

to

var imgObj = $(’.image’);

I get errors about uncaught exceptions. Is there a way to do what I’m trying to accomplish?

I’m not too familiar with JS so my apologies if this is a foolish question. Thanks!

ajaxBlender.com

February 18, 2010

Chris,

To turn to a certain class of grey, you may want to try this: var imgObj = $(’.image’)[0];

Thanks,

Alex

Josu3E

June 24, 2010

If your class name is “gray” so you should use:

var imgObj = $(’.gray’);

…I haven’t tested yet but it looks more logical.

eno

June 25, 2010

Nice script, tnx. But to reset the colors?
Cheers

ajaxBlender.com

July 1, 2010

Eno,

Thanks for your comment. To reset the image you should just reload the image again (for example: $(’#image-container’).html(”); )

If I didn’t understand your question correctly, just let me know.

Alex

tuba

August 12, 2010

very nice tutorial, I would like to give an effect using jquery too

dennis84

August 19, 2010

thanks for the snippet. i modified your code to this…

$.fn.greyscale = function() {
return this.each(function() {
if ($.browser.msie) {
this.style.filter = “progid:DXImageTransform.Microsoft.BasicImage(grayScale=1)”
} else {
this.src = grayscaleImage(this)
}
})
}

function grayscaleImage(imgObj) {

}

$(document).ready(function() {
$(”#image”).greyscale()
})

kevin

September 1, 2010

just tested and seems to work fine. I managed to have it done on the .hover the picture. Is there any way to “turn it off” on the rollout (or any other action) ?

Pete G

September 12, 2010

Thanks for this, I’ve just finished putting together an example usage on my site – http://petegoodman.com/labs/konami-code/

Javier España

October 27, 2010

I tried to use this but I keep getting an error:

Security error” code: “1000
[Break on this error] var imgPixels = canvasContext.getImageData(0, 0, imgW, imgH);

Here’s que slightly modified js:

http://www.cuencadamico.com.ar/js/slideshow.autoplay.js

Any ideas?

Lauris

December 2, 2010

You don’t need to imbricate two loops looping through picture’s width and height.

“data” property returns an array, you can loop through this array with +4 increments.

for(var i = 0; i < imgPixels.data.length; i=i+4){
. var avg = (imgPixels.data[i] + imgPixels.data[i+1] + imgPixels.data[i+2]) / 3;
. imgPixels.data[i] = avg;
. imgPixels.data[i+1] = avg;
. imgPixels.data[i+2] = avg;
}

vincent

January 11, 2011

hi,
I already used your code with jpg files and it works well.
But now I want to use this code with png files and it isn’t work.
google chrome says : Uncaught Error: SECURITY_ERR: DOM Exception 18

you can see yourself at : http://www.ogre.be

Why it doesn’t work?

Jdsans

February 2, 2011

It doesn’t work if the image URL is given directly written in the src attribute.

Ortal

February 8, 2011

Hi, thanks for your very useful tutorial.
Though (I’m a newbie to JS), I don’t fully understand how to apply it… I mean: where do I put the code (I surely need some function, I guess) and how do I call it inside the html.
Thank you in advance!

alex

February 13, 2011

How to set the speed of animation?

Olinklist

February 13, 2011

Some pretty & cool from this snipet code.
How come to change the color other than grayscale, can we?

frederic

February 18, 2011

thanks for sharing this great trick! it wirked with me! great post!

Pushpinder Bagga

February 21, 2011

Thanks, can we do this on mouse over? I mean show the desaturated images and on mouse over show the original?

ajaxBlender.com

February 25, 2011

Hello Jdsans
You should put an absolute URL. Relative URL will not work.

Jdsans

April 17, 2011

I used absolute url only,not relative url.
But in the demo you have used relative url’s for images

Josh Reisner

April 26, 2011

This is a great script! I’m having an issue with WebKit though, for some reason it won’t load a bunch at the same time. See the following URL. Firefox handles it no problem, Safari and Chrome show blank images. But when you trigger mouse over then out, the grayscale effect works.

http://kate.joshreisner.com/
http://kate.joshreisner.com/scripts/global.js

Any advice to get them all to load on ready? Thanks.

nachomaans

May 3, 2011

Thank you for the IE filter tip, which was added as a fallback for IE on this page: http://kiridara.com/
Other browsers use a smooth transition.

Josh Reisner

July 4, 2011

Re my earlier comment, the issue for me was that I was using $(document).ready(), when i should have been using $(window).load(). That way, it waits until all the images are loaded in the browser before executing the effect.

mina

August 14, 2011

not working with Firefox put work fine with opera
thanks for this great tutorial

Mike

September 19, 2011

I get an error: INDEX_SIZE_ERR: Dom Exception 1.

$(document).ready(function() {
var imgObj = document.getElementById(’image’);
desaturate(imgObj);
});

jeetendra kumar singh

October 8, 2011

nice code
but it is not giving expected result for another colors
like
i want to change the image color as user select
rgb

solsTiCe

October 21, 2011

great !
I had hard time to use your code to make grey out overlay of image as I wanted. To create a hover effect with the saturated image. It works now.

http://sorobanexam.org/about.html

I just found that someone created a plugin from your code http://plugins.jquery.com/project/desaturate

ricette cocktail

November 16, 2011

Re my earlier comment, the issue for me was that I was using $(document).ready(), when i should have been using $(window).load(). That way, it waits until all the images are loaded in the browser before executing the effect.

Streaming Movies

April 11, 2012

This is a great script! I’m having an issue with WebKit though, for some reason it won’t load a bunch at the same time. See the following URL. Firefox handles it no problem, Safari and Chrome show blank images. But when you trigger mouse over then out, the grayscale effect works.

Ayaz Chishti

May 3, 2012

Hi, Can we convert all images of gallery list to grayscale?

Leave a comment

Your name

June 18, 2013

Spam protection. Enter result of expression you see in the box below.

8 + 1 =