14 septembre 2010

Drawing a point on an HTML5 canvas

Drawing a single point seems to be the easiest task to do on any graphic device. However it's not as easy as expected on a simple HTML5 canvas element. Even if the HTML5 canvas provides advances graphic primitives to draw lines or images, it does not have any function to draw a single point.

In order to draw a single point you'll have to:

  • obtain a portion of the image data
  • calculate the index of the pixel in the image data
  • set the RGB and alpha component of the pixel
  • write back the data to the image

Getting a portion of the image data that can be processed and written back is a powerful procedure that allows for example to write image filters. However it's quite too complicated when you just want to draw one or more pixels.

Here is a real example:

// Get a reference to the canvas element 
  var elem = document.getElementById('canvas');
  if (!elem || !elem.getContext) return;

  // Get the 2D graphic context   
  var context = elem.getContext('2d');    
  if (!context) return;     

  // Obtain a portion of the graphic data
  function get_image_data(context, w, h) {     

    // Not all browsers implement createImageData. On such browsers
    // we obtain the ImageData object using the getImageData method. 
    // The worst-case scenario is to create an object *similar* to
    // the ImageData object and hope for the best luck.     
    if (context.createImageData) {      
      return context.createImageData(w, h);     
    } else if (context.getImageData) {       
      return context.getImageData(0, 0, w, h);     
    } else {       
      return {'width' : w, 'height' : h, 'data' : new Array(w*h*4)};     

  // Draw a pixel on the canvas   
  function point(imgd, x, y) {          

    // Calculate the pixel offset from the coordinates     
    var idx = (x + (y * imgd.width)) * 4;      

    // Modify the graphic data     
    imgd.data[idx] = 0;     // Red     
    imgd.data[idx+1] = 0;   // Green     
    imgd.data[idx+2] = 0;   // Blue     
    imgd.data[idx+3] = 255; // Alpha channel   

  var imgd = get_image_data(context, 400, 300);   
  point(imgd, i, j);  // Replace i and j with real coordinates
  context.putImageData(imgd, 0, 0);  


1 commentaire:

  1. Also possible to use the fillRect:

    c.fillStyle = "black";