canvas教程

Taking Picture From Webcam Using Canvas

字号+ 作者:H5之家 来源:H5之家 2016-08-30 11:00 我要评论( )

Taking Picture From Webcam Using Canvas,Webcam,byDavidBurilloNotice:thispostmayaskyourauthorizationtouseyourwebcam.Thisisduetolivesamplesembeddedinthi

Webcam, by David Burillo


Taking Picture From Webcam Using Canvas


Notice:this post may ask your authorization to use your webcam. This is due to live samples embedded in this post.

I recently needed to take a picture from a web browser using webcam. As this is a basic need, I thought it would be quite easy. Yet, solution is not trivial, and implies both using new user media html5 API and some canvas manipulation. Here is a reminder which may be useful to everyone.

Displaying Webcam Stream in Browser

First step is to display the webcam stream into the browser. It is easily done using the getUserMedia HTML5 API. Support is quite limited (neither supported on Safari / iOS, nor on IE, but supported on Edge, Firefox and Chrome). A solution for oldest browsers is to fallback on a Flash solution. However, it won’t be fixed on mobiles, and we would need to use an extra framework such as PhoneGap in this case.

As dealing with fallback would be quite cumbersome, and as we don’t want to write some ugly prefixed code such as:

const getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;

We are going to use a polyfill written by @addyosmani : getUserMedia.js . It uses either the native implementation or Flash fallback depending of browser support. Exactly what we need.

First, let’s install it (I’m using Webpack, hence the save-dev ):

npm install --save-dev getusermedia-js

Let’s now initialize a video stream and display it in the browser using the freshly installed package:

import { getUserMedia } from 'getusermedia-js'; getUserMedia({ video: true, audio: false, width: 640, height: 480, el: 'stream', // render live video in #stream swffile: require('getusermedia-js/dist/fallback/jscam_canvas_only.swf'), }, stream => { const video = document.querySelector('#stream video'); video.src = window.URL.createObjectURL(stream); video.play(); }, err => console.error(err));

We start by calling the getUserMedia polyfill, specifying it we don’t care about audio, the preview video dimensions, and where to insert it (in the #stream element). We also specify the path to our Flash fallback (included in the lib). I didn’t test it as all my installed browsers support this feature, but it should work this way.

Note that if we don’t use any module bundler, we need to replace the require call by the path of the fallback.

Second and third arguments are respectively success and error callbacks. Let’s focus on the success handler, as we just log errors in case of failure. Once we get the webcam stream, we point the video tag to its URL, retrieved using the URL.createObjectURL method. We should not forget to call the play method on our video to prevent from being stuck at the first frame.

At this step, we are able to display our webcam stream:

Taking a Picture using Canvas and Live Webcam Stream

Now, we need to isolate a single frame into a picture. Principle is not trivial: we need to add a canvas element to our page, set the canvas content to current video frame, and then convert canvas content to data URL.

We update our HTML code to add a Capture button:

<div> <div></div> <img src="#"/> <p><button>Capture</button></p> </div>

We added an image used to display our snapped view once user has pressed the capture button. As we don’t have any image at initialization, we set the src attribute to # . There is a lot of discussion about how to set an image with no src attribute . I opted for the anchor # which triggers an extra request to current page, which have been just downloaded and is still in cache. A very little overhead.

Browsers may display a broken image icon using # . To prevent this behavior, let’s use some CSS:

img[src="#"] { display: none; }

Let’s update our javascript code to capture a single video frame:

const startVideo = stream => { const video = document.querySelector('#stream video'); video.src = window.URL.createObjectURL(stream); video.play(); }; const stopVideo = stream => { const video = document.querySelector('#stream video'); video.parentNode.removeChild(video); // free memory before page unloading window.URL.revokeObjectURL(stream); } const capture = () => { // add canvas element const canvas = document.createElement('canvas'); document.querySelector('body').appendChild(canvas); // set canvas dimensions to video ones to not truncate picture const videoElement = document.querySelector('#stream video'); canvas.width = videoElement.width; canvas.height = videoElement.height; // copy full video frame into the canvas canvas.getContext('2d').drawImage(videoElement, 0, 0, videoElement.width, videoElement.height); // get image data URL and remove canvas const snapshot = canvas.toDataURL("image/png"); canvas.parentNode.removeChild(canvas); // update grid picture source document.querySelector('#grid').setAttribute('src', snapshot); }; getUserMedia({ video: true, audio: false, width: 640, height: 480, el: 'stream', // render live video in #stream swffile: require('getusermedia-js/dist/fallback/jscam_canvas_only.swf'), }, stream => { startVideo(stream); document.getElementById('capture').addEventListener('click', () => { capture(); stopVideo(stream); }); }, err => console.error(err));

We moved previous success callback content into a dedicated startVideo function, and add an event listener on the capture button. All other code is either self explained or commented.

Note the revokeObjectURL call to prevent from some memory leaks, as explained on Mozilla documentation :

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • Canvas实现拖拽粘性小球

    Canvas实现拖拽粘性小球

    2016-07-25 14:01

  • JavaFX: Canvas/Nashorn Demo of the Week #2

    JavaFX: Canvas/Nashorn Demo of the Week #2

    2016-07-23 10:00

  • Canvas画图基础

    Canvas画图基础

    2016-07-22 15:03

  • javascript学习笔记整理(对象基础)

    javascript学习笔记整理(对象基础)

    2015-11-11 19:53

网友点评
a