Generating Bitmap Images On The Fly For Canvas in Javascript

admin  

When we develop games or different tools we have to generate images on the fly or to alter existing images. In plain javascript we don’t have an existing Bitmap class and we don’t really need it. We have to perform the following operations:

Let’s start creating a canvas object. We can create directly in the html using canvas tag or we can create it dynamically using javascript code:

var canvas = document.createElement('canvas'); 
canvas.id = "thecanvas"; 
canvas.width = 640;
canvas.height = 480; 
document.body.appendChild(canvas);

Once we have the canvas in place we need to get the imagedata object from the canvas. The imagedata is copy of what is displayed on canvas. We need first to get the canvas context which returns a new ImageData object compatible with the canvas. If we need to modify the existing image displayed in Canvas we can get a copy of the existing canvas:

var imageData = canvas.getContext("2d").createImageData(canvas.clientWidth, canvas.clientHeight);
// or
var imageData = canvas.getContext("2d").getImageData(0, 0, canvas.clientWidth, canvas.clientHeight);

 

The imagedata which is returned contains an array of bytes of values 0 – 255. Each pixel is represented by four values for red, green, blue and alpha. The length of the array is width * height. In order to access the pixel at x, y we need the 4 values stored at (x + y * width).

function setPixel(imageData, x, y, r, g, b, a){

    var index = (x + y * imageData.width);
    imageData.data[index * 4 + 0] = r;
    imageData.data[index * 4 + 1] = g;
    imageData.data[index * 4 + 2] = b;
    imageData.data[index * 4 + 3] = a;
}

After we change the pixels as we want we need to put the imagedata back in to the canvas, using it’s context:

canvas.getContext("2d").putImageData(imageData, 0, 0);

In the following section we create a canvas object and display a generated chess table pattern in it entirely javascript. We are using the following code to fill alternating rectangles, directly in the imagedata before putting it in the canvas:

var cellsize = 20;
for (var i = 0; i < imageData.width; i += 2 * cellsize)
{
    for (var j = 0; j < imageData.height; j += cellsize)
    {
        var diff = ((j / cellsize) % 2) * cellsize;
        for (var x = i + diff; (x < i + diff + cellsize) && (x < imageData.width); x++)
        {
            for (var y = j; y < j + cellsize; y++)
            {
                setPixel(imageData, x, y, 120, 120, 120, 255);
            }
        }
    }
}

Here is the code in action: