From b80511d5d2d73ad854cbec90ffcdb719efe90862 Mon Sep 17 00:00:00 2001 From: "Ciro S. Costa" Date: Sun, 1 Jun 2014 15:49:59 -0300 Subject: [PATCH] first try --- .jshintrc | 3 +- build/js/src.min.js | 2 +- build/qcode-decoder.min.js | 2 +- examples/index.html | 32 ++++++++++++++---- gulpfile.js | 6 ++-- src/qcode-decoder.js | 69 ++++++++++++++++++++++++++++++++------ 6 files changed, 92 insertions(+), 22 deletions(-) diff --git a/.jshintrc b/.jshintrc index 3655baf..287b783 100644 --- a/.jshintrc +++ b/.jshintrc @@ -18,6 +18,7 @@ "test": false, "ok": false, "asyncTest": false, - "expect": false + "expect": false, + "MediaStreamTrack": false } } diff --git a/build/js/src.min.js b/build/js/src.min.js index 402c58c..51929c3 100644 --- a/build/js/src.min.js +++ b/build/js/src.min.js @@ -1 +1 @@ -function QRCodeDecoder(){this.tmrCapture=null,this.canvasElem=null}QRCodeDecoder.prototype.prepareCanvas=function(e,t,a){return t&&a&&(e.style.width=t+"px",e.style.height=a+"px",e.width=t,e.height=a),qrcode.setCanvasElement(e),this.canvasElem=e,e},QRCodeDecoder.prototype._captureToCanvas=function(){var e=this;this.tmrCapture&&clearTimeout(this.tmrCapture);var t=this.canvasElem.getContext("2d");t.clearRect(0,0,this.canvasElem.width,this.canvasElem.height);try{t.drawImage(this.videoElem,0,0);try{qrcode.decode()}catch(a){console.log(a),this.tmrCapture=setTimeout(function(){e._captureToCanvas.apply(e,null)},500)}}catch(a){console.log(a),this.tmrCapture=setTimeout(function(){e._captureToCanvas.apply(e,null)},500)}},QRCodeDecoder.prototype.hasGetUserMedia=function(){return!!(navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia||navigator.msGetUserMedia)},QRCodeDecoder.prototype.isCanvasSupported=function(){var e=document.createElement("canvas");return!(!e.getContext||!e.getContext("2d"))},QRCodeDecoder.prototype.prepareVideo=function(e,t){var a=this;navigator.getUserMedia=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia||navigator.msGetUserMedia,navigator.getUserMedia?navigator.getUserMedia({video:!0,audio:!1},function(t){e.src=window.URL.createObjectURL(t),a.videoElem=e,setTimeout(function(){a._captureToCanvas.apply(a,null)},500)},t):console.log("Couldn't get video from camera"),setTimeout(function(){a._captureToCanvas.apply(a,null)},500)},QRCodeDecoder.prototype.setDecoderCallback=function(e){qrcode.callback=e},QRCodeDecoder.prototype.decodeFromSrc=function(e){qrcode.decode(e)}; \ No newline at end of file +function QRCodeDecoder(){this.tmrCapture=null,this.canvasElem=null}QRCodeDecoder.prototype.prepareCanvas=function(e,t,o){return t&&o&&(e.style.width=t+"px",e.style.height=o+"px",e.width=t,e.height=o),qrcode.setCanvasElement(e),this.canvasElem=e,e},QRCodeDecoder.prototype._captureToCanvas=function(){var e=this;this.tmrCapture&&clearTimeout(this.tmrCapture);var t=this.canvasElem.getContext("2d");t.clearRect(0,0,this.canvasElem.width,this.canvasElem.height);try{t.drawImage(this.videoElem,0,0);try{qrcode.decode()}catch(o){this.tmrCapture=setTimeout(function(){e._captureToCanvas.apply(e,null)},500)}}catch(o){this.tmrCapture=setTimeout(function(){e._captureToCanvas.apply(e,null)},500)}},QRCodeDecoder.prototype.hasGetUserMedia=function(){return!!(navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia||navigator.msGetUserMedia)},QRCodeDecoder.prototype.isCanvasSupported=function(){var e=document.createElement("canvas");return!(!e.getContext||!e.getContext("2d"))},QRCodeDecoder.prototype.prepareVideo=function(e,t,o){var a=this;o=o?o:t;var r={video:!0,audio:!1};return console.log("jiadsojioads"),navigator.getUserMedia=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia||navigator.msGetUserMedia,navigator.getUserMedia?t?(this.getSources(function(i){for(var n in i){var c=i[n];c.facing===t&&(r.video={optional:[{sourceId:c.id}]})}a.callGUM(e,r,a,o)}),void setTimeout(function(){a._captureToCanvas.apply(a,null)},500)):void a.callGUM(e,r,a,o):void console.log("Couldn't get video from camera")},QRCodeDecoder.prototype.callGUM=function(e,t,o,a){console.log(a),navigator.getUserMedia(t,function(t){e.src=window.URL.createObjectURL(t),o.videoElem=e,setTimeout(function(){o._captureToCanvas.apply(o,null)},500)},a||function(){})},QRCodeDecoder.prototype.getSources=function(e){var t=[];MediaStreamTrack.getSources(function(o){for(var a=0;a!==o.length;++a){var r=o[a];"video"===r.kind&&t.push(r)}e(t)})},QRCodeDecoder.prototype.setDecoderCallback=function(e){qrcode.callback=e},QRCodeDecoder.prototype.decodeFromSrc=function(e){qrcode.decode(e)}; \ No newline at end of file diff --git a/build/qcode-decoder.min.js b/build/qcode-decoder.min.js index 4aa6be7..fdd4429 100644 --- a/build/qcode-decoder.min.js +++ b/build/qcode-decoder.min.js @@ -15,4 +15,4 @@ function URShift(e,r){return e>=0?e>>r:(e>>r)+(2<<~r)}qrcode={},qrcode.imagedata function FinderPattern(t,e,r){this.x=t,this.y=e,this.count=1,this.estimatedModuleSize=r,this.__defineGetter__("EstimatedModuleSize",function(){return this.estimatedModuleSize}),this.__defineGetter__("Count",function(){return this.count}),this.__defineGetter__("X",function(){return this.x}),this.__defineGetter__("Y",function(){return this.y}),this.incrementCount=function(){this.count++},this.aboutEquals=function(t,e,r){if(Math.abs(e-this.y)<=t&&Math.abs(r-this.x)<=t){var i=Math.abs(t-this.estimatedModuleSize);return 1>=i||i/this.estimatedModuleSize<=1}return!1}}function FinderPatternInfo(t){this.bottomLeft=t[0],this.topLeft=t[1],this.topRight=t[2],this.__defineGetter__("BottomLeft",function(){return this.bottomLeft}),this.__defineGetter__("TopLeft",function(){return this.topLeft}),this.__defineGetter__("TopRight",function(){return this.topRight})}function FinderPatternFinder(){this.image=null,this.possibleCenters=[],this.hasSkipped=!1,this.crossCheckStateCount=new Array(0,0,0,0,0),this.resultPointCallback=null,this.__defineGetter__("CrossCheckStateCount",function(){return this.crossCheckStateCount[0]=0,this.crossCheckStateCount[1]=0,this.crossCheckStateCount[2]=0,this.crossCheckStateCount[3]=0,this.crossCheckStateCount[4]=0,this.crossCheckStateCount}),this.foundPatternCross=function(t){for(var e=0,r=0;5>r;r++){var i=t[r];if(0==i)return!1;e+=i}if(7>e)return!1;var s=Math.floor((e<=0&&s[e+h*qrcode.width];)o[2]++,h--;if(0>h)return 0/0;for(;h>=0&&!s[e+h*qrcode.width]&&o[1]<=r;)o[1]++,h--;if(0>h||o[1]>r)return 0/0;for(;h>=0&&s[e+h*qrcode.width]&&o[0]<=r;)o[0]++,h--;if(o[0]>r)return 0/0;for(h=t+1;n>h&&s[e+h*qrcode.width];)o[2]++,h++;if(h==n)return 0/0;for(;n>h&&!s[e+h*qrcode.width]&&o[3]=r)return 0/0;for(;n>h&&s[e+h*qrcode.width]&&o[4]=r)return 0/0;var a=o[0]+o[1]+o[2]+o[3]+o[4];return 5*Math.abs(a-i)>=2*i?0/0:this.foundPatternCross(o)?this.centerFromEnd(o,h):0/0},this.crossCheckHorizontal=function(t,e,r,i){for(var s=this.image,n=qrcode.width,o=this.CrossCheckStateCount,h=t;h>=0&&s[h+e*qrcode.width];)o[2]++,h--;if(0>h)return 0/0;for(;h>=0&&!s[h+e*qrcode.width]&&o[1]<=r;)o[1]++,h--;if(0>h||o[1]>r)return 0/0;for(;h>=0&&s[h+e*qrcode.width]&&o[0]<=r;)o[0]++,h--;if(o[0]>r)return 0/0;for(h=t+1;n>h&&s[h+e*qrcode.width];)o[2]++,h++;if(h==n)return 0/0;for(;n>h&&!s[h+e*qrcode.width]&&o[3]=r)return 0/0;for(;n>h&&s[h+e*qrcode.width]&&o[4]=r)return 0/0;var a=o[0]+o[1]+o[2]+o[3]+o[4];return 5*Math.abs(a-i)>=i?0/0:this.foundPatternCross(o)?this.centerFromEnd(o,h):0/0},this.handlePossibleCenter=function(t,e,r){var i=t[0]+t[1]+t[2]+t[3]+t[4],s=this.centerFromEnd(t,r),n=this.crossCheckVertical(e,Math.floor(s),t[2],i);if(!isNaN(n)&&(s=this.crossCheckHorizontal(Math.floor(s),Math.floor(n),t[2],i),!isNaN(s))){for(var o=i/7,h=!1,a=this.possibleCenters.length,f=0;a>f;f++){var u=this.possibleCenters[f];if(u.aboutEquals(o,n,s)){u.incrementCount(),h=!0;break}}if(!h){var d=new FinderPattern(s,n,o);this.possibleCenters.push(d),null!=this.resultPointCallback&&this.resultPointCallback.foundPossibleResultPoint(d)}return!0}return!1},this.selectBestPatterns=function(){var t=this.possibleCenters.length;if(3>t)throw"Couldn't find enough finder patterns";if(t>3){for(var e=0,r=0,i=0;t>i;i++){var s=this.possibleCenters[i].EstimatedModuleSize;e+=s,r+=s*s}var n=e/t;this.possibleCenters.sort(function(t,e){var r=Math.abs(e.EstimatedModuleSize-n),i=Math.abs(t.EstimatedModuleSize-n);return i>r?-1:r==i?0:1});for(var o=Math.sqrt(r/t-n*n),h=Math.max(.2*n,o),i=0;i3;i++){var a=this.possibleCenters[i];Math.abs(a.EstimatedModuleSize-n)>h&&(this.possibleCenters.remove(i),i--)}}return this.possibleCenters.length>3&&this.possibleCenters.sort(function(t,e){return t.count>e.count?-1:t.count=t)return 0;for(var e=null,r=0;t>r;r++){var i=this.possibleCenters[r];if(i.Count>=CENTER_QUORUM){if(null!=e)return this.hasSkipped=!0,Math.floor((Math.abs(e.X-i.X)-Math.abs(e.Y-i.Y))/2);e=i}}return 0},this.haveMultiplyConfirmedCenters=function(){for(var t=0,e=0,r=this.possibleCenters.length,i=0;r>i;i++){var s=this.possibleCenters[i];s.Count>=CENTER_QUORUM&&(t++,e+=s.EstimatedModuleSize)}if(3>t)return!1;for(var n=e/r,o=0,i=0;r>i;i++)s=this.possibleCenters[i],o+=Math.abs(s.EstimatedModuleSize-n);return.05*e>=o},this.findFinderPattern=function(t){var e=!1;this.image=t;var r=qrcode.height,i=qrcode.width,s=Math.floor(3*r/(4*MAX_MODULES));(MIN_SKIP>s||e)&&(s=MIN_SKIP);for(var n=!1,o=new Array(5),h=s-1;r>h&&!n;h+=s){o[0]=0,o[1]=0,o[2]=0,o[3]=0,o[4]=0;for(var a=0,f=0;i>f;f++)if(t[f+h*qrcode.width])1==(1&a)&&a++,o[a]++;else if(0==(1&a))if(4==a)if(this.foundPatternCross(o)){var u=this.handlePossibleCenter(o,h,f);if(u)if(s=2,this.hasSkipped)n=this.haveMultiplyConfirmedCenters();else{var d=this.findRowSkip();d>o[2]&&(h+=d-o[2]-s,f=i-1)}else{do f++;while(i>f&&!t[f+h*qrcode.width]);f--}a=0,o[0]=0,o[1]=0,o[2]=0,o[3]=0,o[4]=0}else o[0]=o[2],o[1]=o[3],o[2]=o[4],o[3]=1,o[4]=0,a=3;else o[++a]++;else o[a]++;if(this.foundPatternCross(o)){var u=this.handlePossibleCenter(o,h,i);u&&(s=o[0],this.hasSkipped&&(n=haveMultiplyConfirmedCenters()))}}var l=this.selectBestPatterns();return qrcode.orderBestPatterns(l),new FinderPatternInfo(l)}}var MIN_SKIP=3,MAX_MODULES=57,INTEGER_MATH_SHIFT=8,CENTER_QUORUM=2;qrcode.orderBestPatterns=function(t){function e(t,e){return xDiff=t.X-e.X,yDiff=t.Y-e.Y,Math.sqrt(xDiff*xDiff+yDiff*yDiff)}function r(t,e,r){var i=e.x,s=e.y;return(r.x-i)*(t.y-s)-(r.y-s)*(t.x-i)}var i,s,n,o=e(t[0],t[1]),h=e(t[1],t[2]),a=e(t[0],t[2]);if(h>=o&&h>=a?(s=t[0],i=t[1],n=t[2]):a>=h&&a>=o?(s=t[1],i=t[0],n=t[2]):(s=t[2],i=t[0],n=t[1]),r(i,s,n)<0){var f=i;i=n,n=f}t[0]=i,t[1]=s,t[2]=n}; function AlignmentPattern(t,e,i){this.x=t,this.y=e,this.count=1,this.estimatedModuleSize=i,this.__defineGetter__("EstimatedModuleSize",function(){return this.estimatedModuleSize}),this.__defineGetter__("Count",function(){return this.count}),this.__defineGetter__("X",function(){return Math.floor(this.x)}),this.__defineGetter__("Y",function(){return Math.floor(this.y)}),this.incrementCount=function(){this.count++},this.aboutEquals=function(t,e,i){if(Math.abs(e-this.y)<=t&&Math.abs(i-this.x)<=t){var r=Math.abs(t-this.estimatedModuleSize);return 1>=r||r/this.estimatedModuleSize<=1}return!1}}function AlignmentPatternFinder(t,e,i,r,n,s,h){this.image=t,this.possibleCenters=new Array,this.startX=e,this.startY=i,this.width=r,this.height=n,this.moduleSize=s,this.crossCheckStateCount=new Array(0,0,0),this.resultPointCallback=h,this.centerFromEnd=function(t,e){return e-t[2]-t[1]/2},this.foundPatternCross=function(t){for(var e=this.moduleSize,i=e/2,r=0;3>r;r++)if(Math.abs(e-t[r])>=i)return!1;return!0},this.crossCheckVertical=function(t,e,i,r){var n=this.image,s=qrcode.height,h=this.crossCheckStateCount;h[0]=0,h[1]=0,h[2]=0;for(var o=t;o>=0&&n[e+o*qrcode.width]&&h[1]<=i;)h[1]++,o--;if(0>o||h[1]>i)return 0/0;for(;o>=0&&!n[e+o*qrcode.width]&&h[0]<=i;)h[0]++,o--;if(h[0]>i)return 0/0;for(o=t+1;s>o&&n[e+o*qrcode.width]&&h[1]<=i;)h[1]++,o++;if(o==s||h[1]>i)return 0/0;for(;s>o&&!n[e+o*qrcode.width]&&h[2]<=i;)h[2]++,o++;if(h[2]>i)return 0/0;var a=h[0]+h[1]+h[2];return 5*Math.abs(a-r)>=2*r?0/0:this.foundPatternCross(h)?this.centerFromEnd(h,o):0/0},this.handlePossibleCenter=function(t,e,i){var r=t[0]+t[1]+t[2],n=this.centerFromEnd(t,i),s=this.crossCheckVertical(e,Math.floor(n),2*t[1],r);if(!isNaN(s)){for(var h=(t[0]+t[1]+t[2])/3,o=this.possibleCenters.length,a=0;o>a;a++){var u=this.possibleCenters[a];if(u.aboutEquals(h,s,n))return new AlignmentPattern(n,s,h)}var l=new AlignmentPattern(n,s,h);this.possibleCenters.push(l),null!=this.resultPointCallback&&this.resultPointCallback.foundPossibleResultPoint(l)}return null},this.find=function(){for(var e=this.startX,n=this.height,s=e+r,h=i+(n>>1),o=new Array(0,0,0),a=0;n>a;a++){var u=h+(0==(1&a)?a+1>>1:-(a+1>>1));o[0]=0,o[1]=0,o[2]=0;for(var l=e;s>l&&!t[l+qrcode.width*u];)l++;for(var f=0;s>l;){if(t[l+u*qrcode.width])if(1==f)o[f]++;else if(2==f){if(this.foundPatternCross(o)){var d=this.handlePossibleCenter(o,u,l);if(null!=d)return d}o[0]=o[2],o[1]=1,o[2]=0,f=1}else o[++f]++;else 1==f&&f++,o[f]++;l++}if(this.foundPatternCross(o)){var d=this.handlePossibleCenter(o,u,s);if(null!=d)return d}}if(0!=this.possibleCenters.length)return this.possibleCenters[0];throw"Couldn't find enough alignment patterns"}} function QRCodeDataBlockReader(t,i,e){this.blockPointer=0,this.bitPointer=7,this.dataLength=0,this.blocks=t,this.numErrorCorrectionCode=e,9>=i?this.dataLengthMode=0:i>=10&&26>=i?this.dataLengthMode=1:i>=27&&40>=i&&(this.dataLengthMode=2),this.getNextBits=function(t){var i=0;if(tr;r++)e+=1<>this.bitPointer-t+1,this.bitPointer-=t,i}if(t>8-(t-(this.bitPointer+1)),this.bitPointer=this.bitPointer-t%8,this.bitPointer<0&&(this.bitPointer=8+this.bitPointer),i}if(t>8-(t-(this.bitPointer+1+8));return i=o+s+a,this.bitPointer=this.bitPointer-(t-8)%8,this.bitPointer<0&&(this.bitPointer=8+this.bitPointer),i}return 0},this.NextMode=function(){return this.blockPointer>this.blocks.length-this.numErrorCorrectionCode-2?0:this.getNextBits(4)},this.getDataLength=function(t){for(var i=0;;){if(t>>i==1)break;i++}return this.getNextBits(qrcode.sizeOfDataLengthInfo[this.dataLengthMode][i])},this.getRomanAndFigureString=function(t){var i=t,e=0,r="",n=new Array("0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"," ","$","%","*","+","-",".","/",":");do if(i>1){e=this.getNextBits(11);var h=Math.floor(e/45),o=e%45;r+=n[h],r+=n[o],i-=2}else 1==i&&(e=this.getNextBits(6),r+=n[e],i-=1);while(i>0);return r},this.getFigureString=function(t){var i=t,e=0,r="";do i>=3?(e=this.getNextBits(10),100>e&&(r+="0"),10>e&&(r+="0"),i-=3):2==i?(e=this.getNextBits(7),10>e&&(r+="0"),i-=2):1==i&&(e=this.getNextBits(4),i-=1),r+=e;while(i>0);return r},this.get8bitByteArray=function(t){var i=t,e=0,r=new Array;do e=this.getNextBits(8),r.push(e),i--;while(i>0);return r},this.getKanjiString=function(t){var i=t,e=0,r="";do{e=getNextBits(13);var n=e%192,h=e/192,o=(h<<8)+n,s=0;s=40956>=o+33088?o+33088:o+49472,r+=String.fromCharCode(s),i--}while(i>0);return r},this.__defineGetter__("DataByte",function(){for(var t=new Array,i=1,e=2,r=4,n=8;;){var h=this.NextMode();if(0==h){if(t.length>0)break;throw"Empty data block"}if(h!=i&&h!=e&&h!=r&&h!=n)throw"Invalid mode: "+h+" in (block:"+this.blockPointer+" bit:"+this.bitPointer+")";if(dataLength=this.getDataLength(h),1>dataLength)throw"Invalid data length: "+dataLength;switch(h){case i:for(var o=this.getFigureString(dataLength),s=new Array(o.length),a=0;a - + - +
+ + +
+ + + diff --git a/gulpfile.js b/gulpfile.js index f257c39..7cdfc03 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -79,10 +79,10 @@ gulp.task('scripts', function() { }); /** - * Hinting and testing + * jshint and testing */ -gulp.task('hinting', function () { +gulp.task('jshint', function () { return gulp.src(_.union(paths.scripts, paths.tests)) .pipe(jshint()) .pipe(jshint.reporter('default')) @@ -118,7 +118,7 @@ gulp.task('clean', function () { }); -gulp.task('test', ['hinting', 'qunit']); +gulp.task('test', ['jshint', 'qunit']); gulp.task('default', ['test', 'build']); gulp.task('watch', function() { diff --git a/src/qcode-decoder.js b/src/qcode-decoder.js index 71ebfe1..6babe4b 100644 --- a/src/qcode-decoder.js +++ b/src/qcode-decoder.js @@ -48,14 +48,14 @@ QRCodeDecoder.prototype._captureToCanvas = function () { qrcode.decode(); } catch(e){ - console.log(e); + // console.log(e); this.tmrCapture = setTimeout(function () { scope._captureToCanvas.apply(scope, null); }, 500); } } catch(e){ - console.log(e); + // console.log(e); this.tmrCapture = setTimeout(function () { scope._captureToCanvas.apply(scope, null); }, 500); @@ -82,11 +82,18 @@ QRCodeDecoder.prototype.isCanvasSupported = function () { /** * Prepares the video element for receiving camera's input. * @param {DOMElement} videoElem