Mozilla

Taking pictures with the Camera API – part of WebAPI

Through the Camera API, part of WebAPI, it becomes possible to take pictures with your device’s camera and upload them into the current web page. This is achieved through an input element with type="file" and an accept attribute to declare that it accepts images.

The HTML looks like this:

<input type="file" id="take-picture" accept="image/*">

When the users choose to activate this HTML element, they are presented with an option from where they want to choose a file, where the device’s camera is one of the options. If the camera is selected, it goes into picture taking mode.

After the picture has been taken, the user is presented with a choice to accept or discard it. If accepted, it gets sent to the <input type="file"> element and its onchange event is triggered.

Get a reference to the taken picture

With the help of the File API you can then access the taken picture/chosen file:

var takePicture = document.querySelector("#take-picture");
takePicture.onchange = function (event) {
    // Get a reference to the taken picture or chosen file
    var files = event.target.files,
        file;
    if (files && files.length > 0) {
        file = files[0];
    }
};

Presenting the taken picture in the web page

Once we have a reference to the taken picture (i.e. file) we can then use createObjectURL to create a URL referencing the picture and setting it to the src of an image:

// Image reference
var showPicture = document.querySelector("#show-picture");
 
// Get window.URL object
var URL = window.URL || window.webkitURL;
 
// Create ObjectURL
var imgURL = URL.createObjectURL(file);
 
// Set img src to ObjectURL
showPicture.src = imgURL;
 
// For performance reasons, revoke used ObjectURLs
URL.revokeObjectURL(imgURL);

If createObjectURL isn’t supported, an alternative is to fallback to FileReader:

// Fallback if createObjectURL is not supported
var fileReader = new FileReader();
fileReader.onload = function (event) {
    showPicture.src = event.target.result;
};
fileReader.readAsDataURL(file);

Complete example demo and code

If you want a complete working example page, I’ve created a Camera API demo. Here is the code for the HTML page and its accompanying JavaScript file:

HTML page

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Camera API</title>
        <link rel="stylesheet" href="css/base.css" type="text/css" media="screen">
    </head>
 
    <body>
 
        <div class="container">
            <h1>Camera API</h1>
 
            <section class="main-content">
                <p>A demo of the Camera API, currently implemented in Firefox and Google Chrome on Android. Choose to take a picture with your device's camera and a preview will be shown through createObjectURL or a FileReader object (choosing local files supported too).</p>
 
                <p>
                    <input type="file" id="take-picture" accept="image/*">
                </p>
 
                <h2>Preview:</h2>
                <p>
                    <img src="about:blank" alt="" id="show-picture">
                </p>
 
                <p id="error"></p>
 
            </section>
 
            <p class="footer">All the code is available in the <a href="https://github.com/robnyman/robnyman.github.com/tree/master/camera-api">Camera API repository on GitHub</a>.</p>
        </div>
 
 
        <script src="js/base.js"></script>
 
 
    </body>
</html>

JavaScript file

(function () {
    var takePicture = document.querySelector("#take-picture"),
        showPicture = document.querySelector("#show-picture");
 
    if (takePicture &amp;&amp; showPicture) {
        // Set events
        takePicture.onchange = function (event) {
            // Get a reference to the taken picture or chosen file
            var files = event.target.files,
                file;
            if (files && files.length > 0) {
                file = files[0];
                try {
                    // Get window.URL object
                    var URL = window.URL || window.webkitURL;
 
                    // Create ObjectURL
                    var imgURL = URL.createObjectURL(file);
 
                    // Set img src to ObjectURL
                    showPicture.src = imgURL;
 
                    // Revoke ObjectURL
                    URL.revokeObjectURL(imgURL);
                }
                catch (e) {
                    try {
                        // Fallback if createObjectURL is not supported
                        var fileReader = new FileReader();
                        fileReader.onload = function (event) {
                            showPicture.src = event.target.result;
                        };
                        fileReader.readAsDataURL(file);
                    }
                    catch (e) {
                        //
                        var error = document.querySelector("#error");
                        if (error) {
                            error.innerHTML = "Neither createObjectURL or FileReader are supported";
                        }
                    }
                }
            }
        };
    }
})();

Web browser support

  • Camera API is currently supported in Firefox and Google Chrome on Android devices.
  • createObjectURL is supported in Firefox, Google Chrome and Internet Explorer 10+.
  • FileReader is supported in Firefox, Google Chrome, Internet Explorer 10+ and Opera 11.6+.

The future

With WebRTC – which is support for real time, audio, video & data communications between two browsers – and a navigator.getUserMedia approach we will see much more of this in the near future, in a number of the major web browsers. For more information, please see our Web Platform Roadmap for Firefox.

But for now, you can enjoy taking/capturing pictures!

12 comments

Comments are now closed.

  1. John Drinkwater wrote on April 3rd, 2012 at 02:05:

    For those interested, https://bugzilla.mozilla.org/show_bug.cgi?id=692955 is the tracking bug for the Camera API landing in desktop Firefox :)

    1. Robert Nyman wrote on April 3rd, 2012 at 06:48:

      Yes, the very interesting next step! Thanks for pointing it out.

    2. Prasanna Venkadesh wrote on August 20th, 2012 at 07:08:

      Have the bug been fixed ? or am not sure. I am using Firefox 17 Nightly Build where i have enabled ” media.navigator.enabled” object’s value to true.

      https://people.mozilla.com/~anarayanan/gum_test.html — this works fine with all types (Video, Audio and Image). Whereas CameraAPI Demo page http://people.mozilla.com/~fdesre/capture/ fails.

    3. Prasanna Venkadesh wrote on August 20th, 2012 at 07:18:

      I feel sorry for my previous comment, I founded that development for it is still in progress to make this feature land in Desktop. Btw, the article described here is great :-)

      1. Robert Nyman wrote on August 20th, 2012 at 11:49:

        No worries!
        And yes, Desktop support and WebRTC in general is on its way. For now, though, you’ll have to play around with it on Android phones!

  2. Wolden wrote on June 5th, 2012 at 04:48:

    Hi ;)

    Looking for a way to store the temp picture in localStorage. imgURL is a local string ‘moz-filedata:…’. Is there a method to create a base64 string from this local string in order to export it later for further uses?

    WA

    1. Robert Nyman wrote on June 5th, 2012 at 05:40:

      Glad you asked! :-)

      I wrote about that in Saving images and files in localStorage and Storing images and files in IndexedDB.

      1. Wolden wrote on June 5th, 2012 at 17:58:

        Oh thanks ;)

        I was hoping it was possible to convert the local string in base64 without using canvas – that was of course my first idea. When googling ‘convert URL.createObjectURL img in base64′ I found a lot of references to BLOb… It seems to be an other way to do the stuff, no ?

        1. Wolden wrote on June 5th, 2012 at 18:07:

          sorry, just saw right now you talk about blobs further in the article. The comments are sometimes a little hard to understand for a non-native english-speaker but I’ll try to get the point later ;-)

          1. Robert Nyman wrote on June 6th, 2012 at 23:07:

            Yes, if you want to use base64 it has to be a combination of FileReader and canvas: depending on web browser support.

            Otherwise, blobs are they way to go, but not every web browser support it yet.

  3. david knikols wrote on June 22nd, 2012 at 14:43:

    Great stuff, real amazing, exactly what I was trying to learn about, but I still have a huge question maybe it sounds huge cause Im a newbie in codes, anyway here it goes—-supposed I include this function on a mobile site with the intention of people taking a picture to get a quote on an object, once they take the picture, how can I work it or code it or implement a way to get that picture back to me so I can look at it and be able to respond back to the quote, I keep rattling my brain around that.

    1. Robert Nyman wrote on June 25th, 2012 at 06:33:

      Thanks!
      I wrote about how to upload files in Utilizing the HTML5 File API to choose, upload, preview and see progress for multiple files. Hope it helps!

Comments are closed for this article.