Reading A BMP File In JavaScript
Written by Ian Elliot   
Monday, 19 August 2013
Article Index
Reading A BMP File In JavaScript
Converting Bits To Bitmap
Converting From Bitmap To ImageData
Complete Program Listing

Converting From Bitmap To ImageData

The bitmap object we have just created is just a nicer version of the bitmap data in the file. To be of any use in JavaScript it has to be converted into a JavaScript object that can work with say a Canvas element. The basic bitmap object for Canvas element is the ImageData object. Converting to it is fairly easy but it does have some tricky points that you have to get right. 

The first thing we need is an ImageData object but this can only be created from a Canvas object. In most cases it would be more efficient to generate the ImageData object using any canvas object that was already created in the page but in this case let's create a temporary Canvas object just for this function to use:

 

function convertToImageData(bitmap) {
 canvas = document.createElement("canvas");
 var ctx = canvas.getContext("2d");
 var Width = bitmap.infoheader.biWidth;
 var Height = bitmap.infoheader.biHeight;
 var imageData = ctx.createImageData(
                           Width, Height);

 

Notice that the Canvas object isn't added to the DOM - it isn't displayed just used to create an ImageData object of the correct size. The Width and Height variables are created because they are going to be used in a for loop and it is clearer and more efficient to cache the references in this way. We also need some other data:

var data = imageData.data;
var bmpdata = bitmap.pixels;
var stride = bitmap.stride;

Now we can start to transfer the pixel data from the bitmap object to the ImageData object. The data property takes the form of an array of RGBA values with four array element to one pixel. So the first pixel is stored as data[0], data[1], data[2] and data[3] as Red, Green, Blue, Alpha values. The data in the bitmap object is stored as BGR with no Alpha value. That is its first pixel is stored in bmpdata[0], bmpdata[1] and bmpdata[2] as Blue, Green and Red. 

Clearly we are going to have to do some re-ordering of values as the pixels are transferred.

We also have the problem that the ImageData has a stride in bytes equal to the row size*4 but the bitmap data could have a stride in bytes equal to the row size *3 rounded up to a multiple of four.  

Add to this the fact that the the rows are stored starting from the top of the image in the BMP and from the bottom in the ImageData and you can see that it is very tricky to keep track of everything.

we are going to have to keep track of where we are in each array separately. 

The pixel at x,y is stored starting at

(x + Width * (Height - y)) * 4;

in the ImageData and at 

x * 3 + stride * y;

in the BMP. 

Putting all of this together we get:

 

for (var y = 0; y < Height; ++y) {
 for (var x = 0; x < Width; ++x) {
  var index1 = (x+Width*(Height-y))*4;
  var index2 = x * 3 + stride * y;
  data[index1] = bmpdata[index2 + 2];
  data[index1 + 1] = bmpdata[index2 + 1];
  data[index1 + 2] = bmpdata[index2];
  data[index1 + 3] = 255;
 }
}

Is there an easier way to do this? 

Now we have the data stored in the ImageData object which can be returned as the result of the function:

 return imageData;
}

Trying it out

Now we have an ImageData object the BMP can, at last be displayed in a Canvas element. 

All we need is a suitable Canvas element:

<canvas id="canvas1"
 width="128"
 height="128">
This text is displayed if your browser
does not support HTML5 Canvas.
</canvas>

And at the start of the script we need to add:

var canvas1 = document.getElementById('canvas1');
var ctx1 = canvas1.getContext('2d');

The imageData is stored in the canvas as part of the processImage

ctx1.putImageData(imageData, 0, 0);

Of course you may also have to change the size of the Canvas element to show the bitmap off. 

final

 

Where Next?

This has been mostly an exercise in using JavaScript typed arrays but you could push the program on so that it can read any BMP file. You need to cope with different formats, including paletted data and compression. 

An interesting project would be to convert the data to a data URL which could then be loaded as a standard IMG tag.

 

This is part of a series on implementing data structures in JavaScript and the follow-on to 

 

Related Articles: 

 

 

To be informed about new articles on I Programmer, subscribe to the RSS feed, follow us on Google+Twitter, Linkedin or Facebook or sign up for our weekly newsletter.

 

Banner


A Customisable Weather Forecast

Having an accurate weather forecast is critical for many situations, in particular for deciding weather conditions are suitable for to deploy infrastructure inspection drones. This [ ... ]



Setting Up Site-To-Site OpenVPN

Setting up a point-to-point VPN is relatively easy but site-to-site is much more complicated involving certificates and more IP addresses than you can count. Find out how to do it using OpenVPN.


Other Projects

 



Last Updated ( Tuesday, 27 August 2013 )