How to Manipulate Pixels with the HTML5 Canvas Tag - dummies

How to Manipulate Pixels with the HTML5 Canvas Tag

By Andy Harris

With HTML5, you can extract the data of a canvas tag into the underlying pixel data. Manipulating this data gives you extensive control of your image in real time. You can use this data for color balancing as well as for experimenting with your own blurs, sharpens, and chroma-key effects.

No matter what format an image is stored in on the file system, it is displayed as a list of pixels. Each pixel is represented (in the standard 32-bit system, anyway) by four integers: RGBA. The R represents how much red is in the current dot, G stands for green, and B stands for blue. The A stands for alpha, which is a measure of the transparency of the image. Each of these values can vary from 0 to 255. When you convert an image to the image data format, you get a huge array of integers. Each group of four images represents a single pixel of color data.

This code changes the color balance of an image:

   function draw(){
    var drawing = document.getElementById("drawing");
    var con = drawing.getContext("2d");
    var original = document.getElementById("original");
    CANV_WIDTH = 200;
    CANV_HEIGHT = 200;
    //draw the original on the canvas
    con.drawImage(original, 0, 0);
    //get the image data
    imgData = con.getImageData(0, 0, 200, 200);
    //loop through image data
    for (row = 0; row < CANV_HEIGHT; row++){
      for (col = 0; col < CANV_WIDTH; col++){
        //find current pixel
        index = (col + (row * imgData.width)) * 4;
        //separate into color values
        r =[index];
        g =[index + 1];
        b =[index + 2];
        a =[index + 3];
        //manipulate color values
        r -= 20;
        g += 50;
        b -= 30;
        a = a;
        //manage boundary conditions
        if (r > 255){
          r = 255;
        if (r < 0){
          r = 0;
        if (g > 255){
          g = 255;
        if (g < 0){
          g = 0;
        if (b > 255){
          r = 255;
        if (b < 0){
          b = 0;
        if (a > 255){
          a = 255;
        if (a < 0){
          a = 0;
        //return new values to data[index] = r;[index+1] = g;[index+2] = b;[index+3] = a;
      } // end col for loop
    } // end row for loop
    //draw new image onto canvas
    con.putImageData(imgData, 0, 0);
  } // end function

While the code listing seems quite long, it really isn’t too difficult to follow:

  1. Draw an original image.

    The technique you’ll use extracts data from a canvas element, so to modify an image, you first need to draw it onto a canvas. You can use the ordinary drawImage() method.

  2. Extract the image data.

    The getImageData() method gets the picture displayed by the current canvas and places it in a huge array of integers.

  3. Make a loop to handle the rows.

    Image data is broken into rows and columns. Each row goes from 0 to the height of the canvas, so make a for loop to iterate through the rows.

  4. Make another loop to handle the columns.

    Inside each row is enough data to go from 0 to the width of the canvas, so make a second for loop inside the first. It’s very common to use a pair of nested for loops to step through two-dimensional data like image information.

  5. Find the index in imageData for the current row and column.

    The imageData array contains four integers for each pixel, so we have to do a little math to figure out where the first integer for each pixel is. The easiest formula is to multiply the row number by the width of the canvas, add that to the column number, and multiply the entire result by four.

  6. Pull the corresponding color values from the index.

    The index also represents the red value of the current pixel. The next int holds the green value, followed by the blue value, and finally the alpha value.

  7. Manipulate the color values as you want.

    If you’re going to do a color-balancing app, you can simply add or subtract values to change the overall color balance. You can also do much more elaborate work if you want to play around with pixel-level image manipulation.

  8. Check for boundaries.

    A pixel value cannot be lower than 0 or higher than 255, so check for both of these boundaries and adjust all pixel values to be within legal limits.

  9. Return manipulated values back to the imgData array.

    You can copy values back to the array, and you should do so to make the changes visible.

  10. Draw the image data back to the canvas.

    The putImageData() function draws the current image data back to the canvas as an ordinary image. The new version of the image will reflect the changes.