Grayscale Image With Javascript

Gambar Asli

Gambar Asli

After

After

function grayscale(image, bPlaceImage)
{
  var myCanvas=document.createElement("canvas");
  var myCanvasContext=myCanvas.getContext("2d");

  var imgWidth=image.width;
  var imgHeight=image.height;
  // You'll get some string error if you fail to specify the dimensions
  myCanvas.width= imgWidth;
  myCanvas.height=imgHeight;
  //  alert(imgWidth);
  myCanvasContext.drawImage(image,0,0);

  // This function cannot be called if the image is not rom the same domain.
  // You'll get security error if you do.
  var imageData=myCanvasContext.getImageData(0,0, imgWidth, imgHeight);

  // This loop gets every pixels on the image and
    for (j=0; j<imageData.height; i++)
    {
      for (i=0; i<imageData.width; j++)
      {
         var index=(i*4)*imageData.width+(j*4);
         var red=imageData.data[index];
         var green=imageData.data[index+1];
         var blue=imageData.data[index+2];
         var alpha=imageData.data[index+3];
         var average=(red+green+blue)/3;
   	    imageData.data[index]=average;
         imageData.data[index+1]=average;
         imageData.data[index+2]=average;
         imageData.data[index+3]=alpha;
       }
     }

    if (bPlaceImage)
	{
	  var myDiv=document.createElement("div");
	     myDiv.appendChild(myCanvas);
	  image.parentNode.appendChild(myCanvas);
	}
	return myCanvas.toDataURL();
  }

The function takes two parameters: an image (from <img> element), which must have been loaded. In this example, I made sure that the image has been loaded by attaching the function call to onload. The other parameter is a flag I added to indicate whether the image should be placed on the html page next to the original image. The function returns an Image object (you can see this being used on the Using Canvas for Mouse Over example below).

<img id="myImage" src="image.gif"  onload="javascript:grayscale(this, true);"></img>

Inside the function, create a canvas element:

var myCanvas=document.createElement("canvas");

Get the context of the canvas (to draw in the canvas, we need to do work on a canvas context).

var myCanvasContext=myCanvas.getContext("2d");

Then we set the dimensions to be the same as the image

var imgWidth=image.width;
var imgHeight=image.height;
// You'll get some string error if you fail to specify the dimensions
myCanvas.width= imgWidth;
myCanvas.height=imgHeight;

Because I want to manipulate the image, I need to be able to access the pixel data to retrieve the pixel colors, so we need to draw the image into the canvas first to get a duplicate of the original.

myCanvasContext.drawImage(image,0,0);

Call getImageData to retrieve the ImageData object. (this object will have the pixel data)

// This function cannot be called if the image is not from the same domain.
// You'll get security error

var imageData=myCanvasContext.getImageData(0,0,
imgWidth-1, imgHeight-1);

Change every pixel to level of gray. This simple algorithm averages the red, green, and blue components of every pixels. Note that I use ImageData.width and ImageData.height, not the Image.width and Image.height as they might be aligned differently (in our case, it doesn’t really matter because the extra pixels are not going to show up in the final result).

for (j=0; j
{
for (i=0; i
{
var index=(i*4)*imageData.width+(j*4);

var red=imageData.data[index];
var green=imageData.data[index+1];
var blue=imageData.data[index+2];
var alpha=imageData.data[index+3];

var average=(red+green+blue)/3;

imageData.data[index]=average;
imageData.data[index+1]=average;
imageData.data[index+2]=average;
imageData.data[index+3]=alpha;
}
}

Every pixel is represented by 4 numbers in the format of red, green, blue, and alpha. Each color is a number between 0 to 255. In the code, you can see where I retrieved the red, green, blue, and alpha in the portion below:

var red=imageData.data[index];
var green=imageData.data[index+1];
var blue=imageData.data[index+2];
var alpha=imageData.data[index+3];
var average=(red+green+blue)/3;

Then I averaged them. (To read about color, see INTERPRETING THE NUMBERS section in this other tutorial – disregard the discussion about web-safe color.)

The alpha is not used in my example and there really is no need for the last line below, but you could turn some color transparent by changing this alpha value to something between 0 to 255 where 0 means fully invisible and 255 means fully visible).

imageData.data[index]=average;
imageData.data[index+1]=average;
imageData.data[index+2]=average;
imageData.data[index+3]=alpha;

Puting back back the modified image into the image:

myCanvasContext.putImageData(imageData,0,0,0,0, imageData.width,
imageData.height);

The rest of the code reates a new <div> element to insert the new canvas (which has the new gray-scale version of the image) into it. This part of the code is not really part of the subject and will only be executed if bPlaceImage is true. I added it for demonstration purpose.

var myDiv=document.createElement("div");
myDiv.appendChild(myCanvas);
image.parentNode.appendChild(myCanvas);

The return value of the function is an Image.src object which can be used to replace existing image (see the next example for its use).

return myCanvas.toDataURL();

3 thoughts on “Grayscale Image With Javascript

  1. terima kasih atas info nya, mas..

    cuma ada error nya tuh…
    looping ga ada ujung nya, sampe muncul error “unresponsive script” klo ga salah.
    pas saya liat2 bagian ini,
    —————————————–
    // This loop gets every pixels on the image and
    for (j=0; j<imageData.height; i++)
    {
    for (i=0; i<imageData.width; j++)
    {
    —————————————–
    ternyata ada yg aneh dengan i++ dan j++, kok kebalik ya?
    saya ganti i++ jadi j++, dan sebaliknya, jadi gini,
    —————————————–
    // This loop gets every pixels on the image and
    for (j=0; j<imageData.height; j++)
    {
    for (i=0; i<imageData.width; i++)
    {
    —————————————–
    dah ga error sih, tapi hasilnya tidak sesuai.
    akhirnya saya balik lagi semuanya… jadi gini
    —————————————–
    // This loop gets every pixels on the image and
    for (i=0; i<imageData.height; i++)
    {
    for (j=0; j<imageData.width; j++)
    {
    —————————————–
    baru deh… hasilnya sesuai harapan.

Leave a Reply