From 89afa2f0dee1f8bb4ee6a668a3b10ecb2f258622 Mon Sep 17 00:00:00 2001 From: Joseph Huckaby Date: Sun, 23 Aug 2015 12:17:19 -0700 Subject: [PATCH] Added optional constraints custom parameter for user media, with docs. --- README.md | 34 +++++++++++++++++++++- bower.json | 2 +- build.sh | 2 +- demos/constraints.html | 66 ++++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- webcam.js | 15 ++++------ webcam.min.js | 4 +-- 7 files changed, 110 insertions(+), 15 deletions(-) create mode 100644 demos/constraints.html diff --git a/README.md b/README.md index 0c93f2c..ef524f4 100644 --- a/README.md +++ b/README.md @@ -387,11 +387,43 @@ Finally, in your server-side script, grab the form data as if it were a plain fo if (!$result) die("Could not save image! Check file permissions."); ``` +## Custom User Media Constraints (Advanced) + +The HTML5 getUserMedia API has a constraints system by which you can specify optional or mandatory requirements for the video stream. These include things such a minimum or maximum resolution and/or framerate. By default, WebcamJS will specify a mandatory minimum width and height, matching your `dest_width` and `dest_height` parameters. However, if you want to customize this, you can set a `constraints` parameter using `Webcam.set()`, and pass in an object containing all the custom constraints you want. Example: + +```javascript + Webcam.set( 'constraints', { + mandatory: { + minWidth: 1280, + minHeight: 720, + minFrameRate: 30 + }, + optional: [ + { minFrameRate: 60 } + ] + } ); +``` + +To remove the mandatory constraints and instead just specify the resolution you would prefer, you can set simple `width` and `height` properties like this: + +```javascript + Webcam.set( 'constraints', { + width: 1280, + height: 720 + } ); +``` + +Please call this this before calling `Webcam.attach()`. + +Note that some browsers may not support every possible constraint, so consult your browser's documentation and test in all your supported browsers before using this advanced feature. For example, as of this writing Chrome 44 doesn't support framerate constraints. + +For more information see the [Media Capture Spec](http://w3c.github.io/mediacapture-main/getusermedia.html#idl-def-Constraints) and the [WebRTC Constraints Spec](http://tools.ietf.org/id/draft-alvestrand-constraints-resolution-00.html). + ## License The MIT License (MIT) -Copyright (c) 2012 - 2014 Joseph Huckaby +Copyright (c) 2012 - 2015 Joseph Huckaby Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/bower.json b/bower.json index 50829ec..166207a 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "webcamjs", - "version": "1.0.3", + "version": "1.0.4", "homepage": "https://github.com/jhuckaby/webcamjs", "authors": [ "Joseph Huckaby " diff --git a/build.sh b/build.sh index bdcb3ee..1c3c043 100755 --- a/build.sh +++ b/build.sh @@ -3,4 +3,4 @@ # Build Script for WebcamJS # Install uglifyjs first: sudo npm install uglify-js -g -uglifyjs webcam.js -o webcam.min.js --mangle --reserved "Webcam" --preamble "// WebcamJS v1.0.3 - http://github.com/jhuckaby/webcamjs - MIT Licensed" +uglifyjs webcam.js -o webcam.min.js --mangle --reserved "Webcam" --preamble "// WebcamJS v1.0.4 - http://github.com/jhuckaby/webcamjs - MIT Licensed" diff --git a/demos/constraints.html b/demos/constraints.html new file mode 100644 index 0000000..9ff07d4 --- /dev/null +++ b/demos/constraints.html @@ -0,0 +1,66 @@ + + + + + + WebcamJS Constraints Test Page + + + +
Your captured image will appear here...
+ +

WebcamJS Constraints Test Page

+

Demonstrates using the HTML5 user media constraints object

+ +
+ + + + + + + + +
+ +
+ + + + + + diff --git a/package.json b/package.json index 9e696d1..39fca86 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "webcamjs", - "version": "1.0.3", + "version": "1.0.4", "description": "HTML5 Webcam Image Capture Library with Flash Fallback", "author": "Joseph Huckaby ", "homepage": "https://github.com/jhuckaby/webcamjs", diff --git a/webcam.js b/webcam.js index d9f3a91..4b5b8f1 100644 --- a/webcam.js +++ b/webcam.js @@ -1,4 +1,4 @@ -// WebcamJS v1.0.3 +// WebcamJS v1.0.4 // Webcam library for capturing JPEG/PNG images in JavaScript // Attempts getUserMedia, falls back to Flash // Author: Joseph Huckaby: http://github.com/jhuckaby @@ -9,7 +9,7 @@ (function(window) { var Webcam = { - version: '1.0.3', + version: '1.0.4', // globals protocol: location.protocol.match(/https/i) ? 'https' : 'http', @@ -28,7 +28,8 @@ var Webcam = { force_flash: false, // force flash mode, flip_horiz: false, // flip image horiz (mirror mode) fps: 30, // camera frames per second - upload_name: 'webcam' // name of file in upload post data + upload_name: 'webcam', // name of file in upload post data + constraints: null // custom user media constraints }, hooks: {}, // callback hook functions @@ -122,15 +123,11 @@ var Webcam = { var self = this; navigator.getUserMedia({ "audio": false, - "video": { + "video": this.params.constraints || { mandatory: { minWidth: this.params.dest_width, minHeight: this.params.dest_height - }/* , - frameRate: { - ideal: this.params.fps, - max: this.params.fps - } */ + } } }, function(stream) { diff --git a/webcam.min.js b/webcam.min.js index d27a2f2..743136c 100644 --- a/webcam.min.js +++ b/webcam.min.js @@ -1,2 +1,2 @@ -// WebcamJS v1.0.3 - http://github.com/jhuckaby/webcamjs - MIT Licensed -(function(e){var Webcam={version:"1.0.3",protocol:location.protocol.match(/https/i)?"https":"http",swfURL:"",loaded:false,live:false,userMedia:true,params:{width:0,height:0,dest_width:0,dest_height:0,image_format:"jpeg",jpeg_quality:90,force_flash:false,flip_horiz:false,fps:30,upload_name:"webcam"},hooks:{},init:function(){var t=this;navigator.getUserMedia=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia||navigator.msGetUserMedia;e.URL=e.URL||e.webkitURL||e.mozURL||e.msURL;this.userMedia=this.userMedia&&!!navigator.getUserMedia&&!!e.URL;if(navigator.userAgent.match(/Firefox\D+(\d+)/)){if(parseInt(RegExp.$1,10)<21)this.userMedia=null}if(this.userMedia){e.addEventListener("beforeunload",function(e){if(t.stream){t.stream.stop();t.stream=null}})}},attach:function(t){if(typeof t=="string"){t=document.getElementById(t)||document.querySelector(t)}if(!t){return this.dispatch("error","Could not locate DOM element to attach to.")}this.container=t;t.innerHTML="";var a=document.createElement("div");t.appendChild(a);this.peg=a;if(!this.params.width)this.params.width=t.offsetWidth;if(!this.params.height)this.params.height=t.offsetHeight;if(!this.params.dest_width)this.params.dest_width=this.params.width;if(!this.params.dest_height)this.params.dest_height=this.params.height;if(this.params.force_flash)this.userMedia=null;if(typeof this.params.fps!=="number")this.params.fps=30;var i=this.params.width/this.params.dest_width;var s=this.params.height/this.params.dest_height;if(this.userMedia){var r=document.createElement("video");r.setAttribute("autoplay","autoplay");r.style.width=""+this.params.dest_width+"px";r.style.height=""+this.params.dest_height+"px";if(i!=1||s!=1){t.style.overflow="hidden";r.style.webkitTransformOrigin="0px 0px";r.style.mozTransformOrigin="0px 0px";r.style.msTransformOrigin="0px 0px";r.style.oTransformOrigin="0px 0px";r.style.transformOrigin="0px 0px";r.style.webkitTransform="scaleX("+i+") scaleY("+s+")";r.style.mozTransform="scaleX("+i+") scaleY("+s+")";r.style.msTransform="scaleX("+i+") scaleY("+s+")";r.style.oTransform="scaleX("+i+") scaleY("+s+")";r.style.transform="scaleX("+i+") scaleY("+s+")"}t.appendChild(r);this.video=r;var o=this;navigator.getUserMedia({audio:false,video:{mandatory:{minWidth:this.params.dest_width,minHeight:this.params.dest_height}}},function(t){r.src=e.URL.createObjectURL(t)||t;Webcam.stream=t;Webcam.loaded=true;Webcam.live=true;Webcam.dispatch("load");Webcam.dispatch("live");Webcam.flip()},function(e){return o.dispatch("error","Could not access webcam.")})}else{e.Webcam=Webcam;var h=document.createElement("div");h.innerHTML=this.getSWFHTML();t.appendChild(h)}if(this.params.crop_width&&this.params.crop_height){var n=Math.floor(this.params.crop_width*i);var l=Math.floor(this.params.crop_height*s);t.style.width=""+n+"px";t.style.height=""+l+"px";t.style.overflow="hidden";t.scrollLeft=Math.floor(this.params.width/2-n/2);t.scrollTop=Math.floor(this.params.height/2-l/2)}else{t.style.width=""+this.params.width+"px";t.style.height=""+this.params.height+"px"}},reset:function(){if(this.preview_active)this.unfreeze();this.unflip();if(this.userMedia){try{this.stream.stop()}catch(e){}delete this.stream;delete this.video}if(this.container){this.container.innerHTML="";delete this.container}this.loaded=false;this.live=false},set:function(){if(arguments.length==1){for(var e in arguments[0]){this.params[e]=arguments[0][e]}}else{this.params[arguments[0]]=arguments[1]}},on:function(e,t){e=e.replace(/^on/i,"").toLowerCase();if(!this.hooks[e])this.hooks[e]=[];this.hooks[e].push(t)},off:function(e,t){e=e.replace(/^on/i,"").toLowerCase();if(this.hooks[e]){if(t){var a=this.hooks[e].indexOf(t);if(a>-1)this.hooks[e].splice(a,1)}else{this.hooks[e]=[]}}},dispatch:function(){var t=arguments[0].replace(/^on/i,"").toLowerCase();var a=Array.prototype.slice.call(arguments,1);if(this.hooks[t]&&this.hooks[t].length){for(var i=0,s=this.hooks[t].length;iERROR: the Webcam.js Flash fallback does not work from local disk. Please run it from a web server.'}if(!this.detectFlash()){this.dispatch("error","Adobe Flash Player not found. Please install from get.adobe.com/flashplayer and try again.");return'

ERROR: No Adobe Flash Player detected. Webcam.js relies on Flash for browsers that do not support getUserMedia (like yours).

'}if(!this.swfURL){var a="";var i=document.getElementsByTagName("script");for(var s=0,r=i.length;s';return t},getMovie:function(){if(!this.loaded)return this.dispatch("error","Flash Movie is not loaded yet");var e=document.getElementById("webcam_movie_obj");if(!e||!e._snap)e=document.getElementById("webcam_movie_embed");if(!e)this.dispatch("error","Cannot locate Flash movie in DOM");return e},freeze:function(){var e=this;var t=this.params;if(this.preview_active)this.unfreeze();var a=this.params.width/this.params.dest_width;var i=this.params.height/this.params.dest_height;this.unflip();var s=t.crop_width||t.dest_width;var r=t.crop_height||t.dest_height;var o=document.createElement("canvas");o.width=s;o.height=r;var h=o.getContext("2d");this.preview_canvas=o;this.preview_context=h;if(a!=1||i!=1){o.style.webkitTransformOrigin="0px 0px";o.style.mozTransformOrigin="0px 0px";o.style.msTransformOrigin="0px 0px";o.style.oTransformOrigin="0px 0px";o.style.transformOrigin="0px 0px";o.style.webkitTransform="scaleX("+a+") scaleY("+i+")";o.style.mozTransform="scaleX("+a+") scaleY("+i+")";o.style.msTransform="scaleX("+a+") scaleY("+i+")";o.style.oTransform="scaleX("+a+") scaleY("+i+")";o.style.transform="scaleX("+a+") scaleY("+i+")"}this.snap(function(){o.style.position="relative";o.style.left=""+e.container.scrollLeft+"px";o.style.top=""+e.container.scrollTop+"px";e.container.insertBefore(o,e.peg);e.container.style.overflow="hidden";e.preview_active=true},o)},unfreeze:function(){if(this.preview_active){this.container.removeChild(this.preview_canvas);delete this.preview_context;delete this.preview_canvas;this.preview_active=false;this.flip()}},flip:function(){if(this.params.flip_horiz){var e=this.container.style;e.webkitTransform="scaleX(-1)";e.mozTransform="scaleX(-1)";e.msTransform="scaleX(-1)";e.oTransform="scaleX(-1)";e.transform="scaleX(-1)";e.filter="FlipH";e.msFilter="FlipH"}},unflip:function(){if(this.params.flip_horiz){var e=this.container.style;e.webkitTransform="scaleX(1)";e.mozTransform="scaleX(1)";e.msTransform="scaleX(1)";e.oTransform="scaleX(1)";e.transform="scaleX(1)";e.filter="";e.msFilter=""}},savePreview:function(e,t){var a=this.params;var i=this.preview_canvas;var s=this.preview_context;if(t){var r=t.getContext("2d");r.drawImage(i,0,0)}e(t?null:i.toDataURL("image/"+a.image_format,a.jpeg_quality/100),i,s);this.unfreeze()},snap:function(e,t){var a=this;var i=this.params;if(!this.loaded)return this.dispatch("error","Webcam is not loaded yet");if(!e)return this.dispatch("error","Please provide a callback function or canvas to snap()");if(this.preview_active){this.savePreview(e,t);return null}var s=document.createElement("canvas");s.width=this.params.dest_width;s.height=this.params.dest_height;var r=s.getContext("2d");if(this.params.flip_horiz){r.translate(i.dest_width,0);r.scale(-1,1)}var o=function(){if(this.src&&this.width&&this.height){r.drawImage(this,0,0,i.dest_width,i.dest_height)}if(i.crop_width&&i.crop_height){var a=document.createElement("canvas");a.width=i.crop_width;a.height=i.crop_height;var o=a.getContext("2d");o.drawImage(s,Math.floor(i.dest_width/2-i.crop_width/2),Math.floor(i.dest_height/2-i.crop_height/2),i.crop_width,i.crop_height,0,0,i.crop_width,i.crop_height);r=o;s=a}if(t){var h=t.getContext("2d");h.drawImage(s,0,0)}e(t?null:s.toDataURL("image/"+i.image_format,i.jpeg_quality/100),s,r)};if(this.userMedia){r.drawImage(this.video,0,0,this.params.dest_width,this.params.dest_height);o()}else{var h=this.getMovie()._snap();var n=new Image;n.onload=o;n.src="data:image/"+this.params.image_format+";base64,"+h}return null},configure:function(e){if(!e)e="camera";this.getMovie()._configure(e)},flashNotify:function(e,t){switch(e){case"flashLoadComplete":this.loaded=true;this.dispatch("load");break;case"cameraLive":this.live=true;this.dispatch("live");this.flip();break;case"error":this.dispatch("error",t);break;default:break}},b64ToUint6:function(e){return e>64&&e<91?e-65:e>96&&e<123?e-71:e>47&&e<58?e+4:e===43?62:e===47?63:0},base64DecToArr:function(e,t){var a=e.replace(/[^A-Za-z0-9\+\/]/g,""),i=a.length,s=t?Math.ceil((i*3+1>>2)/t)*t:i*3+1>>2,r=new Uint8Array(s);for(var o,h,n=0,l=0,c=0;c>>(16>>>o&24)&255}n=0}}return r},upload:function(e,t,a){var i=this.params.upload_name||"webcam";var s="";if(e.match(/^data\:image\/(\w+)/))s=RegExp.$1;else throw"Cannot locate image format in Data URI";var r=e.replace(/^data\:image\/\w+\;base64\,/,"");var o=new XMLHttpRequest;o.open("POST",t,true);if(o.upload&&o.upload.addEventListener){o.upload.addEventListener("progress",function(e){if(e.lengthComputable){var t=e.loaded/e.total;Webcam.dispatch("uploadProgress",t,e)}},false)}var h=this;o.onload=function(){if(a)a.apply(h,[o.status,o.responseText,o.statusText]);Webcam.dispatch("uploadComplete",o.status,o.responseText,o.statusText)};var n=new Blob([this.base64DecToArr(r)],{type:"image/"+s});var l=new FormData;l.append(i,n,i+"."+s.replace(/e/,""));o.send(l)}};Webcam.init();if(typeof define==="function"&&define.amd){define(function(){return Webcam})}else if(typeof module==="object"&&module.exports){module.exports=Webcam}else{e.Webcam=Webcam}})(window); \ No newline at end of file +// WebcamJS v1.0.4 - http://github.com/jhuckaby/webcamjs - MIT Licensed +(function(e){var Webcam={version:"1.0.4",protocol:location.protocol.match(/https/i)?"https":"http",swfURL:"",loaded:false,live:false,userMedia:true,params:{width:0,height:0,dest_width:0,dest_height:0,image_format:"jpeg",jpeg_quality:90,force_flash:false,flip_horiz:false,fps:30,upload_name:"webcam",constraints:null},hooks:{},init:function(){var t=this;navigator.getUserMedia=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia||navigator.msGetUserMedia;e.URL=e.URL||e.webkitURL||e.mozURL||e.msURL;this.userMedia=this.userMedia&&!!navigator.getUserMedia&&!!e.URL;if(navigator.userAgent.match(/Firefox\D+(\d+)/)){if(parseInt(RegExp.$1,10)<21)this.userMedia=null}if(this.userMedia){e.addEventListener("beforeunload",function(e){if(t.stream){t.stream.stop();t.stream=null}})}},attach:function(t){if(typeof t=="string"){t=document.getElementById(t)||document.querySelector(t)}if(!t){return this.dispatch("error","Could not locate DOM element to attach to.")}this.container=t;t.innerHTML="";var a=document.createElement("div");t.appendChild(a);this.peg=a;if(!this.params.width)this.params.width=t.offsetWidth;if(!this.params.height)this.params.height=t.offsetHeight;if(!this.params.dest_width)this.params.dest_width=this.params.width;if(!this.params.dest_height)this.params.dest_height=this.params.height;if(this.params.force_flash)this.userMedia=null;if(typeof this.params.fps!=="number")this.params.fps=30;var i=this.params.width/this.params.dest_width;var s=this.params.height/this.params.dest_height;if(this.userMedia){var r=document.createElement("video");r.setAttribute("autoplay","autoplay");r.style.width=""+this.params.dest_width+"px";r.style.height=""+this.params.dest_height+"px";if(i!=1||s!=1){t.style.overflow="hidden";r.style.webkitTransformOrigin="0px 0px";r.style.mozTransformOrigin="0px 0px";r.style.msTransformOrigin="0px 0px";r.style.oTransformOrigin="0px 0px";r.style.transformOrigin="0px 0px";r.style.webkitTransform="scaleX("+i+") scaleY("+s+")";r.style.mozTransform="scaleX("+i+") scaleY("+s+")";r.style.msTransform="scaleX("+i+") scaleY("+s+")";r.style.oTransform="scaleX("+i+") scaleY("+s+")";r.style.transform="scaleX("+i+") scaleY("+s+")"}t.appendChild(r);this.video=r;var o=this;navigator.getUserMedia({audio:false,video:this.params.constraints||{mandatory:{minWidth:this.params.dest_width,minHeight:this.params.dest_height}}},function(t){r.src=e.URL.createObjectURL(t)||t;Webcam.stream=t;Webcam.loaded=true;Webcam.live=true;Webcam.dispatch("load");Webcam.dispatch("live");Webcam.flip()},function(e){return o.dispatch("error","Could not access webcam.")})}else{e.Webcam=Webcam;var h=document.createElement("div");h.innerHTML=this.getSWFHTML();t.appendChild(h)}if(this.params.crop_width&&this.params.crop_height){var n=Math.floor(this.params.crop_width*i);var l=Math.floor(this.params.crop_height*s);t.style.width=""+n+"px";t.style.height=""+l+"px";t.style.overflow="hidden";t.scrollLeft=Math.floor(this.params.width/2-n/2);t.scrollTop=Math.floor(this.params.height/2-l/2)}else{t.style.width=""+this.params.width+"px";t.style.height=""+this.params.height+"px"}},reset:function(){if(this.preview_active)this.unfreeze();this.unflip();if(this.userMedia){try{this.stream.stop()}catch(e){}delete this.stream;delete this.video}if(this.container){this.container.innerHTML="";delete this.container}this.loaded=false;this.live=false},set:function(){if(arguments.length==1){for(var e in arguments[0]){this.params[e]=arguments[0][e]}}else{this.params[arguments[0]]=arguments[1]}},on:function(e,t){e=e.replace(/^on/i,"").toLowerCase();if(!this.hooks[e])this.hooks[e]=[];this.hooks[e].push(t)},off:function(e,t){e=e.replace(/^on/i,"").toLowerCase();if(this.hooks[e]){if(t){var a=this.hooks[e].indexOf(t);if(a>-1)this.hooks[e].splice(a,1)}else{this.hooks[e]=[]}}},dispatch:function(){var t=arguments[0].replace(/^on/i,"").toLowerCase();var a=Array.prototype.slice.call(arguments,1);if(this.hooks[t]&&this.hooks[t].length){for(var i=0,s=this.hooks[t].length;iERROR: the Webcam.js Flash fallback does not work from local disk. Please run it from a web server.'}if(!this.detectFlash()){this.dispatch("error","Adobe Flash Player not found. Please install from get.adobe.com/flashplayer and try again.");return'

ERROR: No Adobe Flash Player detected. Webcam.js relies on Flash for browsers that do not support getUserMedia (like yours).

'}if(!this.swfURL){var a="";var i=document.getElementsByTagName("script");for(var s=0,r=i.length;s';return t},getMovie:function(){if(!this.loaded)return this.dispatch("error","Flash Movie is not loaded yet");var e=document.getElementById("webcam_movie_obj");if(!e||!e._snap)e=document.getElementById("webcam_movie_embed");if(!e)this.dispatch("error","Cannot locate Flash movie in DOM");return e},freeze:function(){var e=this;var t=this.params;if(this.preview_active)this.unfreeze();var a=this.params.width/this.params.dest_width;var i=this.params.height/this.params.dest_height;this.unflip();var s=t.crop_width||t.dest_width;var r=t.crop_height||t.dest_height;var o=document.createElement("canvas");o.width=s;o.height=r;var h=o.getContext("2d");this.preview_canvas=o;this.preview_context=h;if(a!=1||i!=1){o.style.webkitTransformOrigin="0px 0px";o.style.mozTransformOrigin="0px 0px";o.style.msTransformOrigin="0px 0px";o.style.oTransformOrigin="0px 0px";o.style.transformOrigin="0px 0px";o.style.webkitTransform="scaleX("+a+") scaleY("+i+")";o.style.mozTransform="scaleX("+a+") scaleY("+i+")";o.style.msTransform="scaleX("+a+") scaleY("+i+")";o.style.oTransform="scaleX("+a+") scaleY("+i+")";o.style.transform="scaleX("+a+") scaleY("+i+")"}this.snap(function(){o.style.position="relative";o.style.left=""+e.container.scrollLeft+"px";o.style.top=""+e.container.scrollTop+"px";e.container.insertBefore(o,e.peg);e.container.style.overflow="hidden";e.preview_active=true},o)},unfreeze:function(){if(this.preview_active){this.container.removeChild(this.preview_canvas);delete this.preview_context;delete this.preview_canvas;this.preview_active=false;this.flip()}},flip:function(){if(this.params.flip_horiz){var e=this.container.style;e.webkitTransform="scaleX(-1)";e.mozTransform="scaleX(-1)";e.msTransform="scaleX(-1)";e.oTransform="scaleX(-1)";e.transform="scaleX(-1)";e.filter="FlipH";e.msFilter="FlipH"}},unflip:function(){if(this.params.flip_horiz){var e=this.container.style;e.webkitTransform="scaleX(1)";e.mozTransform="scaleX(1)";e.msTransform="scaleX(1)";e.oTransform="scaleX(1)";e.transform="scaleX(1)";e.filter="";e.msFilter=""}},savePreview:function(e,t){var a=this.params;var i=this.preview_canvas;var s=this.preview_context;if(t){var r=t.getContext("2d");r.drawImage(i,0,0)}e(t?null:i.toDataURL("image/"+a.image_format,a.jpeg_quality/100),i,s);this.unfreeze()},snap:function(e,t){var a=this;var i=this.params;if(!this.loaded)return this.dispatch("error","Webcam is not loaded yet");if(!e)return this.dispatch("error","Please provide a callback function or canvas to snap()");if(this.preview_active){this.savePreview(e,t);return null}var s=document.createElement("canvas");s.width=this.params.dest_width;s.height=this.params.dest_height;var r=s.getContext("2d");if(this.params.flip_horiz){r.translate(i.dest_width,0);r.scale(-1,1)}var o=function(){if(this.src&&this.width&&this.height){r.drawImage(this,0,0,i.dest_width,i.dest_height)}if(i.crop_width&&i.crop_height){var a=document.createElement("canvas");a.width=i.crop_width;a.height=i.crop_height;var o=a.getContext("2d");o.drawImage(s,Math.floor(i.dest_width/2-i.crop_width/2),Math.floor(i.dest_height/2-i.crop_height/2),i.crop_width,i.crop_height,0,0,i.crop_width,i.crop_height);r=o;s=a}if(t){var h=t.getContext("2d");h.drawImage(s,0,0)}e(t?null:s.toDataURL("image/"+i.image_format,i.jpeg_quality/100),s,r)};if(this.userMedia){r.drawImage(this.video,0,0,this.params.dest_width,this.params.dest_height);o()}else{var h=this.getMovie()._snap();var n=new Image;n.onload=o;n.src="data:image/"+this.params.image_format+";base64,"+h}return null},configure:function(e){if(!e)e="camera";this.getMovie()._configure(e)},flashNotify:function(e,t){switch(e){case"flashLoadComplete":this.loaded=true;this.dispatch("load");break;case"cameraLive":this.live=true;this.dispatch("live");this.flip();break;case"error":this.dispatch("error",t);break;default:break}},b64ToUint6:function(e){return e>64&&e<91?e-65:e>96&&e<123?e-71:e>47&&e<58?e+4:e===43?62:e===47?63:0},base64DecToArr:function(e,t){var a=e.replace(/[^A-Za-z0-9\+\/]/g,""),i=a.length,s=t?Math.ceil((i*3+1>>2)/t)*t:i*3+1>>2,r=new Uint8Array(s);for(var o,h,n=0,l=0,c=0;c>>(16>>>o&24)&255}n=0}}return r},upload:function(e,t,a){var i=this.params.upload_name||"webcam";var s="";if(e.match(/^data\:image\/(\w+)/))s=RegExp.$1;else throw"Cannot locate image format in Data URI";var r=e.replace(/^data\:image\/\w+\;base64\,/,"");var o=new XMLHttpRequest;o.open("POST",t,true);if(o.upload&&o.upload.addEventListener){o.upload.addEventListener("progress",function(e){if(e.lengthComputable){var t=e.loaded/e.total;Webcam.dispatch("uploadProgress",t,e)}},false)}var h=this;o.onload=function(){if(a)a.apply(h,[o.status,o.responseText,o.statusText]);Webcam.dispatch("uploadComplete",o.status,o.responseText,o.statusText)};var n=new Blob([this.base64DecToArr(r)],{type:"image/"+s});var l=new FormData;l.append(i,n,i+"."+s.replace(/e/,""));o.send(l)}};Webcam.init();if(typeof define==="function"&&define.amd){define(function(){return Webcam})}else if(typeof module==="object"&&module.exports){module.exports=Webcam}else{e.Webcam=Webcam}})(window); \ No newline at end of file