Creating Web Apps - The Camera API
Written by Mike James   
Sunday, 21 October 2012
Article Index
Creating Web Apps - The Camera API
Customizing

If we are going to make web apps as powerful as native apps we are going to have to explore some of the less well known areas of HTML5. In this article the main topic is how to take a photo, but we also learn a lot about the file API.

This article is one in a series on creating web apps:

 

 

HTML5 has introduced a few APIs that are designed to make it possible to interact with more hardware. The Camera API, for example. Well it isn't really a Camera API, it is more properly called the HTML Media Capture and in theory it allows you to access the audio, image and video capture capabilities of a device. In this article, however, the task is to discover how to take a photo. Capturing audio and video follows exactly the same route, but with different types of problem along the way.

It is also worth mentioning that there is another "camera" API - the HTML Media Capture and Streams API. This is much more sophisticated and much more useful, but at the moment only Chrome supports it. Mozilla is working on adding it to Firefox, but currently it is in a difficult stage of development. This is one of the many areas where HTML has to do better, but let's see what the Media Capture API can do for us.

The first thing to say is that the Media Capture API is a small extension of the FileAPI, which allows you to get the user to pick a file or set of files that are stored on their machine. The only difference is that in this case the file that is selected is an image file created by the user taking a photo.

Yes that's correct the user has to take the photo. For security reasons the Media Capture API only allows you to get a photo that the user takes, i.e. they have to be fully aware that your app it acquiring a picture. You can't secretly snap something while their device is just sitting idle, say, or set up an automatic system that takes a picture every few minutes. The need to keep the user "in the loop" is a big cause of some of the problems in using the facility.

Snap!

The basic idea is that you place an input element with type="file" plus a specification of the type of file you want using the accept attribute. The file types can be one of the MIME types: image/*, sound/* or video/*. As we are interested in taking a photo, the only type we need is image/*,

Hence the tag that we need on the HTML page is:

<input type="file" id="snap" accept="image/*" >

If you try this out you will discover that Chrome displays:

 

chrome1

 

and Firefox displays

 

firefox1

 

Neither of which are particularly stylish or even suggest that a camera might be involved.

In fact, what happens if you click on the button is that you are offered a the range of input devices that are supported and the camera will be just one option. Your user has to know that you want them to take a picture to make this work.

You can, in theory, narrow down the choice using the capture parameter set to one of camera. camcorder, microphone and filesystem, but in practice these don't seem to be supported. For example, if you try:

 <input type="file" id="snap"
      accept="image/*;capture=camera" >

 

you will almost certainly find that it makes no difference. 

OK, let's suppose that the user gets the idea that they have to select the camera and take a picture. How to you retrieve the file?

The answer to this is the same as how you get the list of files back from the standard file picker - only now there should be only a single file.

When the user has taken the photo this triggers an onchange event. To retrieve the file that corresponds to the image you just have to write the event handler. Once again it is worth emphasising that this next step is exactly the same irrespective of the file's source - it could have come from the camera, audio, video or from the file system.

The first thing we need to do is add an onchange event handler to the input element.

var snap = document.getElementById("snap"); snap.onchange=function(e){

Noithing new here.

 

Next we retrieve the list of files that the user might have selected from the event object. In our case there should only be a single file corresponding to the picture taken with the camera so we might as well reduce the file array to a single element:

var file=e.target.files[0];

It would also be worth checking that a file had actually been returned, but lets keep things as simple as possible.

Using Files

Now we have the file object corresponding to the file what can we do with it?

We could upload it using standard Ajax techniques or we could make use of it within the page using the File API to convert it into an array or string. Often however all you really want to do with a photo is to display it on the web page. For this you need to be able to set an img elements src attribute to a URL - but you don't have a URL to the file.

The solution of this problem is to make use of the object URL which will convert any file to a data URL i.e. it will pack the data contained in the file into a URL. The only problem with using this is that currently Webkit browsers i.e. Chrome and Safari use a prefix. What this means is that we have to do the operation in two steps. First creating the ObjectURL and then using it:

var URL=window.URL|| window.webkitURL;
var fileURL=URL.createObjectURL(file);

Now we have the image as a data URL we can set it to display in an img element:

var img= document.getElementById("showPhoto"); img.src=fileURL;
URL.revokeObjectURL(fileURL);

The final instruction destroys the ObjectURL object because we don't need it any more and it takes a lot of memory.

The complete event handler is:

var snap = document.getElementById("snap");
snap.onchange=function(e){
 var file=e.target.files[0];
 var URL=window.URL|| window.webkitURL;
 var fileURL=URL.createObjectURL(file);
 var img= document.getElementById("showPhoto");
 img.src=fileURL;
 URL.revokeObjectURL(fileURL);
};

and the HTML needed to make it work is

<input type="file" id="snap"
         accept="image/*;capture=camera" >
<img src="about:blank" id="showPhoto"
                            width="300">
 

 

Banner



Last Updated ( Monday, 21 January 2013 )