This post has been sitting around unfinished since April so I thought I should finish it and get it out there.

In this post I am going to show how you can capture an image from a webcam via JavaScript and convert it to a Data URI which can then be saved in a database or displayed in an IMG tag.

Note: This is more of a proof of concept rather than a best practices example so the code is a bit messy and hacked together from various sources.

I have only tested this on Safari for iOS 6 and latest Chrome with a webcam. It may or may no work in other browsers.

View demo

All explanations for the the code and markup are in the code comments, so please read them for more detail.

Here is a basic HTML page with some simple CSS for this demonstration:

#container {
    margin: 0px auto;
    width: 500px;
    height: 375px;
    border: 10px #333 solid;
}
#videoElement {
    width: 500px;
    height: 375px;
    background-color: #666;
}
#canvas {
    width: 500px;
    height: 375px;
    background-color: #CCC;
}

In the body we add the following elements:

<!-- On iOS 6 we can use the file select input with the following attributes to capture an image from the camera -->
<input id="fileselect" accept="image/*" type="file" />

<!-- For devices that support getUserMedia and have a webcam we can display the feed in a video element -->
<div id="container"><video id="videoElement" autoplay="autoplay" width="300" height="150">

</video></div>
<!-- Selected image will be draw to a canvas -->
<canvas id="canvas" width="500" height="375"></canvas>

<!-- Used to capture frame from webcam video feed -->
<input id="save" type="button" value="Save" />

<!-- Or alternatively added to an img tag -->
<img id="imgtag" alt="capture" width="500" height="375" />

<!-- For the JavaScript below -->
<script></script>

Finally we’ll add the following Javascript to the script tag inside the body:

var video = document.querySelector("#videoElement");

// check for getUserMedia support
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia;

if (navigator.getUserMedia) {
  // get webcam feed if available
  navigator.getUserMedia({video: true}, handleVideo, videoError);
}

function handleVideo(stream) {
  // if found attach feed to video element
  video.src = window.URL.createObjectURL(stream);
}

function videoError(e) {
  // no webcam found - do something
}

var v,canvas,context,w,h;
var imgtag = document.getElementById('imgtag'); // get reference to img tag
var sel = document.getElementById('fileselect'); // get reference to file select input element

// when DOM loaded, get canvas 2D context and store width and height of element
v = document.getElementById('videoElement');
canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
w = canvas.width;
h = canvas.height;

function draw(v,c,w,h) {

  if(v.paused || v.ended) return false; // if no video, exit here

  context.drawImage(v,0,0,w,h); // draw video feed to canvas

  var uri = canvas.toDataURL("image/png"); // convert canvas to data URI

  // console.log(uri); // uncomment line to log URI for testing
  imgtag.src = uri; // add URI to IMG tag src
}

document.getElementById('save').addEventListener('click',function(e){
  draw(v,context,w,h); // when save button is clicked, draw video feed to canvas
});

// for iOS

// create file reader
var fr;

sel.addEventListener('change',function(e){
  var f = sel.files[0]; // get selected file (camera capture)

  fr = new FileReader();
  fr.onload = receivedData; // add onload event

  fr.readAsDataURL(f); // get captured image as data URI
})

function receivedData() {
  // readAsDataURL is finished - add URI to IMG tag src
  imgtag.src = fr.result;
}

That is all the code that’s required. The new HTML5 APIs make it very quick and easy to do some interesting stuff!

View demo