Webcam to canvas or data URI with HTML5 and Javascript

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Display Webcam Stream</title>
 
<style>
#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;
}
</style>

</head>
 
<body>

</body>
</html>

In the body we add the following elements:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- On iOS 6 we can use the file select input with the following attributes to capture an image from the camera -->
<input id="fileselect" type="file" accept="image/*" capture="camera">

<!-- For devices that support getUserMedia and have a webcam we can display the feed in a video element -->
<div id="container">
    <video autoplay id="videoElement">
     
    </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 type="button" value="Save" id="save" />

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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

document.addEventListener('DOMContentLoaded', function(){
    // 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;

},false);

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

Posted toExperiments HTML HTML5 iOS Javascript Web Design