From aeb181ed785420798c5f45d0503946505c166d73 Mon Sep 17 00:00:00 2001 From: Minhaz Date: Fri, 1 May 2020 17:10:08 +0800 Subject: [PATCH 1/2] Fix inconsistency between viewfinder qrbox and actual feed in canvas --- .gitignore | 1 + README.md | 6 +- changelog.md | 13 ++ html5-qrcode.js | 367 ++++++++++++++++++++++------------- minified/html5-qrcode.min.js | 2 +- package.json | 4 +- transpiled/html5-qrcode.js | 238 ++++++++++++++--------- 7 files changed, 400 insertions(+), 231 deletions(-) create mode 100644 changelog.md diff --git a/.gitignore b/.gitignore index e617da4..c39acac 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .DS_Store node_modules/ package-lock.json +.vscode/ \ No newline at end of file diff --git a/README.md b/README.md index be315e3..cf71644 100644 --- a/README.md +++ b/README.md @@ -56,8 +56,9 @@ npm i html5-qrcode Add an element you want to use as placeholder for QR Code scanner ```html -
+
``` +> Ideally do not set the height of this container as the height should depend on the height of the video feed from the camera. The library would honor existing width otherwise apply the default width. The height is derived from the aspect ratio of the video feed. Add `minified/html5-qrcode.min.js` in your web page. > I would recommend using the minified version as it's transformed to standard javascript. The `html5-qrcode.js` is written with ECMAScript and may not be supported in the older version of the browsers. I wrote in this as it's easier to maintain! @@ -135,9 +136,10 @@ You can alternatively leverage QR Code scanning for local files on the device or Define the HTML container and import the javascript library as mentioned above ```html -
+
``` +> It's not mandatory to set the height and width of the HTML element. If provided the library would try to honour it. If it's not set the library would set a default width and derive the height based on the input image's aspect ratio. Add an `Input` element for supporting file selection like this: ```html diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..15fcc3f --- /dev/null +++ b/changelog.md @@ -0,0 +1,13 @@ +### Version 1.0.7 + + Fixed the video size issue in [issues/21](https://github.com/mebjas/html5-qrcode/issues/21) + + Removed fixed height of viewfinder, now the height is based on the video stream. The width is honored if the input element has a default width. Otherwise default width is applied. + + If `config.qrbox` is greater than derived height, the config is ignored & no shading is applied. + + The sequence of steps have changed + + First we get the video feed from the selected camera + + Then we render video + + Then based on the height of the video we set the canvas and start scanning. + + For file scanning, if the container element has some height or width both are honored. + Otherwise default width is applied and height is derived from the image. + +### Older versions +Mostly covered in [readme](./README.md), changelog tracking started since `version 1.0.7` \ No newline at end of file diff --git a/html5-qrcode.js b/html5-qrcode.js index 59b602c..912a5ad 100644 --- a/html5-qrcode.js +++ b/html5-qrcode.js @@ -12,8 +12,6 @@ * browser support. Alternatively the transpiled code lives in transpiled/html5-qrcode.js */ class Html5Qrcode { - static DEFAULT_HEIGHT = 300; - static DEFAULT_HEIGHT_OFFSET = 2; static DEFAULT_WIDTH = 300; static DEFAULT_WIDTH_OFFSET = 2; static SCAN_DEFAULT_FPS = 2; @@ -98,12 +96,16 @@ class Html5Qrcode { // Create configuration by merging default and input settings. const config = configuration ? configuration : {}; config.fps = config.fps ? config.fps : Html5Qrcode.SCAN_DEFAULT_FPS; - + // qr shaded box const isShadedBoxEnabled = config.qrbox != undefined; const element = document.getElementById(this._elementId); const width = element.clientWidth ? element.clientWidth : Html5Qrcode.DEFAULT_WIDTH; - const height = element.clientHeight ? element.clientHeight : Html5Qrcode.DEFAULT_HEIGHT; + element.style.position = "relative"; + + // Setup QR code. + this._shouldScan = true; + qrcode.callback = qrCodeSuccessCallback; // Validate before insertion if (isShadedBoxEnabled) { @@ -112,41 +114,55 @@ class Html5Qrcode { throw `minimum size of 'config.qrbox' is ${Html5Qrcode.MIN_QR_BOX_SIZE}px.`; } - if (qrboxSize > width || qrboxSize > height) { + if (qrboxSize > width) { throw "'config.qrbox' should not be greater than the " - + "width and height of the HTML element."; + + "width of the HTML element."; } } - const qrRegion = isShadedBoxEnabled ? this._getShadedRegionBounds(width, height, config.qrbox) : { - x: 0, - y: 0, - width: width, - height: height - }; - - const videoElement = this._createVideoElement(width, height); - const canvasElement = this._createCanvasElement(qrRegion.width, qrRegion.height); - const context = canvasElement.getContext('2d'); - context.canvas.width = qrRegion.width; - context.canvas.height = qrRegion.height; + //#region local methods + /** + * Setups the UI elements, changes the state of this class. + * + * @param width derived width of viewfinder. + * @param height derived height of viewfinder. + */ + const setupUi = (width, height) => { + const qrboxSize = config.qrbox; + if (qrboxSize > height) { + console.log("[Warning] [Html5Qrcode] config.qrboxsize is greater " + + "than video height. Shading will be ignored"); + } - element.style.position = "relative"; - element.append(videoElement); - element.append(canvasElement); - if (isShadedBoxEnabled) { - this._possiblyInsertShadingElement(element, height, qrRegion); + const shouldShadingBeApplied = isShadedBoxEnabled && qrboxSize <= height; + const defaultQrRegion = { + x: 0, + y: 0, + width: width, + height: height + }; + const qrRegion = shouldShadingBeApplied + ? this._getShadedRegionBounds(width, height, qrboxSize) + : defaultQrRegion; + + const canvasElement = this._createCanvasElement(qrRegion.width, qrRegion.height); + const context = canvasElement.getContext('2d'); + context.canvas.width = qrRegion.width; + context.canvas.height = qrRegion.height; + + // Insert the canvas + element.append(canvasElement); + if (shouldShadingBeApplied) { + this._possiblyInsertShadingElement(element, height, qrRegion); + } + + // Update local states + $this._qrRegion = qrRegion; + $this._context = context; + $this._element = element; + $this._canvasElement = canvasElement; } - - // save local states - this._element = element; - this._videoElement = videoElement; - this._canvasElement = canvasElement; - - // Setup QR code. - this._shouldScan = true; - qrcode.callback = qrCodeSuccessCallback; - + // Method that scans forever. const foreverScan = () => { if (!$this._shouldScan) { @@ -154,54 +170,110 @@ class Html5Qrcode { return; } if ($this._localMediaStream) { + + // difference in held video dimensions and rendered video dimensions + // require scaling + const videoElement = $this._videoElement; + const widthRatio = videoElement.videoWidth / videoElement.clientWidth; + const heightRatio = videoElement.videoHeight / videoElement.clientHeight; + const sWidthOffset = $this._qrRegion.width * widthRatio; + const sHeightOffset = $this._qrRegion.height * heightRatio; + // Only decode the relevant area, ignore the shaded area, More reference: // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage - context.drawImage( - videoElement, - /* sx= */ qrRegion.x, - /* sy= */ qrRegion.y, - /* sWidth= */ qrRegion.width, - /* sHeight= */ qrRegion.height, + $this._context.drawImage( + $this._videoElement, + /* sx= */ $this._qrRegion.x, + /* sy= */ $this._qrRegion.y, + /* sWidth= */ sWidthOffset, + /* sHeight= */ sHeightOffset, /* dx= */ 0, /* dy= */ 0, - /* dWidth= */ qrRegion.width, - /* dHeight= */ qrRegion.height); + /* dWidth= */ $this._qrRegion.width, + /* dHeight= */ $this._qrRegion.height); try { qrcode.decode(); } catch (exception) { qrCodeErrorCallback(`QR code parse error, error = ${exception}`); } } - $this._foreverScanTimeout = setTimeout(foreverScan, Html5Qrcode._getTimeoutFps(config.fps)); + $this._foreverScanTimeout = setTimeout( + foreverScan, Html5Qrcode._getTimeoutFps(config.fps)); } // success callback when user media (Camera) is attached. - const getUserMediaSuccessCallback = stream => { - videoElement.srcObject = stream; - videoElement.play(); - $this._localMediaStream = stream; - foreverScan(); - } + const getUserMediaSuccessCallback = mediaStream => { + return new Promise((resolve, reject) => { + const setupVideo = () => { + $this._videoElement = this._createVideoElement(width); + element.append($this._videoElement); + // Attach listeners to video. + $this._videoElement.onabort = reject; + $this._videoElement.onerror = reject; + $this._videoElement.onplaying = () => { + const videoWidth = $this._videoElement.clientWidth; + const videoHeight = $this._videoElement.clientHeight; + setupUi(videoWidth, videoHeight); + + // start scanning after video feed has started + foreverScan(); + resolve(); + } + + $this._videoElement.srcObject = mediaStream; + $this._videoElement.play(); + } + $this._localMediaStream = mediaStream; + setupVideo(); + + // TODO(mebjas): see if constaints can be applied on camera + // for better results or performance. + + // const constraints = { + // width: { min: width , ideal: width, max: width }, + // frameRate: { ideal: 30, max: 30 } + // } + // const track = mediaStream.getVideoTracks()[0]; + // track.applyConstraints(constraints) + // .then(() => setupVideo()) + // .catch(error => { + // console.log("[Warning] [Html5Qrcode] Constriants could not be " + // + "satisfied, ignoring constraints", error); + // setupVideo(); + // }); + }); + } + //#endregion + return new Promise((resolve, reject) => { if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { + const videoConstraints = { + deviceId: { exact: cameraId } + }; navigator.mediaDevices.getUserMedia( - { audio: false, video: { deviceId: { exact: cameraId }}}) + { audio: false, video: videoConstraints }) .then(stream => { - getUserMediaSuccessCallback(stream); - $this._isScanning = true; - resolve(); + getUserMediaSuccessCallback(stream) + .then(ignore => { + $this._isScanning = true; + resolve(); + }) + .catch(reject); }) .catch(err => { reject(`Error getting userMedia, error = ${err}`); }); } else if (navigator.getUserMedia) { - const getCameraConfig = { video: { optional: [{ sourceId: cameraId }]}}; + const getCameraConfig = { video: { optional: [ { sourceId: cameraId } ]}}; navigator.getUserMedia(getCameraConfig, stream => { - getUserMediaSuccessCallback(stream); - $this._isScanning = true; - resolve(); + getUserMediaSuccessCallback(stream) + .then(ignore => { + $this._isScanning = true; + resolve(); + }) + .catch(reject); }, err => { reject(`Error getting userMedia, error = ${err}`); }); @@ -243,6 +315,12 @@ class Html5Qrcode { $this._element.removeChild($this._canvasElement); removeQrRegion(); $this._isScanning = false; + if ($this._qrRegion) { + $this._qrRegion = null; + } + if ($this._context) { + $this._context = null; + } resolve(true); } @@ -285,37 +363,41 @@ class Html5Qrcode { throw "Close ongoing scan before scanning a file."; } - const computeCanvasDrawConfig = (imageWidth, imageHeight) => { - const element = document.getElementById($this._elementId); - const width = element.clientWidth ? element.clientWidth : Html5Qrcode.DEFAULT_WIDTH; - const height = element.clientHeight ? element.clientHeight : Html5Qrcode.DEFAULT_HEIGHT; - - if (imageWidth <= width && imageHeight <= height) { - // no downsampling needed. - const xoffset = (width - imageWidth) / 2; - const yoffset = (height - imageHeight) / 2; - return { - x: xoffset, - y: yoffset, - width: imageWidth, - height: imageHeight - } + const computeCanvasDrawConfig = ( + imageWidth, + imageHeight, + containerWidth, + containerHeight) => { + + if (imageWidth <= containerWidth && imageHeight <= containerHeight) { + // no downsampling needed. + const xoffset = (containerWidth - imageWidth) / 2; + const yoffset = (containerHeight - imageHeight) / 2; + return { + x: xoffset, + y: yoffset, + width: imageWidth, + height: imageHeight + }; } else { - const formerImageWidth = imageWidth; - const formerImageHeight = imageHeight; - if (imageWidth > width) { - imageHeight = (width / imageWidth) * imageHeight; - imageWidth = width; - } - - if (imageHeight > height) { - imageWidth = (height / imageHeight) * imageWidth; - imageHeight = height; - } - - Html5Qrcode._log(`Image downsampled from ${formerImageWidth}X${formerImageHeight}` - + ` to ${imageWidth}X${imageHeight}.`) - return computeCanvasDrawConfig(imageWidth, imageHeight); + const formerImageWidth = imageWidth; + const formerImageHeight = imageHeight; + if (imageWidth > containerWidth) { + imageHeight = (containerWidth / imageWidth) * imageHeight; + imageWidth = containerWidth; + } + + if (imageHeight > containerHeight) { + imageWidth = (containerHeight / imageHeight) * imageWidth; + imageHeight = containerHeight; + } + + Html5Qrcode._log( + `Image downsampled from ${formerImageWidth}X${formerImageHeight}` + + ` to ${imageWidth}X${imageHeight}.`); + + return computeCanvasDrawConfig( + imageWidth, imageHeight, containerWidth, containerHeight); } } @@ -326,54 +408,59 @@ class Html5Qrcode { const inputImage = new Image; inputImage.onload = () => { - const element = document.getElementById($this._elementId); - const containerWidth = element.clientWidth ? element.clientWidth : Html5Qrcode.DEFAULT_WIDTH; - const containerHeight = element.clientHeight ? element.clientHeight : Html5Qrcode.DEFAULT_HEIGHT; - const imageWidth = inputImage.width; - const imageHeight = inputImage.height; - const config = computeCanvasDrawConfig(imageWidth, imageHeight); - if (showImage) { - const visibleCanvas = $this._createCanvasElement( - containerWidth, containerHeight, 'qr-canvas-visible'); - visibleCanvas.style.display = "inline-block"; - element.appendChild(visibleCanvas); - const context = visibleCanvas.getContext('2d'); - context.canvas.width = containerWidth; - context.canvas.height = containerHeight; - // More reference - // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage - context.drawImage( - inputImage, - /* sx= */ 0, - /* sy= */ 0, - /* sWidth= */ imageWidth, - /* sHeight= */ imageHeight, - /* dx= */ config.x, - /* dy= */ config.y, - /* dWidth= */ config.width, - /* dHeight= */ config.height); - } + const imageWidth = inputImage.width; + const imageHeight = inputImage.height; + const element = document.getElementById($this._elementId); + const containerWidth = element.clientWidth + ? element.clientWidth : Html5Qrcode.DEFAULT_WIDTH; + // No default height anymore. + const containerHeight = element.clientHeight + ? element.clientHeight : imageHeight ; - const hiddenCanvas = $this._createCanvasElement(config.width, config.height); - element.appendChild(hiddenCanvas); - const context = hiddenCanvas.getContext('2d'); - context.canvas.width = config.width; - context.canvas.height = config.height; - context.drawImage( - inputImage, - /* sx= */ 0, - /* sy= */ 0, - /* sWidth= */ imageWidth, - /* sHeight= */ imageHeight, - /* dx= */ 0, - /* dy= */ 0, - /* dWidth= */ config.width, - /* dHeight= */ config.height); - try { - resolve(qrcode.decode()); - } catch (exception) { - reject(`QR code parse error, error = ${exception}`); - } + const config = computeCanvasDrawConfig( + imageWidth, imageHeight, containerWidth, containerHeight); + if (showImage) { + const visibleCanvas = $this._createCanvasElement( + containerWidth, containerHeight, 'qr-canvas-visible'); + visibleCanvas.style.display = "inline-block"; + element.appendChild(visibleCanvas); + const context = visibleCanvas.getContext('2d'); + context.canvas.width = containerWidth; + context.canvas.height = containerHeight; + // More reference + // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage + context.drawImage( + inputImage, + /* sx= */ 0, + /* sy= */ 0, + /* sWidth= */ imageWidth, + /* sHeight= */ imageHeight, + /* dx= */ config.x, + /* dy= */ config.y, + /* dWidth= */ config.width, + /* dHeight= */ config.height); + } + + const hiddenCanvas = $this._createCanvasElement(config.width, config.height); + element.appendChild(hiddenCanvas); + const context = hiddenCanvas.getContext('2d'); + context.canvas.width = config.width; + context.canvas.height = config.height; + context.drawImage( + inputImage, + /* sx= */ 0, + /* sy= */ 0, + /* sWidth= */ imageWidth, + /* sHeight= */ imageHeight, + /* dx= */ 0, + /* dy= */ 0, + /* dWidth= */ config.width, + /* dHeight= */ config.height); + try { + resolve(qrcode.decode()); + } catch (exception) { + reject(`QR code parse error, error = ${exception}`); + } } inputImage.onerror = reject; @@ -391,7 +478,7 @@ class Html5Qrcode { * closed before calling this method, else it will throw exception. */ clear() { - this._clearElement(); + this._clearElement(); } /** @@ -409,7 +496,8 @@ class Html5Qrcode { && navigator.mediaDevices.enumerateDevices && navigator.mediaDevices.getUserMedia) { this._log("navigator.mediaDevices used"); - navigator.mediaDevices.getUserMedia({audio: false, video: true}).then(ignore => { + navigator.mediaDevices.getUserMedia({audio: false, video: true}) + .then(ignore => { navigator.mediaDevices.enumerateDevices() .then(devices => { const results = []; @@ -428,7 +516,8 @@ class Html5Qrcode { .catch(err => { reject(`${err.name} : ${err.message}`); }); - }).catch(err => { + }) + .catch(err => { reject(`${err.name} : ${err.message}`); }) } else if (MediaStreamTrack && MediaStreamTrack.getSources) { @@ -475,9 +564,8 @@ class Html5Qrcode { return canvasElement; } - _createVideoElement(width, height) { + _createVideoElement(width) { const videoElement = document.createElement('video'); - videoElement.style.height = `${height}px`; videoElement.style.width = `${width}px`; videoElement.muted = true; videoElement.playsInline = true; @@ -538,7 +626,8 @@ class Html5Qrcode { elem.style.height = `${qrRegion.y}px`; break; case Html5Qrcode.SHADED_BOTTOM: - elem.style.bottom = "0px"; + const top = qrRegion.y + qrRegion.height; + elem.style.top = `${top}px`; elem.style.left = `${qrRegion.x}px`; elem.style.width = `${qrRegion.width}px`; elem.style.height = `${qrRegion.y}px`; diff --git a/minified/html5-qrcode.min.js b/minified/html5-qrcode.min.js index 1fee0cf..0a7e53a 100644 --- a/minified/html5-qrcode.min.js +++ b/minified/html5-qrcode.min.js @@ -1,4 +1,4 @@ function ECB(e,t){this.count=e,this.dataCodewords=t,this.__defineGetter__("Count",function(){return this.count}),this.__defineGetter__("DataCodewords",function(){return this.dataCodewords})}function ECBlocks(e,t,n){this.ecCodewordsPerBlock=e,this.ecBlocks=n?[t,n]:Array(t),this.__defineGetter__("ECCodewordsPerBlock",function(){return this.ecCodewordsPerBlock}),this.__defineGetter__("TotalECCodewords",function(){return this.ecCodewordsPerBlock*this.NumBlocks}),this.__defineGetter__("NumBlocks",function(){for(var e=0,t=0;ti;i++)for(var r=this.alignmentPatternCenters[i]-2,o=0;n>o;o++)0==i&&(0==o||o==n-1)||i==n-1&&0==o||t.setRegion(this.alignmentPatternCenters[o]-2,r,5,5);return t.setRegion(6,9,1,e-17),t.setRegion(9,6,e-17,1),6f;f+=2){var d=e[f],w=e[f+1],u=r*d+a*w+l;e[f]=(n*d+o*w+h)/u,e[f+1]=(i*d+s*w+c)/u}},this.transformPoints2=function(e,t){for(var n=e.length,i=0;n>i;i++){var r=e[i],o=t[i],s=this.a13*r+this.a23*o+this.a33;e[i]=(this.a11*r+this.a21*o+this.a31)/s,t[i]=(this.a12*r+this.a22*o+this.a32)/s}},this.buildAdjoint=function(){return new PerspectiveTransform(this.a22*this.a33-this.a23*this.a32,this.a23*this.a31-this.a21*this.a33,this.a21*this.a32-this.a22*this.a31,this.a13*this.a32-this.a12*this.a33,this.a11*this.a33-this.a13*this.a31,this.a12*this.a31-this.a11*this.a32,this.a12*this.a23-this.a13*this.a22,this.a13*this.a21-this.a11*this.a23,this.a11*this.a22-this.a12*this.a21)},this.times=function(e){return new PerspectiveTransform(this.a11*e.a11+this.a21*e.a12+this.a31*e.a13,this.a11*e.a21+this.a21*e.a22+this.a31*e.a23,this.a11*e.a31+this.a21*e.a32+this.a31*e.a33,this.a12*e.a11+this.a22*e.a12+this.a32*e.a13,this.a12*e.a21+this.a22*e.a22+this.a32*e.a23,this.a12*e.a31+this.a22*e.a32+this.a32*e.a33,this.a13*e.a11+this.a23*e.a12+this.a33*e.a13,this.a13*e.a21+this.a23*e.a22+this.a33*e.a23,this.a13*e.a31+this.a23*e.a32+this.a33*e.a33)}}function DetectorResult(e,t){this.bits=e,this.points=t}function Detector(e){this.image=e,this.resultPointCallback=null,this.sizeOfBlackWhiteBlackRun=function(e,t,n,i){var r=Math.abs(i-t)>Math.abs(n-e);if(r){var o=e;e=t,t=o,o=n,n=i,i=o}for(var s=Math.abs(n-e),a=Math.abs(i-t),h=-s>>1,c=i>t?1:-1,l=n>e?1:-1,f=0,d=e,o=t;d!=n;d+=l){var w=r?o:d,u=r?d:o;if(1==f?this.image[w+u*qrcode.width]&&f++:this.image[w+u*qrcode.width]||f++,3==f)return i=d-e,t=o-t,Math.sqrt(i*i+t*t);if(h+=a,h>0){if(o==i)break;o+=c,h-=s}}return e=n-e,t=i-t,Math.sqrt(e*e+t*t)},this.sizeOfBlackWhiteBlackRunBothWays=function(e,t,n,i){var r=this.sizeOfBlackWhiteBlackRun(e,t,n,i),o=1;return n=e-(n-e),0>n?(o=e/(e-n),n=0):n>=qrcode.width&&(o=(qrcode.width-1-e)/(n-e),n=qrcode.width-1),i=Math.floor(t-(i-t)*o),o=1,0>i?(o=t/(t-i),i=0):i>=qrcode.height&&(o=(qrcode.height-1-t)/(i-t),i=qrcode.height-1),n=Math.floor(e+(n-e)*o),r+=this.sizeOfBlackWhiteBlackRun(e,t,n,i),r-1},this.calculateModuleSizeOneWay=function(e,t){var n=this.sizeOfBlackWhiteBlackRunBothWays(Math.floor(e.X),Math.floor(e.Y),Math.floor(t.X),Math.floor(t.Y)),i=this.sizeOfBlackWhiteBlackRunBothWays(Math.floor(t.X),Math.floor(t.Y),Math.floor(e.X),Math.floor(e.Y));return isNaN(n)?i/7:isNaN(i)?n/7:(n+i)/14},this.calculateModuleSize=function(e,t,n){return(this.calculateModuleSizeOneWay(e,t)+this.calculateModuleSizeOneWay(e,n))/2},this.distance=function(e,t){return xDiff=e.X-t.X,yDiff=e.Y-t.Y,Math.sqrt(xDiff*xDiff+yDiff*yDiff)},this.computeDimension=function(e,t,n,i){switch(t=Math.round(this.distance(e,t)/i),e=Math.round(this.distance(e,n)/i),e=(t+e>>1)+7,3&e){case 0:e++;break;case 2:e--;break;case 3:throw"Error"}return e},this.findAlignmentInRegion=function(e,t,n,i){var r=Math.floor(i*e);if(i=Math.max(0,t-r),t=Math.min(qrcode.width-1,t+r),3*e>t-i)throw"Error";var o=Math.max(0,n-r);return n=Math.min(qrcode.height-1,n+r),new AlignmentPatternFinder(this.image,i,o,t-i,n-o,e,this.resultPointCallback).find()},this.createTransform=function(e,t,n,i,r){r-=3.5;var o,s,a;return null!=i?(o=i.X,i=i.Y,s=a=r-3):(o=t.X-e.X+n.X,i=t.Y-e.Y+n.Y,s=a=r),PerspectiveTransform.quadrilateralToQuadrilateral(3.5,3.5,r,3.5,s,a,3.5,r,e.X,e.Y,t.X,t.Y,o,i,n.X,n.Y)},this.sampleGrid=function(e,t,n){return GridSampler.sampleGrid3(e,n,t)},this.processFinderPatternInfo=function(e){var t=e.TopLeft,n=e.TopRight;e=e.BottomLeft;var i=this.calculateModuleSize(t,n,e);if(1>i)throw"Error";var r=this.computeDimension(t,n,e,i),o=Version.getProvisionalVersionForDimension(r),s=o.DimensionForVersion-7,a=null;if(0>3&3),this.dataMask=7&e,this.__defineGetter__("ErrorCorrectionLevel",function(){return this.errorCorrectionLevel}),this.__defineGetter__("DataMask",function(){return this.dataMask}),this.GetHashCode=function(){return this.errorCorrectionLevel.ordinal()<<3|dataMask},this.Equals=function(e){return this.errorCorrectionLevel==e.errorCorrectionLevel&&this.dataMask==e.dataMask}}function ErrorCorrectionLevel(e,t,n){this.ordinal_Renamed_Field=e,this.bits=t,this.name=n,this.__defineGetter__("Bits",function(){return this.bits}),this.__defineGetter__("Name",function(){return this.name}),this.ordinal=function(){return this.ordinal_Renamed_Field}}function BitMatrix(e,t){if(t||(t=e),1>e||1>t)throw"Both dimensions must be greater than 0";this.width=e,this.height=t;var n=e>>5;for(0!=(31&e)&&n++,this.rowSize=n,this.bits=Array(n*t),n=0;n>5)],31&e))},this.set_Renamed=function(e,t){this.bits[t*this.rowSize+(e>>5)]|=1<<(31&e)},this.flip=function(e,t){this.bits[t*this.rowSize+(e>>5)]^=1<<(31&e)},this.clear=function(){for(var e=this.bits.length,t=0;e>t;t++)this.bits[t]=0},this.setRegion=function(e,t,n,i){if(0>t||0>e)throw"Left and top must be nonnegative";if(1>i||1>n)throw"Height and width must be at least 1";if(n=e+n,i=t+i,i>this.height||n>this.width)throw"The region must fit inside the matrix";for(;i>t;t++)for(var r=t*this.rowSize,o=e;n>o;o++)this.bits[r+(o>>5)]|=1<<(31&o)}}function DataBlock(e,t){this.numDataCodewords=e,this.codewords=t,this.__defineGetter__("NumDataCodewords",function(){return this.numDataCodewords}),this.__defineGetter__("Codewords",function(){return this.codewords})}function BitMatrixParser(e){var t=e.Dimension;if(21>t||1!=(3&t))throw"Error BitMatrixParser";this.bitMatrix=e,this.parsedFormatInfo=this.parsedVersion=null,this.copyBit=function(e,t,n){return this.bitMatrix.get_Renamed(e,t)?n<<1|1:n<<1},this.readFormatInformation=function(){if(null!=this.parsedFormatInfo)return this.parsedFormatInfo;for(var e=0,t=0;6>t;t++)e=this.copyBit(t,8,e);for(e=this.copyBit(7,8,e),e=this.copyBit(8,8,e),e=this.copyBit(8,7,e),t=5;t>=0;t--)e=this.copyBit(8,t,e);if(this.parsedFormatInfo=FormatInformation.decodeFormatInformation(e),null!=this.parsedFormatInfo)return this.parsedFormatInfo;for(var n=this.bitMatrix.Dimension,e=0,i=n-8,t=n-1;t>=i;t--)e=this.copyBit(t,8,e);for(t=n-7;n>t;t++)e=this.copyBit(8,t,e);if(this.parsedFormatInfo=FormatInformation.decodeFormatInformation(e),null!=this.parsedFormatInfo)return this.parsedFormatInfo;throw"Error readFormatInformation"},this.readVersion=function(){if(null!=this.parsedVersion)return this.parsedVersion;var e=this.bitMatrix.Dimension,t=e-17>>2;if(6>=t)return Version.getVersionForNumber(t);for(var t=0,n=e-11,i=5;i>=0;i--)for(var r=e-9;r>=n;r--)t=this.copyBit(r,i,t);if(this.parsedVersion=Version.decodeVersionInformation(t),null!=this.parsedVersion&&this.parsedVersion.DimensionForVersion==e)return this.parsedVersion;for(t=0,r=5;r>=0;r--)for(i=e-9;i>=n;i--)t=this.copyBit(r,i,t);if(this.parsedVersion=Version.decodeVersionInformation(t),null!=this.parsedVersion&&this.parsedVersion.DimensionForVersion==e)return this.parsedVersion;throw"Error readVersion"},this.readCodewords=function(){var e=this.readFormatInformation(),t=this.readVersion(),n=DataMask.forReference(e.DataMask),e=this.bitMatrix.Dimension;n.unmaskBitMatrix(this.bitMatrix,e);for(var n=t.buildFunctionPattern(),i=!0,r=Array(t.TotalCodewords),o=0,s=0,a=0,h=e-1;h>0;h-=2){6==h&&h--;for(var c=0;e>c;c++)for(var l=i?e-1-c:c,f=0;2>f;f++)n.get_Renamed(h-f,l)||(a++,s<<=1,this.bitMatrix.get_Renamed(h-f,l)&&(s|=1),8==a&&(r[o++]=s,s=a=0));i^=1}if(o!=t.TotalCodewords)throw"Error readCodewords";return r}}function DataMask000(){this.unmaskBitMatrix=function(e,t){for(var n=0;t>n;n++)for(var i=0;t>i;i++)this.isMasked(n,i)&&e.flip(i,n)},this.isMasked=function(e,t){return 0==(e+t&1)}}function DataMask001(){this.unmaskBitMatrix=function(e,t){for(var n=0;t>n;n++)for(var i=0;t>i;i++)this.isMasked(n,i)&&e.flip(i,n)},this.isMasked=function(e){return 0==(1&e)}}function DataMask010(){this.unmaskBitMatrix=function(e,t){for(var n=0;t>n;n++)for(var i=0;t>i;i++)this.isMasked(n,i)&&e.flip(i,n)},this.isMasked=function(e,t){return 0==t%3}}function DataMask011(){this.unmaskBitMatrix=function(e,t){for(var n=0;t>n;n++)for(var i=0;t>i;i++)this.isMasked(n,i)&&e.flip(i,n)},this.isMasked=function(e,t){return 0==(e+t)%3}}function DataMask100(){this.unmaskBitMatrix=function(e,t){for(var n=0;t>n;n++)for(var i=0;t>i;i++)this.isMasked(n,i)&&e.flip(i,n)},this.isMasked=function(e,t){return 0==(URShift(e,1)+t/3&1)}}function DataMask101(){this.unmaskBitMatrix=function(e,t){for(var n=0;t>n;n++)for(var i=0;t>i;i++)this.isMasked(n,i)&&e.flip(i,n)},this.isMasked=function(e,t){var n=e*t;return 0==(1&n)+n%3}}function DataMask110(){this.unmaskBitMatrix=function(e,t){for(var n=0;t>n;n++)for(var i=0;t>i;i++)this.isMasked(n,i)&&e.flip(i,n)},this.isMasked=function(e,t){var n=e*t;return 0==((1&n)+n%3&1)}}function DataMask111(){this.unmaskBitMatrix=function(e,t){for(var n=0;t>n;n++)for(var i=0;t>i;i++)this.isMasked(n,i)&&e.flip(i,n)},this.isMasked=function(e,t){return 0==((e+t&1)+e*t%3&1)}}function ReedSolomonDecoder(e){this.field=e,this.decode=function(e,t){for(var n=new GF256Poly(this.field,e),i=Array(t),r=0;rr;r++){var s=n.evaluateAt(this.field.exp(r));i[i.length-1-r]=s,0!=s&&(o=!1)}if(!o)for(r=new GF256Poly(this.field,i),n=this.runEuclideanAlgorithm(this.field.buildMonomial(t,1),r,t),r=n[1],n=this.findErrorLocations(n[0]),i=this.findErrorMagnitudes(r,n,!1),r=0;ro)throw"ReedSolomonException Bad error location";e[o]=GF256.addOrSubtract(e[o],i[r])}},this.runEuclideanAlgorithm=function(e,t,n){if(e.Degree=Math.floor(n/2);){var a=e,h=i,c=o;if(e=t,i=r,o=s,e.Zero)throw"r_{i-1} was zero";for(t=a,s=this.field.Zero,r=e.getCoefficient(e.Degree),r=this.field.inverse(r);t.Degree>=e.Degree&&!t.Zero;){var a=t.Degree-e.Degree,l=this.field.multiply(t.getCoefficient(t.Degree),r),s=s.addOrSubtract(this.field.buildMonomial(a,l));t=t.addOrSubtract(e.multiplyByMonomial(a,l))}r=s.multiply1(i).addOrSubtract(h),s=s.multiply1(o).addOrSubtract(c)}if(n=s.getCoefficient(0),0==n)throw"ReedSolomonException sigmaTilde(0) was zero";return n=this.field.inverse(n),e=s.multiply2(n),n=t.multiply2(n),[e,n]},this.findErrorLocations=function(e){var t=e.Degree;if(1==t)return Array(e.getCoefficient(1));for(var n=Array(t),i=0,r=1;256>r&&t>i;r++)0==e.evaluateAt(r)&&(n[i]=this.field.inverse(r),i++);if(i!=t)throw"Error locator degree does not match number of roots";return n},this.findErrorMagnitudes=function(e,t,n){for(var i=t.length,r=Array(i),o=0;i>o;o++){for(var s=this.field.inverse(t[o]),a=1,h=0;i>h;h++)o!=h&&(a=this.field.multiply(a,GF256.addOrSubtract(1,this.field.multiply(t[h],s))));r[o]=this.field.multiply(e.evaluateAt(s),this.field.inverse(a)),n&&(r[o]=this.field.multiply(r[o],s))}return r}}function GF256Poly(e,t){if(null==t||0==t.length)throw"System.ArgumentException";this.field=e;var n=t.length;if(n>1&&0==t[0]){for(var i=1;n>i&&0==t[i];)i++;if(i==n)this.coefficients=e.Zero.coefficients;else{for(this.coefficients=Array(n-i),n=0;nn;n++)e=GF256.addOrSubtract(e,this.coefficients[n]);return e}for(var i=this.coefficients[0],n=1;t>n;n++)i=GF256.addOrSubtract(this.field.multiply(e,i),this.coefficients[n]);return i},this.addOrSubtract=function(t){if(this.field!=t.field)throw"GF256Polys do not have same GF256 field";if(this.Zero)return t;if(t.Zero)return this;var n=this.coefficients;if(t=t.coefficients,n.length>t.length){var i=n,n=t;t=i}for(var i=Array(t.length),r=t.length-n.length,o=0;r>o;o++)i[o]=t[o];for(o=r;oo;o++)for(var s=t[o],a=0;i>a;a++)r[o+a]=GF256.addOrSubtract(r[o+a],this.field.multiply(s,e[a]));return new GF256Poly(this.field,r)},this.multiply2=function(e){if(0==e)return this.field.Zero;if(1==e)return this;for(var t=this.coefficients.length,n=Array(t),i=0;t>i;i++)n[i]=this.field.multiply(this.coefficients[i],e);return new GF256Poly(this.field,n)},this.multiplyByMonomial=function(e,t){if(0>e)throw"System.ArgumentException";if(0==t)return this.field.Zero;for(var n=this.coefficients.length,i=Array(n+e),r=0;rr;r++)i[r]=this.field.multiply(this.coefficients[r],t);return new GF256Poly(this.field,i)},this.divide=function(e){if(this.field!=e.field)throw"GF256Polys do not have same GF256 field";if(e.Zero)throw"Divide by 0";for(var t=this.field.Zero,n=this,i=e.getCoefficient(e.Degree),i=this.field.inverse(i);n.Degree>=e.Degree&&!n.Zero;)var r=n.Degree-e.Degree,o=this.field.multiply(n.getCoefficient(n.Degree),i),s=e.multiplyByMonomial(r,o),r=this.field.buildMonomial(r,o),t=t.addOrSubtract(r),n=n.addOrSubtract(s);return[t,n]}}function GF256(e){this.expTable=Array(256),this.logTable=Array(256);for(var t=1,n=0;256>n;n++)this.expTable[n]=t,t<<=1,t>=256&&(t^=e);for(n=0;255>n;n++)this.logTable[this.expTable[n]]=n;e=Array(1),e[0]=0,this.zero=new GF256Poly(this,Array(e)),e=Array(1),e[0]=1,this.one=new GF256Poly(this,Array(e)),this.__defineGetter__("Zero",function(){return this.zero}),this.__defineGetter__("One",function(){return this.one}),this.buildMonomial=function(e,t){if(0>e)throw"System.ArgumentException";if(0==t)return zero;for(var n=Array(e+1),i=0;i=0?e>>t:(e>>t)+(2<<~t)}function FinderPattern(e,t,n){this.x=e,this.y=t,this.count=1,this.estimatedModuleSize=n,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(e,t,n){return Math.abs(t-this.y)<=e&&Math.abs(n-this.x)<=e?(e=Math.abs(e-this.estimatedModuleSize),1>=e||1>=e/this.estimatedModuleSize):!1}}function FinderPatternInfo(e){this.bottomLeft=e[0],this.topLeft=e[1],this.topRight=e[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=[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(e){for(var t=0,n=0;5>n;n++){var i=e[n];if(0==i)return!1;t+=i}return 7>t?!1:(t=Math.floor((t<=0&&r[t+a*qrcode.width];)s[2]++,a--;if(0>a)return 0/0;for(;a>=0&&!r[t+a*qrcode.width]&&s[1]<=n;)s[1]++,a--;if(0>a||s[1]>n)return 0/0;for(;a>=0&&r[t+a*qrcode.width]&&s[0]<=n;)s[0]++,a--;if(s[0]>n)return 0/0;for(a=e+1;o>a&&r[t+a*qrcode.width];)s[2]++,a++;if(a==o)return 0/0;for(;o>a&&!r[t+a*qrcode.width]&&s[3]=n)return 0/0;for(;o>a&&r[t+a*qrcode.width]&&s[4]=n||5*Math.abs(s[0]+s[1]+s[2]+s[3]+s[4]-i)>=2*i?0/0:this.foundPatternCross(s)?this.centerFromEnd(s,a):0/0},this.crossCheckHorizontal=function(e,t,n,i){for(var r=this.image,o=qrcode.width,s=this.CrossCheckStateCount,a=e;a>=0&&r[a+t*qrcode.width];)s[2]++,a--;if(0>a)return 0/0;for(;a>=0&&!r[a+t*qrcode.width]&&s[1]<=n;)s[1]++,a--;if(0>a||s[1]>n)return 0/0;for(;a>=0&&r[a+t*qrcode.width]&&s[0]<=n;)s[0]++,a--;if(s[0]>n)return 0/0;for(a=e+1;o>a&&r[a+t*qrcode.width];)s[2]++,a++;if(a==o)return 0/0;for(;o>a&&!r[a+t*qrcode.width]&&s[3]=n)return 0/0;for(;o>a&&r[a+t*qrcode.width]&&s[4]=n||5*Math.abs(s[0]+s[1]+s[2]+s[3]+s[4]-i)>=i?0/0:this.foundPatternCross(s)?this.centerFromEnd(s,a):0/0},this.handlePossibleCenter=function(e,t,n){var i=e[0]+e[1]+e[2]+e[3]+e[4];if(n=this.centerFromEnd(e,n),t=this.crossCheckVertical(t,Math.floor(n),e[2],i),!isNaN(t)&&(n=this.crossCheckHorizontal(Math.floor(n),Math.floor(t),e[2],i),!isNaN(n))){e=i/7;for(var i=!1,r=this.possibleCenters.length,o=0;r>o;o++){var s=this.possibleCenters[o];if(s.aboutEquals(e,t,n)){s.incrementCount(),i=!0;break}}return i||(n=new FinderPattern(n,t,e),this.possibleCenters.push(n),null!=this.resultPointCallback&&this.resultPointCallback.foundPossibleResultPoint(n)),!0}return!1},this.selectBestPatterns=function(){var e=this.possibleCenters.length;if(3>e)throw"Couldn't find enough finder patterns";if(e>3){for(var t=0,n=0;e>n;n++)t+=this.possibleCenters[n].EstimatedModuleSize;for(e=t/e,n=0;n.2*e&&(this.possibleCenters.remove(n),n--)}return[this.possibleCenters[0],this.possibleCenters[1],this.possibleCenters[2]]},this.findRowSkip=function(){var e=this.possibleCenters.length;if(1>=e)return 0;for(var t=null,n=0;e>n;n++){var i=this.possibleCenters[n];if(i.Count>=CENTER_QUORUM){if(null!=t)return this.hasSkipped=!0,Math.floor((Math.abs(t.X-i.X)-Math.abs(t.Y-i.Y))/2);t=i}}return 0},this.haveMultiplyConfirmedCenters=function(){for(var e=0,t=0,n=this.possibleCenters.length,i=0;n>i;i++){var r=this.possibleCenters[i];r.Count>=CENTER_QUORUM&&(e++,t+=r.EstimatedModuleSize)}if(3>e)return!1;for(var e=t/n,o=0,i=0;n>i;i++)r=this.possibleCenters[i],o+=Math.abs(r.EstimatedModuleSize-e);return.05*t>=o},this.findFinderPattern=function(e){this.image=e;var t=qrcode.height,n=qrcode.width,i=Math.floor(3*t/(4*MAX_MODULES));MIN_SKIP>i&&(i=MIN_SKIP);for(var r=!1,o=Array(5),s=i-1;t>s&&!r;s+=i){o[0]=0,o[1]=0,o[2]=0,o[3]=0;for(var a=o[4]=0,h=0;n>h;h++)if(e[h+s*qrcode.width])1==(1&a)&&a++,o[a]++;else if(0==(1&a))if(4==a)if(this.foundPatternCross(o)){if(a=this.handlePossibleCenter(o,s,h))i=2,this.hasSkipped?r=this.haveMultiplyConfirmedCenters():(a=this.findRowSkip(),a>o[2]&&(s+=a-o[2]-i,h=n-1));else{do h++;while(n>h&&!e[h+s*qrcode.width]);h--}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]++;this.foundPatternCross(o)&&this.handlePossibleCenter(o,s,n)&&(i=o[0],this.hasSkipped&&(r=haveMultiplyConfirmedCenters()))}return e=this.selectBestPatterns(),qrcode.orderBestPatterns(e),new FinderPatternInfo(e)}}function AlignmentPattern(e,t,n){this.x=e,this.y=t,this.count=1,this.estimatedModuleSize=n,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(e,t,n){return Math.abs(t-this.y)<=e&&Math.abs(n-this.x)<=e?(e=Math.abs(e-this.estimatedModuleSize),1>=e||1>=e/this.estimatedModuleSize):!1}}function AlignmentPatternFinder(e,t,n,i,r,o,s){this.image=e,this.possibleCenters=[],this.startX=t,this.startY=n,this.width=i,this.height=r,this.moduleSize=o,this.crossCheckStateCount=[0,0,0],this.resultPointCallback=s,this.centerFromEnd=function(e,t){return t-e[2]-e[1]/2},this.foundPatternCross=function(e){for(var t=this.moduleSize,n=t/2,i=0;3>i;i++)if(Math.abs(t-e[i])>=n)return!1;return!0},this.crossCheckVertical=function(e,t,n,i){var r=this.image,o=qrcode.height,s=this.crossCheckStateCount; s[0]=0,s[1]=0,s[2]=0;for(var a=e;a>=0&&r[t+a*qrcode.width]&&s[1]<=n;)s[1]++,a--;if(0>a||s[1]>n)return 0/0;for(;a>=0&&!r[t+a*qrcode.width]&&s[0]<=n;)s[0]++,a--;if(s[0]>n)return 0/0;for(a=e+1;o>a&&r[t+a*qrcode.width]&&s[1]<=n;)s[1]++,a++;if(a==o||s[1]>n)return 0/0;for(;o>a&&!r[t+a*qrcode.width]&&s[2]<=n;)s[2]++,a++;return s[2]>n||5*Math.abs(s[0]+s[1]+s[2]-i)>=2*i?0/0:this.foundPatternCross(s)?this.centerFromEnd(s,a):0/0},this.handlePossibleCenter=function(e,t,n){var i=e[0]+e[1]+e[2];if(n=this.centerFromEnd(e,n),t=this.crossCheckVertical(t,Math.floor(n),2*e[1],i),!isNaN(t)){e=(e[0]+e[1]+e[2])/3;for(var i=this.possibleCenters.length,r=0;i>r;r++)if(this.possibleCenters[r].aboutEquals(e,t,n))return new AlignmentPattern(n,t,e);n=new AlignmentPattern(n,t,e),this.possibleCenters.push(n),null!=this.resultPointCallback&&this.resultPointCallback.foundPossibleResultPoint(n)}return null},this.find=function(){for(var t=this.startX,r=this.height,o=t+i,s=n+(r>>1),a=[0,0,0],h=0;r>h;h++){var c=s+(0==(1&h)?h+1>>1:-(h+1>>1));a[0]=0,a[1]=0,a[2]=0;for(var l=t;o>l&&!e[l+qrcode.width*c];)l++;for(var f=0;o>l;){if(e[l+c*qrcode.width])if(1==f)a[f]++;else if(2==f){if(this.foundPatternCross(a)&&(f=this.handlePossibleCenter(a,c,l),null!=f))return f;a[0]=a[2],a[1]=1,a[2]=0,f=1}else a[++f]++;else 1==f&&f++,a[f]++;l++}if(this.foundPatternCross(a)&&(f=this.handlePossibleCenter(a,c,o),null!=f))return f}if(0!=this.possibleCenters.length)return this.possibleCenters[0];throw"Couldn't find enough alignment patterns"}}function QRCodeDataBlockReader(e,t,n){this.blockPointer=0,this.bitPointer=7,this.dataLength=0,this.blocks=e,this.numErrorCorrectionCode=n,9>=t?this.dataLengthMode=0:t>=10&&26>=t?this.dataLengthMode=1:t>=27&&40>=t&&(this.dataLengthMode=2),this.getNextBits=function(e){var t=0;if(et;t++)n+=1<>this.bitPointer-e+1,this.bitPointer-=e,t}if(e>8-(e-(this.bitPointer+1)),this.bitPointer-=e%8,0>this.bitPointer&&(this.bitPointer=8+this.bitPointer),t}if(e>8-(e-(this.bitPointer+1+8))),this.bitPointer-=(e-8)%8,0>this.bitPointer&&(this.bitPointer=8+this.bitPointer),t}return 0},this.NextMode=function(){return this.blockPointer>this.blocks.length-this.numErrorCorrectionCode-2?0:this.getNextBits(4)},this.getDataLength=function(e){for(var t=0;1!=e>>t;)t++;return this.getNextBits(qrcode.sizeOfDataLengthInfo[this.dataLengthMode][t])},this.getRomanAndFigureString=function(e){var t=0,n="",i="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:".split("");do if(e>1){var t=this.getNextBits(11),r=t%45,n=n+i[Math.floor(t/45)],n=n+i[r];e-=2}else 1==e&&(t=this.getNextBits(6),n+=i[t],e-=1);while(e>0);return n},this.getFigureString=function(e){var t=0,n="";do e>=3?(t=this.getNextBits(10),100>t&&(n+="0"),10>t&&(n+="0"),e-=3):2==e?(t=this.getNextBits(7),10>t&&(n+="0"),e-=2):1==e&&(t=this.getNextBits(4),e-=1),n+=t;while(e>0);return n},this.get8bitByteArray=function(e){var t=0,n=[];do t=this.getNextBits(8),n.push(t),e--;while(e>0);return n},this.getKanjiString=function(e){var t=0,n="";do{var t=getNextBits(13),t=(t/192<<8)+t%192,i=0,i=40956>=t+33088?t+33088:t+49472,n=n+String.fromCharCode(i);e--}while(e>0);return n},this.__defineGetter__("DataByte",function(){for(var e=[];;){var t=this.NextMode();if(0==t){if(0dataLength)throw"Invalid data length: "+dataLength;switch(t){case 1:for(var t=this.getFigureString(dataLength),n=Array(t.length),i=0;is||s>n||-1>a||a>i)throw"Error.checkAndNudgePoints ";r=!1,-1==s?(t[o]=0,r=!0):s==n&&(t[o]=n-1,r=!0),-1==a?(t[o+1]=0,r=!0):a==i&&(t[o+1]=i-1,r=!0)}for(r=!0,o=t.Length-2;o>=0&&r;o-=2){if(s=Math.floor(t[o]),a=Math.floor(t[o+1]),-1>s||s>n||-1>a||a>i)throw"Error.checkAndNudgePoints ";r=!1,-1==s?(t[o]=0,r=!0):s==n&&(t[o]=n-1,r=!0),-1==a?(t[o+1]=0,r=!0):a==i&&(t[o+1]=i-1,r=!0)}},sampleGrid3:function(e,t,n){for(var i=new BitMatrix(t),r=Array(t<<1),o=0;t>o;o++){for(var s=r.length,a=o+.5,h=0;s>h;h+=2)r[h]=(h>>1)+.5,r[h+1]=a;n.transformPoints1(r),GridSampler.checkAndNudgePoints(e,r);try{for(h=0;s>h;h+=2){var c=4*Math.floor(r[h])+4*Math.floor(r[h+1])*qrcode.width,l=e[Math.floor(r[h])+qrcode.width*Math.floor(r[h+1])];qrcode.imagedata.data[c]=l?255:0,qrcode.imagedata.data[c+1]=l?255:0,qrcode.imagedata.data[c+2]=0,qrcode.imagedata.data[c+3]=255,l&&i.set_Renamed(h>>1,o)}}catch(f){throw"Error.checkAndNudgePoints"}}return i},sampleGridx:function(e,t,n,i,r,o,s,a,h,c,l,f,d,w,u,C,E,B){return n=PerspectiveTransform.quadrilateralToQuadrilateral(n,i,r,o,s,a,h,c,l,f,d,w,u,C,E,B),GridSampler.sampleGrid3(e,t,n)}},Version.VERSION_DECODE_INFO=[31892,34236,39577,42195,48118,51042,55367,58893,63784,68472,70749,76311,79154,84390,87683,92361,96236,102084,102881,110507,110734,117786,119615,126325,127568,133589,136944,141498,145311,150283,152622,158308,161089,167017],Version.VERSIONS=buildVersions(),Version.getVersionForNumber=function(e){if(1>e||e>40)throw"ArgumentException";return Version.VERSIONS[e-1]},Version.getProvisionalVersionForDimension=function(e){if(1!=e%4)throw"Error getProvisionalVersionForDimension";try{return Version.getVersionForNumber(e-17>>2)}catch(t){throw"Error getVersionForNumber"}},Version.decodeVersionInformation=function(e){for(var t=4294967295,n=0,i=0;ir&&(n=i+7,t=r)}return 3>=t?this.getVersionForNumber(n):null},PerspectiveTransform.quadrilateralToQuadrilateral=function(e,t,n,i,r,o,s,a,h,c,l,f,d,w,u,C){return e=this.quadrilateralToSquare(e,t,n,i,r,o,s,a),this.squareToQuadrilateral(h,c,l,f,d,w,u,C).times(e)},PerspectiveTransform.squareToQuadrilateral=function(e,t,n,i,r,o,s,a){return dy2=a-o,dy3=t-i+o-a,0==dy2&&0==dy3?new PerspectiveTransform(n-e,r-n,e,i-t,o-i,t,0,0,1):(dx1=n-r,dx2=s-r,dx3=e-n+r-s,dy1=i-o,denominator=dx1*dy2-dx2*dy1,a13=(dx3*dy2-dx2*dy3)/denominator,a23=(dx1*dy3-dx3*dy1)/denominator,new PerspectiveTransform(n-e+a13*n,s-e+a23*s,e,i-t+a13*i,a-t+a23*a,t,a13,a23,1))},PerspectiveTransform.quadrilateralToSquare=function(e,t,n,i,r,o,s,a){return this.squareToQuadrilateral(e,t,n,i,r,o,s,a).buildAdjoint()};var FORMAT_INFO_MASK_QR=21522,FORMAT_INFO_DECODE_LOOKUP=[[21522,0],[20773,1],[24188,2],[23371,3],[17913,4],[16590,5],[20375,6],[19104,7],[30660,8],[29427,9],[32170,10],[30877,11],[26159,12],[25368,13],[27713,14],[26998,15],[5769,16],[5054,17],[7399,18],[6608,19],[1890,20],[597,21],[3340,22],[2107,23],[13663,24],[12392,25],[16177,26],[14854,27],[9396,28],[8579,29],[11994,30],[11245,31]],BITS_SET_IN_HALF_BYTE=[0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4];FormatInformation.numBitsDiffering=function(e,t){return e^=t,BITS_SET_IN_HALF_BYTE[15&e]+BITS_SET_IN_HALF_BYTE[15&URShift(e,4)]+BITS_SET_IN_HALF_BYTE[15&URShift(e,8)]+BITS_SET_IN_HALF_BYTE[15&URShift(e,12)]+BITS_SET_IN_HALF_BYTE[15&URShift(e,16)]+BITS_SET_IN_HALF_BYTE[15&URShift(e,20)]+BITS_SET_IN_HALF_BYTE[15&URShift(e,24)]+BITS_SET_IN_HALF_BYTE[15&URShift(e,28)]},FormatInformation.decodeFormatInformation=function(e){var t=FormatInformation.doDecodeFormatInformation(e);return null!=t?t:FormatInformation.doDecodeFormatInformation(e^FORMAT_INFO_MASK_QR)},FormatInformation.doDecodeFormatInformation=function(e){for(var t=4294967295,n=0,i=0;io&&(n=r[1],t=o)}return 3>=t?new FormatInformation(n):null},ErrorCorrectionLevel.forBits=function(e){if(0>e||e>=FOR_BITS.Length)throw"ArgumentException";return FOR_BITS[e]};var L=new ErrorCorrectionLevel(0,1,"L"),M=new ErrorCorrectionLevel(1,0,"M"),Q=new ErrorCorrectionLevel(2,3,"Q"),H=new ErrorCorrectionLevel(3,2,"H"),FOR_BITS=[M,L,H,Q];DataBlock.getDataBlocks=function(e,t,n){if(e.length!=t.TotalCodewords)throw"ArgumentException";var i=t.getECBlocksForLevel(n);n=0;var r=i.getECBlocks();for(t=0;t=0&&n[r].codewords.length!=t;)r--;for(r++,i=t-i.ECCodewordsPerBlock,t=a=0;i>t;t++)for(s=0;o>s;s++)n[s].codewords[t]=e[a++];for(s=r;o>s;s++)n[s].codewords[i]=e[a++];for(h=n[0].codewords.length,t=i;h>t;t++)for(s=0;o>s;s++)n[s].codewords[r>s?t:t+1]=e[a++];return n},DataMask={forReference:function(e){if(0>e||e>7)throw"System.ArgumentException";return DataMask.DATA_MASKS[e]}},DataMask.DATA_MASKS=[new DataMask000,new DataMask001,new DataMask010,new DataMask011,new DataMask100,new DataMask101,new DataMask110,new DataMask111],GF256.QR_CODE_FIELD=new GF256(285),GF256.DATA_MATRIX_FIELD=new GF256(301),GF256.addOrSubtract=function(e,t){return e^t},Decoder={},Decoder.rsDecoder=new ReedSolomonDecoder(GF256.QR_CODE_FIELD),Decoder.correctErrors=function(e,t){for(var n=e.length,i=Array(n),r=0;n>r;r++)i[r]=255&e[r];n=e.length-t;try{Decoder.rsDecoder.decode(i,n)}catch(o){throw o}for(r=0;t>r;r++)e[r]=i[r]},Decoder.decode=function(e){var t=new BitMatrixParser(e);e=t.readVersion();for(var n=t.readFormatInformation().ErrorCorrectionLevel,t=t.readCodewords(),t=DataBlock.getDataBlocks(t,e,n),i=0,r=0;rr;r++)i[o++]=a[r]}return new QRCodeDataBlockReader(i,e.VersionNumber,n.Bits)},qrcode={imagedata:null,width:0,height:0,qrCodeSymbol:null,debug:!1,sizeOfDataLengthInfo:[[10,9,8,8],[12,11,16,10],[14,13,16,12]],callback:null,decode:function(e){if(0==arguments.length){var t=document.getElementById("qr-canvas"),n=t.getContext("2d");return qrcode.width=t.width,qrcode.height=t.height,qrcode.imagedata=n.getImageData(0,0,qrcode.width,qrcode.height),qrcode.result=qrcode.process(n),null!=qrcode.callback&&qrcode.callback(qrcode.result),qrcode.result}var i=new Image;i.onload=function(){var e=document.createElement("canvas"),t=e.getContext("2d"),n=document.getElementById("out-canvas");null!=n&&(n=n.getContext("2d"),n.clearRect(0,0,320,240),n.drawImage(i,0,0,320,240)),e.width=i.width,e.height=i.height,t.drawImage(i,0,0),qrcode.width=i.width,qrcode.height=i.height;try{qrcode.imagedata=t.getImageData(0,0,i.width,i.height)}catch(r){return qrcode.result="Cross domain image reading not supported in your browser! Save it to your computer then drag and drop the file!",void(null!=qrcode.callback&&qrcode.callback(qrcode.result))}try{qrcode.result=qrcode.process(t)}catch(o){console.log(o),qrcode.result="error decoding QR Code"}null!=qrcode.callback&&qrcode.callback(qrcode.result)},i.src=e},decode_utf8:function(e){return decodeURIComponent(escape(e))},process:function(e){var t=(new Date).getTime(),n=qrcode.grayScaleToBitmap(qrcode.grayscale());if(qrcode.debug){for(var i=0;i=r?!0:!1}return t},getMiddleBrightnessPerArea:function(e){for(var t=Math.floor(qrcode.width/4),n=Math.floor(qrcode.height/4),i=Array(4),r=0;4>r;r++){i[r]=Array(4);for(var o=0;4>o;o++)i[r][o]=[0,0]}for(r=0;4>r;r++)for(o=0;4>o;o++){i[o][r][0]=255;for(var s=0;n>s;s++)for(var a=0;t>a;a++){var h=e[t*o+a+(n*r+s)*qrcode.width];hi[o][r][1]&&(i[o][r][1]=h)}}for(e=Array(4),t=0;4>t;t++)e[t]=Array(4);for(r=0;4>r;r++)for(o=0;4>o;o++)e[o][r]=Math.floor((i[o][r][0]+i[o][r][1])/2);return e},grayScaleToBitmap:function(e){for(var t=qrcode.getMiddleBrightnessPerArea(e),n=t.length,i=Math.floor(qrcode.width/n),r=Math.floor(qrcode.height/n),o=Array(qrcode.height*qrcode.width),s=0;n>s;s++)for(var a=0;n>a;a++)for(var h=0;r>h;h++)for(var c=0;i>c;c++)o[i*a+c+(r*s+h)*qrcode.width]=e[i*a+c+(r*s+h)*qrcode.width]e?this.length+e:e,this.push.apply(this,n)};var MIN_SKIP=3,MAX_MODULES=57,INTEGER_MATH_SHIFT=8,CENTER_QUORUM=2;qrcode.orderBestPatterns=function(e){function t(e,t){return xDiff=e.X-t.X,yDiff=e.Y-t.Y,Math.sqrt(xDiff*xDiff+yDiff*yDiff)}var n=t(e[0],e[1]),i=t(e[1],e[2]),r=t(e[0],e[2]);i>=n&&i>=r?(i=e[0],n=e[1],r=e[2]):r>=i&&r>=n?(i=e[1],n=e[0],r=e[2]):(i=e[2],n=e[0],r=e[1]);var o=i.x,s=i.y;0>(r.x-o)*(n.y-s)-(r.y-s)*(n.x-o)&&(o=n,n=r,r=o),e[0]=n,e[1]=i,e[2]=r}; -function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,t){for(var n=0;ns||h>d)throw"'config.qrbox' should not be greater than the width and height of the HTML element."}var u=c?this._getShadedRegionBounds(s,d,r.qrbox):{x:0,y:0,width:s,height:d},m=this._createVideoElement(s,d),_=this._createCanvasElement(u.width,u.height),g=_.getContext("2d");g.canvas.width=u.width,g.canvas.height=u.height,l.style.position="relative",l.append(m),l.append(_),c&&this._possiblyInsertShadingElement(l,d,u),this._element=l,this._videoElement=m,this._canvasElement=_,this._shouldScan=!0,qrcode.callback=i;var f=function(t){m.srcObject=t,m.play(),o._localMediaStream=t,function t(){if(o._shouldScan){if(o._localMediaStream){g.drawImage(m,u.x,u.y,u.width,u.height,0,0,u.width,u.height);try{qrcode.decode()}catch(e){a("QR code parse error, error = ".concat(e))}}o._foreverScanTimeout=setTimeout(t,e._getTimeoutFps(r.fps))}}()};return new Promise(function(e,n){if(navigator.mediaDevices&&navigator.mediaDevices.getUserMedia)navigator.mediaDevices.getUserMedia({audio:!1,video:{deviceId:{exact:t}}}).then(function(t){f(t),o._isScanning=!0,e()}).catch(function(e){n("Error getting userMedia, error = ".concat(e))});else if(navigator.getUserMedia){var i={video:{optional:[{sourceId:t}]}};navigator.getUserMedia(i,function(t){f(t),o._isScanning=!0,e()},function(e){n("Error getting userMedia, error = ".concat(e))})}else n("Web camera streaming not supported by the browser.")})}},{key:"stop",value:function(){this._shouldScan=!1,clearTimeout(this._foreverScanTimeout);var t=this;return new Promise(function(n,i){qrcode.callback=null;var a=t._localMediaStream.getVideoTracks().length,o=0,r=function(){t._localMediaStream=null,t._element.removeChild(t._videoElement),t._element.removeChild(t._canvasElement),function(){for(;t._element.getElementsByClassName(e.SHADED_REGION_CLASSNAME).length;){var n=t._element.getElementsByClassName(e.SHADED_REGION_CLASSNAME)[0];t._element.removeChild(n)}}(),t._isScanning=!1,n(!0)};t._localMediaStream.getVideoTracks().forEach(function(e){e.stop(),++o>=a&&r()})})}},{key:"scanFile",value:function(t,n){var i=this;if(!(t&&t instanceof File))throw"imageFile argument is mandatory and should be instance of File. Use 'event.target.files[0]'";if(n=void 0===n||n,i._isScanning)throw"Close ongoing scan before scanning a file.";return new Promise(function(a,o){i._possiblyCloseLastScanImageFile(),i._clearElement(),i._lastScanImageFile=t;var r=new Image;r.onload=function(){var t=document.getElementById(i._elementId),c=t.clientWidth?t.clientWidth:e.DEFAULT_WIDTH,l=t.clientHeight?t.clientHeight:e.DEFAULT_HEIGHT,s=r.width,d=r.height,h=function t(n,a){var o=document.getElementById(i._elementId),r=o.clientWidth?o.clientWidth:e.DEFAULT_WIDTH,c=o.clientHeight?o.clientHeight:e.DEFAULT_HEIGHT;if(n<=r&&a<=c)return{x:(r-n)/2,y:(c-a)/2,width:n,height:a};var l=n,s=a;return n>r&&(a*=r/n,n=r),a>c&&(n*=c/a,a=c),e._log("Image downsampled from ".concat(l,"X").concat(s)+" to ".concat(n,"X").concat(a,".")),t(n,a)}(s,d);if(n){var u=i._createCanvasElement(c,l,"qr-canvas-visible");u.style.display="inline-block",t.appendChild(u);var m=u.getContext("2d");m.canvas.width=c,m.canvas.height=l,m.drawImage(r,0,0,s,d,h.x,h.y,h.width,h.height)}var _=i._createCanvasElement(h.width,h.height);t.appendChild(_);var g=_.getContext("2d");g.canvas.width=h.width,g.canvas.height=h.height,g.drawImage(r,0,0,s,d,0,0,h.width,h.height);try{a(qrcode.decode())}catch(e){o("QR code parse error, error = ".concat(e))}},r.onerror=o,r.onabort=o,r.onstalled=o,r.onsuspend=o,r.src=URL.createObjectURL(t)})}},{key:"clear",value:function(){this._clearElement()}},{key:"_clearElement",value:function(){if(this._isScanning)throw"Cannot clear while scan is ongoing, close it first.";document.getElementById(this._elementId).innerHTML=""}},{key:"_createCanvasElement",value:function(e,t,n){var i=e,a=t,o=document.createElement("canvas");return o.style.width="".concat(i,"px"),o.style.height="".concat(a,"px"),o.style.display="none",o.id=null==n?"qr-canvas":n,o}},{key:"_createVideoElement",value:function(e,t){var n=document.createElement("video");return n.style.height="".concat(t,"px"),n.style.width="".concat(e,"px"),n.muted=!0,n.playsInline=!0,n}},{key:"_getShadedRegionBounds",value:function(e,t,n){if(n>e||n>t)throw"'config.qrbox' should not be greater than the width and height of the HTML element.";return{x:(e-n)/2,y:(t-n)/2,width:n,height:n}}},{key:"_possiblyInsertShadingElement",value:function(t,n,i){0==i.x&&0==i.y||(t.append(this._createShadedElement(n,i,e.SHADED_LEFT)),t.append(this._createShadedElement(n,i,e.SHADED_RIGHT)),t.append(this._createShadedElement(n,i,e.SHADED_TOP)),t.append(this._createShadedElement(n,i,e.SHADED_BOTTOM)))}},{key:"_createShadedElement",value:function(t,n,i){var a=document.createElement("div");switch(a.style.position="absolute",a.style.height="".concat(t,"px"),a.className=e.SHADED_REGION_CLASSNAME,a.id="".concat(e.SHADED_REGION_CLASSNAME,"_").concat(i),a.style.background="#0000007a",i){case e.SHADED_LEFT:a.style.top="0px",a.style.left="0px",a.style.width="".concat(n.x,"px"),a.style.height="".concat(t,"px");break;case e.SHADED_RIGHT:a.style.top="0px",a.style.right="0px",a.style.width="".concat(n.x,"px"),a.style.height="".concat(t,"px");break;case e.SHADED_TOP:a.style.top="0px",a.style.left="".concat(n.x,"px"),a.style.width="".concat(n.width,"px"),a.style.height="".concat(n.y,"px");break;case e.SHADED_BOTTOM:a.style.bottom="0px",a.style.left="".concat(n.x,"px"),a.style.width="".concat(n.width,"px"),a.style.height="".concat(n.y,"px");break;default:throw"Unsupported shadingPosition"}return a}},{key:"_possiblyCloseLastScanImageFile",value:function(){this._lastScanImageFile&&(URL.revokeObjectURL(this._lastScanImageFile),this._lastScanImageFile=null)}}],[{key:"getCameras",value:function(){var e=this;return new Promise(function(t,n){if(navigator.mediaDevices&&navigator.mediaDevices.enumerateDevices&&navigator.mediaDevices.getUserMedia)e._log("navigator.mediaDevices used"),navigator.mediaDevices.getUserMedia({audio:!1,video:!0}).then(function(i){navigator.mediaDevices.enumerateDevices().then(function(n){for(var i=[],a=0;ad)throw"'config.qrbox' should not be greater than the width of the HTML element."}var u=function(t){return new Promise(function(n,i){r._localMediaStream=t,r._videoElement=o._createVideoElement(d),s.append(r._videoElement),r._videoElement.onabort=i,r._videoElement.onerror=i,r._videoElement.onplaying=function(){!function(e,t){var n=c.qrbox;n>t&&console.log("[Warning] [Html5Qrcode] config.qrboxsize is greater than video height. Shading will be ignored");var i=l&&n<=t,a={x:0,y:0,width:e,height:t},d=i?o._getShadedRegionBounds(e,t,n):a,h=o._createCanvasElement(d.width,d.height),u=h.getContext("2d");u.canvas.width=d.width,u.canvas.height=d.height,s.append(h),i&&o._possiblyInsertShadingElement(s,t,d),r._qrRegion=d,r._context=u,r._element=s,r._canvasElement=h}(r._videoElement.clientWidth,r._videoElement.clientHeight),function t(){if(r._shouldScan){if(r._localMediaStream){var n=r._videoElement,i=n.videoWidth/n.clientWidth,o=n.videoHeight/n.clientHeight,l=r._qrRegion.width*i,s=r._qrRegion.height*o;r._context.drawImage(r._videoElement,r._qrRegion.x,r._qrRegion.y,l,s,0,0,r._qrRegion.width,r._qrRegion.height);try{qrcode.decode()}catch(e){a("QR code parse error, error = ".concat(e))}}r._foreverScanTimeout=setTimeout(t,e._getTimeoutFps(c.fps))}}(),n()},r._videoElement.srcObject=t,r._videoElement.play()})};return new Promise(function(e,n){if(navigator.mediaDevices&&navigator.mediaDevices.getUserMedia){var i={deviceId:{exact:t}};navigator.mediaDevices.getUserMedia({audio:!1,video:i}).then(function(t){u(t).then(function(t){r._isScanning=!0,e()}).catch(n)}).catch(function(e){n("Error getting userMedia, error = ".concat(e))})}else if(navigator.getUserMedia){var a={video:{optional:[{sourceId:t}]}};navigator.getUserMedia(a,function(t){u(t).then(function(t){r._isScanning=!0,e()}).catch(n)},function(e){n("Error getting userMedia, error = ".concat(e))})}else n("Web camera streaming not supported by the browser.")})}},{key:"stop",value:function(){this._shouldScan=!1,clearTimeout(this._foreverScanTimeout);var t=this;return new Promise(function(n,i){qrcode.callback=null;var a=t._localMediaStream.getVideoTracks().length,o=0,r=function(){t._localMediaStream=null,t._element.removeChild(t._videoElement),t._element.removeChild(t._canvasElement),function(){for(;t._element.getElementsByClassName(e.SHADED_REGION_CLASSNAME).length;){var n=t._element.getElementsByClassName(e.SHADED_REGION_CLASSNAME)[0];t._element.removeChild(n)}}(),t._isScanning=!1,t._qrRegion&&(t._qrRegion=null),t._context&&(t._context=null),n(!0)};t._localMediaStream.getVideoTracks().forEach(function(e){e.stop(),++o>=a&&r()})})}},{key:"scanFile",value:function(t,n){var i=this;if(!(t&&t instanceof File))throw"imageFile argument is mandatory and should be instance of File. Use 'event.target.files[0]'";if(n=void 0===n||n,i._isScanning)throw"Close ongoing scan before scanning a file.";return new Promise(function(a,o){i._possiblyCloseLastScanImageFile(),i._clearElement(),i._lastScanImageFile=t;var r=new Image;r.onload=function(){var t=r.width,c=r.height,l=document.getElementById(i._elementId),s=l.clientWidth?l.clientWidth:e.DEFAULT_WIDTH,d=l.clientHeight?l.clientHeight:c,h=function t(n,i,a,o){if(n<=a&&i<=o)return{x:(a-n)/2,y:(o-i)/2,width:n,height:i};var r=n,c=i;return n>a&&(i*=a/n,n=a),i>o&&(n*=o/i,i=o),e._log("Image downsampled from ".concat(r,"X").concat(c)+" to ".concat(n,"X").concat(i,".")),t(n,i,a,o)}(t,c,s,d);if(n){var u=i._createCanvasElement(s,d,"qr-canvas-visible");u.style.display="inline-block",l.appendChild(u);var _=u.getContext("2d");_.canvas.width=s,_.canvas.height=d,_.drawImage(r,0,0,t,c,h.x,h.y,h.width,h.height)}var g=i._createCanvasElement(h.width,h.height);l.appendChild(g);var m=g.getContext("2d");m.canvas.width=h.width,m.canvas.height=h.height,m.drawImage(r,0,0,t,c,0,0,h.width,h.height);try{a(qrcode.decode())}catch(e){o("QR code parse error, error = ".concat(e))}},r.onerror=o,r.onabort=o,r.onstalled=o,r.onsuspend=o,r.src=URL.createObjectURL(t)})}},{key:"clear",value:function(){this._clearElement()}},{key:"_clearElement",value:function(){if(this._isScanning)throw"Cannot clear while scan is ongoing, close it first.";document.getElementById(this._elementId).innerHTML=""}},{key:"_createCanvasElement",value:function(e,t,n){var i=e,a=t,o=document.createElement("canvas");return o.style.width="".concat(i,"px"),o.style.height="".concat(a,"px"),o.style.display="none",o.id=null==n?"qr-canvas":n,o}},{key:"_createVideoElement",value:function(e){var t=document.createElement("video");return t.style.width="".concat(e,"px"),t.muted=!0,t.playsInline=!0,t}},{key:"_getShadedRegionBounds",value:function(e,t,n){if(n>e||n>t)throw"'config.qrbox' should not be greater than the width and height of the HTML element.";return{x:(e-n)/2,y:(t-n)/2,width:n,height:n}}},{key:"_possiblyInsertShadingElement",value:function(t,n,i){0==i.x&&0==i.y||(t.append(this._createShadedElement(n,i,e.SHADED_LEFT)),t.append(this._createShadedElement(n,i,e.SHADED_RIGHT)),t.append(this._createShadedElement(n,i,e.SHADED_TOP)),t.append(this._createShadedElement(n,i,e.SHADED_BOTTOM)))}},{key:"_createShadedElement",value:function(t,n,i){var a=document.createElement("div");switch(a.style.position="absolute",a.style.height="".concat(t,"px"),a.className=e.SHADED_REGION_CLASSNAME,a.id="".concat(e.SHADED_REGION_CLASSNAME,"_").concat(i),a.style.background="#0000007a",i){case e.SHADED_LEFT:a.style.top="0px",a.style.left="0px",a.style.width="".concat(n.x,"px"),a.style.height="".concat(t,"px");break;case e.SHADED_RIGHT:a.style.top="0px",a.style.right="0px",a.style.width="".concat(n.x,"px"),a.style.height="".concat(t,"px");break;case e.SHADED_TOP:a.style.top="0px",a.style.left="".concat(n.x,"px"),a.style.width="".concat(n.width,"px"),a.style.height="".concat(n.y,"px");break;case e.SHADED_BOTTOM:var o=n.y+n.height;a.style.top="".concat(o,"px"),a.style.left="".concat(n.x,"px"),a.style.width="".concat(n.width,"px"),a.style.height="".concat(n.y,"px");break;default:throw"Unsupported shadingPosition"}return a}},{key:"_possiblyCloseLastScanImageFile",value:function(){this._lastScanImageFile&&(URL.revokeObjectURL(this._lastScanImageFile),this._lastScanImageFile=null)}}],[{key:"getCameras",value:function(){var e=this;return new Promise(function(t,n){if(navigator.mediaDevices&&navigator.mediaDevices.enumerateDevices&&navigator.mediaDevices.getUserMedia)e._log("navigator.mediaDevices used"),navigator.mediaDevices.getUserMedia({audio:!1,video:!0}).then(function(i){navigator.mediaDevices.enumerateDevices().then(function(n){for(var i=[],a=0;a width || qrboxSize > height) { - throw "'config.qrbox' should not be greater than the " + "width and height of the HTML element."; + if (qrboxSize > width) { + throw "'config.qrbox' should not be greater than the " + "width of the HTML element."; } - } + } //#region local methods - var qrRegion = isShadedBoxEnabled ? this._getShadedRegionBounds(width, height, config.qrbox) : { - x: 0, - y: 0, - width: width, - height: height - }; + /** + * Setups the UI elements, changes the state of this class. + * + * @param width derived width of viewfinder. + * @param height derived height of viewfinder. + */ - var videoElement = this._createVideoElement(width, height); - var canvasElement = this._createCanvasElement(qrRegion.width, qrRegion.height); + var setupUi = function setupUi(width, height) { + var qrboxSize = config.qrbox; - var context = canvasElement.getContext('2d'); - context.canvas.width = qrRegion.width; - context.canvas.height = qrRegion.height; - element.style.position = "relative"; - element.append(videoElement); - element.append(canvasElement); + if (qrboxSize > height) { + console.log("[Warning] [Html5Qrcode] config.qrboxsize is greater " + "than video height. Shading will be ignored"); + } - if (isShadedBoxEnabled) { - this._possiblyInsertShadingElement(element, height, qrRegion); - } // save local states + var shouldShadingBeApplied = isShadedBoxEnabled && qrboxSize <= height; + var defaultQrRegion = { + x: 0, + y: 0, + width: width, + height: height + }; + var qrRegion = shouldShadingBeApplied ? _this._getShadedRegionBounds(width, height, qrboxSize) : defaultQrRegion; + var canvasElement = _this._createCanvasElement(qrRegion.width, qrRegion.height); - this._element = element; - this._videoElement = videoElement; - this._canvasElement = canvasElement; // Setup QR code. + var context = canvasElement.getContext('2d'); + context.canvas.width = qrRegion.width; + context.canvas.height = qrRegion.height; // Insert the canvas + + element.append(canvasElement); + + if (shouldShadingBeApplied) { + _this._possiblyInsertShadingElement(element, height, qrRegion); + } // Update local states + + + $this._qrRegion = qrRegion; + $this._context = context; + $this._element = element; + $this._canvasElement = canvasElement; + }; // Method that scans forever. - this._shouldScan = true; - qrcode.callback = qrCodeSuccessCallback; // Method that scans forever. var foreverScan = function foreverScan() { if (!$this._shouldScan) { @@ -151,25 +170,32 @@ var Html5Qrcode = /*#__PURE__*/function () { } if ($this._localMediaStream) { - // Only decode the relevant area, ignore the shaded area, More reference: + // difference in held video dimensions and rendered video dimensions + // require scaling + var videoElement = $this._videoElement; + var widthRatio = videoElement.videoWidth / videoElement.clientWidth; + var heightRatio = videoElement.videoHeight / videoElement.clientHeight; + var sWidthOffset = $this._qrRegion.width * widthRatio; + var sHeightOffset = $this._qrRegion.height * heightRatio; // Only decode the relevant area, ignore the shaded area, More reference: // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage - context.drawImage(videoElement, + + $this._context.drawImage($this._videoElement, /* sx= */ - qrRegion.x, + $this._qrRegion.x, /* sy= */ - qrRegion.y, + $this._qrRegion.y, /* sWidth= */ - qrRegion.width, + sWidthOffset, /* sHeight= */ - qrRegion.height, + sHeightOffset, /* dx= */ 0, /* dy= */ 0, /* dWidth= */ - qrRegion.width, + $this._qrRegion.width, /* dHeight= */ - qrRegion.height); + $this._qrRegion.height); try { qrcode.decode(); @@ -182,26 +208,63 @@ var Html5Qrcode = /*#__PURE__*/function () { }; // success callback when user media (Camera) is attached. - var getUserMediaSuccessCallback = function getUserMediaSuccessCallback(stream) { - videoElement.srcObject = stream; - videoElement.play(); - $this._localMediaStream = stream; - foreverScan(); - }; + var getUserMediaSuccessCallback = function getUserMediaSuccessCallback(mediaStream) { + return new Promise(function (resolve, reject) { + var setupVideo = function setupVideo() { + $this._videoElement = _this._createVideoElement(width); + element.append($this._videoElement); // Attach listeners to video. + + $this._videoElement.onabort = reject; + $this._videoElement.onerror = reject; + + $this._videoElement.onplaying = function () { + var videoWidth = $this._videoElement.clientWidth; + var videoHeight = $this._videoElement.clientHeight; + setupUi(videoWidth, videoHeight); // start scanning after video feed has started + + foreverScan(); + resolve(); + }; + + $this._videoElement.srcObject = mediaStream; + + $this._videoElement.play(); + }; + + $this._localMediaStream = mediaStream; + setupVideo(); // TODO(mebjas): see if constaints can be applied on camera + // for better results or performance. + // const constraints = { + // width: { min: width , ideal: width, max: width }, + // frameRate: { ideal: 30, max: 30 } + // } + // const track = mediaStream.getVideoTracks()[0]; + // track.applyConstraints(constraints) + // .then(() => setupVideo()) + // .catch(error => { + // console.log("[Warning] [Html5Qrcode] Constriants could not be " + // + "satisfied, ignoring constraints", error); + // setupVideo(); + // }); + }); + }; //#endregion + return new Promise(function (resolve, reject) { if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { + var videoConstraints = { + deviceId: { + exact: cameraId + } + }; navigator.mediaDevices.getUserMedia({ audio: false, - video: { - deviceId: { - exact: cameraId - } - } + video: videoConstraints }).then(function (stream) { - getUserMediaSuccessCallback(stream); - $this._isScanning = true; - resolve(); + getUserMediaSuccessCallback(stream).then(function (ignore) { + $this._isScanning = true; + resolve(); + })["catch"](reject); })["catch"](function (err) { reject("Error getting userMedia, error = ".concat(err)); }); @@ -214,9 +277,10 @@ var Html5Qrcode = /*#__PURE__*/function () { } }; navigator.getUserMedia(getCameraConfig, function (stream) { - getUserMediaSuccessCallback(stream); - $this._isScanning = true; - resolve(); + getUserMediaSuccessCallback(stream).then(function (ignore) { + $this._isScanning = true; + resolve(); + })["catch"](reject); }, function (err) { reject("Error getting userMedia, error = ".concat(err)); }); @@ -264,6 +328,15 @@ var Html5Qrcode = /*#__PURE__*/function () { removeQrRegion(); $this._isScanning = false; + + if ($this._qrRegion) { + $this._qrRegion = null; + } + + if ($this._context) { + $this._context = null; + } + resolve(true); }; @@ -310,15 +383,11 @@ var Html5Qrcode = /*#__PURE__*/function () { throw "Close ongoing scan before scanning a file."; } - var computeCanvasDrawConfig = function computeCanvasDrawConfig(imageWidth, imageHeight) { - var element = document.getElementById($this._elementId); - var width = element.clientWidth ? element.clientWidth : Html5Qrcode.DEFAULT_WIDTH; - var height = element.clientHeight ? element.clientHeight : Html5Qrcode.DEFAULT_HEIGHT; - - if (imageWidth <= width && imageHeight <= height) { + var computeCanvasDrawConfig = function computeCanvasDrawConfig(imageWidth, imageHeight, containerWidth, containerHeight) { + if (imageWidth <= containerWidth && imageHeight <= containerHeight) { // no downsampling needed. - var xoffset = (width - imageWidth) / 2; - var yoffset = (height - imageHeight) / 2; + var xoffset = (containerWidth - imageWidth) / 2; + var yoffset = (containerHeight - imageHeight) / 2; return { x: xoffset, y: yoffset, @@ -329,19 +398,19 @@ var Html5Qrcode = /*#__PURE__*/function () { var formerImageWidth = imageWidth; var formerImageHeight = imageHeight; - if (imageWidth > width) { - imageHeight = width / imageWidth * imageHeight; - imageWidth = width; + if (imageWidth > containerWidth) { + imageHeight = containerWidth / imageWidth * imageHeight; + imageWidth = containerWidth; } - if (imageHeight > height) { - imageWidth = height / imageHeight * imageWidth; - imageHeight = height; + if (imageHeight > containerHeight) { + imageWidth = containerHeight / imageHeight * imageWidth; + imageHeight = containerHeight; } Html5Qrcode._log("Image downsampled from ".concat(formerImageWidth, "X").concat(formerImageHeight) + " to ".concat(imageWidth, "X").concat(imageHeight, ".")); - return computeCanvasDrawConfig(imageWidth, imageHeight); + return computeCanvasDrawConfig(imageWidth, imageHeight, containerWidth, containerHeight); } }; @@ -354,12 +423,13 @@ var Html5Qrcode = /*#__PURE__*/function () { var inputImage = new Image(); inputImage.onload = function () { - var element = document.getElementById($this._elementId); - var containerWidth = element.clientWidth ? element.clientWidth : Html5Qrcode.DEFAULT_WIDTH; - var containerHeight = element.clientHeight ? element.clientHeight : Html5Qrcode.DEFAULT_HEIGHT; var imageWidth = inputImage.width; var imageHeight = inputImage.height; - var config = computeCanvasDrawConfig(imageWidth, imageHeight); + var element = document.getElementById($this._elementId); + var containerWidth = element.clientWidth ? element.clientWidth : Html5Qrcode.DEFAULT_WIDTH; // No default height anymore. + + var containerHeight = element.clientHeight ? element.clientHeight : imageHeight; + var config = computeCanvasDrawConfig(imageWidth, imageHeight, containerWidth, containerHeight); if (showImage) { var visibleCanvas = $this._createCanvasElement(containerWidth, containerHeight, 'qr-canvas-visible'); @@ -465,10 +535,8 @@ var Html5Qrcode = /*#__PURE__*/function () { }, { key: "_createCanvasElement", value: function _createCanvasElement(width, height, customId) { - var canvasWidth = width; // - Html5Qrcode.DEFAULT_WIDTH_OFFSET; - - var canvasHeight = height; // - Html5Qrcode.DEFAULT_HEIGHT_OFFSET; - + var canvasWidth = width; + var canvasHeight = height; var canvasElement = document.createElement('canvas'); canvasElement.style.width = "".concat(canvasWidth, "px"); canvasElement.style.height = "".concat(canvasHeight, "px"); @@ -479,9 +547,8 @@ var Html5Qrcode = /*#__PURE__*/function () { } }, { key: "_createVideoElement", - value: function _createVideoElement(width, height) { + value: function _createVideoElement(width) { var videoElement = document.createElement('video'); - videoElement.style.height = "".concat(height, "px"); videoElement.style.width = "".concat(width, "px"); videoElement.muted = true; videoElement.playsInline = true; @@ -548,7 +615,8 @@ var Html5Qrcode = /*#__PURE__*/function () { break; case Html5Qrcode.SHADED_BOTTOM: - elem.style.bottom = "0px"; + var top = qrRegion.y + qrRegion.height; + elem.style.top = "".concat(top, "px"); elem.style.left = "".concat(qrRegion.x, "px"); elem.style.width = "".concat(qrRegion.width, "px"); elem.style.height = "".concat(qrRegion.y, "px"); @@ -571,11 +639,11 @@ var Html5Qrcode = /*#__PURE__*/function () { }], [{ key: "getCameras", value: function getCameras() { - var _this = this; + var _this2 = this; return new Promise(function (resolve, reject) { if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices && navigator.mediaDevices.getUserMedia) { - _this._log("navigator.mediaDevices used"); + _this2._log("navigator.mediaDevices used"); navigator.mediaDevices.getUserMedia({ audio: false, @@ -595,7 +663,7 @@ var Html5Qrcode = /*#__PURE__*/function () { } } - _this._log("".concat(results.length, " results found")); + _this2._log("".concat(results.length, " results found")); resolve(results); })["catch"](function (err) { @@ -605,7 +673,7 @@ var Html5Qrcode = /*#__PURE__*/function () { reject("".concat(err.name, " : ").concat(err.message)); }); } else if (MediaStreamTrack && MediaStreamTrack.getSources) { - _this._log("MediaStreamTrack.getSources used"); + _this2._log("MediaStreamTrack.getSources used"); var callback = function callback(sourceInfos) { var results = []; @@ -621,14 +689,14 @@ var Html5Qrcode = /*#__PURE__*/function () { } } - _this._log("".concat(results.length, " results found")); + _this2._log("".concat(results.length, " results found")); resolve(results); }; MediaStreamTrack.getSources(callback); } else { - _this._log("unable to query supported devices."); + _this2._log("unable to query supported devices."); reject("unable to query supported devices."); } @@ -651,10 +719,6 @@ var Html5Qrcode = /*#__PURE__*/function () { return Html5Qrcode; }(); -_defineProperty(Html5Qrcode, "DEFAULT_HEIGHT", 300); - -_defineProperty(Html5Qrcode, "DEFAULT_HEIGHT_OFFSET", 2); - _defineProperty(Html5Qrcode, "DEFAULT_WIDTH", 300); _defineProperty(Html5Qrcode, "DEFAULT_WIDTH_OFFSET", 2); From aafa29cc4e8605005d85415549e90117d84872d5 Mon Sep 17 00:00:00 2001 From: Minhaz Date: Fri, 1 May 2020 17:40:01 +0800 Subject: [PATCH 2/2] Some lint fixed --- html5-qrcode.js | 52 +++++++++++++++++++++--------------- minified/html5-qrcode.min.js | 2 +- transpiled/html5-qrcode.js | 40 ++++++++++++++------------- 3 files changed, 52 insertions(+), 42 deletions(-) diff --git a/html5-qrcode.js b/html5-qrcode.js index 912a5ad..2fa98e1 100644 --- a/html5-qrcode.js +++ b/html5-qrcode.js @@ -103,8 +103,8 @@ class Html5Qrcode { const width = element.clientWidth ? element.clientWidth : Html5Qrcode.DEFAULT_WIDTH; element.style.position = "relative"; - // Setup QR code. this._shouldScan = true; + this._element = element; qrcode.callback = qrCodeSuccessCallback; // Validate before insertion @@ -130,7 +130,7 @@ class Html5Qrcode { const setupUi = (width, height) => { const qrboxSize = config.qrbox; if (qrboxSize > height) { - console.log("[Warning] [Html5Qrcode] config.qrboxsize is greater " + console.warn("[Html5Qrcode] config.qrboxsize is greater " + "than video height. Shading will be ignored"); } @@ -159,7 +159,6 @@ class Html5Qrcode { // Update local states $this._qrRegion = qrRegion; $this._context = context; - $this._element = element; $this._canvasElement = canvasElement; } @@ -171,8 +170,8 @@ class Html5Qrcode { } if ($this._localMediaStream) { - // difference in held video dimensions and rendered video dimensions - // require scaling + // There is difference in size of rendered video and one that is + // considered by the canvas. We need to account for scaling factor. const videoElement = $this._videoElement; const widthRatio = videoElement.videoWidth / videoElement.clientWidth; const heightRatio = videoElement.videoHeight / videoElement.clientHeight; @@ -202,17 +201,17 @@ class Html5Qrcode { } // success callback when user media (Camera) is attached. - const getUserMediaSuccessCallback = mediaStream => { + const onMediaStreamReceived = mediaStream => { return new Promise((resolve, reject) => { const setupVideo = () => { - $this._videoElement = this._createVideoElement(width); - element.append($this._videoElement); + const videoElement = this._createVideoElement(width); + $this._element.append(videoElement); // Attach listeners to video. - $this._videoElement.onabort = reject; - $this._videoElement.onerror = reject; - $this._videoElement.onplaying = () => { - const videoWidth = $this._videoElement.clientWidth; - const videoHeight = $this._videoElement.clientHeight; + videoElement.onabort = reject; + videoElement.onerror = reject; + videoElement.onplaying = () => { + const videoWidth = videoElement.clientWidth; + const videoHeight = videoElement.clientHeight; setupUi(videoWidth, videoHeight); // start scanning after video feed has started @@ -220,8 +219,11 @@ class Html5Qrcode { resolve(); } - $this._videoElement.srcObject = mediaStream; - $this._videoElement.play(); + videoElement.srcObject = mediaStream; + videoElement.play(); + + // Set state + $this._videoElement = videoElement; } $this._localMediaStream = mediaStream; @@ -254,8 +256,8 @@ class Html5Qrcode { navigator.mediaDevices.getUserMedia( { audio: false, video: videoConstraints }) .then(stream => { - getUserMediaSuccessCallback(stream) - .then(ignore => { + onMediaStreamReceived(stream) + .then(_ => { $this._isScanning = true; resolve(); }) @@ -265,11 +267,17 @@ class Html5Qrcode { reject(`Error getting userMedia, error = ${err}`); }); } else if (navigator.getUserMedia) { - const getCameraConfig = { video: { optional: [ { sourceId: cameraId } ]}}; + const getCameraConfig = { + video: { + optional: [{ + sourceId: cameraId + }] + } + }; navigator.getUserMedia(getCameraConfig, stream => { - getUserMediaSuccessCallback(stream) - .then(ignore => { + onMediaStreamReceived(stream) + .then(_ => { $this._isScanning = true; resolve(); }) @@ -496,8 +504,8 @@ class Html5Qrcode { && navigator.mediaDevices.enumerateDevices && navigator.mediaDevices.getUserMedia) { this._log("navigator.mediaDevices used"); - navigator.mediaDevices.getUserMedia({audio: false, video: true}) - .then(ignore => { + navigator.mediaDevices.getUserMedia({ audio: false, video: true }) + .then(_ => { navigator.mediaDevices.enumerateDevices() .then(devices => { const results = []; diff --git a/minified/html5-qrcode.min.js b/minified/html5-qrcode.min.js index 0a7e53a..2c3e2d8 100644 --- a/minified/html5-qrcode.min.js +++ b/minified/html5-qrcode.min.js @@ -1,4 +1,4 @@ function ECB(e,t){this.count=e,this.dataCodewords=t,this.__defineGetter__("Count",function(){return this.count}),this.__defineGetter__("DataCodewords",function(){return this.dataCodewords})}function ECBlocks(e,t,n){this.ecCodewordsPerBlock=e,this.ecBlocks=n?[t,n]:Array(t),this.__defineGetter__("ECCodewordsPerBlock",function(){return this.ecCodewordsPerBlock}),this.__defineGetter__("TotalECCodewords",function(){return this.ecCodewordsPerBlock*this.NumBlocks}),this.__defineGetter__("NumBlocks",function(){for(var e=0,t=0;ti;i++)for(var r=this.alignmentPatternCenters[i]-2,o=0;n>o;o++)0==i&&(0==o||o==n-1)||i==n-1&&0==o||t.setRegion(this.alignmentPatternCenters[o]-2,r,5,5);return t.setRegion(6,9,1,e-17),t.setRegion(9,6,e-17,1),6f;f+=2){var d=e[f],w=e[f+1],u=r*d+a*w+l;e[f]=(n*d+o*w+h)/u,e[f+1]=(i*d+s*w+c)/u}},this.transformPoints2=function(e,t){for(var n=e.length,i=0;n>i;i++){var r=e[i],o=t[i],s=this.a13*r+this.a23*o+this.a33;e[i]=(this.a11*r+this.a21*o+this.a31)/s,t[i]=(this.a12*r+this.a22*o+this.a32)/s}},this.buildAdjoint=function(){return new PerspectiveTransform(this.a22*this.a33-this.a23*this.a32,this.a23*this.a31-this.a21*this.a33,this.a21*this.a32-this.a22*this.a31,this.a13*this.a32-this.a12*this.a33,this.a11*this.a33-this.a13*this.a31,this.a12*this.a31-this.a11*this.a32,this.a12*this.a23-this.a13*this.a22,this.a13*this.a21-this.a11*this.a23,this.a11*this.a22-this.a12*this.a21)},this.times=function(e){return new PerspectiveTransform(this.a11*e.a11+this.a21*e.a12+this.a31*e.a13,this.a11*e.a21+this.a21*e.a22+this.a31*e.a23,this.a11*e.a31+this.a21*e.a32+this.a31*e.a33,this.a12*e.a11+this.a22*e.a12+this.a32*e.a13,this.a12*e.a21+this.a22*e.a22+this.a32*e.a23,this.a12*e.a31+this.a22*e.a32+this.a32*e.a33,this.a13*e.a11+this.a23*e.a12+this.a33*e.a13,this.a13*e.a21+this.a23*e.a22+this.a33*e.a23,this.a13*e.a31+this.a23*e.a32+this.a33*e.a33)}}function DetectorResult(e,t){this.bits=e,this.points=t}function Detector(e){this.image=e,this.resultPointCallback=null,this.sizeOfBlackWhiteBlackRun=function(e,t,n,i){var r=Math.abs(i-t)>Math.abs(n-e);if(r){var o=e;e=t,t=o,o=n,n=i,i=o}for(var s=Math.abs(n-e),a=Math.abs(i-t),h=-s>>1,c=i>t?1:-1,l=n>e?1:-1,f=0,d=e,o=t;d!=n;d+=l){var w=r?o:d,u=r?d:o;if(1==f?this.image[w+u*qrcode.width]&&f++:this.image[w+u*qrcode.width]||f++,3==f)return i=d-e,t=o-t,Math.sqrt(i*i+t*t);if(h+=a,h>0){if(o==i)break;o+=c,h-=s}}return e=n-e,t=i-t,Math.sqrt(e*e+t*t)},this.sizeOfBlackWhiteBlackRunBothWays=function(e,t,n,i){var r=this.sizeOfBlackWhiteBlackRun(e,t,n,i),o=1;return n=e-(n-e),0>n?(o=e/(e-n),n=0):n>=qrcode.width&&(o=(qrcode.width-1-e)/(n-e),n=qrcode.width-1),i=Math.floor(t-(i-t)*o),o=1,0>i?(o=t/(t-i),i=0):i>=qrcode.height&&(o=(qrcode.height-1-t)/(i-t),i=qrcode.height-1),n=Math.floor(e+(n-e)*o),r+=this.sizeOfBlackWhiteBlackRun(e,t,n,i),r-1},this.calculateModuleSizeOneWay=function(e,t){var n=this.sizeOfBlackWhiteBlackRunBothWays(Math.floor(e.X),Math.floor(e.Y),Math.floor(t.X),Math.floor(t.Y)),i=this.sizeOfBlackWhiteBlackRunBothWays(Math.floor(t.X),Math.floor(t.Y),Math.floor(e.X),Math.floor(e.Y));return isNaN(n)?i/7:isNaN(i)?n/7:(n+i)/14},this.calculateModuleSize=function(e,t,n){return(this.calculateModuleSizeOneWay(e,t)+this.calculateModuleSizeOneWay(e,n))/2},this.distance=function(e,t){return xDiff=e.X-t.X,yDiff=e.Y-t.Y,Math.sqrt(xDiff*xDiff+yDiff*yDiff)},this.computeDimension=function(e,t,n,i){switch(t=Math.round(this.distance(e,t)/i),e=Math.round(this.distance(e,n)/i),e=(t+e>>1)+7,3&e){case 0:e++;break;case 2:e--;break;case 3:throw"Error"}return e},this.findAlignmentInRegion=function(e,t,n,i){var r=Math.floor(i*e);if(i=Math.max(0,t-r),t=Math.min(qrcode.width-1,t+r),3*e>t-i)throw"Error";var o=Math.max(0,n-r);return n=Math.min(qrcode.height-1,n+r),new AlignmentPatternFinder(this.image,i,o,t-i,n-o,e,this.resultPointCallback).find()},this.createTransform=function(e,t,n,i,r){r-=3.5;var o,s,a;return null!=i?(o=i.X,i=i.Y,s=a=r-3):(o=t.X-e.X+n.X,i=t.Y-e.Y+n.Y,s=a=r),PerspectiveTransform.quadrilateralToQuadrilateral(3.5,3.5,r,3.5,s,a,3.5,r,e.X,e.Y,t.X,t.Y,o,i,n.X,n.Y)},this.sampleGrid=function(e,t,n){return GridSampler.sampleGrid3(e,n,t)},this.processFinderPatternInfo=function(e){var t=e.TopLeft,n=e.TopRight;e=e.BottomLeft;var i=this.calculateModuleSize(t,n,e);if(1>i)throw"Error";var r=this.computeDimension(t,n,e,i),o=Version.getProvisionalVersionForDimension(r),s=o.DimensionForVersion-7,a=null;if(0>3&3),this.dataMask=7&e,this.__defineGetter__("ErrorCorrectionLevel",function(){return this.errorCorrectionLevel}),this.__defineGetter__("DataMask",function(){return this.dataMask}),this.GetHashCode=function(){return this.errorCorrectionLevel.ordinal()<<3|dataMask},this.Equals=function(e){return this.errorCorrectionLevel==e.errorCorrectionLevel&&this.dataMask==e.dataMask}}function ErrorCorrectionLevel(e,t,n){this.ordinal_Renamed_Field=e,this.bits=t,this.name=n,this.__defineGetter__("Bits",function(){return this.bits}),this.__defineGetter__("Name",function(){return this.name}),this.ordinal=function(){return this.ordinal_Renamed_Field}}function BitMatrix(e,t){if(t||(t=e),1>e||1>t)throw"Both dimensions must be greater than 0";this.width=e,this.height=t;var n=e>>5;for(0!=(31&e)&&n++,this.rowSize=n,this.bits=Array(n*t),n=0;n>5)],31&e))},this.set_Renamed=function(e,t){this.bits[t*this.rowSize+(e>>5)]|=1<<(31&e)},this.flip=function(e,t){this.bits[t*this.rowSize+(e>>5)]^=1<<(31&e)},this.clear=function(){for(var e=this.bits.length,t=0;e>t;t++)this.bits[t]=0},this.setRegion=function(e,t,n,i){if(0>t||0>e)throw"Left and top must be nonnegative";if(1>i||1>n)throw"Height and width must be at least 1";if(n=e+n,i=t+i,i>this.height||n>this.width)throw"The region must fit inside the matrix";for(;i>t;t++)for(var r=t*this.rowSize,o=e;n>o;o++)this.bits[r+(o>>5)]|=1<<(31&o)}}function DataBlock(e,t){this.numDataCodewords=e,this.codewords=t,this.__defineGetter__("NumDataCodewords",function(){return this.numDataCodewords}),this.__defineGetter__("Codewords",function(){return this.codewords})}function BitMatrixParser(e){var t=e.Dimension;if(21>t||1!=(3&t))throw"Error BitMatrixParser";this.bitMatrix=e,this.parsedFormatInfo=this.parsedVersion=null,this.copyBit=function(e,t,n){return this.bitMatrix.get_Renamed(e,t)?n<<1|1:n<<1},this.readFormatInformation=function(){if(null!=this.parsedFormatInfo)return this.parsedFormatInfo;for(var e=0,t=0;6>t;t++)e=this.copyBit(t,8,e);for(e=this.copyBit(7,8,e),e=this.copyBit(8,8,e),e=this.copyBit(8,7,e),t=5;t>=0;t--)e=this.copyBit(8,t,e);if(this.parsedFormatInfo=FormatInformation.decodeFormatInformation(e),null!=this.parsedFormatInfo)return this.parsedFormatInfo;for(var n=this.bitMatrix.Dimension,e=0,i=n-8,t=n-1;t>=i;t--)e=this.copyBit(t,8,e);for(t=n-7;n>t;t++)e=this.copyBit(8,t,e);if(this.parsedFormatInfo=FormatInformation.decodeFormatInformation(e),null!=this.parsedFormatInfo)return this.parsedFormatInfo;throw"Error readFormatInformation"},this.readVersion=function(){if(null!=this.parsedVersion)return this.parsedVersion;var e=this.bitMatrix.Dimension,t=e-17>>2;if(6>=t)return Version.getVersionForNumber(t);for(var t=0,n=e-11,i=5;i>=0;i--)for(var r=e-9;r>=n;r--)t=this.copyBit(r,i,t);if(this.parsedVersion=Version.decodeVersionInformation(t),null!=this.parsedVersion&&this.parsedVersion.DimensionForVersion==e)return this.parsedVersion;for(t=0,r=5;r>=0;r--)for(i=e-9;i>=n;i--)t=this.copyBit(r,i,t);if(this.parsedVersion=Version.decodeVersionInformation(t),null!=this.parsedVersion&&this.parsedVersion.DimensionForVersion==e)return this.parsedVersion;throw"Error readVersion"},this.readCodewords=function(){var e=this.readFormatInformation(),t=this.readVersion(),n=DataMask.forReference(e.DataMask),e=this.bitMatrix.Dimension;n.unmaskBitMatrix(this.bitMatrix,e);for(var n=t.buildFunctionPattern(),i=!0,r=Array(t.TotalCodewords),o=0,s=0,a=0,h=e-1;h>0;h-=2){6==h&&h--;for(var c=0;e>c;c++)for(var l=i?e-1-c:c,f=0;2>f;f++)n.get_Renamed(h-f,l)||(a++,s<<=1,this.bitMatrix.get_Renamed(h-f,l)&&(s|=1),8==a&&(r[o++]=s,s=a=0));i^=1}if(o!=t.TotalCodewords)throw"Error readCodewords";return r}}function DataMask000(){this.unmaskBitMatrix=function(e,t){for(var n=0;t>n;n++)for(var i=0;t>i;i++)this.isMasked(n,i)&&e.flip(i,n)},this.isMasked=function(e,t){return 0==(e+t&1)}}function DataMask001(){this.unmaskBitMatrix=function(e,t){for(var n=0;t>n;n++)for(var i=0;t>i;i++)this.isMasked(n,i)&&e.flip(i,n)},this.isMasked=function(e){return 0==(1&e)}}function DataMask010(){this.unmaskBitMatrix=function(e,t){for(var n=0;t>n;n++)for(var i=0;t>i;i++)this.isMasked(n,i)&&e.flip(i,n)},this.isMasked=function(e,t){return 0==t%3}}function DataMask011(){this.unmaskBitMatrix=function(e,t){for(var n=0;t>n;n++)for(var i=0;t>i;i++)this.isMasked(n,i)&&e.flip(i,n)},this.isMasked=function(e,t){return 0==(e+t)%3}}function DataMask100(){this.unmaskBitMatrix=function(e,t){for(var n=0;t>n;n++)for(var i=0;t>i;i++)this.isMasked(n,i)&&e.flip(i,n)},this.isMasked=function(e,t){return 0==(URShift(e,1)+t/3&1)}}function DataMask101(){this.unmaskBitMatrix=function(e,t){for(var n=0;t>n;n++)for(var i=0;t>i;i++)this.isMasked(n,i)&&e.flip(i,n)},this.isMasked=function(e,t){var n=e*t;return 0==(1&n)+n%3}}function DataMask110(){this.unmaskBitMatrix=function(e,t){for(var n=0;t>n;n++)for(var i=0;t>i;i++)this.isMasked(n,i)&&e.flip(i,n)},this.isMasked=function(e,t){var n=e*t;return 0==((1&n)+n%3&1)}}function DataMask111(){this.unmaskBitMatrix=function(e,t){for(var n=0;t>n;n++)for(var i=0;t>i;i++)this.isMasked(n,i)&&e.flip(i,n)},this.isMasked=function(e,t){return 0==((e+t&1)+e*t%3&1)}}function ReedSolomonDecoder(e){this.field=e,this.decode=function(e,t){for(var n=new GF256Poly(this.field,e),i=Array(t),r=0;rr;r++){var s=n.evaluateAt(this.field.exp(r));i[i.length-1-r]=s,0!=s&&(o=!1)}if(!o)for(r=new GF256Poly(this.field,i),n=this.runEuclideanAlgorithm(this.field.buildMonomial(t,1),r,t),r=n[1],n=this.findErrorLocations(n[0]),i=this.findErrorMagnitudes(r,n,!1),r=0;ro)throw"ReedSolomonException Bad error location";e[o]=GF256.addOrSubtract(e[o],i[r])}},this.runEuclideanAlgorithm=function(e,t,n){if(e.Degree=Math.floor(n/2);){var a=e,h=i,c=o;if(e=t,i=r,o=s,e.Zero)throw"r_{i-1} was zero";for(t=a,s=this.field.Zero,r=e.getCoefficient(e.Degree),r=this.field.inverse(r);t.Degree>=e.Degree&&!t.Zero;){var a=t.Degree-e.Degree,l=this.field.multiply(t.getCoefficient(t.Degree),r),s=s.addOrSubtract(this.field.buildMonomial(a,l));t=t.addOrSubtract(e.multiplyByMonomial(a,l))}r=s.multiply1(i).addOrSubtract(h),s=s.multiply1(o).addOrSubtract(c)}if(n=s.getCoefficient(0),0==n)throw"ReedSolomonException sigmaTilde(0) was zero";return n=this.field.inverse(n),e=s.multiply2(n),n=t.multiply2(n),[e,n]},this.findErrorLocations=function(e){var t=e.Degree;if(1==t)return Array(e.getCoefficient(1));for(var n=Array(t),i=0,r=1;256>r&&t>i;r++)0==e.evaluateAt(r)&&(n[i]=this.field.inverse(r),i++);if(i!=t)throw"Error locator degree does not match number of roots";return n},this.findErrorMagnitudes=function(e,t,n){for(var i=t.length,r=Array(i),o=0;i>o;o++){for(var s=this.field.inverse(t[o]),a=1,h=0;i>h;h++)o!=h&&(a=this.field.multiply(a,GF256.addOrSubtract(1,this.field.multiply(t[h],s))));r[o]=this.field.multiply(e.evaluateAt(s),this.field.inverse(a)),n&&(r[o]=this.field.multiply(r[o],s))}return r}}function GF256Poly(e,t){if(null==t||0==t.length)throw"System.ArgumentException";this.field=e;var n=t.length;if(n>1&&0==t[0]){for(var i=1;n>i&&0==t[i];)i++;if(i==n)this.coefficients=e.Zero.coefficients;else{for(this.coefficients=Array(n-i),n=0;nn;n++)e=GF256.addOrSubtract(e,this.coefficients[n]);return e}for(var i=this.coefficients[0],n=1;t>n;n++)i=GF256.addOrSubtract(this.field.multiply(e,i),this.coefficients[n]);return i},this.addOrSubtract=function(t){if(this.field!=t.field)throw"GF256Polys do not have same GF256 field";if(this.Zero)return t;if(t.Zero)return this;var n=this.coefficients;if(t=t.coefficients,n.length>t.length){var i=n,n=t;t=i}for(var i=Array(t.length),r=t.length-n.length,o=0;r>o;o++)i[o]=t[o];for(o=r;oo;o++)for(var s=t[o],a=0;i>a;a++)r[o+a]=GF256.addOrSubtract(r[o+a],this.field.multiply(s,e[a]));return new GF256Poly(this.field,r)},this.multiply2=function(e){if(0==e)return this.field.Zero;if(1==e)return this;for(var t=this.coefficients.length,n=Array(t),i=0;t>i;i++)n[i]=this.field.multiply(this.coefficients[i],e);return new GF256Poly(this.field,n)},this.multiplyByMonomial=function(e,t){if(0>e)throw"System.ArgumentException";if(0==t)return this.field.Zero;for(var n=this.coefficients.length,i=Array(n+e),r=0;rr;r++)i[r]=this.field.multiply(this.coefficients[r],t);return new GF256Poly(this.field,i)},this.divide=function(e){if(this.field!=e.field)throw"GF256Polys do not have same GF256 field";if(e.Zero)throw"Divide by 0";for(var t=this.field.Zero,n=this,i=e.getCoefficient(e.Degree),i=this.field.inverse(i);n.Degree>=e.Degree&&!n.Zero;)var r=n.Degree-e.Degree,o=this.field.multiply(n.getCoefficient(n.Degree),i),s=e.multiplyByMonomial(r,o),r=this.field.buildMonomial(r,o),t=t.addOrSubtract(r),n=n.addOrSubtract(s);return[t,n]}}function GF256(e){this.expTable=Array(256),this.logTable=Array(256);for(var t=1,n=0;256>n;n++)this.expTable[n]=t,t<<=1,t>=256&&(t^=e);for(n=0;255>n;n++)this.logTable[this.expTable[n]]=n;e=Array(1),e[0]=0,this.zero=new GF256Poly(this,Array(e)),e=Array(1),e[0]=1,this.one=new GF256Poly(this,Array(e)),this.__defineGetter__("Zero",function(){return this.zero}),this.__defineGetter__("One",function(){return this.one}),this.buildMonomial=function(e,t){if(0>e)throw"System.ArgumentException";if(0==t)return zero;for(var n=Array(e+1),i=0;i=0?e>>t:(e>>t)+(2<<~t)}function FinderPattern(e,t,n){this.x=e,this.y=t,this.count=1,this.estimatedModuleSize=n,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(e,t,n){return Math.abs(t-this.y)<=e&&Math.abs(n-this.x)<=e?(e=Math.abs(e-this.estimatedModuleSize),1>=e||1>=e/this.estimatedModuleSize):!1}}function FinderPatternInfo(e){this.bottomLeft=e[0],this.topLeft=e[1],this.topRight=e[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=[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(e){for(var t=0,n=0;5>n;n++){var i=e[n];if(0==i)return!1;t+=i}return 7>t?!1:(t=Math.floor((t<=0&&r[t+a*qrcode.width];)s[2]++,a--;if(0>a)return 0/0;for(;a>=0&&!r[t+a*qrcode.width]&&s[1]<=n;)s[1]++,a--;if(0>a||s[1]>n)return 0/0;for(;a>=0&&r[t+a*qrcode.width]&&s[0]<=n;)s[0]++,a--;if(s[0]>n)return 0/0;for(a=e+1;o>a&&r[t+a*qrcode.width];)s[2]++,a++;if(a==o)return 0/0;for(;o>a&&!r[t+a*qrcode.width]&&s[3]=n)return 0/0;for(;o>a&&r[t+a*qrcode.width]&&s[4]=n||5*Math.abs(s[0]+s[1]+s[2]+s[3]+s[4]-i)>=2*i?0/0:this.foundPatternCross(s)?this.centerFromEnd(s,a):0/0},this.crossCheckHorizontal=function(e,t,n,i){for(var r=this.image,o=qrcode.width,s=this.CrossCheckStateCount,a=e;a>=0&&r[a+t*qrcode.width];)s[2]++,a--;if(0>a)return 0/0;for(;a>=0&&!r[a+t*qrcode.width]&&s[1]<=n;)s[1]++,a--;if(0>a||s[1]>n)return 0/0;for(;a>=0&&r[a+t*qrcode.width]&&s[0]<=n;)s[0]++,a--;if(s[0]>n)return 0/0;for(a=e+1;o>a&&r[a+t*qrcode.width];)s[2]++,a++;if(a==o)return 0/0;for(;o>a&&!r[a+t*qrcode.width]&&s[3]=n)return 0/0;for(;o>a&&r[a+t*qrcode.width]&&s[4]=n||5*Math.abs(s[0]+s[1]+s[2]+s[3]+s[4]-i)>=i?0/0:this.foundPatternCross(s)?this.centerFromEnd(s,a):0/0},this.handlePossibleCenter=function(e,t,n){var i=e[0]+e[1]+e[2]+e[3]+e[4];if(n=this.centerFromEnd(e,n),t=this.crossCheckVertical(t,Math.floor(n),e[2],i),!isNaN(t)&&(n=this.crossCheckHorizontal(Math.floor(n),Math.floor(t),e[2],i),!isNaN(n))){e=i/7;for(var i=!1,r=this.possibleCenters.length,o=0;r>o;o++){var s=this.possibleCenters[o];if(s.aboutEquals(e,t,n)){s.incrementCount(),i=!0;break}}return i||(n=new FinderPattern(n,t,e),this.possibleCenters.push(n),null!=this.resultPointCallback&&this.resultPointCallback.foundPossibleResultPoint(n)),!0}return!1},this.selectBestPatterns=function(){var e=this.possibleCenters.length;if(3>e)throw"Couldn't find enough finder patterns";if(e>3){for(var t=0,n=0;e>n;n++)t+=this.possibleCenters[n].EstimatedModuleSize;for(e=t/e,n=0;n.2*e&&(this.possibleCenters.remove(n),n--)}return[this.possibleCenters[0],this.possibleCenters[1],this.possibleCenters[2]]},this.findRowSkip=function(){var e=this.possibleCenters.length;if(1>=e)return 0;for(var t=null,n=0;e>n;n++){var i=this.possibleCenters[n];if(i.Count>=CENTER_QUORUM){if(null!=t)return this.hasSkipped=!0,Math.floor((Math.abs(t.X-i.X)-Math.abs(t.Y-i.Y))/2);t=i}}return 0},this.haveMultiplyConfirmedCenters=function(){for(var e=0,t=0,n=this.possibleCenters.length,i=0;n>i;i++){var r=this.possibleCenters[i];r.Count>=CENTER_QUORUM&&(e++,t+=r.EstimatedModuleSize)}if(3>e)return!1;for(var e=t/n,o=0,i=0;n>i;i++)r=this.possibleCenters[i],o+=Math.abs(r.EstimatedModuleSize-e);return.05*t>=o},this.findFinderPattern=function(e){this.image=e;var t=qrcode.height,n=qrcode.width,i=Math.floor(3*t/(4*MAX_MODULES));MIN_SKIP>i&&(i=MIN_SKIP);for(var r=!1,o=Array(5),s=i-1;t>s&&!r;s+=i){o[0]=0,o[1]=0,o[2]=0,o[3]=0;for(var a=o[4]=0,h=0;n>h;h++)if(e[h+s*qrcode.width])1==(1&a)&&a++,o[a]++;else if(0==(1&a))if(4==a)if(this.foundPatternCross(o)){if(a=this.handlePossibleCenter(o,s,h))i=2,this.hasSkipped?r=this.haveMultiplyConfirmedCenters():(a=this.findRowSkip(),a>o[2]&&(s+=a-o[2]-i,h=n-1));else{do h++;while(n>h&&!e[h+s*qrcode.width]);h--}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]++;this.foundPatternCross(o)&&this.handlePossibleCenter(o,s,n)&&(i=o[0],this.hasSkipped&&(r=haveMultiplyConfirmedCenters()))}return e=this.selectBestPatterns(),qrcode.orderBestPatterns(e),new FinderPatternInfo(e)}}function AlignmentPattern(e,t,n){this.x=e,this.y=t,this.count=1,this.estimatedModuleSize=n,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(e,t,n){return Math.abs(t-this.y)<=e&&Math.abs(n-this.x)<=e?(e=Math.abs(e-this.estimatedModuleSize),1>=e||1>=e/this.estimatedModuleSize):!1}}function AlignmentPatternFinder(e,t,n,i,r,o,s){this.image=e,this.possibleCenters=[],this.startX=t,this.startY=n,this.width=i,this.height=r,this.moduleSize=o,this.crossCheckStateCount=[0,0,0],this.resultPointCallback=s,this.centerFromEnd=function(e,t){return t-e[2]-e[1]/2},this.foundPatternCross=function(e){for(var t=this.moduleSize,n=t/2,i=0;3>i;i++)if(Math.abs(t-e[i])>=n)return!1;return!0},this.crossCheckVertical=function(e,t,n,i){var r=this.image,o=qrcode.height,s=this.crossCheckStateCount; s[0]=0,s[1]=0,s[2]=0;for(var a=e;a>=0&&r[t+a*qrcode.width]&&s[1]<=n;)s[1]++,a--;if(0>a||s[1]>n)return 0/0;for(;a>=0&&!r[t+a*qrcode.width]&&s[0]<=n;)s[0]++,a--;if(s[0]>n)return 0/0;for(a=e+1;o>a&&r[t+a*qrcode.width]&&s[1]<=n;)s[1]++,a++;if(a==o||s[1]>n)return 0/0;for(;o>a&&!r[t+a*qrcode.width]&&s[2]<=n;)s[2]++,a++;return s[2]>n||5*Math.abs(s[0]+s[1]+s[2]-i)>=2*i?0/0:this.foundPatternCross(s)?this.centerFromEnd(s,a):0/0},this.handlePossibleCenter=function(e,t,n){var i=e[0]+e[1]+e[2];if(n=this.centerFromEnd(e,n),t=this.crossCheckVertical(t,Math.floor(n),2*e[1],i),!isNaN(t)){e=(e[0]+e[1]+e[2])/3;for(var i=this.possibleCenters.length,r=0;i>r;r++)if(this.possibleCenters[r].aboutEquals(e,t,n))return new AlignmentPattern(n,t,e);n=new AlignmentPattern(n,t,e),this.possibleCenters.push(n),null!=this.resultPointCallback&&this.resultPointCallback.foundPossibleResultPoint(n)}return null},this.find=function(){for(var t=this.startX,r=this.height,o=t+i,s=n+(r>>1),a=[0,0,0],h=0;r>h;h++){var c=s+(0==(1&h)?h+1>>1:-(h+1>>1));a[0]=0,a[1]=0,a[2]=0;for(var l=t;o>l&&!e[l+qrcode.width*c];)l++;for(var f=0;o>l;){if(e[l+c*qrcode.width])if(1==f)a[f]++;else if(2==f){if(this.foundPatternCross(a)&&(f=this.handlePossibleCenter(a,c,l),null!=f))return f;a[0]=a[2],a[1]=1,a[2]=0,f=1}else a[++f]++;else 1==f&&f++,a[f]++;l++}if(this.foundPatternCross(a)&&(f=this.handlePossibleCenter(a,c,o),null!=f))return f}if(0!=this.possibleCenters.length)return this.possibleCenters[0];throw"Couldn't find enough alignment patterns"}}function QRCodeDataBlockReader(e,t,n){this.blockPointer=0,this.bitPointer=7,this.dataLength=0,this.blocks=e,this.numErrorCorrectionCode=n,9>=t?this.dataLengthMode=0:t>=10&&26>=t?this.dataLengthMode=1:t>=27&&40>=t&&(this.dataLengthMode=2),this.getNextBits=function(e){var t=0;if(et;t++)n+=1<>this.bitPointer-e+1,this.bitPointer-=e,t}if(e>8-(e-(this.bitPointer+1)),this.bitPointer-=e%8,0>this.bitPointer&&(this.bitPointer=8+this.bitPointer),t}if(e>8-(e-(this.bitPointer+1+8))),this.bitPointer-=(e-8)%8,0>this.bitPointer&&(this.bitPointer=8+this.bitPointer),t}return 0},this.NextMode=function(){return this.blockPointer>this.blocks.length-this.numErrorCorrectionCode-2?0:this.getNextBits(4)},this.getDataLength=function(e){for(var t=0;1!=e>>t;)t++;return this.getNextBits(qrcode.sizeOfDataLengthInfo[this.dataLengthMode][t])},this.getRomanAndFigureString=function(e){var t=0,n="",i="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:".split("");do if(e>1){var t=this.getNextBits(11),r=t%45,n=n+i[Math.floor(t/45)],n=n+i[r];e-=2}else 1==e&&(t=this.getNextBits(6),n+=i[t],e-=1);while(e>0);return n},this.getFigureString=function(e){var t=0,n="";do e>=3?(t=this.getNextBits(10),100>t&&(n+="0"),10>t&&(n+="0"),e-=3):2==e?(t=this.getNextBits(7),10>t&&(n+="0"),e-=2):1==e&&(t=this.getNextBits(4),e-=1),n+=t;while(e>0);return n},this.get8bitByteArray=function(e){var t=0,n=[];do t=this.getNextBits(8),n.push(t),e--;while(e>0);return n},this.getKanjiString=function(e){var t=0,n="";do{var t=getNextBits(13),t=(t/192<<8)+t%192,i=0,i=40956>=t+33088?t+33088:t+49472,n=n+String.fromCharCode(i);e--}while(e>0);return n},this.__defineGetter__("DataByte",function(){for(var e=[];;){var t=this.NextMode();if(0==t){if(0dataLength)throw"Invalid data length: "+dataLength;switch(t){case 1:for(var t=this.getFigureString(dataLength),n=Array(t.length),i=0;is||s>n||-1>a||a>i)throw"Error.checkAndNudgePoints ";r=!1,-1==s?(t[o]=0,r=!0):s==n&&(t[o]=n-1,r=!0),-1==a?(t[o+1]=0,r=!0):a==i&&(t[o+1]=i-1,r=!0)}for(r=!0,o=t.Length-2;o>=0&&r;o-=2){if(s=Math.floor(t[o]),a=Math.floor(t[o+1]),-1>s||s>n||-1>a||a>i)throw"Error.checkAndNudgePoints ";r=!1,-1==s?(t[o]=0,r=!0):s==n&&(t[o]=n-1,r=!0),-1==a?(t[o+1]=0,r=!0):a==i&&(t[o+1]=i-1,r=!0)}},sampleGrid3:function(e,t,n){for(var i=new BitMatrix(t),r=Array(t<<1),o=0;t>o;o++){for(var s=r.length,a=o+.5,h=0;s>h;h+=2)r[h]=(h>>1)+.5,r[h+1]=a;n.transformPoints1(r),GridSampler.checkAndNudgePoints(e,r);try{for(h=0;s>h;h+=2){var c=4*Math.floor(r[h])+4*Math.floor(r[h+1])*qrcode.width,l=e[Math.floor(r[h])+qrcode.width*Math.floor(r[h+1])];qrcode.imagedata.data[c]=l?255:0,qrcode.imagedata.data[c+1]=l?255:0,qrcode.imagedata.data[c+2]=0,qrcode.imagedata.data[c+3]=255,l&&i.set_Renamed(h>>1,o)}}catch(f){throw"Error.checkAndNudgePoints"}}return i},sampleGridx:function(e,t,n,i,r,o,s,a,h,c,l,f,d,w,u,C,E,B){return n=PerspectiveTransform.quadrilateralToQuadrilateral(n,i,r,o,s,a,h,c,l,f,d,w,u,C,E,B),GridSampler.sampleGrid3(e,t,n)}},Version.VERSION_DECODE_INFO=[31892,34236,39577,42195,48118,51042,55367,58893,63784,68472,70749,76311,79154,84390,87683,92361,96236,102084,102881,110507,110734,117786,119615,126325,127568,133589,136944,141498,145311,150283,152622,158308,161089,167017],Version.VERSIONS=buildVersions(),Version.getVersionForNumber=function(e){if(1>e||e>40)throw"ArgumentException";return Version.VERSIONS[e-1]},Version.getProvisionalVersionForDimension=function(e){if(1!=e%4)throw"Error getProvisionalVersionForDimension";try{return Version.getVersionForNumber(e-17>>2)}catch(t){throw"Error getVersionForNumber"}},Version.decodeVersionInformation=function(e){for(var t=4294967295,n=0,i=0;ir&&(n=i+7,t=r)}return 3>=t?this.getVersionForNumber(n):null},PerspectiveTransform.quadrilateralToQuadrilateral=function(e,t,n,i,r,o,s,a,h,c,l,f,d,w,u,C){return e=this.quadrilateralToSquare(e,t,n,i,r,o,s,a),this.squareToQuadrilateral(h,c,l,f,d,w,u,C).times(e)},PerspectiveTransform.squareToQuadrilateral=function(e,t,n,i,r,o,s,a){return dy2=a-o,dy3=t-i+o-a,0==dy2&&0==dy3?new PerspectiveTransform(n-e,r-n,e,i-t,o-i,t,0,0,1):(dx1=n-r,dx2=s-r,dx3=e-n+r-s,dy1=i-o,denominator=dx1*dy2-dx2*dy1,a13=(dx3*dy2-dx2*dy3)/denominator,a23=(dx1*dy3-dx3*dy1)/denominator,new PerspectiveTransform(n-e+a13*n,s-e+a23*s,e,i-t+a13*i,a-t+a23*a,t,a13,a23,1))},PerspectiveTransform.quadrilateralToSquare=function(e,t,n,i,r,o,s,a){return this.squareToQuadrilateral(e,t,n,i,r,o,s,a).buildAdjoint()};var FORMAT_INFO_MASK_QR=21522,FORMAT_INFO_DECODE_LOOKUP=[[21522,0],[20773,1],[24188,2],[23371,3],[17913,4],[16590,5],[20375,6],[19104,7],[30660,8],[29427,9],[32170,10],[30877,11],[26159,12],[25368,13],[27713,14],[26998,15],[5769,16],[5054,17],[7399,18],[6608,19],[1890,20],[597,21],[3340,22],[2107,23],[13663,24],[12392,25],[16177,26],[14854,27],[9396,28],[8579,29],[11994,30],[11245,31]],BITS_SET_IN_HALF_BYTE=[0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4];FormatInformation.numBitsDiffering=function(e,t){return e^=t,BITS_SET_IN_HALF_BYTE[15&e]+BITS_SET_IN_HALF_BYTE[15&URShift(e,4)]+BITS_SET_IN_HALF_BYTE[15&URShift(e,8)]+BITS_SET_IN_HALF_BYTE[15&URShift(e,12)]+BITS_SET_IN_HALF_BYTE[15&URShift(e,16)]+BITS_SET_IN_HALF_BYTE[15&URShift(e,20)]+BITS_SET_IN_HALF_BYTE[15&URShift(e,24)]+BITS_SET_IN_HALF_BYTE[15&URShift(e,28)]},FormatInformation.decodeFormatInformation=function(e){var t=FormatInformation.doDecodeFormatInformation(e);return null!=t?t:FormatInformation.doDecodeFormatInformation(e^FORMAT_INFO_MASK_QR)},FormatInformation.doDecodeFormatInformation=function(e){for(var t=4294967295,n=0,i=0;io&&(n=r[1],t=o)}return 3>=t?new FormatInformation(n):null},ErrorCorrectionLevel.forBits=function(e){if(0>e||e>=FOR_BITS.Length)throw"ArgumentException";return FOR_BITS[e]};var L=new ErrorCorrectionLevel(0,1,"L"),M=new ErrorCorrectionLevel(1,0,"M"),Q=new ErrorCorrectionLevel(2,3,"Q"),H=new ErrorCorrectionLevel(3,2,"H"),FOR_BITS=[M,L,H,Q];DataBlock.getDataBlocks=function(e,t,n){if(e.length!=t.TotalCodewords)throw"ArgumentException";var i=t.getECBlocksForLevel(n);n=0;var r=i.getECBlocks();for(t=0;t=0&&n[r].codewords.length!=t;)r--;for(r++,i=t-i.ECCodewordsPerBlock,t=a=0;i>t;t++)for(s=0;o>s;s++)n[s].codewords[t]=e[a++];for(s=r;o>s;s++)n[s].codewords[i]=e[a++];for(h=n[0].codewords.length,t=i;h>t;t++)for(s=0;o>s;s++)n[s].codewords[r>s?t:t+1]=e[a++];return n},DataMask={forReference:function(e){if(0>e||e>7)throw"System.ArgumentException";return DataMask.DATA_MASKS[e]}},DataMask.DATA_MASKS=[new DataMask000,new DataMask001,new DataMask010,new DataMask011,new DataMask100,new DataMask101,new DataMask110,new DataMask111],GF256.QR_CODE_FIELD=new GF256(285),GF256.DATA_MATRIX_FIELD=new GF256(301),GF256.addOrSubtract=function(e,t){return e^t},Decoder={},Decoder.rsDecoder=new ReedSolomonDecoder(GF256.QR_CODE_FIELD),Decoder.correctErrors=function(e,t){for(var n=e.length,i=Array(n),r=0;n>r;r++)i[r]=255&e[r];n=e.length-t;try{Decoder.rsDecoder.decode(i,n)}catch(o){throw o}for(r=0;t>r;r++)e[r]=i[r]},Decoder.decode=function(e){var t=new BitMatrixParser(e);e=t.readVersion();for(var n=t.readFormatInformation().ErrorCorrectionLevel,t=t.readCodewords(),t=DataBlock.getDataBlocks(t,e,n),i=0,r=0;rr;r++)i[o++]=a[r]}return new QRCodeDataBlockReader(i,e.VersionNumber,n.Bits)},qrcode={imagedata:null,width:0,height:0,qrCodeSymbol:null,debug:!1,sizeOfDataLengthInfo:[[10,9,8,8],[12,11,16,10],[14,13,16,12]],callback:null,decode:function(e){if(0==arguments.length){var t=document.getElementById("qr-canvas"),n=t.getContext("2d");return qrcode.width=t.width,qrcode.height=t.height,qrcode.imagedata=n.getImageData(0,0,qrcode.width,qrcode.height),qrcode.result=qrcode.process(n),null!=qrcode.callback&&qrcode.callback(qrcode.result),qrcode.result}var i=new Image;i.onload=function(){var e=document.createElement("canvas"),t=e.getContext("2d"),n=document.getElementById("out-canvas");null!=n&&(n=n.getContext("2d"),n.clearRect(0,0,320,240),n.drawImage(i,0,0,320,240)),e.width=i.width,e.height=i.height,t.drawImage(i,0,0),qrcode.width=i.width,qrcode.height=i.height;try{qrcode.imagedata=t.getImageData(0,0,i.width,i.height)}catch(r){return qrcode.result="Cross domain image reading not supported in your browser! Save it to your computer then drag and drop the file!",void(null!=qrcode.callback&&qrcode.callback(qrcode.result))}try{qrcode.result=qrcode.process(t)}catch(o){console.log(o),qrcode.result="error decoding QR Code"}null!=qrcode.callback&&qrcode.callback(qrcode.result)},i.src=e},decode_utf8:function(e){return decodeURIComponent(escape(e))},process:function(e){var t=(new Date).getTime(),n=qrcode.grayScaleToBitmap(qrcode.grayscale());if(qrcode.debug){for(var i=0;i=r?!0:!1}return t},getMiddleBrightnessPerArea:function(e){for(var t=Math.floor(qrcode.width/4),n=Math.floor(qrcode.height/4),i=Array(4),r=0;4>r;r++){i[r]=Array(4);for(var o=0;4>o;o++)i[r][o]=[0,0]}for(r=0;4>r;r++)for(o=0;4>o;o++){i[o][r][0]=255;for(var s=0;n>s;s++)for(var a=0;t>a;a++){var h=e[t*o+a+(n*r+s)*qrcode.width];hi[o][r][1]&&(i[o][r][1]=h)}}for(e=Array(4),t=0;4>t;t++)e[t]=Array(4);for(r=0;4>r;r++)for(o=0;4>o;o++)e[o][r]=Math.floor((i[o][r][0]+i[o][r][1])/2);return e},grayScaleToBitmap:function(e){for(var t=qrcode.getMiddleBrightnessPerArea(e),n=t.length,i=Math.floor(qrcode.width/n),r=Math.floor(qrcode.height/n),o=Array(qrcode.height*qrcode.width),s=0;n>s;s++)for(var a=0;n>a;a++)for(var h=0;r>h;h++)for(var c=0;i>c;c++)o[i*a+c+(r*s+h)*qrcode.width]=e[i*a+c+(r*s+h)*qrcode.width]e?this.length+e:e,this.push.apply(this,n)};var MIN_SKIP=3,MAX_MODULES=57,INTEGER_MATH_SHIFT=8,CENTER_QUORUM=2;qrcode.orderBestPatterns=function(e){function t(e,t){return xDiff=e.X-t.X,yDiff=e.Y-t.Y,Math.sqrt(xDiff*xDiff+yDiff*yDiff)}var n=t(e[0],e[1]),i=t(e[1],e[2]),r=t(e[0],e[2]);i>=n&&i>=r?(i=e[0],n=e[1],r=e[2]):r>=i&&r>=n?(i=e[1],n=e[0],r=e[2]):(i=e[2],n=e[0],r=e[1]);var o=i.x,s=i.y;0>(r.x-o)*(n.y-s)-(r.y-s)*(n.x-o)&&(o=n,n=r,r=o),e[0]=n,e[1]=i,e[2]=r}; -function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,t){for(var n=0;nd)throw"'config.qrbox' should not be greater than the width of the HTML element."}var u=function(t){return new Promise(function(n,i){r._localMediaStream=t,r._videoElement=o._createVideoElement(d),s.append(r._videoElement),r._videoElement.onabort=i,r._videoElement.onerror=i,r._videoElement.onplaying=function(){!function(e,t){var n=c.qrbox;n>t&&console.log("[Warning] [Html5Qrcode] config.qrboxsize is greater than video height. Shading will be ignored");var i=l&&n<=t,a={x:0,y:0,width:e,height:t},d=i?o._getShadedRegionBounds(e,t,n):a,h=o._createCanvasElement(d.width,d.height),u=h.getContext("2d");u.canvas.width=d.width,u.canvas.height=d.height,s.append(h),i&&o._possiblyInsertShadingElement(s,t,d),r._qrRegion=d,r._context=u,r._element=s,r._canvasElement=h}(r._videoElement.clientWidth,r._videoElement.clientHeight),function t(){if(r._shouldScan){if(r._localMediaStream){var n=r._videoElement,i=n.videoWidth/n.clientWidth,o=n.videoHeight/n.clientHeight,l=r._qrRegion.width*i,s=r._qrRegion.height*o;r._context.drawImage(r._videoElement,r._qrRegion.x,r._qrRegion.y,l,s,0,0,r._qrRegion.width,r._qrRegion.height);try{qrcode.decode()}catch(e){a("QR code parse error, error = ".concat(e))}}r._foreverScanTimeout=setTimeout(t,e._getTimeoutFps(c.fps))}}(),n()},r._videoElement.srcObject=t,r._videoElement.play()})};return new Promise(function(e,n){if(navigator.mediaDevices&&navigator.mediaDevices.getUserMedia){var i={deviceId:{exact:t}};navigator.mediaDevices.getUserMedia({audio:!1,video:i}).then(function(t){u(t).then(function(t){r._isScanning=!0,e()}).catch(n)}).catch(function(e){n("Error getting userMedia, error = ".concat(e))})}else if(navigator.getUserMedia){var a={video:{optional:[{sourceId:t}]}};navigator.getUserMedia(a,function(t){u(t).then(function(t){r._isScanning=!0,e()}).catch(n)},function(e){n("Error getting userMedia, error = ".concat(e))})}else n("Web camera streaming not supported by the browser.")})}},{key:"stop",value:function(){this._shouldScan=!1,clearTimeout(this._foreverScanTimeout);var t=this;return new Promise(function(n,i){qrcode.callback=null;var a=t._localMediaStream.getVideoTracks().length,o=0,r=function(){t._localMediaStream=null,t._element.removeChild(t._videoElement),t._element.removeChild(t._canvasElement),function(){for(;t._element.getElementsByClassName(e.SHADED_REGION_CLASSNAME).length;){var n=t._element.getElementsByClassName(e.SHADED_REGION_CLASSNAME)[0];t._element.removeChild(n)}}(),t._isScanning=!1,t._qrRegion&&(t._qrRegion=null),t._context&&(t._context=null),n(!0)};t._localMediaStream.getVideoTracks().forEach(function(e){e.stop(),++o>=a&&r()})})}},{key:"scanFile",value:function(t,n){var i=this;if(!(t&&t instanceof File))throw"imageFile argument is mandatory and should be instance of File. Use 'event.target.files[0]'";if(n=void 0===n||n,i._isScanning)throw"Close ongoing scan before scanning a file.";return new Promise(function(a,o){i._possiblyCloseLastScanImageFile(),i._clearElement(),i._lastScanImageFile=t;var r=new Image;r.onload=function(){var t=r.width,c=r.height,l=document.getElementById(i._elementId),s=l.clientWidth?l.clientWidth:e.DEFAULT_WIDTH,d=l.clientHeight?l.clientHeight:c,h=function t(n,i,a,o){if(n<=a&&i<=o)return{x:(a-n)/2,y:(o-i)/2,width:n,height:i};var r=n,c=i;return n>a&&(i*=a/n,n=a),i>o&&(n*=o/i,i=o),e._log("Image downsampled from ".concat(r,"X").concat(c)+" to ".concat(n,"X").concat(i,".")),t(n,i,a,o)}(t,c,s,d);if(n){var u=i._createCanvasElement(s,d,"qr-canvas-visible");u.style.display="inline-block",l.appendChild(u);var _=u.getContext("2d");_.canvas.width=s,_.canvas.height=d,_.drawImage(r,0,0,t,c,h.x,h.y,h.width,h.height)}var g=i._createCanvasElement(h.width,h.height);l.appendChild(g);var m=g.getContext("2d");m.canvas.width=h.width,m.canvas.height=h.height,m.drawImage(r,0,0,t,c,0,0,h.width,h.height);try{a(qrcode.decode())}catch(e){o("QR code parse error, error = ".concat(e))}},r.onerror=o,r.onabort=o,r.onstalled=o,r.onsuspend=o,r.src=URL.createObjectURL(t)})}},{key:"clear",value:function(){this._clearElement()}},{key:"_clearElement",value:function(){if(this._isScanning)throw"Cannot clear while scan is ongoing, close it first.";document.getElementById(this._elementId).innerHTML=""}},{key:"_createCanvasElement",value:function(e,t,n){var i=e,a=t,o=document.createElement("canvas");return o.style.width="".concat(i,"px"),o.style.height="".concat(a,"px"),o.style.display="none",o.id=null==n?"qr-canvas":n,o}},{key:"_createVideoElement",value:function(e){var t=document.createElement("video");return t.style.width="".concat(e,"px"),t.muted=!0,t.playsInline=!0,t}},{key:"_getShadedRegionBounds",value:function(e,t,n){if(n>e||n>t)throw"'config.qrbox' should not be greater than the width and height of the HTML element.";return{x:(e-n)/2,y:(t-n)/2,width:n,height:n}}},{key:"_possiblyInsertShadingElement",value:function(t,n,i){0==i.x&&0==i.y||(t.append(this._createShadedElement(n,i,e.SHADED_LEFT)),t.append(this._createShadedElement(n,i,e.SHADED_RIGHT)),t.append(this._createShadedElement(n,i,e.SHADED_TOP)),t.append(this._createShadedElement(n,i,e.SHADED_BOTTOM)))}},{key:"_createShadedElement",value:function(t,n,i){var a=document.createElement("div");switch(a.style.position="absolute",a.style.height="".concat(t,"px"),a.className=e.SHADED_REGION_CLASSNAME,a.id="".concat(e.SHADED_REGION_CLASSNAME,"_").concat(i),a.style.background="#0000007a",i){case e.SHADED_LEFT:a.style.top="0px",a.style.left="0px",a.style.width="".concat(n.x,"px"),a.style.height="".concat(t,"px");break;case e.SHADED_RIGHT:a.style.top="0px",a.style.right="0px",a.style.width="".concat(n.x,"px"),a.style.height="".concat(t,"px");break;case e.SHADED_TOP:a.style.top="0px",a.style.left="".concat(n.x,"px"),a.style.width="".concat(n.width,"px"),a.style.height="".concat(n.y,"px");break;case e.SHADED_BOTTOM:var o=n.y+n.height;a.style.top="".concat(o,"px"),a.style.left="".concat(n.x,"px"),a.style.width="".concat(n.width,"px"),a.style.height="".concat(n.y,"px");break;default:throw"Unsupported shadingPosition"}return a}},{key:"_possiblyCloseLastScanImageFile",value:function(){this._lastScanImageFile&&(URL.revokeObjectURL(this._lastScanImageFile),this._lastScanImageFile=null)}}],[{key:"getCameras",value:function(){var e=this;return new Promise(function(t,n){if(navigator.mediaDevices&&navigator.mediaDevices.enumerateDevices&&navigator.mediaDevices.getUserMedia)e._log("navigator.mediaDevices used"),navigator.mediaDevices.getUserMedia({audio:!1,video:!0}).then(function(i){navigator.mediaDevices.enumerateDevices().then(function(n){for(var i=[],a=0;ad)throw"'config.qrbox' should not be greater than the width of the HTML element."}var u=function(t){return new Promise(function(n,i){var h;r._localMediaStream=t,h=o._createVideoElement(d),r._element.append(h),h.onabort=i,h.onerror=i,h.onplaying=function(){!function(e,t){var n=c.qrbox;n>t&&console.warn("[Html5Qrcode] config.qrboxsize is greater than video height. Shading will be ignored");var i=l&&n<=t,a={x:0,y:0,width:e,height:t},d=i?o._getShadedRegionBounds(e,t,n):a,h=o._createCanvasElement(d.width,d.height),u=h.getContext("2d");u.canvas.width=d.width,u.canvas.height=d.height,s.append(h),i&&o._possiblyInsertShadingElement(s,t,d),r._qrRegion=d,r._context=u,r._canvasElement=h}(h.clientWidth,h.clientHeight),function t(){if(r._shouldScan){if(r._localMediaStream){var n=r._videoElement,i=n.videoWidth/n.clientWidth,o=n.videoHeight/n.clientHeight,l=r._qrRegion.width*i,s=r._qrRegion.height*o;r._context.drawImage(r._videoElement,r._qrRegion.x,r._qrRegion.y,l,s,0,0,r._qrRegion.width,r._qrRegion.height);try{qrcode.decode()}catch(e){a("QR code parse error, error = ".concat(e))}}r._foreverScanTimeout=setTimeout(t,e._getTimeoutFps(c.fps))}}(),n()},h.srcObject=t,h.play(),r._videoElement=h})};return new Promise(function(e,n){if(navigator.mediaDevices&&navigator.mediaDevices.getUserMedia){var i={deviceId:{exact:t}};navigator.mediaDevices.getUserMedia({audio:!1,video:i}).then(function(t){u(t).then(function(t){r._isScanning=!0,e()}).catch(n)}).catch(function(e){n("Error getting userMedia, error = ".concat(e))})}else if(navigator.getUserMedia){var a={video:{optional:[{sourceId:t}]}};navigator.getUserMedia(a,function(t){u(t).then(function(t){r._isScanning=!0,e()}).catch(n)},function(e){n("Error getting userMedia, error = ".concat(e))})}else n("Web camera streaming not supported by the browser.")})}},{key:"stop",value:function(){this._shouldScan=!1,clearTimeout(this._foreverScanTimeout);var t=this;return new Promise(function(n,i){qrcode.callback=null;var a=t._localMediaStream.getVideoTracks().length,o=0,r=function(){t._localMediaStream=null,t._element.removeChild(t._videoElement),t._element.removeChild(t._canvasElement),function(){for(;t._element.getElementsByClassName(e.SHADED_REGION_CLASSNAME).length;){var n=t._element.getElementsByClassName(e.SHADED_REGION_CLASSNAME)[0];t._element.removeChild(n)}}(),t._isScanning=!1,t._qrRegion&&(t._qrRegion=null),t._context&&(t._context=null),n(!0)};t._localMediaStream.getVideoTracks().forEach(function(e){e.stop(),++o>=a&&r()})})}},{key:"scanFile",value:function(t,n){var i=this;if(!(t&&t instanceof File))throw"imageFile argument is mandatory and should be instance of File. Use 'event.target.files[0]'";if(n=void 0===n||n,i._isScanning)throw"Close ongoing scan before scanning a file.";return new Promise(function(a,o){i._possiblyCloseLastScanImageFile(),i._clearElement(),i._lastScanImageFile=t;var r=new Image;r.onload=function(){var t=r.width,c=r.height,l=document.getElementById(i._elementId),s=l.clientWidth?l.clientWidth:e.DEFAULT_WIDTH,d=l.clientHeight?l.clientHeight:c,h=function t(n,i,a,o){if(n<=a&&i<=o)return{x:(a-n)/2,y:(o-i)/2,width:n,height:i};var r=n,c=i;return n>a&&(i*=a/n,n=a),i>o&&(n*=o/i,i=o),e._log("Image downsampled from ".concat(r,"X").concat(c)+" to ".concat(n,"X").concat(i,".")),t(n,i,a,o)}(t,c,s,d);if(n){var u=i._createCanvasElement(s,d,"qr-canvas-visible");u.style.display="inline-block",l.appendChild(u);var g=u.getContext("2d");g.canvas.width=s,g.canvas.height=d,g.drawImage(r,0,0,t,c,h.x,h.y,h.width,h.height)}var _=i._createCanvasElement(h.width,h.height);l.appendChild(_);var m=_.getContext("2d");m.canvas.width=h.width,m.canvas.height=h.height,m.drawImage(r,0,0,t,c,0,0,h.width,h.height);try{a(qrcode.decode())}catch(e){o("QR code parse error, error = ".concat(e))}},r.onerror=o,r.onabort=o,r.onstalled=o,r.onsuspend=o,r.src=URL.createObjectURL(t)})}},{key:"clear",value:function(){this._clearElement()}},{key:"_clearElement",value:function(){if(this._isScanning)throw"Cannot clear while scan is ongoing, close it first.";document.getElementById(this._elementId).innerHTML=""}},{key:"_createCanvasElement",value:function(e,t,n){var i=e,a=t,o=document.createElement("canvas");return o.style.width="".concat(i,"px"),o.style.height="".concat(a,"px"),o.style.display="none",o.id=null==n?"qr-canvas":n,o}},{key:"_createVideoElement",value:function(e){var t=document.createElement("video");return t.style.width="".concat(e,"px"),t.muted=!0,t.playsInline=!0,t}},{key:"_getShadedRegionBounds",value:function(e,t,n){if(n>e||n>t)throw"'config.qrbox' should not be greater than the width and height of the HTML element.";return{x:(e-n)/2,y:(t-n)/2,width:n,height:n}}},{key:"_possiblyInsertShadingElement",value:function(t,n,i){0==i.x&&0==i.y||(t.append(this._createShadedElement(n,i,e.SHADED_LEFT)),t.append(this._createShadedElement(n,i,e.SHADED_RIGHT)),t.append(this._createShadedElement(n,i,e.SHADED_TOP)),t.append(this._createShadedElement(n,i,e.SHADED_BOTTOM)))}},{key:"_createShadedElement",value:function(t,n,i){var a=document.createElement("div");switch(a.style.position="absolute",a.style.height="".concat(t,"px"),a.className=e.SHADED_REGION_CLASSNAME,a.id="".concat(e.SHADED_REGION_CLASSNAME,"_").concat(i),a.style.background="#0000007a",i){case e.SHADED_LEFT:a.style.top="0px",a.style.left="0px",a.style.width="".concat(n.x,"px"),a.style.height="".concat(t,"px");break;case e.SHADED_RIGHT:a.style.top="0px",a.style.right="0px",a.style.width="".concat(n.x,"px"),a.style.height="".concat(t,"px");break;case e.SHADED_TOP:a.style.top="0px",a.style.left="".concat(n.x,"px"),a.style.width="".concat(n.width,"px"),a.style.height="".concat(n.y,"px");break;case e.SHADED_BOTTOM:var o=n.y+n.height;a.style.top="".concat(o,"px"),a.style.left="".concat(n.x,"px"),a.style.width="".concat(n.width,"px"),a.style.height="".concat(n.y,"px");break;default:throw"Unsupported shadingPosition"}return a}},{key:"_possiblyCloseLastScanImageFile",value:function(){this._lastScanImageFile&&(URL.revokeObjectURL(this._lastScanImageFile),this._lastScanImageFile=null)}}],[{key:"getCameras",value:function(){var e=this;return new Promise(function(t,n){if(navigator.mediaDevices&&navigator.mediaDevices.enumerateDevices&&navigator.mediaDevices.getUserMedia)e._log("navigator.mediaDevices used"),navigator.mediaDevices.getUserMedia({audio:!1,video:!0}).then(function(i){navigator.mediaDevices.enumerateDevices().then(function(n){for(var i=[],a=0;a height) { - console.log("[Warning] [Html5Qrcode] config.qrboxsize is greater " + "than video height. Shading will be ignored"); + console.warn("[Html5Qrcode] config.qrboxsize is greater " + "than video height. Shading will be ignored"); } var shouldShadingBeApplied = isShadedBoxEnabled && qrboxSize <= height; @@ -158,7 +158,6 @@ var Html5Qrcode = /*#__PURE__*/function () { $this._qrRegion = qrRegion; $this._context = context; - $this._element = element; $this._canvasElement = canvasElement; }; // Method that scans forever. @@ -170,8 +169,8 @@ var Html5Qrcode = /*#__PURE__*/function () { } if ($this._localMediaStream) { - // difference in held video dimensions and rendered video dimensions - // require scaling + // There is difference in size of rendered video and one that is + // considered by the canvas. We need to account for scaling factor. var videoElement = $this._videoElement; var widthRatio = videoElement.videoWidth / videoElement.clientWidth; var heightRatio = videoElement.videoHeight / videoElement.clientHeight; @@ -208,27 +207,30 @@ var Html5Qrcode = /*#__PURE__*/function () { }; // success callback when user media (Camera) is attached. - var getUserMediaSuccessCallback = function getUserMediaSuccessCallback(mediaStream) { + var onMediaStreamReceived = function onMediaStreamReceived(mediaStream) { return new Promise(function (resolve, reject) { var setupVideo = function setupVideo() { - $this._videoElement = _this._createVideoElement(width); - element.append($this._videoElement); // Attach listeners to video. + var videoElement = _this._createVideoElement(width); + + $this._element.append(videoElement); // Attach listeners to video. + - $this._videoElement.onabort = reject; - $this._videoElement.onerror = reject; + videoElement.onabort = reject; + videoElement.onerror = reject; - $this._videoElement.onplaying = function () { - var videoWidth = $this._videoElement.clientWidth; - var videoHeight = $this._videoElement.clientHeight; + videoElement.onplaying = function () { + var videoWidth = videoElement.clientWidth; + var videoHeight = videoElement.clientHeight; setupUi(videoWidth, videoHeight); // start scanning after video feed has started foreverScan(); resolve(); }; - $this._videoElement.srcObject = mediaStream; + videoElement.srcObject = mediaStream; + videoElement.play(); // Set state - $this._videoElement.play(); + $this._videoElement = videoElement; }; $this._localMediaStream = mediaStream; @@ -261,7 +263,7 @@ var Html5Qrcode = /*#__PURE__*/function () { audio: false, video: videoConstraints }).then(function (stream) { - getUserMediaSuccessCallback(stream).then(function (ignore) { + onMediaStreamReceived(stream).then(function (_) { $this._isScanning = true; resolve(); })["catch"](reject); @@ -277,7 +279,7 @@ var Html5Qrcode = /*#__PURE__*/function () { } }; navigator.getUserMedia(getCameraConfig, function (stream) { - getUserMediaSuccessCallback(stream).then(function (ignore) { + onMediaStreamReceived(stream).then(function (_) { $this._isScanning = true; resolve(); })["catch"](reject); @@ -648,7 +650,7 @@ var Html5Qrcode = /*#__PURE__*/function () { navigator.mediaDevices.getUserMedia({ audio: false, video: true - }).then(function (ignore) { + }).then(function (_) { navigator.mediaDevices.enumerateDevices().then(function (devices) { var results = [];