Pixel Manipulation Using Canvas in HTML5

Canvas Pixel Manipulation in HTML5

 
One of the interesting features of the HTML5 canvas is it's ability to manipulate pixels. It is possible to get access to the individual pixels of HTML5 canvas. You do so using an ImageData object. The ImageData object contains an array of pixels. By accessing this array you can manipulate the pixels.
 
The 2D Context API provides you with three methods that help you draw pixel-by-pixel:
  • createImageData
  • getImageData
  • putImageData

Creating an Imagedata Object

 
Creating an ImageData object is done using the 2D Context function createImageData(). The following is an example:
 
var imgData = ctx.createImageData(80,80);
 
The width and height properties of the createImageData() function set the width and height in pixels. The example above creates an ImageData object with an 80 by 80-pixel area.
 

What is createImageData?

 
createImageData has two variants:
  1. createImageData(sw,sh) Returns an ImageData object with the given dimensions in CSS pixels. All the pixels in the returned object are transparent black.
  2. createImageData(imagedata) Returns an ImageData object with the same dimensions as the argument. All the pixels in the returned object are transparent black. 

Imagedata Object Properties

 
The ImageData object has three properties:
  • width
  • height
  • data
The width and height properties contain the width and height of the graphical data area.
 
The data property is a byte array containing the pixel values. The data property is of type CanvasPixelArray, holding a number of elements equal to "width*height*4"; this means that for every pixel you define the red, green, blue and alpha values of all the pixels.
 
The getImageData() allows you to get the pixel data from any rectangular area. See: getImageData(x,y,length,breath)
 
where: x,y = The starting point of the rectangular area length = length of the rectangular area breath = breath of the rectangular area
 

Manipulating the pixels

 
Each pixel in the data array consists of 4-byte values. One value for the red color, green color, and blue color, and a value for the alpha channel. The color of a pixel is determined by mixing red, green and blue together to make up the final color. The alpha channel tells how transparent the pixel is.
 
Here in this example, we set the red color and alpha value:
  1. for (var i = 0, len = pix.length; i < len; i += 4) {  
  2.  pix[i] = 255; // red channel  
  3.  pix[i + 3] = 127; // alpha channel  
  4. }  
  5. To read the value of the pixel we use the code:  
  6.  for (var i = 0, len = pix.length; i < len; i += 4) {  
  7.   // red  
  8.   pix[i] = 255 - pix[i];  
  9.   // green  
  10.   pix[i + 1] = 128 - pix[i + 1];  
  11.   // blue  
  12.   pix[i + 2] = 255 - pix[i + 2];  
  13.   // i+3 is alpha (the fourth element)  
  14.  } 

Copying the pixels on a Canvas

 
You can now copy them onto the canvas using the 2D Context function putImageData().
 

What is putImageData?

 
Paints the data from the given ImageData object onto the canvas. If a dirty rectangle is provided, only the pixels from that rectangle are painted. In the preceding example, we have manipulated the pixel color data and used putImageData to draw it.
 
There are two versions of the putImageFunction().
 
The first version of the putImageData() function copies all the pixels onto the canvas.
 
ctx.putImageData(imgData, 300, 200);
 
The second version of the putImageData() function can copy a rectangle of the pixels onto the canvas instead of all of the pixels.This version I have not used in the example.
 
Let us assume that:
  1. varcanvasX = 25;  
  2. varcanvasY = 25;  
  3. varsx = 0;  
  4. varsy = 0;  
  5. varsWidth  = 25;  
  6. varsHeight = 25;  
  7. context.putImageData(imageData, canvasX, canvasY,sx, sy, sWidth, sHeight);  
Here the sx and sy parameters (sourceX and sourceY) are the x and y coordinates of the left upper corner of the rectangle to be copied from the pixel array.
 
The sWidth and sHeight parameters (sourceWidth and sourceHeight) are the width and height of the rectangle to copy from the pixel array.
 
Browser Support
 
It is supported in all major browsers such as Chrome, Safari, Firefox, Opera.
 
Note: If the canvas has images loaded from the hard disk and you try to access pixel information using the getImageData() method, it will not work and will show a security violation "NS_ERROR_DOM_SECURITY_ERR". This is because the DOM will not allow pixel data to be accessed if the underlying image is from a different domain. When the image comes from the hard disk, the DOM does not know that the image is from the same domain and hence throws the error. To test your code without running into this error, run a local webserver like Apache or test your code from the server itself.
 
Example
  1. <!DOCTYPEhtml>  
  2. <htmllang="en"xmlns="http://www.w3.org/1999/xhtml">  
  3. <head>  
  4.     <metacharset="utf-8"/>  
  5.     <title>Canvas Pixel Manipulation</title>  
  6. </head>  
  7. <body>  
  8.     <canvasid="canvas1"width="600"height="600"></canvas>  
  9.     <scripttype="text/javascript">  
  10.         var ctx = document.getElementById('canvas1').getContext('2d');  
  11.    
  12.         // Drawing a square using Pixel Manipulation  
  13.         var imgData = ctx.createImageData(80, 80);  
  14.         var pix = imgData.data;  
  15.    
  16.         // Loop over each pixel and set a transparent red.  
  17.         for (var i = 0, len = pix.length; i < len; i += 4) {  
  18.             pix[i] = 255; // red channel  
  19.             pix[i + 3] = 127; // alpha channel  
  20.         }  
  21.    
  22.         // Draw the ImageData object at the given (x,y) coordinates.  
  23.         ctx.putImageData(imgData, 0, 0);  
  24.    
  25.         // Changing the RGB values of pixels from drawn canvas  
  26.         var imgData = ctx.getImageData(0, 0, 200, 100);  
  27.         var pix = imgData.data;  
  28.    
  29.         // Loop over each pixel and invert the color.  
  30.         for (var i = 0, len = pix.length; i < len; i += 4) {  
  31.             // red  
  32.             pix[i] = 255 - pix[i];  
  33.    
  34.             // green  
  35.             pix[i + 1] = 128 - pix[i + 1];  
  36.    
  37.             // blue  
  38.             pix[i + 2] = 255 - pix[i + 2];  
  39.    
  40.             // i+3 is alpha (the fourth element)  
  41.         }  
  42.         // Draw the ImageData at the given (x,y) coordinates.  
  43.         ctx.putImageData(imgData, 300, 200);  
  44.     </script>  
  45. </body>  
  46. </html> 
Output  
 
pixel.jpg