Capturing an image from a webcam

TurtleTopiary picture TurtleTopiary · Feb 24, 2013 · Viewed 9.7k times · Source

I'm attempting to randomly capture an image from a webcam and then save it to my server, right now i'm using getUserMedia to stream the webcam to video element then I can capture an image to a canvas using a button but i'm not sure how to save that image from the canvas to my server.

Another issue is getUserMedia only works in Chrome, Opera and Firefox, is there any alternative for IE?

This is what i'm currently working with:

    <video id="video" width="640" height="480" autoplay></video>
<button id="snap">Snap Photo</button>
<canvas id="canvas" width="640" height="480"></canvas>
<button id="getBase" onclick="getBase()">Get Base64</button>
<textarea id="textArea"></textarea>

<script>

    // Put event listeners into place
    window.addEventListener("DOMContentLoaded", function() {
        // Grab elements, create settings, etc.
        var canvas = document.getElementById("canvas"),         
        context = canvas.getContext("2d"),
        video = document.getElementById("video"),
        videoObj = { "video": true },
        errBack = function(error) {
        console.log("Video capture error: ", error.code); 
        };

        // Put video listeners into place
        if(navigator.getUserMedia) { // Standard
            navigator.getUserMedia(videoObj, function(stream) {
                video.src = stream;
                video.play();
            }, errBack);
        } else if(navigator.webkitGetUserMedia) { // WebKit-prefixed
            navigator.webkitGetUserMedia(videoObj, function(stream){
                video.src = window.webkitURL.createObjectURL(stream);
                video.play();
            }, errBack);
        }

        // Trigger photo take
        document.getElementById("snap").addEventListener("click", function() {
            context.drawImage(video, 0, 0, 640, 480);
        });

        document.getElementByID("getBase").addEventListener("click", getBase());

    }, false);                  

    function getBase(){
        var imgBase = canvas.toDataURL("image/png");

        document.getElementByID("textArea").value=imgBase;
    }
</script>`

Thanks Heaps

Answer

Robot Woods picture Robot Woods · Feb 24, 2013

You can use canvas.toDataUrl to get a base64 encoded string that you can post as a parameter to a script on your server that will read it in and store as an image file.

Here is a shortened version of an actual implementation of this approach:

<script>
function saveImage(){
    var xmlhttp;
    xmlhttp=((window.XMLHttpRequest)?new XMLHttpRequest():new ActiveXObject("Microsoft.XMLHTTP"));
    xmlhttp.onreadystatechange=function(){
        if (xmlhttp.readyState==4){
            if(xmlhttp.status==200){
                //handle success                
            }
        }
    }
    xmlhttp.open("POST",baseURL,true);
    var oldCanvas = under.toDataURL("image/png");
    var params=oldCanvas;
    xmlhttp.setRequestHeader("Content-type", "application/upload");
    xmlhttp.setRequestHeader("Content-length", params.length);
    xmlhttp.setRequestHeader("Connection", "close");
    xmlhttp.send(params);
}
</script>

and here is an example PHP script that accepts the base64 string, converts to a .png, gives it a random filename, and saves:

<?php
if((isset($GLOBALS["HTTP_RAW_POST_DATA"]))){
    //some validation is necessary, this is just a proof of concept
    if(isset($GLOBALS["HTTP_RAW_POST_DATA"])){
        $params=explode('&',$GLOBALS["HTTP_RAW_POST_DATA"]);
        $imgsrc=str_replace(' ','+',$params[0]);
        $im = imagecreatefrompng($imgsrc);
    }
    if($im){
        $background = imagecolorallocatealpha($im, 255,255,255,127);
        imagecolortransparent($im, $background);
        //random file name
        $m = rand(10e16, 10e24);
        $filename=base_convert($m, 10, 36);
        //save image
        imagepng($im, 'images/'.$filename.'.png');
        imagedestroy($im);
        $size = getimagesize('images/'.$filename.'.png');
        $iH=$size[1];
        $iW=$size[0];
        echo "{\"filename\":\"".$filename."\",\"width\":\"".$iW."\",\"height\":\"".$iH."\"}";
    }
}
?>