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

Reading in a graphics file that HTML doesn't support is fairly easy using JavaScript's new typed array feature. In this project we read, decode and display a BMP file. 

The complete code for the project is listed at the end of the article and is also available, to registered users, in the CodeBin.

This is part three of a three part series on typed arrays:

 

If you don't know much about typed arrays then read the first two parts.

 

A Project - Reading A BMP File

BMP files are very common on Windows machines but they have hardly ever been supported within a web page. Using typed arrays and some new facilities in the File API and Canvas we can read in almost any format file - as long as we know its format. 

In the case of BMP files the format is very well documented - Wikipedia BMP Format and you can find a C definition by examining the appropriate header files using Visual Studio say. A previous project read in a BMP file using C# via the C definition and to make it easier to convert C programs that use BMP files it makes sense to stick to the slightly awkward naming conventions for the various fields. 

The file containing the BMP could be downloaded using Ajax and then displayed in a Canvas. You could even package the whole thing as a web component so that a BMP could be included in a web page just as easily as a standard image. 

For the demonstration it is easier to allow the user to select a local file to be loaded and processed. This also provides an opertunity to see how easy it is to work with the local filing system - but only if the user manually selects the file.

Reading In The File

First we have to solve the problem of reading in a BMP file to test the program. This can be done using the input file tag and the new file handling API. 

Start a new HTML page and add the tag:

<input type="file" id="input">

This displays a Choose File button. When the user clicks it they are shown a file selection dialog box. When they finally select a file the input object fires a change event.  In principle the user can select multiple files but for this example it is easier to suppose that they select a single BMP file. 

To work with the file the user selected we have to add an event handler for the change event:

var inputElement = document.getElementById("input");
inputElement.addEventListener("change",
                      handleFiles, false);

Now all of the work is going to be done in the handleFiles function:

function handleFiles(e) {
 var file = e.target.files[0];
 var reader = new FileReader();  reader.addEventListener("load",
                       processimage, false);  reader.readAsArrayBuffer(file);
}

We get the details of the first, and in most cases only, file selected. It is also assumed that it is a valid BMP file. To read the file into an ArrayBuffer all we have to do is create a FileReader object and use its readAsArrayBuffer method - specifying the file to read in. As with most I/O methods this is an asynchronous method and we need to provide a callback function that works with the file's data once it is loaded. 

Of course for a real application you would have to check that there hasn't been an error in reading the file but for simplicity this is ignored.

In this case the callback is the processimage function which is the next thing we have to write. 

 

Banner

 

Processing The BMP

For simplicity it is assumed that the user has selected a valid BMP file. For testing the simplest thing to do is to use Paint to create a small BMP file say 128x128 and to save it in 24 bit color format - as this is the only format the demo program decodes.

original

Sample BMP

 

 

The processimage function just calls two other functions that do all the work:

 

function processimage(e) {
 var buffer = e.target.result;
 var bitmap = getBMP(buffer); 
 var imageData = convertToImageData(bitmap);  ctx1.putImageData(imageData, 0, 0);

}

 

The ArrayBuffer is returned to the event handler as the result property of the event object.

Next we call getBMP to convert the raw data into the buffer into a bitmap object which it returns. This is where all of the typed array and DataView work is done.

The bitmap object that it returns is a custom object built to store all of the data in the BMP file in a useable form. That is, the bitmap object isn't something that is useable by JavaScript, i.e. you can't simply assign it to a canvas or img element.

The final function convertToImageData uses the bitmap object to extract the pixel data and store it in an ImageData object - i.e. a bitmap object that JavaScript does understand. You can display an ImageData object in a Canvas element which is what the last line of the function does. In this case ctx1 is the drawing context of a global canvas object. 

So first let's take a look at the getBMP function.

Banner

 



Last Updated ( Tuesday, 27 August 2013 )