diff --git a/Gruntfile.js b/Gruntfile.js index 45dbfa7..28d0b9e 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -34,6 +34,7 @@ module.exports = function(grunt) { }, "baseUrl" : "src", "name" : "quagga", + "useStrict": true, "out" : "dist/quagga.js", "include" : ['quagga'], "optimize" : "none", diff --git a/README.md b/README.md index df49725..ccf7280 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ quaggaJS ======== -- [Changelog](#changelog) (2015-06-13) +- [Changelog](#changelog) (2015-07-08) ## What is QuaggaJS? @@ -80,12 +80,16 @@ version `quagga.min.js` and places both files in the `dist` folder. You can check out the [examples][github_examples] to get an idea of how to use QuaggaJS. Basically the library exposes the following API: -### Quagga.init(config, callback) +### Quagga.init(config, callback) This method initializes the library for a given configuration `config` (see -below) and invokes the `callback` when Quagga is ready to start. The -initialization process also requests for camera access if real-time detection is -configured. +below) and invokes the `callback(err)` when Quagga has finished its +bootstrapping phase. The initialization process also requests for camera +access if real-time detection is configured. In case of an error, the `err` +parameter is set and contains information about the cause. A potential cause +may be the `inputStream.type` is set to `LiveStream`, but the browser does +not support this API, or simply if the user denies the permission to use the +camera. ```javascript Quagga.init({ @@ -96,7 +100,11 @@ Quagga.init({ decoder : { readers : ["code_128_reader"] } - }, function() { + }, function(err) { + if (err) { + console.log(err); + return + } console.log("Initialization finished. Ready to start"); Quagga.start(); }); @@ -143,7 +151,8 @@ empty. ```javascript { "codeResult": { - "code": "FANAVF1461710", + "code": "FANAVF1461710", // the decoded code as a string + "format": "code_128", // or code_39, codabar, ean_13, ean_8, upc_a, upc_e "start": 355, "end": 26, "codeset": 100, @@ -223,7 +232,8 @@ The default `config` object is set as followed: right: "0%", // right offset left: "0%", // left offset bottom: "0%" // bottom offset - } + }, + singleChannel: false // true: only the red color-channel is read }, tracking: false, debug: false, @@ -269,11 +279,13 @@ locating-mechanism for more robust results. ```javascript Quagga.decodeSingle({ - readers: ['code_128_reader'], - locate: true, // try to locate the barcode in the image - src: '/test/fixtures/code_128/image-001.jpg' // or 'data:image/jpg;base64,' + data + decoder: { + readers: ["code_128_reader"] // List of active readers + }, + locate: true, // try to locate the barcode in the image + src: '/test/fixtures/code_128/image-001.jpg' // or 'data:image/jpg;base64,' + data }, function(result){ - console.log(result); + console.log(result); }); ``` @@ -297,8 +309,87 @@ web-workers, and their restriction not to have access to the DOM, the configuration must be explicitly set to `config.numOfWorkers = 0` in order to work. +## ResultCollector + +Quagga is not perfect by any means and may produce false positives from time +to time. In order to find out which images produced those false positives, +the built-in ``ResultCollector`` will support you and me helping squashing +bugs in the implementation. + +### Creating a ``ResultCollector`` + +You can easily create a new ``ResultCollector`` by calling its ``create`` +method with a configuration. + +```javascript +var resultCollector = Quagga.ResultCollector.create({ + capture: true, // keep track of the image producing this result + capacity: 20, // maximum number of results to store + blacklist: [ // list containing codes which should not be recorded + {code: "3574660239843", format: "ean_13"}], + filter: function(codeResult) { + // only store results which match this constraint + // returns true/false + // e.g.: return codeResult.format === "ean_13"; + return true; + } +}); +``` + +### Using a ``ResultCollector`` + +After creating a ``ResultCollector`` you have to attach it to Quagga by +calling ``Quagga.registerResultCollector(resultCollector)``. + +### Reading results + +After a test/recording session, you can now print the collected results which +do not fit into a certain schema. Calling ``getResults`` on the +``resultCollector`` returns an ``Array`` containing objects with: + +```javascript +{ + codeResult: {}, // same as in onDetected event + frame: "data:image/png;base64,iVBOR..." // dataURL of the gray-scaled image +} +``` + +The ``frame`` property is an internal representation of the image and +therefore only available in gray-scale. The dataURL representation allows +easy saving/rendering of the image. + +### Comparing results + +Now, having the frames available on disk, you can load each single image by +calling ``decodeSingle`` with the same configuration as used during recording +. In order to reproduce the exact same result, you have to make sure to turn +on the ``singleChannel`` flag in the configuration when using ``decodeSingle``. + ## Changelog +### 2015-07-08 +- Improvements + - Parameter tweaking to reduce false-positives significantly (for the + entire EAN and UPC family) + - Fixing bug in parity check for UPC-E codes + - Fixing bug in alignment for EAN-8 codes + +### 2015-07-06 +- Improvements + - Added `err` parameter to [Quagga.init()](#quaggainit) callback + function + +### 2015-06-21 +- Features + - Added ``singleChannel`` configuration to ``inputStream`` (in [config] + (#configobject)) + - Added ``ResultCollector`` functionality (see [ResultCollector] + (#resultcollector)) + +### 2015-06-13 +- Improvements + - Added ``format`` property to ``codeResult`` (in [result](#resultobject)) + ### 2015-06-13 - Improvements - Added fixes for ``Code39Reader`` (trailing whitespace was missing) diff --git a/dist/quagga.js b/dist/quagga.js index b07df34..a2db04c 100644 --- a/dist/quagga.js +++ b/dist/quagga.js @@ -437,7 +437,7 @@ define("almond", function(){}); define( 'barcode_reader',[],function() { - + "use strict"; function BarcodeReader() { this._row = []; @@ -600,6 +600,9 @@ define( } else { result.direction = BarcodeReader.DIRECTION.FORWARD; } + if (result) { + result.format = self.FORMAT; + } return result; }; @@ -614,6 +617,11 @@ define( } return true; }; + + Object.defineProperty(BarcodeReader.prototype, "FORMAT", { + value: 'unknown', + writeable: false + }); BarcodeReader.DIRECTION = { FORWARD : 1, @@ -638,7 +646,7 @@ define( "./barcode_reader" ], function(BarcodeReader) { - + "use strict"; function Code128Reader() { BarcodeReader.call(this); @@ -764,7 +772,8 @@ define( [2, 3, 3, 1, 1, 1, 2] ]}, SINGLE_CODE_ERROR: {value: 1}, - AVG_CODE_ERROR: {value: 0.5} + AVG_CODE_ERROR: {value: 0.5}, + FORMAT: {value: "code_128", writeable: false} }; Code128Reader.prototype = Object.create(BarcodeReader.prototype, properties); @@ -793,67 +802,17 @@ define( } else { if (counterPos === counter.length - 1) { normalized = self._normalize(counter); - for ( code = 0; code < self.CODE_PATTERN.length; code++) { - error = self._matchPattern(normalized, self.CODE_PATTERN[code]); - if (error < bestMatch.error) { - bestMatch.code = code; - bestMatch.error = error; + if (normalized) { + for (code = 0; code < self.CODE_PATTERN.length; code++) { + error = self._matchPattern(normalized, self.CODE_PATTERN[code]); + if (error < bestMatch.error) { + bestMatch.code = code; + bestMatch.error = error; + } } - } - bestMatch.end = i; - return bestMatch; - } else { - counterPos++; - } - counter[counterPos] = 1; - isWhite = !isWhite; - } - } - return null; - }; - - Code128Reader.prototype._findEnd = function() { - var counter = [0, 0, 0, 0, 0, 0, 0], - i, - self = this, - offset = self._nextSet(self._row), - isWhite = !self._row[offset], - counterPos = 0, - bestMatch = { - error : Number.MAX_VALUE, - code : -1, - start : 0, - end : 0 - }, - error, - j, - sum, - normalized; - - for ( i = offset; i < self._row.length; i++) { - if (self._row[i] ^ isWhite) { - counter[counterPos]++; - } else { - if (counterPos === counter.length - 1) { - sum = 0; - for ( j = 0; j < counter.length; j++) { - sum += counter[j]; - } - normalized = self._normalize(counter, 13); - error = self._matchPattern(normalized, self.CODE_PATTERN[self.STOP_CODE]); - if (error < self.AVG_CODE_ERROR) { - bestMatch.error = error; - bestMatch.start = i - sum; bestMatch.end = i; return bestMatch; } - - for ( j = 0; j < 5; j++) { - counter[j] = counter[j + 2]; - } - counter[5] = 0; - counter[6] = 0; - counterPos--; } else { counterPos++; } @@ -893,17 +852,19 @@ define( sum += counter[j]; } normalized = self._normalize(counter); - for ( code = self.START_CODE_A; code <= self.START_CODE_C; code++) { - error = self._matchPattern(normalized, self.CODE_PATTERN[code]); - if (error < bestMatch.error) { - bestMatch.code = code; - bestMatch.error = error; + if (normalized) { + for (code = self.START_CODE_A; code <= self.START_CODE_C; code++) { + error = self._matchPattern(normalized, self.CODE_PATTERN[code]); + if (error < bestMatch.error) { + bestMatch.code = code; + bestMatch.error = error; + } + } + if (bestMatch.error < self.AVG_CODE_ERROR) { + bestMatch.start = i - sum; + bestMatch.end = i; + return bestMatch; } - } - if (bestMatch.error < self.AVG_CODE_ERROR) { - bestMatch.start = i - sum; - bestMatch.end = i; - return bestMatch; } for ( j = 0; j < 4; j++) { @@ -1052,7 +1013,7 @@ define( // find end bar code.end = self._nextUnset(self._row, code.end); - if (code.end === self._row.length) { + if(!self._verifyTrailingWhitespace(code)){ return null; } @@ -1063,9 +1024,15 @@ define( return null; } + if (!result.length) { + return null; + } + // remove last code from result (checksum) result.splice(result.length - 1, 1); + + return { code : result.join(""), start : startInfo.start, @@ -1076,6 +1043,20 @@ define( endInfo : code }; }; + + + BarcodeReader.prototype._verifyTrailingWhitespace = function(endInfo) { + var self = this, + trailingWhitespaceEnd; + + trailingWhitespaceEnd = endInfo.end + ((endInfo.end - endInfo.start) / 2); + if (trailingWhitespaceEnd < self._row.length) { + if (self._matchRange(endInfo.end, trailingWhitespaceEnd, 0)) { + return endInfo; + } + } + return null; + }; return (Code128Reader); } @@ -1088,7 +1069,7 @@ define( "./barcode_reader" ], function(BarcodeReader) { - + "use strict"; function EANReader(opts) { BarcodeReader.call(this, opts); @@ -1124,8 +1105,9 @@ define( [2, 1, 1, 3] ]}, CODE_FREQUENCY : {value: [0, 11, 13, 14, 19, 25, 28, 21, 22, 26]}, - SINGLE_CODE_ERROR: {value: 0.7}, - AVG_CODE_ERROR: {value: 0.3} + SINGLE_CODE_ERROR: {value: 0.67}, + AVG_CODE_ERROR: {value: 0.27}, + FORMAT: {value: "ean_13", writeable: false} }; EANReader.prototype = Object.create(BarcodeReader.prototype, properties); @@ -1158,18 +1140,20 @@ define( } else { if (counterPos === counter.length - 1) { normalized = self._normalize(counter); - for ( code = 0; code < coderange; code++) { - error = self._matchPattern(normalized, self.CODE_PATTERN[code]); - if (error < bestMatch.error) { - bestMatch.code = code; - bestMatch.error = error; + if (normalized) { + for (code = 0; code < coderange; code++) { + error = self._matchPattern(normalized, self.CODE_PATTERN[code]); + if (error < bestMatch.error) { + bestMatch.code = code; + bestMatch.error = error; + } } + bestMatch.end = i; + if (bestMatch.error > self.AVG_CODE_ERROR) { + return null; + } + return bestMatch; } - bestMatch.end = i; - if (bestMatch.error > self.AVG_CODE_ERROR) { - return null; - } - return bestMatch; } else { counterPos++; } @@ -1226,13 +1210,15 @@ define( sum += counter[j]; } normalized = self._normalize(counter); - error = self._matchPattern(normalized, pattern); + if (normalized) { + error = self._matchPattern(normalized, pattern); - if (error < epsilon) { - bestMatch.error = error; - bestMatch.start = i - sum; - bestMatch.end = i; - return bestMatch; + if (error < epsilon) { + bestMatch.error = error; + bestMatch.start = i - sum; + bestMatch.end = i; + return bestMatch; + } } if (tryHarder) { for ( j = 0; j < counter.length - 2; j++) { @@ -1416,7 +1402,7 @@ define( /* global define */ define('image_loader',[],function() { - + "use strict"; var ImageLoader = {}; ImageLoader.load = function(directory, callback, offset, size, sequence) { @@ -1480,7 +1466,7 @@ define('image_loader',[],function() { /* global define */ define('input_stream',["image_loader"], function(ImageLoader) { - + "use strict"; var InputStream = {}; InputStream.createVideoStream = function(video) { @@ -1827,7 +1813,7 @@ define("typedefs", (function (global) { /* global define */ define('subImage',["typedefs"], function() { - + "use strict"; /** * Construct representing a part of another {ImageWrapper}. Shares data @@ -1951,7 +1937,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ (function() { - + "use strict"; var shim = {}; if (typeof(exports) === 'undefined') { @@ -5796,7 +5782,7 @@ if(typeof(exports) !== 'undefined') { /* global define */ define('cluster',["gl-matrix"], function(glMatrix) { - + "use strict"; var vec2 = glMatrix.vec2; /** @@ -5869,7 +5855,7 @@ define('cluster',["gl-matrix"], function(glMatrix) { /* global define */ define('array_helper',[],function() { - + "use strict"; return { init : function(arr, val) { @@ -5956,7 +5942,7 @@ define('array_helper',[],function() { define('cv_utils',['cluster', "array_helper", "gl-matrix"], function(Cluster2, ArrayHelper, glMatrix) { - + "use strict"; /* * cv_utils.js * Collection of CV functions and libraries @@ -6439,13 +6425,19 @@ define('cv_utils',['cluster', "array_helper", "gl-matrix"], function(Cluster2, A }; - CVUtils.computeGray = function(imageData, outArray) { - var l = imageData.length / 4; - var i = 0; - for ( i = 0; i < l; i++) { - //outArray[i] = (0.299*imageData[i*4+0] + 0.587*imageData[i*4+1] + 0.114*imageData[i*4+2]); + CVUtils.computeGray = function(imageData, outArray, config) { + var l = (imageData.length / 4) | 0, + i, + singleChannel = config && config.singleChannel === true; - outArray[i] = Math.floor(0.299 * imageData[i * 4 + 0] + 0.587 * imageData[i * 4 + 1] + 0.114 * imageData[i * 4 + 2]); + if (singleChannel) { + for (i = 0; i < l; i++) { + outArray[i] = imageData[i * 4 + 0]; + } + } else { + for (i = 0; i < l; i++) { + outArray[i] = Math.floor(0.299 * imageData[i * 4 + 0] + 0.587 * imageData[i * 4 + 1] + 0.114 * imageData[i * 4 + 2]); + } } }; @@ -6676,7 +6668,7 @@ define('image_wrapper',[ ], function(SubImage, CVUtils, ArrayHelper, glMatrix) { - + 'use strict'; var vec2 = glMatrix.vec2, mat2 = glMatrix.mat2; @@ -7099,7 +7091,7 @@ define('image_wrapper',[ * http://www.codeproject.com/Tips/407172/Connected-Component-Labeling-and-Vectorization */ define('tracer',[],function() { - + "use strict"; var Tracer = { searchDirections : [[0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0], [-1, 1]], @@ -7208,7 +7200,7 @@ define('tracer',[],function() { * http://www.codeproject.com/Tips/407172/Connected-Component-Labeling-and-Vectorization */ define('rasterizer',["tracer"], function(Tracer) { - + "use strict"; var Rasterizer = { createContour2D : function() { @@ -7404,7 +7396,7 @@ define('rasterizer',["tracer"], function(Tracer) { /* global define */ define('skeletonizer',[],function() { - + "use strict"; Math.imul = Math.imul || function(a, b) { var ah = (a >>> 16) & 0xffff; @@ -7619,7 +7611,7 @@ define('skeletonizer',[],function() { /* global define */ define('image_debug',[],function() { - + "use strict"; return { drawRect: function(pos, size, ctx, style){ @@ -7640,6 +7632,26 @@ define('image_debug',[],function() { } ctx.closePath(); ctx.stroke(); + }, + drawImage: function(imageData, size, ctx) { + var canvasData = ctx.getImageData(0, 0, size.x, size.y), + data = canvasData.data, + imageDataPos = imageData.length, + canvasDataPos = data.length, + value; + + if (canvasDataPos/imageDataPos !== 4) { + return false; + } + while(imageDataPos--){ + value = imageData[imageDataPos]; + data[--canvasDataPos] = 255; + data[--canvasDataPos] = value; + data[--canvasDataPos] = value; + data[--canvasDataPos] = value; + } + ctx.putImageData(canvasData, 0, 0); + return true; } }; @@ -8211,7 +8223,7 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I /* global define */ define('bresenham',["cv_utils", "image_wrapper"], function(CVUtils, ImageWrapper) { - + "use strict"; var Bresenham = {}; var Slope = { @@ -8326,6 +8338,7 @@ define('bresenham',["cv_utils", "image_wrapper"], function(CVUtils, ImageWrapper max = result.max, line = result.line, slope, + slope2, center = min + (max - min) / 2, extrema = [], currentDir, @@ -8341,11 +8354,12 @@ define('bresenham',["cv_utils", "image_wrapper"], function(CVUtils, ImageWrapper pos : 0, val : line[0] }); - for ( i = 0; i < line.length - 1; i++) { + for ( i = 0; i < line.length - 2; i++) { slope = (line[i + 1] - line[i]); - if (slope < rThreshold && line[i + 1] < (center*1.5)) { + slope2 = (line[i + 2] - line[i + 1]); + if ((slope + slope2) < rThreshold && line[i + 1] < (center*1.5)) { dir = Slope.DIR.DOWN; - } else if (slope > threshold && line[i + 1] > (center*0.5)) { + } else if ((slope + slope2) > threshold && line[i + 1] > (center*0.5)) { dir = Slope.DIR.UP; } else { dir = currentDir; @@ -8431,7 +8445,7 @@ define( "./array_helper" ], function(BarcodeReader, ArrayHelper) { - + "use strict"; function Code39Reader() { BarcodeReader.call(this); @@ -8441,7 +8455,8 @@ define( ALPHABETH_STRING: {value: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *$/+%"}, ALPHABET: {value: [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 45, 46, 32, 42, 36, 47, 43, 37]}, CHARACTER_ENCODINGS: {value: [0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, 0x124, 0x064, 0x109, 0x049, 0x148, 0x019, 0x118, 0x058, 0x00D, 0x10C, 0x04C, 0x01C, 0x103, 0x043, 0x142, 0x013, 0x112, 0x052, 0x007, 0x106, 0x046, 0x016, 0x181, 0x0C1, 0x1C0, 0x091, 0x190, 0x0D0, 0x085, 0x184, 0x0C4, 0x094, 0x0A8, 0x0A2, 0x08A, 0x02A]}, - ASTERISK: {value: 0x094} + ASTERISK: {value: 0x094}, + FORMAT: {value: "code_39", writeable: false} }; Code39Reader.prototype = Object.create(BarcodeReader.prototype, properties); @@ -8650,7 +8665,7 @@ define( "./code_39_reader" ], function(Code39Reader) { - + "use strict"; function Code39VINReader() { Code39Reader.call(this); @@ -8710,7 +8725,7 @@ define( "./barcode_reader" ], function(BarcodeReader) { - + "use strict"; function CodabarReader() { BarcodeReader.call(this); @@ -8724,7 +8739,8 @@ define( START_END: {value: [0x01A, 0x029, 0x00B, 0x00E]}, MIN_ENCODED_CHARS: {value: 4}, MAX_ACCEPTABLE: {value: 2.0}, - PADDING: {value: 1.5} + PADDING: {value: 1.5}, + FORMAT: {value: "codabar", writeable: false} }; CodabarReader.prototype = Object.create(BarcodeReader.prototype, properties); @@ -9023,13 +9039,17 @@ define( "./ean_reader" ], function(EANReader) { - + "use strict"; function UPCReader() { EANReader.call(this); } - UPCReader.prototype = Object.create(EANReader.prototype); + var properties = { + FORMAT: {value: "upc_a", writeable: false} + }; + + UPCReader.prototype = Object.create(EANReader.prototype, properties); UPCReader.prototype.constructor = UPCReader; UPCReader.prototype._decode = function() { @@ -9054,13 +9074,17 @@ define( "./ean_reader" ], function(EANReader) { - + "use strict"; function EAN8Reader() { EANReader.call(this); } - EAN8Reader.prototype = Object.create(EANReader.prototype); + var properties = { + FORMAT: {value: "ean_8", writeable: false} + }; + + EAN8Reader.prototype = Object.create(EANReader.prototype, properties); EAN8Reader.prototype.constructor = EAN8Reader; EAN8Reader.prototype._decodePayload = function(code, result, decodedCodes) { @@ -9076,7 +9100,7 @@ define( decodedCodes.push(code); } - code = self._findPattern(self.MIDDLE_PATTERN, code.end, true); + code = self._findPattern(self.MIDDLE_PATTERN, code.end, true, false); if (code === null) { return null; } @@ -9105,7 +9129,7 @@ define( "./ean_reader" ], function(EANReader) { - + "use strict"; function UPCEReader() { EANReader.call(this); @@ -9115,7 +9139,8 @@ define( CODE_FREQUENCY : {value: [ [ 56, 52, 50, 49, 44, 38, 35, 42, 41, 37 ], [7, 11, 13, 14, 19, 25, 28, 21, 22, 26]]}, - STOP_PATTERN: { value: [1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7]} + STOP_PATTERN: { value: [1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7]}, + FORMAT: {value: "upc_e", writeable: false} }; UPCEReader.prototype = Object.create(EANReader.prototype, properties); @@ -9134,13 +9159,13 @@ define( if (code.code >= self.CODE_G_START) { code.code = code.code - self.CODE_G_START; codeFrequency |= 1 << (5 - i); - } else { - codeFrequency |= 0 << (5 - i); } result.push(code.code); decodedCodes.push(code); } - self._determineParity(codeFrequency, result); + if (!self._determineParity(codeFrequency, result)) { + return null; + } return code; }; @@ -9155,10 +9180,11 @@ define( if (codeFrequency === self.CODE_FREQUENCY[nrSystem][i]) { result.unshift(nrSystem); result.push(i); - return; + return true; } } } + return false; }; UPCEReader.prototype._convertToUPCA = function(result) { @@ -9234,7 +9260,7 @@ define('barcode_decoder',[ UPCReader, EAN8Reader, UPCEReader) { - + "use strict"; var readers = { code_128_reader: Code128Reader, @@ -9260,8 +9286,7 @@ define('barcode_decoder',[ overlay : null } }, - _barcodeReaders = [], - _barcodeReader = null; + _barcodeReaders = []; initCanvas(); initReaders(); @@ -9346,13 +9371,10 @@ define('barcode_decoder',[ // check if inside image extendLine(ext); - while (ext > 1 && !inputImageWrapper.inImageWithBorder(line[0], 0) || !inputImageWrapper.inImageWithBorder(line[1], 0)) { - ext -= Math.floor(ext/2); + while (ext > 1 && (!inputImageWrapper.inImageWithBorder(line[0], 0) || !inputImageWrapper.inImageWithBorder(line[1], 0))) { + ext -= Math.ceil(ext/2); extendLine(-ext); } - if (ext <= 1) { - return null; - } return line; } @@ -9382,9 +9404,6 @@ define('barcode_decoder',[ for ( i = 0; i < _barcodeReaders.length && result === null; i++) { result = _barcodeReaders[i].decodePattern(barcodeLine.line); - if (result !== null) { - _barcodeReader = _barcodeReaders[i]; - } } if(result === null){ return null; @@ -9513,7 +9532,7 @@ define('barcode_decoder',[ /* global define */ define('frame_grabber',["cv_utils"], function(CVUtils) { - + "use strict"; var FrameGrabber = {}; @@ -9570,7 +9589,7 @@ define('frame_grabber',["cv_utils"], function(CVUtils) { if(doHalfSample){ CVUtils.grayAndHalfSampleFromCanvasData(ctxData, _size, _data); } else { - CVUtils.computeGray(ctxData, _data); + CVUtils.computeGray(ctxData, _data, _streamConfig); } return true; } else { @@ -9592,7 +9611,7 @@ define('frame_grabber',["cv_utils"], function(CVUtils) { /* global define */ define('html_utils',[], function() { - + "use strict"; function createNode(htmlStr) { var temp = document.createElement('div'); @@ -9648,7 +9667,8 @@ define('config',[],function(){ right: "0%", left: "0%", bottom: "0%" - } + }, + singleChannel: false // true: only the red color-channel is read }, tracking: false, debug: false, @@ -9692,7 +9712,7 @@ define('config',[],function(){ /* global define */ define('events',[],function() { - + "use strict"; var _events = function() { var events = {}; @@ -9783,7 +9803,7 @@ define('events',[],function() { /* global define, MediaStreamTrack */ define('camera_access',["html_utils"], function(HtmlUtils) { - + "use strict"; var streamRef, loadedDataHandler; @@ -9794,11 +9814,15 @@ define('camera_access',["html_utils"], function(HtmlUtils) { * @param {Object} failure Callback */ function getUserMedia(constraints, success, failure) { - navigator.getUserMedia(constraints, function(stream) { - streamRef = stream; - var videoSrc = (window.URL && window.URL.createObjectURL(stream)) || stream; - success.apply(null, [videoSrc]); - }, failure); + if (typeof navigator.getUserMedia !== 'undefined') { + navigator.getUserMedia(constraints, function (stream) { + streamRef = stream; + var videoSrc = (window.URL && window.URL.createObjectURL(stream)) || stream; + success.apply(null, [videoSrc]); + }, failure); + } else { + failure(new TypeError("getUserMedia not available")); + } } function loadedData(video, callback) { @@ -9837,7 +9861,7 @@ define('camera_access',["html_utils"], function(HtmlUtils) { video.addEventListener('loadeddata', loadedDataHandler, false); video.play(); }, function(e) { - console.log(e); + callback(e); }); } @@ -9860,7 +9884,7 @@ define('camera_access',["html_utils"], function(HtmlUtils) { facing: "environment" }, config); - if ( typeof MediaStreamTrack.getSources !== 'undefined') { + if ( typeof MediaStreamTrack !== 'undefined' && typeof MediaStreamTrack.getSources !== 'undefined') { MediaStreamTrack.getSources(function(sourceInfos) { var videoSourceId; for (var i = 0; i != sourceInfos.length; ++i) { @@ -9919,10 +9943,68 @@ define('camera_access',["html_utils"], function(HtmlUtils) { }; }); -/* jshint undef: true, unused: true, browser:true, devel: true, evil: true */ +/* jshint undef: true, unused: true, browser:true, devel: true */ /* global define */ +define('result_collector',["image_debug"], function(ImageDebug) { + "use strict"; + + function contains(codeResult, list) { + if (list) { + return list.some(function (item) { + return Object.keys(item).every(function (key) { + return item[key] === codeResult[key]; + }); + }); + } + return false; + } + + function passesFilter(codeResult, filter) { + if (typeof filter === 'function') { + return filter(codeResult); + } + return true; + } + + return { + create: function(config) { + var canvas = document.createElement("canvas"), + ctx = canvas.getContext("2d"), + results = [], + capacity = config.capacity || 20, + capture = config.capture === true; + + function matchesConstraints(codeResult) { + return capacity && codeResult && !contains(codeResult, config.blacklist) && passesFilter(codeResult, config.filter); + } + return { + addResult: function(data, imageSize, codeResult) { + var result = {}; + + if (matchesConstraints(codeResult)) { + capacity--; + result.codeResult = codeResult; + if (capture) { + canvas.width = imageSize.x; + canvas.height = imageSize.y; + ImageDebug.drawImage(data, imageSize, ctx); + result.frame = canvas.toDataURL(); + } + results.push(result); + } + }, + getResults: function() { + return results; + } + }; + } + }; +}); + +/* jshint undef: true, unused: true, browser:true, devel: true, evil: true */ +/* global define */ define('quagga',[ "code_128_reader", "ean_reader", @@ -9936,7 +10018,8 @@ define('quagga',[ "events", "camera_access", "image_debug", - "gl-matrix"], + "gl-matrix", + "result_collector"], function(Code128Reader, EANReader, InputStream, @@ -9949,8 +10032,9 @@ function(Code128Reader, Events, CameraAccess, ImageDebug, - glMatrix) { - + glMatrix, + ResultCollector) { + "use strict"; var _inputStream, _framegrabber, @@ -9970,7 +10054,8 @@ function(Code128Reader, _decoder, _workerPool = [], _onUIThread = true, - vec2 = glMatrix.vec2; + vec2 = glMatrix.vec2, + _resultCollector; function initializeData(imageWrapper) { initBuffers(imageWrapper); @@ -10020,7 +10105,7 @@ function(Code128Reader, if (!err) { _inputStream.trigger("canrecord"); } else { - console.log(err); + return cb(err); } }); } @@ -10032,9 +10117,7 @@ function(Code128Reader, } function canRecord(cb) { - if (_config.locate) { - BarcodeLocator.checkImageConstraints(_inputStream, _config.locator); - } + BarcodeLocator.checkImageConstraints(_inputStream, _config.locator); initCanvas(); _framegrabber = FrameGrabber.create(_inputStream, _canvasContainer.dom.image); initConfig(); @@ -10101,10 +10184,10 @@ function(Code128Reader, console.log(_inputImageWrapper.size); _boxSize = [ - vec2.clone([20, _inputImageWrapper.size.y / 2 - 100]), - vec2.clone([20, _inputImageWrapper.size.y / 2 + 100]), - vec2.clone([_inputImageWrapper.size.x - 20, _inputImageWrapper.size.y / 2 + 100]), - vec2.clone([_inputImageWrapper.size.x - 20, _inputImageWrapper.size.y / 2 - 100]) + vec2.clone([0, 0]), + vec2.clone([0, _inputImageWrapper.size.y]), + vec2.clone([_inputImageWrapper.size.x, _inputImageWrapper.size.y]), + vec2.clone([_inputImageWrapper.size.x, 0]) ]; BarcodeLocator.init(_inputImageWrapper, _config.locator); } @@ -10113,7 +10196,11 @@ function(Code128Reader, if (_config.locate) { return BarcodeLocator.locate(); } else { - return [_boxSize]; + return [[ + vec2.clone(_boxSize[0]), + vec2.clone(_boxSize[1]), + vec2.clone(_boxSize[2]), + vec2.clone(_boxSize[3])]]; } } @@ -10154,10 +10241,16 @@ function(Code128Reader, } } - function publishResult(result) { + function publishResult(result, imageData) { if (_onUIThread) { transformResult(result); + if (imageData && result && result.codeResult) { + if (_resultCollector) { + _resultCollector.addResult(imageData, _inputStream.getCanvasSize(), result.codeResult); + } + } } + Events.publish("processed", result); if (result && result.codeResult) { Events.publish("detected", result); @@ -10173,7 +10266,7 @@ function(Code128Reader, result = _decoder.decodeFromBoundingBoxes(boxes); result = result || {}; result.boxes = boxes; - publishResult(result); + publishResult(result, _inputImageWrapper.data); } else { publishResult(); } @@ -10242,7 +10335,7 @@ function(Code128Reader, function initWorker(cb) { var blobURL, workerThread = { - worker: null, + worker: undefined, imageData: new Uint8Array(_inputStream.getWidth() * _inputStream.getHeight()), busy: true }; @@ -10260,7 +10353,7 @@ function(Code128Reader, } else if (e.data.event === 'processed') { workerThread.imageData = new Uint8Array(e.data.imageData); workerThread.busy = false; - publishResult(e.data.result); + publishResult(e.data.result, workerThread.imageData); } }; @@ -10375,6 +10468,11 @@ function(Code128Reader, setReaders: function(readers) { setReaders(readers); }, + registerResultCollector: function(resultCollector) { + if (resultCollector && typeof resultCollector.addResult === 'function') { + _resultCollector = resultCollector; + } + }, canvas : _canvasContainer, decodeSingle : function(config, resultCallback) { config = HtmlUtils.mergeObjects({ @@ -10402,7 +10500,8 @@ function(Code128Reader, Code128Reader : Code128Reader }, ImageWrapper: ImageWrapper, - ImageDebug: ImageDebug + ImageDebug: ImageDebug, + ResultCollector: ResultCollector }; }); diff --git a/dist/quagga.min.js b/dist/quagga.min.js index 1041972..783e8ad 100644 --- a/dist/quagga.min.js +++ b/dist/quagga.min.js @@ -1,9 +1,9 @@ -/*! quagga 2015-06-13 */ +/*! quagga 2015-07-10 */ !function(a,b){var c=b.toString();"undefined"!=typeof module?module.exports=b(c):a.Quagga=b(c)}(this,function(a){/** * @license almond 0.2.9 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved. * Available via the MIT or new BSD license. * see: http://github.com/jrburke/almond for details */ -var b,c,d;return function(a){function e(a,b){return u.call(a,b)}function f(a,b){var c,d,e,f,g,h,i,j,k,l,m,n=b&&b.split("/"),o=s.map,p=o&&o["*"]||{};if(a&&"."===a.charAt(0))if(b){for(n=n.slice(0,n.length-1),a=a.split("/"),g=a.length-1,s.nodeIdCompat&&w.test(a[g])&&(a[g]=a[g].replace(w,"")),a=n.concat(a),k=0;k0&&(a.splice(k-1,2),k-=2)}a=a.join("/")}else 0===a.indexOf("./")&&(a=a.substring(2));if((n||p)&&o){for(c=a.split("/"),k=c.length;k>0;k-=1){if(d=c.slice(0,k).join("/"),n)for(l=n.length;l>0;l-=1)if(e=o[n.slice(0,l).join("/")],e&&(e=e[d])){f=e,h=k;break}if(f)break;!i&&p&&p[d]&&(i=p[d],j=k)}!f&&i&&(f=i,h=j),f&&(c.splice(0,h,f),a=c.join("/"))}return a}function g(b,c){return function(){return n.apply(a,v.call(arguments,0).concat([b,c]))}}function h(a){return function(b){return f(b,a)}}function i(a){return function(b){q[a]=b}}function j(b){if(e(r,b)){var c=r[b];delete r[b],t[b]=!0,m.apply(a,c)}if(!e(q,b)&&!e(t,b))throw new Error("No "+b);return q[b]}function k(a){var b,c=a?a.indexOf("!"):-1;return c>-1&&(b=a.substring(0,c),a=a.substring(c+1,a.length)),[b,a]}function l(a){return function(){return s&&s.config&&s.config[a]||{}}}var m,n,o,p,q={},r={},s={},t={},u=Object.prototype.hasOwnProperty,v=[].slice,w=/\.js$/;o=function(a,b){var c,d=k(a),e=d[0];return a=d[1],e&&(e=f(e,b),c=j(e)),e?a=c&&c.normalize?c.normalize(a,h(b)):f(a,b):(a=f(a,b),d=k(a),e=d[0],a=d[1],e&&(c=j(e))),{f:e?e+"!"+a:a,n:a,pr:e,p:c}},p={require:function(a){return g(a)},exports:function(a){var b=q[a];return"undefined"!=typeof b?b:q[a]={}},module:function(a){return{id:a,uri:"",exports:q[a],config:l(a)}}},m=function(b,c,d,f){var h,k,l,m,n,s,u=[],v=typeof d;if(f=f||b,"undefined"===v||"function"===v){for(c=!c.length&&d.length?["require","exports","module"]:c,n=0;ng)return Number.MAX_VALUE;d+=e}return d/f},a.prototype._nextSet=function(a,b){var c;for(b=b||0,c=b;c1)for(c=0;cd?(j.start=c-g,j.end=c,j.counter=e,j):null;i++,e[i]=1,h=!h}}else for(e.push(0),c=g;ca?0:a,d=a;b>d;d++)if(this._row[d]!==c)return!1;return!0},a.DIRECTION={FORWARD:1,REVERSE:-1},a.Exception={StartNotFoundException:"Start-Info was not found!",CodeNotFoundException:"Code could not be found!",PatternNotFoundException:"Pattern could not be found!"},a}),d("code_128_reader",["./barcode_reader"],function(a){function b(){a.call(this)}var c={CODE_SHIFT:{value:98},CODE_C:{value:99},CODE_B:{value:100},CODE_A:{value:101},START_CODE_A:{value:103},START_CODE_B:{value:104},START_CODE_C:{value:105},STOP_CODE:{value:106},MODULO:{value:11},CODE_PATTERN:{value:[[2,1,2,2,2,2],[2,2,2,1,2,2],[2,2,2,2,2,1],[1,2,1,2,2,3],[1,2,1,3,2,2],[1,3,1,2,2,2],[1,2,2,2,1,3],[1,2,2,3,1,2],[1,3,2,2,1,2],[2,2,1,2,1,3],[2,2,1,3,1,2],[2,3,1,2,1,2],[1,1,2,2,3,2],[1,2,2,1,3,2],[1,2,2,2,3,1],[1,1,3,2,2,2],[1,2,3,1,2,2],[1,2,3,2,2,1],[2,2,3,2,1,1],[2,2,1,1,3,2],[2,2,1,2,3,1],[2,1,3,2,1,2],[2,2,3,1,1,2],[3,1,2,1,3,1],[3,1,1,2,2,2],[3,2,1,1,2,2],[3,2,1,2,2,1],[3,1,2,2,1,2],[3,2,2,1,1,2],[3,2,2,2,1,1],[2,1,2,1,2,3],[2,1,2,3,2,1],[2,3,2,1,2,1],[1,1,1,3,2,3],[1,3,1,1,2,3],[1,3,1,3,2,1],[1,1,2,3,1,3],[1,3,2,1,1,3],[1,3,2,3,1,1],[2,1,1,3,1,3],[2,3,1,1,1,3],[2,3,1,3,1,1],[1,1,2,1,3,3],[1,1,2,3,3,1],[1,3,2,1,3,1],[1,1,3,1,2,3],[1,1,3,3,2,1],[1,3,3,1,2,1],[3,1,3,1,2,1],[2,1,1,3,3,1],[2,3,1,1,3,1],[2,1,3,1,1,3],[2,1,3,3,1,1],[2,1,3,1,3,1],[3,1,1,1,2,3],[3,1,1,3,2,1],[3,3,1,1,2,1],[3,1,2,1,1,3],[3,1,2,3,1,1],[3,3,2,1,1,1],[3,1,4,1,1,1],[2,2,1,4,1,1],[4,3,1,1,1,1],[1,1,1,2,2,4],[1,1,1,4,2,2],[1,2,1,1,2,4],[1,2,1,4,2,1],[1,4,1,1,2,2],[1,4,1,2,2,1],[1,1,2,2,1,4],[1,1,2,4,1,2],[1,2,2,1,1,4],[1,2,2,4,1,1],[1,4,2,1,1,2],[1,4,2,2,1,1],[2,4,1,2,1,1],[2,2,1,1,1,4],[4,1,3,1,1,1],[2,4,1,1,1,2],[1,3,4,1,1,1],[1,1,1,2,4,2],[1,2,1,1,4,2],[1,2,1,2,4,1],[1,1,4,2,1,2],[1,2,4,1,1,2],[1,2,4,2,1,1],[4,1,1,2,1,2],[4,2,1,1,1,2],[4,2,1,2,1,1],[2,1,2,1,4,1],[2,1,4,1,2,1],[4,1,2,1,2,1],[1,1,1,1,4,3],[1,1,1,3,4,1],[1,3,1,1,4,1],[1,1,4,1,1,3],[1,1,4,3,1,1],[4,1,1,1,1,3],[4,1,1,3,1,1],[1,1,3,1,4,1],[1,1,4,1,3,1],[3,1,1,1,4,1],[4,1,1,1,3,1],[2,1,1,4,1,2],[2,1,1,2,1,4],[2,1,1,2,3,2],[2,3,3,1,1,1,2]]},SINGLE_CODE_ERROR:{value:1},AVG_CODE_ERROR:{value:.5}};return b.prototype=Object.create(a.prototype,c),b.prototype.constructor=b,b.prototype._decodeCode=function(a){var b,c,d,e,f=[0,0,0,0,0,0],g=this,h=a,i=!g._row[h],j=0,k={error:Number.MAX_VALUE,code:-1,start:a,end:a};for(b=h;bc;c++)f[c]=f[c+2];f[5]=0,f[6]=0,j--}else j++;f[j]=1,i=!i}return null},b.prototype._findStart=function(){var a,b,c,d,e,f,g=[0,0,0,0,0,0],h=this,i=h._nextSet(h._row),j=!1,k=0,l={error:Number.MAX_VALUE,code:-1,start:0,end:0};for(a=i;ad;d++)g[d]=g[d+2];g[4]=0,g[5]=0,k--}else k++;g[k]=1,j=!j}return null},b.prototype._decode=function(){var a,b,c,d=this,e=d._findStart(),f=null,g=!1,h=[],i=0,j=0,k=[],l=[],m=!1;if(null===e)return null;switch(f={code:e.code,start:e.start,end:e.end},l.push(f),j=f.code,f.code){case d.START_CODE_A:a=d.CODE_A;break;case d.START_CODE_B:a=d.CODE_B;break;case d.START_CODE_C:a=d.CODE_C;break;default:return null}for(;!g;){if(b=m,m=!1,f=d._decodeCode(f.end),null!==f)switch(f.code!==d.STOP_CODE&&(k.push(f.code),i++,j+=i*f.code),l.push(f),a){case d.CODE_A:if(f.code<64)h.push(String.fromCharCode(32+f.code));else if(f.code<96)h.push(String.fromCharCode(f.code-64));else switch(f.code){case d.CODE_SHIFT:m=!0,a=d.CODE_B;break;case d.CODE_B:a=d.CODE_B;break;case d.CODE_C:a=d.CODE_C;break;case d.STOP_CODE:g=!0}break;case d.CODE_B:if(f.code<96)h.push(String.fromCharCode(32+f.code));else switch(f.code!=d.STOP_CODE&&(c=!1),f.code){case d.CODE_SHIFT:m=!0,a=d.CODE_A;break;case d.CODE_A:a=d.CODE_A;break;case d.CODE_C:a=d.CODE_C;break;case d.STOP_CODE:g=!0}break;case d.CODE_C:switch(f.code<100&&h.push(f.code<10?"0"+f.code:f.code),f.code){case d.CODE_A:a=d.CODE_A;break;case d.CODE_B:a=d.CODE_B;break;case d.STOP_CODE:g=!0}}else g=!0;b&&(a=a==d.CODE_A?d.CODE_B:d.CODE_A)}return null===f?null:(f.end=d._nextUnset(d._row,f.end),f.end===d._row.length?null:(j-=i*k[k.length-1],j%103!=k[k.length-1]?null:(h.splice(h.length-1,1),{code:h.join(""),start:e.start,end:f.end,codeset:a,startInfo:e,decodedCodes:l,endInfo:f})))},b}),d("ean_reader",["./barcode_reader"],function(a){function b(b){a.call(this,b)}var c={CODE_L_START:{value:0},MODULO:{value:7},CODE_G_START:{value:10},START_PATTERN:{value:[1/3*7,1/3*7,1/3*7]},STOP_PATTERN:{value:[1/3*7,1/3*7,1/3*7]},MIDDLE_PATTERN:{value:[.2*7,.2*7,.2*7,.2*7,.2*7]},CODE_PATTERN:{value:[[3,2,1,1],[2,2,2,1],[2,1,2,2],[1,4,1,1],[1,1,3,2],[1,2,3,1],[1,1,1,4],[1,3,1,2],[1,2,1,3],[3,1,1,2],[1,1,2,3],[1,2,2,2],[2,2,1,2],[1,1,4,1],[2,3,1,1],[1,3,2,1],[4,1,1,1],[2,1,3,1],[3,1,2,1],[2,1,1,3]]},CODE_FREQUENCY:{value:[0,11,13,14,19,25,28,21,22,26]},SINGLE_CODE_ERROR:{value:.7},AVG_CODE_ERROR:{value:.3}};return b.prototype=Object.create(a.prototype,c),b.prototype.constructor=b,b.prototype._decodeCode=function(a,b){var c,d,e,f,g=[0,0,0,0],h=this,i=a,j=!h._row[i],k=0,l={error:Number.MAX_VALUE,code:-1,start:a,end:a};for(b||(b=h.CODE_PATTERN.length),c=i;cd;d++)e=h._matchPattern(f,h.CODE_PATTERN[d]),eh.AVG_CODE_ERROR?null:l}k++,g[k]=1,j=!j}return null},b.prototype._findPattern=function(a,b,c,d,e){var f,g,h,i,j,k=[],l=this,m=0,n={error:Number.MAX_VALUE,code:-1,start:0,end:0};for(b||(b=l._nextSet(l._row)),void 0===c&&(c=!1),void 0===d&&(d=!0),void 0===e&&(e=l.AVG_CODE_ERROR),f=0;fg)return n.error=g,n.start=f-i,n.end=f,n;if(!d)return null;for(h=0;h=0&&c._matchRange(a,b.start,0))return b;d=b.end,b=null}},b.prototype._verifyTrailingWhitespace=function(a){var b,c=this;return b=a.end+(a.end-a.start),bd;d++){if(a=f._decodeCode(a.end),!a)return null;a.code>=f.CODE_G_START?(a.code=a.code-f.CODE_G_START,g|=1<<5-d):g|=0<<5-d,b.push(a.code),c.push(a)}if(e=f._calculateFirstDigit(g),null===e)return null;if(b.unshift(e),a=f._findPattern(f.MIDDLE_PATTERN,a.end,!0,!1),null===a)return null;for(c.push(a),d=0;6>d;d++){if(a=f._decodeCode(a.end,f.CODE_G_START),!a)return null;c.push(a),b.push(a.code)}return a},b.prototype._decode=function(){var a,b,c=this,d=[],e=[];return(a=c._findStart())?(b={code:a.code,start:a.start,end:a.end},e.push(b),(b=c._decodePayload(b,d,e))&&(b=c._findEnd(b.end,!1))?(e.push(b),c._checksum(d)?{code:d.join(""),start:a.start,end:b.end,codeset:"",startInfo:a,decodedCodes:e}:null):null):null},b.prototype._checksum=function(a){var b,c=0;for(b=a.length-2;b>=0;b-=2)c+=a[b];for(c*=3,b=a.length-1;b>=0;b-=2)c+=a[b];return c%10===0},b}),d("image_loader",[],function(){function a(a,b){a.onload=function(){b.loaded(this)}}var b={};return b.load=function(b,c,d,e,f){var g,h,i,j=new Array(e),k=new Array(j.length);if(f===!1)j[0]=b;else for(g=0;g1?f.size:Math.floor(b/e*f.size):b,d=f.size?b/e>1?Math.floor(e/b*f.size):f.size:e,j.x=c,j.y=d}var c,d,e={},f=null,g=["canrecord","ended"],h={},i={x:0,y:0},j={x:0,y:0};return e.getRealWidth=function(){return a.videoWidth},e.getRealHeight=function(){return a.videoHeight},e.getWidth=function(){return c},e.getHeight=function(){return d},e.setWidth=function(a){c=a},e.setHeight=function(a){d=a},e.setInputStream=function(b){f=b,a.src="undefined"!=typeof b.src?b.src:""},e.ended=function(){return a.ended},e.getConfig=function(){return f},e.setAttribute=function(b,c){a.setAttribute(b,c)},e.pause=function(){a.pause()},e.play=function(){a.play()},e.setCurrentTime=function(b){"LiveStream"!==f.type&&(a.currentTime=b)},e.addEventListener=function(b,c,d){-1!==g.indexOf(b)?(h[b]||(h[b]=[]),h[b].push(c)):a.addEventListener(b,c,d)},e.clearEventHandlers=function(){g.forEach(function(b){var c=h[b];c&&c.length>0&&c.forEach(function(c){a.removeEventListener(b,c)})})},e.trigger=function(a,c){var d,f=h[a];if("canrecord"===a&&b(),f&&f.length>0)for(d=0;d1?g.size:Math.floor(h/i*g.size):h,e=g.size?h/i>1?Math.floor(i/h*g.size):g.size:i,u.x=d,u.y=e,l=!0,j=0,setTimeout(function(){c("canrecord",[])},0)},o,n,g.sequence)}function c(a,b){var c,d=s[a];if(d&&d.length>0)for(c=0;cj?j++:setTimeout(function(){q=!0,c("ended",[])},0)),a):null},f},b}),glMatrixArrayType=Float32Array,"undefined"!=typeof window&&(window.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){window.setTimeout(a,1e3/60)}}(),navigator.getUserMedia=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia||navigator.msGetUserMedia,window.URL=window.URL||window.webkitURL||window.mozURL||window.msURL),d("typedefs",function(a){return function(){var b;return b||a.typedefs}}(this)),d("subImage",["typedefs"],function(){function a(a,b,c){c||(c={data:null,size:b}),this.data=c.data,this.originalSize=c.size,this.I=c,this.from=a,this.size=b}return a.prototype.show=function(a,b){var c,d,e,f,g,h,i;for(b||(b=1),c=a.getContext("2d"),a.width=this.size.x,a.height=this.size.y,d=c.getImageData(0,0,a.width,a.height),e=d.data,f=0,g=0;g0&&(e=1/Math.sqrt(e),a[0]=b[0]*e,a[1]=b[1]*e),a},e.dot=function(a,b){return a[0]*b[0]+a[1]*b[1]},e.cross=function(a,b,c){var d=b[0]*c[1]-b[1]*c[0];return a[0]=a[1]=0,a[2]=d,a},e.lerp=function(a,b,c,d){var e=b[0],f=b[1];return a[0]=e+d*(c[0]-e),a[1]=f+d*(c[1]-f),a},e.transformMat2=function(a,b,c){var d=b[0],e=b[1];return a[0]=c[0]*d+c[2]*e,a[1]=c[1]*d+c[3]*e,a},e.transformMat2d=function(a,b,c){var d=b[0],e=b[1];return a[0]=c[0]*d+c[2]*e+c[4],a[1]=c[1]*d+c[3]*e+c[5],a},e.transformMat3=function(a,b,c){var d=b[0],e=b[1];return a[0]=c[0]*d+c[3]*e+c[6],a[1]=c[1]*d+c[4]*e+c[7],a},e.transformMat4=function(a,b,c){var d=b[0],e=b[1];return a[0]=c[0]*d+c[4]*e+c[12],a[1]=c[1]*d+c[5]*e+c[13],a},e.forEach=function(){var a=e.create();return function(b,c,d,e,f,g){var h,i;for(c||(c=2),d||(d=0),i=e?Math.min(e*c+d,b.length):b.length,h=d;i>h;h+=c)a[0]=b[h],a[1]=b[h+1],f(a,a,g),b[h]=a[0],b[h+1]=a[1];return b}}(),e.str=function(a){return"vec2("+a[0]+", "+a[1]+")"},"undefined"!=typeof a&&(a.vec2=e);var f={};f.create=function(){var a=new c(3);return a[0]=0,a[1]=0,a[2]=0,a},f.clone=function(a){var b=new c(3);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b},f.fromValues=function(a,b,d){var e=new c(3);return e[0]=a,e[1]=b,e[2]=d,e},f.copy=function(a,b){return a[0]=b[0],a[1]=b[1],a[2]=b[2],a},f.set=function(a,b,c,d){return a[0]=b,a[1]=c,a[2]=d,a},f.add=function(a,b,c){return a[0]=b[0]+c[0],a[1]=b[1]+c[1],a[2]=b[2]+c[2],a},f.subtract=function(a,b,c){return a[0]=b[0]-c[0],a[1]=b[1]-c[1],a[2]=b[2]-c[2],a},f.sub=f.subtract,f.multiply=function(a,b,c){return a[0]=b[0]*c[0],a[1]=b[1]*c[1],a[2]=b[2]*c[2],a},f.mul=f.multiply,f.divide=function(a,b,c){return a[0]=b[0]/c[0],a[1]=b[1]/c[1],a[2]=b[2]/c[2],a},f.div=f.divide,f.min=function(a,b,c){return a[0]=Math.min(b[0],c[0]),a[1]=Math.min(b[1],c[1]),a[2]=Math.min(b[2],c[2]),a},f.max=function(a,b,c){return a[0]=Math.max(b[0],c[0]),a[1]=Math.max(b[1],c[1]),a[2]=Math.max(b[2],c[2]),a},f.scale=function(a,b,c){return a[0]=b[0]*c,a[1]=b[1]*c,a[2]=b[2]*c,a},f.distance=function(a,b){var c=b[0]-a[0],d=b[1]-a[1],e=b[2]-a[2];return Math.sqrt(c*c+d*d+e*e)},f.dist=f.distance,f.squaredDistance=function(a,b){var c=b[0]-a[0],d=b[1]-a[1],e=b[2]-a[2];return c*c+d*d+e*e},f.sqrDist=f.squaredDistance,f.length=function(a){var b=a[0],c=a[1],d=a[2];return Math.sqrt(b*b+c*c+d*d)},f.len=f.length,f.squaredLength=function(a){var b=a[0],c=a[1],d=a[2];return b*b+c*c+d*d},f.sqrLen=f.squaredLength,f.negate=function(a,b){return a[0]=-b[0],a[1]=-b[1],a[2]=-b[2],a},f.normalize=function(a,b){var c=b[0],d=b[1],e=b[2],f=c*c+d*d+e*e;return f>0&&(f=1/Math.sqrt(f),a[0]=b[0]*f,a[1]=b[1]*f,a[2]=b[2]*f),a},f.dot=function(a,b){return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]},f.cross=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=c[0],h=c[1],i=c[2];return a[0]=e*i-f*h,a[1]=f*g-d*i,a[2]=d*h-e*g,a},f.lerp=function(a,b,c,d){var e=b[0],f=b[1],g=b[2];return a[0]=e+d*(c[0]-e),a[1]=f+d*(c[1]-f),a[2]=g+d*(c[2]-g),a},f.transformMat4=function(a,b,c){var d=b[0],e=b[1],f=b[2];return a[0]=c[0]*d+c[4]*e+c[8]*f+c[12],a[1]=c[1]*d+c[5]*e+c[9]*f+c[13],a[2]=c[2]*d+c[6]*e+c[10]*f+c[14],a},f.transformQuat=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=c[0],h=c[1],i=c[2],j=c[3],k=j*d+h*f-i*e,l=j*e+i*d-g*f,m=j*f+g*e-h*d,n=-g*d-h*e-i*f;return a[0]=k*j+n*-g+l*-i-m*-h,a[1]=l*j+n*-h+m*-g-k*-i,a[2]=m*j+n*-i+k*-h-l*-g,a},f.forEach=function(){var a=f.create();return function(b,c,d,e,f,g){var h,i;for(c||(c=3),d||(d=0),i=e?Math.min(e*c+d,b.length):b.length,h=d;i>h;h+=c)a[0]=b[h],a[1]=b[h+1],a[2]=b[h+2],f(a,a,g),b[h]=a[0],b[h+1]=a[1],b[h+2]=a[2];return b}}(),f.str=function(a){return"vec3("+a[0]+", "+a[1]+", "+a[2]+")"},"undefined"!=typeof a&&(a.vec3=f);var g={};g.create=function(){var a=new c(4);return a[0]=0,a[1]=0,a[2]=0,a[3]=0,a},g.clone=function(a){var b=new c(4);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b},g.fromValues=function(a,b,d,e){var f=new c(4);return f[0]=a,f[1]=b,f[2]=d,f[3]=e,f},g.copy=function(a,b){return a[0]=b[0],a[1]=b[1],a[2]=b[2],a[3]=b[3],a},g.set=function(a,b,c,d,e){return a[0]=b,a[1]=c,a[2]=d,a[3]=e,a},g.add=function(a,b,c){return a[0]=b[0]+c[0],a[1]=b[1]+c[1],a[2]=b[2]+c[2],a[3]=b[3]+c[3],a},g.subtract=function(a,b,c){return a[0]=b[0]-c[0],a[1]=b[1]-c[1],a[2]=b[2]-c[2],a[3]=b[3]-c[3],a},g.sub=g.subtract,g.multiply=function(a,b,c){return a[0]=b[0]*c[0],a[1]=b[1]*c[1],a[2]=b[2]*c[2],a[3]=b[3]*c[3],a},g.mul=g.multiply,g.divide=function(a,b,c){return a[0]=b[0]/c[0],a[1]=b[1]/c[1],a[2]=b[2]/c[2],a[3]=b[3]/c[3],a},g.div=g.divide,g.min=function(a,b,c){return a[0]=Math.min(b[0],c[0]),a[1]=Math.min(b[1],c[1]),a[2]=Math.min(b[2],c[2]),a[3]=Math.min(b[3],c[3]),a},g.max=function(a,b,c){return a[0]=Math.max(b[0],c[0]),a[1]=Math.max(b[1],c[1]),a[2]=Math.max(b[2],c[2]),a[3]=Math.max(b[3],c[3]),a},g.scale=function(a,b,c){return a[0]=b[0]*c,a[1]=b[1]*c,a[2]=b[2]*c,a[3]=b[3]*c,a},g.distance=function(a,b){var c=b[0]-a[0],d=b[1]-a[1],e=b[2]-a[2],f=b[3]-a[3];return Math.sqrt(c*c+d*d+e*e+f*f)},g.dist=g.distance,g.squaredDistance=function(a,b){var c=b[0]-a[0],d=b[1]-a[1],e=b[2]-a[2],f=b[3]-a[3];return c*c+d*d+e*e+f*f},g.sqrDist=g.squaredDistance,g.length=function(a){var b=a[0],c=a[1],d=a[2],e=a[3];return Math.sqrt(b*b+c*c+d*d+e*e)},g.len=g.length,g.squaredLength=function(a){var b=a[0],c=a[1],d=a[2],e=a[3];return b*b+c*c+d*d+e*e},g.sqrLen=g.squaredLength,g.negate=function(a,b){return a[0]=-b[0],a[1]=-b[1],a[2]=-b[2],a[3]=-b[3],a},g.normalize=function(a,b){var c=b[0],d=b[1],e=b[2],f=b[3],g=c*c+d*d+e*e+f*f;return g>0&&(g=1/Math.sqrt(g),a[0]=b[0]*g,a[1]=b[1]*g,a[2]=b[2]*g,a[3]=b[3]*g),a},g.dot=function(a,b){return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+a[3]*b[3]},g.lerp=function(a,b,c,d){var e=b[0],f=b[1],g=b[2],h=b[3];return a[0]=e+d*(c[0]-e),a[1]=f+d*(c[1]-f),a[2]=g+d*(c[2]-g),a[3]=h+d*(c[3]-h),a},g.transformMat4=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=b[3];return a[0]=c[0]*d+c[4]*e+c[8]*f+c[12]*g,a[1]=c[1]*d+c[5]*e+c[9]*f+c[13]*g,a[2]=c[2]*d+c[6]*e+c[10]*f+c[14]*g,a[3]=c[3]*d+c[7]*e+c[11]*f+c[15]*g,a},g.transformQuat=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=c[0],h=c[1],i=c[2],j=c[3],k=j*d+h*f-i*e,l=j*e+i*d-g*f,m=j*f+g*e-h*d,n=-g*d-h*e-i*f;return a[0]=k*j+n*-g+l*-i-m*-h,a[1]=l*j+n*-h+m*-g-k*-i,a[2]=m*j+n*-i+k*-h-l*-g,a},g.forEach=function(){var a=g.create();return function(b,c,d,e,f,g){var h,i;for(c||(c=4),d||(d=0),i=e?Math.min(e*c+d,b.length):b.length,h=d;i>h;h+=c)a[0]=b[h],a[1]=b[h+1],a[2]=b[h+2],a[3]=b[h+3],f(a,a,g),b[h]=a[0],b[h+1]=a[1],b[h+2]=a[2],b[h+3]=a[3];return b}}(),g.str=function(a){return"vec4("+a[0]+", "+a[1]+", "+a[2]+", "+a[3]+")"},"undefined"!=typeof a&&(a.vec4=g);{var h={};new Float32Array([1,0,0,1])}h.create=function(){var a=new c(4);return a[0]=1,a[1]=0,a[2]=0,a[3]=1,a},h.clone=function(a){var b=new c(4);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b},h.copy=function(a,b){return a[0]=b[0],a[1]=b[1],a[2]=b[2],a[3]=b[3],a},h.identity=function(a){return a[0]=1,a[1]=0,a[2]=0,a[3]=1,a},h.transpose=function(a,b){if(a===b){var c=b[1];a[1]=b[2],a[2]=c}else a[0]=b[0],a[1]=b[2],a[2]=b[1],a[3]=b[3];return a},h.invert=function(a,b){var c=b[0],d=b[1],e=b[2],f=b[3],g=c*f-e*d;return g?(g=1/g,a[0]=f*g,a[1]=-d*g,a[2]=-e*g,a[3]=c*g,a):null},h.adjoint=function(a,b){var c=b[0];return a[0]=b[3],a[1]=-b[1],a[2]=-b[2],a[3]=c,a},h.determinant=function(a){return a[0]*a[3]-a[2]*a[1]},h.multiply=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=b[3],h=c[0],i=c[1],j=c[2],k=c[3];return a[0]=d*h+e*j,a[1]=d*i+e*k,a[2]=f*h+g*j,a[3]=f*i+g*k,a},h.mul=h.multiply,h.rotate=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=b[3],h=Math.sin(c),i=Math.cos(c);return a[0]=d*i+e*h,a[1]=d*-h+e*i,a[2]=f*i+g*h,a[3]=f*-h+g*i,a},h.scale=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=b[3],h=c[0],i=c[1];return a[0]=d*h,a[1]=e*i,a[2]=f*h,a[3]=g*i,a},h.str=function(a){return"mat2("+a[0]+", "+a[1]+", "+a[2]+", "+a[3]+")"},"undefined"!=typeof a&&(a.mat2=h);{var i={};new Float32Array([1,0,0,1,0,0])}i.create=function(){var a=new c(6);return a[0]=1,a[1]=0,a[2]=0,a[3]=1,a[4]=0,a[5]=0,a},i.clone=function(a){var b=new c(6);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b},i.copy=function(a,b){return a[0]=b[0],a[1]=b[1],a[2]=b[2],a[3]=b[3],a[4]=b[4],a[5]=b[5],a},i.identity=function(a){return a[0]=1,a[1]=0,a[2]=0,a[3]=1,a[4]=0,a[5]=0,a},i.invert=function(a,b){var c=b[0],d=b[1],e=b[2],f=b[3],g=b[4],h=b[5],i=c*f-d*e;return i?(i=1/i,a[0]=f*i,a[1]=-d*i,a[2]=-e*i,a[3]=c*i,a[4]=(e*h-f*g)*i,a[5]=(d*g-c*h)*i,a):null},i.determinant=function(a){return a[0]*a[3]-a[1]*a[2]},i.multiply=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=b[3],h=b[4],i=b[5],j=c[0],k=c[1],l=c[2],m=c[3],n=c[4],o=c[5];return a[0]=d*j+e*l,a[1]=d*k+e*m,a[2]=f*j+g*l,a[3]=f*k+g*m,a[4]=j*h+l*i+n,a[5]=k*h+m*i+o,a},i.mul=i.multiply,i.rotate=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=b[3],h=b[4],i=b[5],j=Math.sin(c),k=Math.cos(c);return a[0]=d*k+e*j,a[1]=-d*j+e*k,a[2]=f*k+g*j,a[3]=-f*j+k*g,a[4]=k*h+j*i,a[5]=k*i-j*h,a},i.scale=function(a,b,c){var d=c[0],e=c[1];return a[0]=b[0]*d,a[1]=b[1]*e,a[2]=b[2]*d,a[3]=b[3]*e,a[4]=b[4]*d,a[5]=b[5]*e,a},i.translate=function(a,b,c){return a[0]=b[0],a[1]=b[1],a[2]=b[2],a[3]=b[3],a[4]=b[4]+c[0],a[5]=b[5]+c[1],a},i.str=function(a){return"mat2d("+a[0]+", "+a[1]+", "+a[2]+", "+a[3]+", "+a[4]+", "+a[5]+")"},"undefined"!=typeof a&&(a.mat2d=i);{var j={};new Float32Array([1,0,0,0,1,0,0,0,1])}j.create=function(){var a=new c(9);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},j.clone=function(a){var b=new c(9);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b[6]=a[6],b[7]=a[7],b[8]=a[8],b},j.copy=function(a,b){return a[0]=b[0],a[1]=b[1],a[2]=b[2],a[3]=b[3],a[4]=b[4],a[5]=b[5],a[6]=b[6],a[7]=b[7],a[8]=b[8],a},j.identity=function(a){return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},j.transpose=function(a,b){if(a===b){var c=b[1],d=b[2],e=b[5];a[1]=b[3],a[2]=b[6],a[3]=c,a[5]=b[7],a[6]=d,a[7]=e}else a[0]=b[0],a[1]=b[3],a[2]=b[6],a[3]=b[1],a[4]=b[4],a[5]=b[7],a[6]=b[2],a[7]=b[5],a[8]=b[8];return a},j.invert=function(a,b){var c=b[0],d=b[1],e=b[2],f=b[3],g=b[4],h=b[5],i=b[6],j=b[7],k=b[8],l=k*g-h*j,m=-k*f+h*i,n=j*f-g*i,o=c*l+d*m+e*n;return o?(o=1/o,a[0]=l*o,a[1]=(-k*d+e*j)*o,a[2]=(h*d-e*g)*o,a[3]=m*o,a[4]=(k*c-e*i)*o,a[5]=(-h*c+e*f)*o,a[6]=n*o,a[7]=(-j*c+d*i)*o,a[8]=(g*c-d*f)*o,a):null},j.adjoint=function(a,b){var c=b[0],d=b[1],e=b[2],f=b[3],g=b[4],h=b[5],i=b[6],j=b[7],k=b[8];return a[0]=g*k-h*j,a[1]=e*j-d*k,a[2]=d*h-e*g,a[3]=h*i-f*k,a[4]=c*k-e*i,a[5]=e*f-c*h,a[6]=f*j-g*i,a[7]=d*i-c*j,a[8]=c*g-d*f,a},j.determinant=function(a){var b=a[0],c=a[1],d=a[2],e=a[3],f=a[4],g=a[5],h=a[6],i=a[7],j=a[8];return b*(j*f-g*i)+c*(-j*e+g*h)+d*(i*e-f*h)},j.multiply=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=b[3],h=b[4],i=b[5],j=b[6],k=b[7],l=b[8],m=c[0],n=c[1],o=c[2],p=c[3],q=c[4],r=c[5],s=c[6],t=c[7],u=c[8];return a[0]=m*d+n*g+o*j,a[1]=m*e+n*h+o*k,a[2]=m*f+n*i+o*l,a[3]=p*d+q*g+r*j,a[4]=p*e+q*h+r*k,a[5]=p*f+q*i+r*l,a[6]=s*d+t*g+u*j,a[7]=s*e+t*h+u*k,a[8]=s*f+t*i+u*l,a},j.mul=j.multiply,j.translate=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=b[3],h=b[4],i=b[5],j=b[6],k=b[7],l=b[8],m=c[0],n=c[1];return a[0]=d,a[1]=e,a[2]=f,a[3]=g,a[4]=h,a[5]=i,a[6]=m*d+n*g+j,a[7]=m*e+n*h+k,a[8]=m*f+n*i+l,a},j.rotate=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=b[3],h=b[4],i=b[5],j=b[6],k=b[7],l=b[8],m=Math.sin(c),n=Math.cos(c);return a[0]=n*d+m*g,a[1]=n*e+m*h,a[2]=n*f+m*i,a[3]=n*g-m*d,a[4]=n*h-m*e,a[5]=n*i-m*f,a[6]=j,a[7]=k,a[8]=l,a},j.scale=function(a,b,c){var d=c[0],e=c[2];return a[0]=d*b[0],a[1]=d*b[1],a[2]=d*b[2],a[3]=e*b[3],a[4]=e*b[4],a[5]=e*b[5],a[6]=b[6],a[7]=b[7],a[8]=b[8],a},j.fromMat2d=function(a,b){return a[0]=b[0],a[1]=b[1],a[2]=0,a[3]=b[2],a[4]=b[3],a[5]=0,a[6]=b[4],a[7]=b[5],a[8]=1,a},j.fromQuat=function(a,b){var c=b[0],d=b[1],e=b[2],f=b[3],g=c+c,h=d+d,i=e+e,j=c*g,k=c*h,l=c*i,m=d*h,n=d*i,o=e*i,p=f*g,q=f*h,r=f*i;return a[0]=1-(m+o),a[1]=k+r,a[2]=l-q,a[3]=k-r,a[4]=1-(j+o),a[5]=n+p,a[6]=l+q,a[7]=n-p,a[8]=1-(j+m),a},j.str=function(a){return"mat3("+a[0]+", "+a[1]+", "+a[2]+", "+a[3]+", "+a[4]+", "+a[5]+", "+a[6]+", "+a[7]+", "+a[8]+")"},"undefined"!=typeof a&&(a.mat3=j);{var k={};new Float32Array([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1])}k.create=function(){var a=new c(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},k.clone=function(a){var b=new c(16);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b[6]=a[6],b[7]=a[7],b[8]=a[8],b[9]=a[9],b[10]=a[10],b[11]=a[11],b[12]=a[12],b[13]=a[13],b[14]=a[14],b[15]=a[15],b},k.copy=function(a,b){return a[0]=b[0],a[1]=b[1],a[2]=b[2],a[3]=b[3],a[4]=b[4],a[5]=b[5],a[6]=b[6],a[7]=b[7],a[8]=b[8],a[9]=b[9],a[10]=b[10],a[11]=b[11],a[12]=b[12],a[13]=b[13],a[14]=b[14],a[15]=b[15],a},k.identity=function(a){return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},k.transpose=function(a,b){if(a===b){var c=b[1],d=b[2],e=b[3],f=b[6],g=b[7],h=b[11];a[1]=b[4],a[2]=b[8],a[3]=b[12],a[4]=c,a[6]=b[9],a[7]=b[13],a[8]=d,a[9]=f,a[11]=b[14],a[12]=e,a[13]=g,a[14]=h -}else a[0]=b[0],a[1]=b[4],a[2]=b[8],a[3]=b[12],a[4]=b[1],a[5]=b[5],a[6]=b[9],a[7]=b[13],a[8]=b[2],a[9]=b[6],a[10]=b[10],a[11]=b[14],a[12]=b[3],a[13]=b[7],a[14]=b[11],a[15]=b[15];return a},k.invert=function(a,b){var c=b[0],d=b[1],e=b[2],f=b[3],g=b[4],h=b[5],i=b[6],j=b[7],k=b[8],l=b[9],m=b[10],n=b[11],o=b[12],p=b[13],q=b[14],r=b[15],s=c*h-d*g,t=c*i-e*g,u=c*j-f*g,v=d*i-e*h,w=d*j-f*h,x=e*j-f*i,y=k*p-l*o,z=k*q-m*o,A=k*r-n*o,B=l*q-m*p,C=l*r-n*p,D=m*r-n*q,E=s*D-t*C+u*B+v*A-w*z+x*y;return E?(E=1/E,a[0]=(h*D-i*C+j*B)*E,a[1]=(e*C-d*D-f*B)*E,a[2]=(p*x-q*w+r*v)*E,a[3]=(m*w-l*x-n*v)*E,a[4]=(i*A-g*D-j*z)*E,a[5]=(c*D-e*A+f*z)*E,a[6]=(q*u-o*x-r*t)*E,a[7]=(k*x-m*u+n*t)*E,a[8]=(g*C-h*A+j*y)*E,a[9]=(d*A-c*C-f*y)*E,a[10]=(o*w-p*u+r*s)*E,a[11]=(l*u-k*w-n*s)*E,a[12]=(h*z-g*B-i*y)*E,a[13]=(c*B-d*z+e*y)*E,a[14]=(p*t-o*v-q*s)*E,a[15]=(k*v-l*t+m*s)*E,a):null},k.adjoint=function(a,b){var c=b[0],d=b[1],e=b[2],f=b[3],g=b[4],h=b[5],i=b[6],j=b[7],k=b[8],l=b[9],m=b[10],n=b[11],o=b[12],p=b[13],q=b[14],r=b[15];return a[0]=h*(m*r-n*q)-l*(i*r-j*q)+p*(i*n-j*m),a[1]=-(d*(m*r-n*q)-l*(e*r-f*q)+p*(e*n-f*m)),a[2]=d*(i*r-j*q)-h*(e*r-f*q)+p*(e*j-f*i),a[3]=-(d*(i*n-j*m)-h*(e*n-f*m)+l*(e*j-f*i)),a[4]=-(g*(m*r-n*q)-k*(i*r-j*q)+o*(i*n-j*m)),a[5]=c*(m*r-n*q)-k*(e*r-f*q)+o*(e*n-f*m),a[6]=-(c*(i*r-j*q)-g*(e*r-f*q)+o*(e*j-f*i)),a[7]=c*(i*n-j*m)-g*(e*n-f*m)+k*(e*j-f*i),a[8]=g*(l*r-n*p)-k*(h*r-j*p)+o*(h*n-j*l),a[9]=-(c*(l*r-n*p)-k*(d*r-f*p)+o*(d*n-f*l)),a[10]=c*(h*r-j*p)-g*(d*r-f*p)+o*(d*j-f*h),a[11]=-(c*(h*n-j*l)-g*(d*n-f*l)+k*(d*j-f*h)),a[12]=-(g*(l*q-m*p)-k*(h*q-i*p)+o*(h*m-i*l)),a[13]=c*(l*q-m*p)-k*(d*q-e*p)+o*(d*m-e*l),a[14]=-(c*(h*q-i*p)-g*(d*q-e*p)+o*(d*i-e*h)),a[15]=c*(h*m-i*l)-g*(d*m-e*l)+k*(d*i-e*h),a},k.determinant=function(a){var b=a[0],c=a[1],d=a[2],e=a[3],f=a[4],g=a[5],h=a[6],i=a[7],j=a[8],k=a[9],l=a[10],m=a[11],n=a[12],o=a[13],p=a[14],q=a[15],r=b*g-c*f,s=b*h-d*f,t=b*i-e*f,u=c*h-d*g,v=c*i-e*g,w=d*i-e*h,x=j*o-k*n,y=j*p-l*n,z=j*q-m*n,A=k*p-l*o,B=k*q-m*o,C=l*q-m*p;return r*C-s*B+t*A+u*z-v*y+w*x},k.multiply=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=b[3],h=b[4],i=b[5],j=b[6],k=b[7],l=b[8],m=b[9],n=b[10],o=b[11],p=b[12],q=b[13],r=b[14],s=b[15],t=c[0],u=c[1],v=c[2],w=c[3];return a[0]=t*d+u*h+v*l+w*p,a[1]=t*e+u*i+v*m+w*q,a[2]=t*f+u*j+v*n+w*r,a[3]=t*g+u*k+v*o+w*s,t=c[4],u=c[5],v=c[6],w=c[7],a[4]=t*d+u*h+v*l+w*p,a[5]=t*e+u*i+v*m+w*q,a[6]=t*f+u*j+v*n+w*r,a[7]=t*g+u*k+v*o+w*s,t=c[8],u=c[9],v=c[10],w=c[11],a[8]=t*d+u*h+v*l+w*p,a[9]=t*e+u*i+v*m+w*q,a[10]=t*f+u*j+v*n+w*r,a[11]=t*g+u*k+v*o+w*s,t=c[12],u=c[13],v=c[14],w=c[15],a[12]=t*d+u*h+v*l+w*p,a[13]=t*e+u*i+v*m+w*q,a[14]=t*f+u*j+v*n+w*r,a[15]=t*g+u*k+v*o+w*s,a},k.mul=k.multiply,k.translate=function(a,b,c){var d,e,f,g,h,i,j,k,l,m,n,o,p=c[0],q=c[1],r=c[2];return b===a?(a[12]=b[0]*p+b[4]*q+b[8]*r+b[12],a[13]=b[1]*p+b[5]*q+b[9]*r+b[13],a[14]=b[2]*p+b[6]*q+b[10]*r+b[14],a[15]=b[3]*p+b[7]*q+b[11]*r+b[15]):(d=b[0],e=b[1],f=b[2],g=b[3],h=b[4],i=b[5],j=b[6],k=b[7],l=b[8],m=b[9],n=b[10],o=b[11],a[0]=d,a[1]=e,a[2]=f,a[3]=g,a[4]=h,a[5]=i,a[6]=j,a[7]=k,a[8]=l,a[9]=m,a[10]=n,a[11]=o,a[12]=d*p+h*q+l*r+b[12],a[13]=e*p+i*q+m*r+b[13],a[14]=f*p+j*q+n*r+b[14],a[15]=g*p+k*q+o*r+b[15]),a},k.scale=function(a,b,c){var d=c[0],e=c[1],f=c[2];return a[0]=b[0]*d,a[1]=b[1]*d,a[2]=b[2]*d,a[3]=b[3]*d,a[4]=b[4]*e,a[5]=b[5]*e,a[6]=b[6]*e,a[7]=b[7]*e,a[8]=b[8]*f,a[9]=b[9]*f,a[10]=b[10]*f,a[11]=b[11]*f,a[12]=b[12],a[13]=b[13],a[14]=b[14],a[15]=b[15],a},k.rotate=function(a,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D=e[0],E=e[1],F=e[2],G=Math.sqrt(D*D+E*E+F*F);return Math.abs(G)=1?(a!==b&&(a[0]=i,a[1]=j,a[2]=k,a[3]=l),a):(e=Math.acos(q),f=Math.sqrt(1-q*q),Math.abs(f)<.001?(a[0]=.5*i+.5*m,a[1]=.5*j+.5*n,a[2]=.5*k+.5*o,a[3]=.5*l+.5*p,a):(g=Math.sin((1-d)*e)/f,h=Math.sin(d*e)/f,a[0]=i*g+m*h,a[1]=j*g+n*h,a[2]=k*g+o*h,a[3]=l*g+p*h,a))},l.invert=function(a,b){var c=b[0],d=b[1],e=b[2],f=b[3],g=c*c+d*d+e*e+f*f,h=g?1/g:0;return a[0]=-c*h,a[1]=-d*h,a[2]=-e*h,a[3]=f*h,a},l.conjugate=function(a,b){return a[0]=-b[0],a[1]=-b[1],a[2]=-b[2],a[3]=b[3],a},l.length=g.length,l.len=l.length,l.squaredLength=g.squaredLength,l.sqrLen=l.squaredLength,l.normalize=g.normalize,l.fromMat3=function(){var a=[1,2,0];return function(b,c){var d,e=c[0]+c[4]+c[8];if(e>0)d=Math.sqrt(e+1),b[3]=.5*d,d=.5/d,b[0]=(c[7]-c[5])*d,b[1]=(c[2]-c[6])*d,b[2]=(c[3]-c[1])*d;else{var f=0;c[4]>c[0]&&(f=1),c[8]>c[3*f+f]&&(f=2);var g=a[f],h=a[g];d=Math.sqrt(c[3*f+f]-c[3*g+g]-c[3*h+h]+1),b[f]=.5*d,d=.5/d,b[3]=(c[3*h+g]-c[3*g+h])*d,b[g]=(c[3*g+f]+c[3*f+g])*d,b[h]=(c[3*h+f]+c[3*f+h])*d}return b}}(),l.str=function(a){return"quat("+a[0]+", "+a[1]+", "+a[2]+", "+a[3]+")"},"undefined"!=typeof a&&(a.quat=l)}(a.exports)}(),d("cluster",["gl-matrix"],function(a){var b=a.vec2,c={create:function(a,c){function d(){e(a),f()}function e(a){i[a.id]=a,g.push(a)}function f(){var a,c=0;for(a=0;ac?!0:!1},getPoints:function(){return g},getCenter:function(){return h}}},createPoint:function(a,b,c){return{rad:a[c],point:a,id:b}}};return c}),d("array_helper",[],function(){return{init:function(a,b){for(var c=a.length;c--;)a[c]=b},shuffle:function(a){var b,c,d=a.length-1;for(d;d>=0;d--)b=Math.floor(Math.random()*d),c=a[d],a[d]=a[b],a[b]=c;return a},toPointList:function(a){var b,c,d=[],e=[];for(b=0;b=b&&e.push(a[d]);return e},maxIndex:function(a){var b,c=0;for(b=0;ba[c]&&(c=b);return c},max:function(a){var b,c=0;for(b=0;bc&&(c=a[b]);return c},sum:function(a){for(var b=a.length,c=0;b--;)c+=a[b];return c}}}),d("cv_utils",["cluster","array_helper","gl-matrix"],function(a,b,c){var d={},e=c.vec2,f=c.vec3;return d.imageRef=function(a,b){var c={x:a,y:b,toVec2:function(){return e.clone([this.x,this.y])},toVec3:function(){return f.clone([this.x,this.y,1])},round:function(){return this.x=Math.floor(this.x>0?this.x+.5:this.x-.5),this.y=Math.floor(this.y>0?this.y+.5:this.y-.5),this}};return c},d.computeIntegralImage2=function(a,b){var c,d,e=a.data,f=a.size.x,g=a.size.y,h=b.data,i=0,j=0,k=0,l=0,m=0;for(k=f,i=0,d=1;g>d;d++)i+=e[j],h[k]+=i,j+=f,k+=f;for(j=0,k=1,i=0,c=1;f>c;c++)i+=e[j],h[k]+=i,j++,k++;for(d=1;g>d;d++)for(j=d*f+1,k=(d-1)*f+1,l=d*f,m=(d-1)*f,c=1;f>c;c++)h[j]+=e[j]+h[k]+h[l]-h[m],j++,k++,l++,m++},d.computeIntegralImage=function(a,b){for(var c=a.data,d=a.size.x,e=a.size.y,f=b.data,g=0,h=0;d>h;h++)g+=c[h],f[h]=g;for(var i=1;e>i;i++){g=0;for(var j=0;d>j;j++)g+=c[i*d+j],f[i*d+j]=g+f[(i-1)*d+j]}},d.thresholdImage=function(a,b,c){c||(c=a);for(var d=a.data,e=d.length,f=c.data;e--;)f[e]=d[e]>e]++;return g},d.sharpenLine=function(a){var b,c,d=a.length,e=a[0],f=a[1];for(b=1;d-1>b;b++)c=a[b+1],a[b-1]=2*f-e-c&255,e=f,f=c;return a},d.determineOtsuThreshold=function(a,c){function e(a,b){var c,d=0;for(c=a;b>=c;c++)d+=h[c];return d}function f(a,b){var c,d=0;for(c=a;b>=c;c++)d+=c*h[c];return d}function g(){var g,i,j,k,l,m,n,o=[0],p=(1<k;k++)g=e(0,k),i=e(k+1,p),j=g*i,0===j&&(j=1),l=f(0,k)*i,m=f(k+1,p)*g,n=l-m,o[k]=n*n/j;return b.maxIndex(o)}c||(c=8);var h,i,j=8-c;return i=g(),i<=e;e++)for(f=0;n>f;f++)m[e*n+f]=0,m[(o-1-e)*n+f]=0;for(e=r;o-r>e;e++)for(f=0;r>=f;f++)m[e*n+f]=0,m[e*n+(n-1-f)]=0;for(e=r+1;o-r-1>e;e++)for(f=r+1;n-r>f;f++)g=p[(e-r-1)*n+(f-r-1)],h=p[(e-r-1)*n+(f+r)],i=p[(e+r)*n+(f-r-1)],j=p[(e+r)*n+(f+r)],q=j-i-h+g,k=q/s,m[e*n+f]=l[e*n+f]>k+5?0:1},d.cluster=function(b,c,d){function e(a){var b=!1;for(g=0;gb.x-j&&a.xb.y-k&&a.yd;d++){for(h=Math.floor(Math.random()*a.length),f=[],i=h,f.push(a[i]);null!==(i=c(i,!0));)f.push(a[i]);if(h>0)for(i=h;null!==(i=c(i,!1));)f.push(a[i]);f.length>g.length&&(g=f)}return g}},d.DILATE=1,d.ERODE=2,d.dilate=function(a,b){var c,d,e,f,g,h,i,j=a.data,k=b.data,l=a.size.y,m=a.size.x;for(c=1;l-1>c;c++)for(d=1;m-1>d;d++)f=c-1,g=c+1,h=d-1,i=d+1,e=j[f*m+h]+j[f*m+i]+j[c*m+d]+j[g*m+h]+j[g*m+i],k[c*m+d]=e>0?1:0},d.erode=function(a,b){var c,d,e,f,g,h,i,j=a.data,k=b.data,l=a.size.y,m=a.size.x;for(c=1;l-1>c;c++)for(d=1;m-1>d;d++)f=c-1,g=c+1,h=d-1,i=d+1,e=j[f*m+h]+j[f*m+i]+j[c*m+d]+j[g*m+h]+j[g*m+i],k[c*m+d]=5===e?1:0},d.subtract=function(a,b,c){c||(c=a);for(var d=a.data.length,e=a.data,f=b.data,g=c.data;d--;)g[d]=e[d]-f[d]},d.bitwiseOr=function(a,b,c){c||(c=a);for(var d=a.data.length,e=a.data,f=b.data,g=c.data;d--;)g[d]=e[d]||f[d]},d.countNonZero=function(a){for(var b=a.data.length,c=a.data,d=0;b--;)d+=c[b];return d},d.topGeneric=function(a,b,c){var d,e,f,g,h=0,i=0,j=[];for(d=0;b>d;d++)j[d]={score:0,item:null};for(d=0;di)for(f=j[h],f.score=e,f.item=a[d],i=Number.MAX_VALUE,g=0;b>g;g++)j[g].scoref;){for(d=0;h>d;d++)c[i]=Math.floor((.299*a[4*e+0]+.587*a[4*e+1]+.114*a[4*e+2]+(.299*a[4*(e+1)+0]+.587*a[4*(e+1)+1]+.114*a[4*(e+1)+2])+(.299*a[4*f+0]+.587*a[4*f+1]+.114*a[4*f+2])+(.299*a[4*(f+1)+0]+.587*a[4*(f+1)+1]+.114*a[4*(f+1)+2]))/4),i++,e+=2,f+=2;e+=j,f+=j}},d.computeGray=function(a,b){var c=a.length/4,d=0;for(d=0;c>d;d++)b[d]=Math.floor(.299*a[4*d+0]+.587*a[4*d+1]+.114*a[4*d+2])},d.loadImageArray=function(a,b,c){c||(c=document.createElement("canvas"));var e=new Image;e.callback=b,e.onload=function(){c.width=this.width,c.height=this.height;var a=c.getContext("2d");a.drawImage(this,0,0);var b=new Uint8Array(this.width*this.height);a.drawImage(this,0,0);var e=a.getImageData(0,0,this.width,this.height).data;d.computeGray(e,b),this.callback(b,{x:this.width,y:this.height},this)},e.src=a},d.halfSample=function(a,b){for(var c=a.data,d=a.size.x,e=b.data,f=0,g=d,h=c.length,i=d/2,j=0;h>g;){for(var k=0;i>k;k++)e[j]=Math.floor((c[f]+c[f+1]+c[g]+c[g+1])/4),j++,f+=2,g+=2;f+=d,g+=d}},d.hsv2rgb=function(a,b){var c=a[0],d=a[1],e=a[2],f=e*d,g=f*(1-Math.abs(c/60%2-1)),h=e-f,i=0,j=0,k=0;return b=b||[0,0,0],60>c?(i=f,j=g):120>c?(i=g,j=f):180>c?(j=f,k=g):240>c?(j=g,k=f):300>c?(i=g,k=f):360>c&&(i=f,k=g),b[0]=255*(i+h)|0,b[1]=255*(j+h)|0,b[2]=255*(k+h)|0,b},d._computeDivisors=function(a){var b,c=[],d=[];for(b=1;bb[d]?d++:c++;return e},d.calculatePatchSize=function(a,b){function c(a){for(var b=0,c=a[Math.floor(a.length/2)];b0&&(c=Math.abs(a[b]-m)>Math.abs(a[b-1]-m)?a[b-1]:a[b]),m/ci[k-1]/i[k]?{x:c,y:c}:null}var d,e=this._computeDivisors(b.x),f=this._computeDivisors(b.y),g=Math.max(b.x,b.y),h=this._computeIntersection(e,f),i=[8,10,15,20,32,60,80],j={"x-small":5,small:4,medium:3,large:2,"x-large":1},k=j[a]||j.medium,l=i[k],m=Math.floor(g/l);return d=c(h),d||(d=c(this._computeDivisors(g)),d||(d=c(this._computeDivisors(m*l)))),d},d._parseCSSDimensionValues=function(a){var b={value:parseFloat(a),unit:a.indexOf("%")===a.length-1?"%":"%"};return b},d._dimensionsConverters={top:function(a,b){return"%"===a.unit?Math.floor(b.height*(a.value/100)):void 0},right:function(a,b){return"%"===a.unit?Math.floor(b.width-b.width*(a.value/100)):void 0},bottom:function(a,b){return"%"===a.unit?Math.floor(b.height-b.height*(a.value/100)):void 0},left:function(a,b){return"%"===a.unit?Math.floor(b.width*(a.value/100)):void 0}},d.computeImageArea=function(a,b,c){var e={width:a,height:b},f=Object.keys(c).reduce(function(a,b){var f=c[b],g=d._parseCSSDimensionValues(f),h=d._dimensionsConverters[b](g,e);return a[b]=h,a},{});return{sx:f.left,sy:f.top,sw:f.right-f.left,sh:f.bottom-f.top}},d}),d("image_wrapper",["subImage","cv_utils","array_helper","gl-matrix"],function(a,b,c,d){function e(a,b,d,e){b?this.data=b:d?(this.data=new d(a.x*a.y),d===Array&&e&&c.init(this.data,0)):(this.data=new Uint8Array(a.x*a.y),Uint8Array===Array&&e&&c.init(this.data,0)),this.size=a}var f=d.vec2,g=d.mat2;return e.prototype.inImageWithBorder=function(a,b){return a.x>=b&&a.y>=b&&a.x=0&&u>=0&&n-1>v&&o-1>w){for(i=s,j=0;m>j;++j,f.add(i,y))for(k=0;l>k;++k,f.add(i,p))b.set(k,j,x(a,i[0],i[1]));return 0}var z=n-1,A=o-1,B=0;for(i=s,j=0;m>j;++j,f.add(i,y))for(k=0;l>k;++k,f.add(i,p))0<=i[0]&&0<=i[1]&&i[0]c;c++)for(d=0;e>d;d++)a.data[d*f+c]=this.data[(b.y+d)*this.size.x+b.x+c]},e.prototype.copyTo=function(a){for(var b=this.data.length,c=this.data,d=a.data;b--;)d[b]=c[b]},e.prototype.get=function(a,b){return this.data[b*this.size.x+a]},e.prototype.getSafe=function(a,b){var c;if(!this.indexMapping){for(this.indexMapping={x:[],y:[]},c=0;ca;a++)d[a]=d[(c-1)*b+a]=0;for(a=1;c-1>a;a++)d[a*b]=d[a*b+(b-1)]=0},e.prototype.invert=function(){for(var a=this.data,b=a.length;b--;)a[b]=a[b]?0:1},e.prototype.convolve=function(a){var b,c,d,e,f=a.length/2|0,g=0;for(c=0;c=e;e++)for(d=-f;f>=d;d++)g+=a[e+f][d+f]*this.getSafe(b+d,c+e);this.data[c*this.size.x+b]=g}},e.prototype.moments=function(a){var b,c,d,e,g,h,i,j,k,l,m,n,o=this.data,p=this.size.y,q=this.size.x,r=[],s=[],t=Math.PI,u=t/4;if(0>=a)return s;for(g=0;a>g;g++)r[g]={m00:0,m01:0,m10:0,m11:0,m02:0,m20:0,theta:0,rad:0};for(c=0;p>c;c++)for(e=c*c,b=0;q>b;b++)d=o[c*q+b],d>0&&(h=r[d-1],h.m00+=1,h.m01+=c,h.m10+=b,h.m11+=b*c,h.m02+=e,h.m20+=b*b);for(g=0;a>g;g++)h=r[g],isNaN(h.m00)||0===h.m00||(l=h.m10/h.m00,m=h.m01/h.m00,i=h.m11/h.m00-l*m,j=h.m02/h.m00-m*m,k=h.m20/h.m00-l*l,n=(j-k)/(2*i),n=.5*Math.atan(n)+(i>=0?u:-u)+t,h.theta=(180*n/t+90)%180-90,h.theta<0&&(h.theta+=180),h.rad=n>t?n-t:n,h.vec=f.clone([Math.cos(n),Math.sin(n)]),s.push(h));return s},e.prototype.show=function(a,b){var c,d,e,f,g,h,i;for(b||(b=1),c=a.getContext("2d"),a.width=this.size.x,a.height=this.size.y,d=c.getImageData(0,0,a.width,a.height),e=d.data,f=0,i=0;ic||c>360)&&(c=360);for(var e=[0,1,1],f=[0,0,0],g=[255,255,255],h=[0,0,0],i=[],j=a.getContext("2d"),k=j.getImageData(d.x,d.y,this.size.x,this.size.y),l=k.data,m=this.data.length;m--;)e[0]=this.data[m]*c,i=e[0]<=0?g:e[0]>=360?h:b.hsv2rgb(e,f),l[4*m+0]=i[0],l[4*m+1]=i[1],l[4*m+2]=i[2],l[4*m+3]=255;j.putImageData(k,d.x,d.y)},e}),d("tracer",[],function(){var a={searchDirections:[[0,1],[1,1],[1,0],[1,-1],[0,-1],[-1,-1],[-1,0],[-1,1]],create:function(a,b){function c(a,b,c,d){var e,k,l;for(e=0;7>e;e++){if(k=a.cy+i[a.dir][0],l=a.cx+i[a.dir][1],f=k*j+l,g[f]===b&&(0===h[f]||h[f]===c))return h[f]=c,a.cy=k,a.cx=l,!0;0===h[f]&&(h[f]=d),a.dir=(a.dir+1)%8}return!1}function d(a,b,c){return{dir:c,x:a,y:b,next:null,prev:null}}function e(a,b,e,f,g){var h,i,j,k=null,l={cx:b,cy:a,dir:0};if(c(l,f,e,g)){k=d(b,a,l.dir),h=k,j=l.dir,i=d(l.cx,l.cy,0),i.prev=h,h.next=i,i.next=null,h=i;do l.dir=(l.dir+6)%8,c(l,f,e,g),j!=l.dir?(h.dir=l.dir,i=d(l.cx,l.cy,0),i.prev=h,h.next=i,i.next=null,h=i):(h.dir=j,h.x=l.cx,h.y=l.cy),j=l.dir;while(l.cx!=b||l.cy!=a);k.prev=h.prev,h.prev.next=k}return k}var f,g=a.data,h=b.data,i=this.searchDirections,j=a.size.x;return{trace:function(a,b,d,e){return c(a,b,d,e)},contourTracing:function(a,b,c,d,f){return e(a,b,c,d,f)}}}};return a}),d("rasterizer",["tracer"],function(a){var b={createContour2D:function(){return{dir:null,index:null,firstVertex:null,insideContours:null,nextpeer:null,prevpeer:null}},CONTOUR_DIR:{CW_DIR:0,CCW_DIR:1,UNKNOWN_DIR:2},DIR:{OUTSIDE_EDGE:-32767,INSIDE_EDGE:-32766},create:function(c,d){var e=c.data,f=d.data,g=c.size.x,h=c.size.y,i=a.create(c,d);return{rasterize:function(a){var c,d,j,k,l,m,n,o,p,q,r,s,t=[],u=0;for(s=0;400>s;s++)t[s]=0;for(t[0]=e[0],p=null,m=1;h-1>m;m++)for(k=0,d=t[0],l=1;g-1>l;l++)if(r=m*g+l,0===f[r])if(c=e[r],c!==d){if(0===k)j=u+1,t[j]=c,d=c,n=i.contourTracing(m,l,j,c,b.DIR.OUTSIDE_EDGE),null!==n&&(u++,k=j,o=b.createContour2D(),o.dir=b.CONTOUR_DIR.CW_DIR,o.index=k,o.firstVertex=n,o.nextpeer=p,o.insideContours=null,null!==p&&(p.prevpeer=o),p=o);else if(n=i.contourTracing(m,l,b.DIR.INSIDE_EDGE,c,k),null!==n){for(o=b.createContour2D(),o.firstVertex=n,o.insideContours=null,o.dir=0===a?b.CONTOUR_DIR.CCW_DIR:b.CONTOUR_DIR.CW_DIR,o.index=a,q=p;null!==q&&q.index!==k;)q=q.nextpeer;null!==q&&(o.nextpeer=q.insideContours,null!==q.insideContours&&(q.insideContours.prevpeer=o),q.insideContours=o)}}else f[r]=k;else f[r]===b.DIR.OUTSIDE_EDGE||f[r]===b.DIR.INSIDE_EDGE?(k=0,d=f[r]===b.DIR.INSIDE_EDGE?e[r]:t[0]):(k=f[r],d=t[k]);for(q=p;null!==q;)q.index=a,q=q.nextpeer;return{cc:p,count:u}},debug:{drawContour:function(a,c){var d,e,f,g=a.getContext("2d"),h=c;for(g.strokeStyle="red",g.fillStyle="red",g.lineWidth=1,d=null!==h?h.insideContours:null;null!==h;){switch(null!==d?(e=d,d=d.nextpeer):(e=h,h=h.nextpeer,d=null!==h?h.insideContours:null),e.dir){case b.CONTOUR_DIR.CW_DIR:g.strokeStyle="red";break;case b.CONTOUR_DIR.CCW_DIR:g.strokeStyle="blue";break;case b.CONTOUR_DIR.UNKNOWN_DIR:g.strokeStyle="green"}f=e.firstVertex,g.beginPath(),g.moveTo(f.x,f.y);do f=f.next,g.lineTo(f.x,f.y);while(f!==e.firstVertex);g.stroke()}}}}}};return b}),d("skeletonizer",[],function(){function a(stdlib, foreign, buffer) {"use asm";var images=new stdlib.Uint8Array(buffer),size=foreign.size|0,imul=stdlib.Math.imul;function erode(inImagePtr, outImagePtr) {inImagePtr=inImagePtr|0;outImagePtr=outImagePtr|0;var v=0,u=0,sum=0,yStart1=0,yStart2=0,xStart1=0,xStart2=0,offset=0;for ( v=1; (v|0)<((size - 1)|0); v=(v+1)|0) {offset=(offset+size)|0;for ( u=1; (u|0)<((size - 1)|0); u=(u+1)|0) {yStart1=(offset - size)|0;yStart2=(offset+size)|0;xStart1=(u - 1)|0;xStart2=(u+1)|0;sum=((images[(inImagePtr+yStart1+xStart1)|0]|0)+(images[(inImagePtr+yStart1+xStart2)|0]|0)+(images[(inImagePtr+offset+u)|0]|0)+(images[(inImagePtr+yStart2+xStart1)|0]|0)+(images[(inImagePtr+yStart2+xStart2)|0]|0))|0;if ((sum|0) == (5|0)) {images[(outImagePtr+offset+u)|0]=1;} else {images[(outImagePtr+offset+u)|0]=0;}}}return;}function subtract(aImagePtr, bImagePtr, outImagePtr) {aImagePtr=aImagePtr|0;bImagePtr=bImagePtr|0;outImagePtr=outImagePtr|0;var length=0;length=imul(size, size)|0;while ((length|0)>0) {length=(length - 1)|0;images[(outImagePtr+length)|0]=((images[(aImagePtr+length)|0]|0) - (images[(bImagePtr+length)|0]|0))|0;}}function bitwiseOr(aImagePtr, bImagePtr, outImagePtr) {aImagePtr=aImagePtr|0;bImagePtr=bImagePtr|0;outImagePtr=outImagePtr|0;var length=0;length=imul(size, size)|0;while ((length|0)>0) {length=(length - 1)|0;images[(outImagePtr+length)|0]=((images[(aImagePtr+length)|0]|0)|(images[(bImagePtr+length)|0]|0))|0;}}function countNonZero(imagePtr) {imagePtr=imagePtr|0;var sum=0,length=0;length=imul(size, size)|0;while ((length|0)>0) {length=(length - 1)|0;sum=((sum|0)+(images[(imagePtr+length)|0]|0))|0;}return (sum|0);}function init(imagePtr, value) {imagePtr=imagePtr|0;value=value|0;var length=0;length=imul(size, size)|0;while ((length|0)>0) {length=(length - 1)|0;images[(imagePtr+length)|0]=value;}}function dilate(inImagePtr, outImagePtr) {inImagePtr=inImagePtr|0;outImagePtr=outImagePtr|0;var v=0,u=0,sum=0,yStart1=0,yStart2=0,xStart1=0,xStart2=0,offset=0;for ( v=1; (v|0)<((size - 1)|0); v=(v+1)|0) {offset=(offset+size)|0;for ( u=1; (u|0)<((size - 1)|0); u=(u+1)|0) {yStart1=(offset - size)|0;yStart2=(offset+size)|0;xStart1=(u - 1)|0;xStart2=(u+1)|0;sum=((images[(inImagePtr+yStart1+xStart1)|0]|0)+(images[(inImagePtr+yStart1+xStart2)|0]|0)+(images[(inImagePtr+offset+u)|0]|0)+(images[(inImagePtr+yStart2+xStart1)|0]|0)+(images[(inImagePtr+yStart2+xStart2)|0]|0))|0;if ((sum|0)>(0|0)) {images[(outImagePtr+offset+u)|0]=1;} else {images[(outImagePtr+offset+u)|0]=0;}}}return;}function memcpy(srcImagePtr, dstImagePtr) {srcImagePtr=srcImagePtr|0;dstImagePtr=dstImagePtr|0;var length=0;length=imul(size, size)|0;while ((length|0)>0) {length=(length - 1)|0;images[(dstImagePtr+length)|0]=(images[(srcImagePtr+length)|0]|0);}}function zeroBorder(imagePtr) {imagePtr=imagePtr|0;var x=0,y=0;for ( x=0; (x|0)<((size - 1)|0); x=(x+1)|0) {images[(imagePtr+x)|0]=0;images[(imagePtr+y)|0]=0;y=((y+size) - 1)|0;images[(imagePtr+y)|0]=0;y=(y+1)|0;}for ( x=0; (x|0)<(size|0); x=(x+1)|0) {images[(imagePtr+y)|0]=0;y=(y+1)|0;}}function skeletonize() {var subImagePtr=0,erodedImagePtr=0,tempImagePtr=0,skelImagePtr=0,sum=0,done=0;erodedImagePtr=imul(size, size)|0;tempImagePtr=(erodedImagePtr+erodedImagePtr)|0;skelImagePtr=(tempImagePtr+erodedImagePtr)|0;init(skelImagePtr, 0);zeroBorder(subImagePtr);do {erode(subImagePtr, erodedImagePtr);dilate(erodedImagePtr, tempImagePtr);subtract(subImagePtr, tempImagePtr, tempImagePtr);bitwiseOr(skelImagePtr, tempImagePtr, skelImagePtr);memcpy(erodedImagePtr, subImagePtr);sum=countNonZero(subImagePtr)|0;done=((sum|0) == 0|0);} while(!done);}return {skeletonize : skeletonize};} -return Math.imul=Math.imul||function(a,b){var c=a>>>16&65535,d=65535&a,e=b>>>16&65535,f=65535&b;return d*f+(c*f+d*e<<16>>>0)|0},a}),d("image_debug",[],function(){return{drawRect:function(a,b,c,d){c.strokeStyle=d.color,c.fillStyle=d.color,c.lineWidth=1,c.beginPath(),c.strokeRect(a.x,a.y,b.x,b.y)},drawPath:function(a,b,c,d){c.strokeStyle=d.color,c.fillStyle=d.color,c.lineWidth=d.lineWidth,c.beginPath(),c.moveTo(a[0][b.x],a[0][b.y]);for(var e=1;eb&&(b+=180),b=(180-b)*Math.PI/180,f=I.clone([Math.cos(b),Math.sin(b),-Math.sin(b),Math.cos(b)]),c=0;cd;d++)H.transformMat2(e.box[d],e.box[d],f);t.boxFromPatches.showTransformed&&g.drawPath(e.box,{x:0,y:1},F.ctx.binary,{color:"#99ff00",lineWidth:2})}for(c=0;cd;d++)e.box[d][0]l&&(l=e.box[d][0]),e.box[d][1]m&&(m=e.box[d][1]);for(h=[[j,k],[l,k],[l,m],[j,m]],t.boxFromPatches.showTransformedBox&&g.drawPath(h,{x:0,y:1},F.ctx.binary,{color:"#ff0000",lineWidth:2}),i=t.halfSample?2:1,f=I.invert(f,f),d=0;4>d;d++)H.transformMat2(h[d],h[d],f);for(t.boxFromPatches.showBB&&g.drawPath(h,{x:0,y:1},F.ctx.binary,{color:"#ff0000",lineWidth:2}),d=0;4>d;d++)H.scale(h[d],h[d],i);return h}function l(){b.otsuThreshold(u,B),B.zeroBorder(),t.showCanvas&&B.show(F.dom.binary,255)}function m(){var a,b,d,e,h,i,j,k,l=[];for(a=0;ab;b++)d.push(0);for(c=z.data.length;c--;)z.data[c]>0&&d[z.data[c]-1]++;return d=d.map(function(a,b){return{val:a,label:b+1}}),d.sort(function(a,b){return b.val-a.val}),e=d.filter(function(a){return a.val>=5})}function o(a,c){var d,e,f,h,i,j=[],l=[],m=[0,1,1],n=[0,0,0];for(d=0;d=2){for(e=0;el&&j.push(a[e]);if(j.length>=2){for(i=j.length,g=p(j),f=0,e=0;e1&&g.length>=j.length/4*3&&g.length>a.length/4&&(f/=g.length,h={index:b[1]*G.x+b[0],pos:{x:c,y:d},box:[H.clone([c,d]),H.clone([c+w.size.x,d]),H.clone([c+w.size.x,d+w.size.y]),H.clone([c,d+w.size.y])],moments:g,rad:f,vec:H.clone([Math.cos(f),Math.sin(f)])},k.push(h))}}return k}function s(a){function c(){var a;for(a=0;ak&&e(h))):z.data[h]=Number.MAX_VALUE}var h,i,j=0,k=.95,l=0,m=[0,1,1],n=[0,0,0];for(f.init(y.data,0),f.init(z.data,0),f.init(A.data,null),h=0;h0&&z.data[h]<=j&&(i=A.data[h],m[0]=z.data[h]/(j+1)*360,b.hsv2rgb(m,n),g.drawRect(i.pos,w.size,F.ctx.binary,{color:"rgb("+n.join(",")+")",lineWidth:2}));return j}var t,u,v,w,x,y,z,A,B,C,D,E,F={ctx:{binary:null},dom:{binary:null}},G={x:0,y:0},H=h.vec2,I=h.mat2,J=this;return{init:function(a,b){t=b,D=a,i(),j()},locate:function(){var a,c,d;if(t.halfSample&&b.halfSample(D,u),l(),a=m(),a.lengthe?null:(c=n(e),0===c.length?null:d=o(c,e))},checkImageConstraints:function(a,c){var d,e,f,g=a.getWidth(),h=a.getHeight(),i=c.halfSample?.5:1;if(a.getConfig().area&&(f=b.computeImageArea(g,h,a.getConfig().area),a.setTopRight({x:f.sx,y:f.sy}),a.setCanvasSize({x:g,y:h}),g=f.sw,h=f.sh),e={x:Math.floor(g*i),y:Math.floor(h*i)},d=b.calculatePatchSize(c.patchSize,e),console.log("Patch-Size: "+JSON.stringify(d)),a.setWidth(Math.floor(Math.floor(e.x/d.x)*(1/i)*d.x)),a.setHeight(Math.floor(Math.floor(e.y/d.y)*(1/i)*d.y)),a.getWidth()%d.x===0&&a.getHeight()%d.y===0)return!0;throw new Error("Image dimensions do not comply with the current settings: Width ("+g+" )and height ("+h+") must a multiple of "+d.x)}}}),d("bresenham",["cv_utils","image_wrapper"],function(a,b){var c={},d={DIR:{UP:1,DOWN:-1}};return c.getBarcodeLine=function(a,b,c){function d(a,b){l=s[b*t+a],u+=l,v=v>l?l:v,w=l>w?l:w,r.push(l)}var e,f,g,h,i,j,k,l,m=0|b.x,n=0|b.y,o=0|c.x,p=0|c.y,q=Math.abs(p-n)>Math.abs(o-m),r=[],s=a.data,t=a.size.x,u=0,v=255,w=0;for(q&&(j=m,m=n,n=j,j=o,o=p,p=j),m>o&&(j=m,m=o,o=j,j=n,n=p,p=j),e=o-m,f=Math.abs(p-n),g=e/2|0,i=n,h=p>n?1:-1,k=m;o>k;k++)q?d(i,k):d(k,i),g-=f,0>g&&(i+=h,g+=e);return{line:r,min:v,max:w}},c.toOtsuBinaryLine=function(c){var d=c.line,e=new b({x:d.length-1,y:1},d),f=a.determineOtsuThreshold(e,5);return d=a.sharpenLine(d),a.thresholdImage(e,f),{line:d,threshold:f}},c.toBinaryLine=function(a){var b,c,e,f,g,h=a.min,i=a.max,j=a.line,k=h+(i-h)/2,l=[],m=(i-h)/12,n=-m;for(c=j[0]>k?d.DIR.UP:d.DIR.DOWN,l.push({pos:0,val:j[0]}),f=0;fb&&j[f+1]<1.5*k?d.DIR.DOWN:b>m&&j[f+1]>.5*k?d.DIR.UP:c,c!==e&&(l.push({pos:f,val:j[f]}),c=e);for(l.push({pos:j.length,val:j[j.length-1]}),g=l[0].pos;gk?0:1;for(f=1;fl[f].val?l[f].val+(l[f+1].val-l[f].val)/3*2|0:l[f+1].val+(l[f].val-l[f+1].val)/3|0,g=l[f].pos;gm?0:1;return{line:j,threshold:m}},c.debug={printFrequency:function(a,b){var c,d=b.getContext("2d");for(b.width=a.length,b.height=256,d.beginPath(),d.strokeStyle="blue",c=0;cd;d++)if(e._row[d]^h)c[i]++;else{if(i++,i===f)break;c[i]=1,h=!h}return c},c.prototype._decode=function(){var a,c,d,e,f=this,g=[0,0,0,0,0,0,0,0,0],h=[],i=f._findStart();if(!i)return null;e=f._nextSet(f._row,i.end);do{if(g=f._toCounters(e,g),d=f._toPattern(g),0>d)return null;if(a=f._patternToChar(d),0>a)return null;h.push(a),c=e,e+=b.sum(g),e=f._nextSet(f._row,e)}while("*"!==a);return h.pop(),h.length&&f._verifyTrailingWhitespace(c,e,g)?{code:h.join(""),start:i.start,end:e,startInfo:i,decodedCodes:h}:null},c.prototype._verifyTrailingWhitespace=function(a,c,d){var e,f=b.sum(d);return e=c-a-f,3*e>=f?!0:!1},c.prototype._patternToChar=function(a){var b,c=this;for(b=0;bb&&(d=a[c]);return d},c.prototype._toPattern=function(a){for(var b,c,d=a.length,e=0,f=d,g=0,h=this;f>3;){for(e=h._findNextWidth(a,e),f=0,b=0,c=0;d>c;c++)a[c]>e&&(b|=1<c&&f>0;c++)if(a[c]>e&&(f--,2*a[c]>=g))return-1;return b}}return-1},c.prototype._findStart=function(){var a,b,c,d=this,e=d._nextSet(d._row),f=e,g=[0,0,0,0,0,0,0,0,0],h=0,i=!1;for(a=e;ab;b++)g[b]=g[b+2];g[7]=0,g[8]=0,h--}else h++;g[h]=1,i=!i}return null},c}),d("code_39_vin_reader",["./code_39_reader"],function(a){function b(){a.call(this)}var c={IOQ:/[IOQ]/g,AZ09:/[A-Z0-9]{17}/};return b.prototype=Object.create(a.prototype),b.prototype.constructor=b,b.prototype._decode=function(){var b=a.prototype._decode.apply(this);if(!b)return null;var d=b.code;if(d)return d=d.replace(c.IOQ,""),d.match(c.AZ09)?this._checkChecksum(d)?(b.code=d,b):null:(console.log("Failed AZ09 pattern code:",d),null)},b.prototype._checkChecksum=function(a){return!!a},b}),d("codabar_reader",["./barcode_reader"],function(a){function b(){a.call(this),this._counters=[]}var c={ALPHABETH_STRING:{value:"0123456789-$:/.+ABCD"},ALPHABET:{value:[48,49,50,51,52,53,54,55,56,57,45,36,58,47,46,43,65,66,67,68]},CHARACTER_ENCODINGS:{value:[3,6,9,96,18,66,33,36,48,72,12,24,69,81,84,21,26,41,11,14]},START_END:{value:[26,41,11,14]},MIN_ENCODED_CHARS:{value:4},MAX_ACCEPTABLE:{value:2},PADDING:{value:1.5}};return b.prototype=Object.create(a.prototype,c),b.prototype.constructor=b,b.prototype._decode=function(){var a,b,c,d,e,f=this,g=[];if(f._fillCounters(),a=f._findStart(),!a)return null;d=a.startCounter;do{if(c=f._toPattern(d),0>c)return null;if(b=f._patternToChar(c),0>b)return null;if(g.push(b),d+=8,g.length>1&&f._isStartEnd(c))break}while(df._counters.length?f._counters.length:d,e=a.start+f._sumCounters(a.startCounter,d-8),{code:g.join(""),start:a.start,end:e,startInfo:a,decodedCodes:g}):null},b.prototype._verifyWhitespace=function(a,b){return(0>=a-1||this._counters[a-1]>=this._calculatePatternLength(a)/2)&&(b+8>=this._counters.length||this._counters[b+7]>=this._calculatePatternLength(b)/2)?!0:!1},b.prototype._calculatePatternLength=function(a){var b,c=0;for(b=a;a+7>b;b++)c+=this._counters[b];return c},b.prototype._thresholdResultPattern=function(a,b){var c,d,e,f,g,h=this,i={space:{narrow:{size:0,counts:0,min:0,max:Number.MAX_VALUE},wide:{size:0,counts:0,min:0,max:Number.MAX_VALUE}},bar:{narrow:{size:0,counts:0,min:0,max:Number.MAX_VALUE},wide:{size:0,counts:0,min:0,max:Number.MAX_VALUE}}},j=b;for(e=0;e=0;f--)c=2===(1&f)?i.bar:i.space,d=1===(1&g)?c.wide:c.narrow,d.size+=h._counters[j+f],d.counts++,g>>=1;j+=8}return["space","bar"].forEach(function(a){var b=i[a];b.wide.min=Math.floor((b.narrow.size/b.narrow.counts+b.wide.size/b.wide.counts)/2),b.narrow.max=Math.ceil(b.wide.min),b.wide.max=Math.ceil((b.wide.size*h.MAX_ACCEPTABLE+h.PADDING)/b.wide.counts)}),i},b.prototype._charToPattern=function(a){var b,c=this,d=a.charCodeAt(0);for(b=0;b=0;d--){if(e=0===(1&d)?j.bar:j.space,f=1===(1&h)?e.wide:e.narrow,g=i._counters[k+d],gf.max)return!1;h>>=1}k+=8}return!0},b.prototype._fillCounters=function(){var a,b=this,c=0,d=!0,e=b._nextUnset(b._row);for(b._counters.length=0,b._counters[c]=0,a=e;ac;c+=2)d=this._counters[c],d>f&&(f=d),e>d&&(e=d);return(e+f)/2|0},b.prototype._toPattern=function(a){var b,c,d,e,f=7,g=a+f,h=1<this._counters.length)return-1;for(b=this._computeAlternatingThreshold(a,g),c=this._computeAlternatingThreshold(a+1,g),d=0;f>d;d++)e=0===(1&d)?b:c,this._counters[a+d]>e&&(i|=h),h>>=1;return i},b.prototype._isStartEnd=function(a){var b;for(b=0;bc;c++)d+=this._counters[c];return d},b.prototype._findStart=function(){var a,b,c,d=this,e=d._nextUnset(d._row);for(a=1;ad;d++){if(a=e._decodeCode(a.end,e.CODE_G_START),!a)return null;b.push(a.code),c.push(a)}if(a=e._findPattern(e.MIDDLE_PATTERN,a.end,!0),null===a)return null;for(c.push(a),d=0;4>d;d++){if(a=e._decodeCode(a.end,e.CODE_G_START),!a)return null;c.push(a),b.push(a.code)}return a},b}),d("upc_e_reader",["./ean_reader"],function(a){function b(){a.call(this)}var c={CODE_FREQUENCY:{value:[[56,52,50,49,44,38,35,42,41,37],[7,11,13,14,19,25,28,21,22,26]]},STOP_PATTERN:{value:[1/6*7,1/6*7,1/6*7,1/6*7,1/6*7,1/6*7]}};return b.prototype=Object.create(a.prototype,c),b.prototype.constructor=b,b.prototype._decodePayload=function(a,b,c){var d,e=this,f=0;for(d=0;6>d;d++){if(a=e._decodeCode(a.end),!a)return null;a.code>=e.CODE_G_START?(a.code=a.code-e.CODE_G_START,f|=1<<5-d):f|=0<<5-d,b.push(a.code),c.push(a)}return e._determineParity(f,b),a},b.prototype._determineParity=function(a,b){var c,d,e=this;for(d=0;d=c?b.concat(a.slice(1,3)).concat([c,0,0,0,0]).concat(a.slice(3,6)):3===c?b.concat(a.slice(1,4)).concat([0,0,0,0,0]).concat(a.slice(4,6)):4===c?b.concat(a.slice(1,5)).concat([0,0,0,0,0,a[5]]):b.concat(a.slice(1,6)).concat([0,0,0,0,c]),b.push(a[a.length-1]),b},b.prototype._checksum=function(b){return a.prototype._checksum.call(this,this._convertToUPCA(b))},b.prototype._findEnd=function(b,c){return c=!0,a.prototype._findEnd.call(this,b,c)},b.prototype._verifyTrailingWhitespace=function(a){var b,c=this;return b=a.end+(a.end-a.start)/2,b1&&!d.inImageWithBorder(a[0],0)||!d.inImageWithBorder(a[1],0);)c-=Math.floor(c/2),e(-c);return 1>=c?null:a}function i(a){return[{x:(a[1][0]-a[0][0])/2+a[0][0],y:(a[1][1]-a[0][1])/2+a[0][1]},{x:(a[3][0]-a[2][0])/2+a[2][0],y:(a[3][1]-a[2][1])/2+a[2][1]}]}function j(e){var f,g=null,h=a.getBarcodeLine(d,e[0],e[1]);for(c.showFrequency&&(b.drawPath(e,{x:"x",y:"y"},o.ctx.overlay,{color:"red",lineWidth:3}),a.debug.printFrequency(h.line,o.dom.frequency)),a.toBinaryLine(h),c.showPattern&&a.debug.printPattern(h.line,o.dom.pattern),f=0;fd&&null===i;d++)e=g/h*d*(d%2===0?-1:1),f={y:e*k,x:e*l},b[0].y+=f.x,b[0].x-=f.y,b[1].y+=f.x,b[1].x-=f.y,i=j(b);return i}function m(a){return Math.sqrt(Math.pow(Math.abs(a[1].y-a[0].y),2)+Math.pow(Math.abs(a[1].x-a[0].x),2))}function n(a){var d,e,f,g,k=o.ctx.overlay;return c.drawBoundingBox&&k&&b.drawPath(a,{x:0,y:1},k,{color:"blue",lineWidth:2}),d=i(a),g=m(d),e=Math.atan2(d[1].y-d[0].y,d[1].x-d[0].x),d=h(d,e,Math.floor(.1*g)),null===d?null:(f=j(d),null===f&&(f=l(a,d,e)),null===f?null:(f&&c.drawScanline&&k&&b.drawPath(d,{x:"x",y:"y"},k,{color:"red",lineWidth:3}),{codeResult:f.codeResult,line:d,angle:e,pattern:f.barcodeLine.line,threshold:f.barcodeLine.threshold}))}var o={ctx:{frequency:null,pattern:null,overlay:null},dom:{frequency:null,pattern:null,overlay:null}},p=[],q=null;return e(),f(),g(),{decodeFromBoundingBox:function(a){return n(a)},decodeFromBoundingBoxes:function(a){var b,c;for(b=0;b0?a.videoWidth>0&&a.videoHeight>0?(console.log(a.videoWidth+"px x "+a.videoHeight+"px"),b()):window.setTimeout(c,500):b("Unable to play video stream. Is webcam working?"),d--}var d=10;c()}function d(a,d,e){b(a,function(a){d.src=a,h&&d.removeEventListener("loadeddata",h,!1),h=c.bind(null,d,e),d.addEventListener("loadeddata",h,!1),d.play()},function(a){console.log(a)})}function e(b,c){var d={audio:!1,video:!0},e=a.mergeObjects({width:640,height:480,minAspectRatio:0,maxAspectRatio:100,facing:"environment"},b);return"undefined"==typeof MediaStreamTrack.getSources?(d.video={mediaSource:"camera",width:{min:e.width,max:e.width},height:{min:e.height,max:e.height},require:["width","height"]},c(d)):void MediaStreamTrack.getSources(function(a){for(var b,f=0;f!=a.length;++f){var g=a[f];"video"==g.kind&&g.facing==e.facing&&(b=g.id)}return d.video={mandatory:{minWidth:e.width,minHeight:e.height,minAspectRatio:e.minAspectRatio,maxAspectRatio:e.maxAspectRatio},optional:[{sourceId:b}]},c(d)})}function f(a,b,c){e(b,function(b){d(b,a,c)})}var g,h;return{request:function(a,b,c){f(a,b,c)},release:function(){var a=g&&g.getVideoTracks();a.length&&a[0].stop(),g=null}}}),d("quagga",["code_128_reader","ean_reader","input_stream","image_wrapper","barcode_locator","barcode_decoder","frame_grabber","html_utils","config","events","camera_access","image_debug","gl-matrix"],function(b,c,d,e,f,g,h,i,j,k,l,m,n){function o(a){u(a),L=g.create(j.decoder,J)}function p(){if("undefined"!=typeof document)for(var a=[{node:document.querySelector("div[data-controls]"),prop:j.controls},{node:M.dom.overlay,prop:j.visual.show}],b=0;b0?B(function(){console.log("Workers created"),s(a)}):(o(),s(a))}function s(a){G.play(),a()}function t(){if("undefined"!=typeof document){var a=document.querySelector("#interactive.viewport");if(M.dom.image=document.querySelector("canvas.imgBuffer"),M.dom.image||(M.dom.image=document.createElement("canvas"),M.dom.image.className="imgBuffer",a&&"ImageStream"==j.inputStream.type&&a.appendChild(M.dom.image)),M.ctx.image=M.dom.image.getContext("2d"),M.dom.image.width=G.getCanvasSize().x,M.dom.image.height=G.getCanvasSize().y,M.dom.overlay=document.querySelector("canvas.drawingBuffer"),!M.dom.overlay){M.dom.overlay=document.createElement("canvas"),M.dom.overlay.className="drawingBuffer",a&&a.appendChild(M.dom.overlay);var b=document.createElement("br");b.setAttribute("clear","all"),a&&a.appendChild(b)}M.ctx.overlay=M.dom.overlay.getContext("2d"),M.dom.overlay.width=G.getCanvasSize().x,M.dom.overlay.height=G.getCanvasSize().y}}function u(a){J=a?a:new e({x:G.getWidth(),y:G.getHeight()}),console.log(J.size),K=[P.clone([20,J.size.y/2-100]),P.clone([20,J.size.y/2+100]),P.clone([J.size.x-20,J.size.y/2+100]),P.clone([J.size.x-20,J.size.y/2-100])],f.init(J,j.locator)}function v(){return j.locate?f.locate():[K]}function w(a){function b(a){for(var b=a.length;b--;)a[b][0]+=f,a[b][1]+=g}function c(a){a[0].x+=f,a[0].y+=g,a[1].x+=f,a[1].y+=g}var d,e=G.getTopRight(),f=e.x,g=e.y;if(a&&(0!==f||0!==g)&&(a.line&&2===a.line.length&&c(a.line),a.boxes&&a.boxes.length>0))for(d=0;d0){if(a=N.filter(function(a){return!a.busy})[0],!a)return;H.attachData(a.imageData)}else H.attachData(J.data);H.grab()&&(a?(a.busy=!0,a.worker.postMessage({cmd:"process",imageData:a.imageData},[a.imageData.buffer])):y())}else y()}function A(){I=!1,function a(){I||(z(),O&&"LiveStream"==j.inputStream.type&&window.requestAnimFrame(a))}()}function B(a){function b(b){N.push(b),N.length>=j.numOfWorkers&&a()}var c;for(N=[],c=0;c0&&N.forEach(function(b){b.worker.postMessage({cmd:"setReaders",readers:a})})}var G,H,I,J,K,L,M={ctx:{image:null,overlay:null},dom:{image:null,overlay:null}},N=[],O=!0,P=n.vec2;return{init:function(a,b,c){return j=i.mergeObjects(j,a),c?(O=!1,o(c),b()):void q(b)},start:function(){A()},stop:function(){I=!0,N.forEach(function(a){a.worker.terminate(),console.log("Worker terminated!")}),N.length=0,"LiveStream"===j.inputStream.type&&(l.release(),G.clearEventHandlers())},pause:function(){I=!0},onDetected:function(a){k.subscribe("detected",a)},onProcessed:function(a){k.subscribe("processed",a)},setReaders:function(a){F(a)},canvas:M,decodeSingle:function(a,b){a=i.mergeObjects({inputStream:{type:"ImageStream",sequence:!1,size:800,src:a.src},numOfWorkers:1,locator:{halfSample:!1}},a),this.init(a,function(){k.once("processed",function(a){I=!0,b.call(null,a)},!0),A()})},Reader:{EANReader:c,Code128Reader:b},ImageWrapper:e,ImageDebug:m}}),c("quagga")}); \ No newline at end of file +var b,c,d;return function(a){function e(a,b){return u.call(a,b)}function f(a,b){var c,d,e,f,g,h,i,j,k,l,m,n=b&&b.split("/"),o=s.map,p=o&&o["*"]||{};if(a&&"."===a.charAt(0))if(b){for(n=n.slice(0,n.length-1),a=a.split("/"),g=a.length-1,s.nodeIdCompat&&w.test(a[g])&&(a[g]=a[g].replace(w,"")),a=n.concat(a),k=0;k0&&(a.splice(k-1,2),k-=2)}a=a.join("/")}else 0===a.indexOf("./")&&(a=a.substring(2));if((n||p)&&o){for(c=a.split("/"),k=c.length;k>0;k-=1){if(d=c.slice(0,k).join("/"),n)for(l=n.length;l>0;l-=1)if(e=o[n.slice(0,l).join("/")],e&&(e=e[d])){f=e,h=k;break}if(f)break;!i&&p&&p[d]&&(i=p[d],j=k)}!f&&i&&(f=i,h=j),f&&(c.splice(0,h,f),a=c.join("/"))}return a}function g(b,c){return function(){return n.apply(a,v.call(arguments,0).concat([b,c]))}}function h(a){return function(b){return f(b,a)}}function i(a){return function(b){q[a]=b}}function j(b){if(e(r,b)){var c=r[b];delete r[b],t[b]=!0,m.apply(a,c)}if(!e(q,b)&&!e(t,b))throw new Error("No "+b);return q[b]}function k(a){var b,c=a?a.indexOf("!"):-1;return c>-1&&(b=a.substring(0,c),a=a.substring(c+1,a.length)),[b,a]}function l(a){return function(){return s&&s.config&&s.config[a]||{}}}var m,n,o,p,q={},r={},s={},t={},u=Object.prototype.hasOwnProperty,v=[].slice,w=/\.js$/;o=function(a,b){var c,d=k(a),e=d[0];return a=d[1],e&&(e=f(e,b),c=j(e)),e?a=c&&c.normalize?c.normalize(a,h(b)):f(a,b):(a=f(a,b),d=k(a),e=d[0],a=d[1],e&&(c=j(e))),{f:e?e+"!"+a:a,n:a,pr:e,p:c}},p={require:function(a){return g(a)},exports:function(a){var b=q[a];return"undefined"!=typeof b?b:q[a]={}},module:function(a){return{id:a,uri:"",exports:q[a],config:l(a)}}},m=function(b,c,d,f){var h,k,l,m,n,s,u=[],v=typeof d;if(f=f||b,"undefined"===v||"function"===v){for(c=!c.length&&d.length?["require","exports","module"]:c,n=0;ng)return Number.MAX_VALUE;d+=e}return d/f},a.prototype._nextSet=function(a,b){var c;for(b=b||0,c=b;c1)for(c=0;cd?(j.start=c-g,j.end=c,j.counter=e,j):null;i++,e[i]=1,h=!h}}else for(e.push(0),c=g;ca?0:a,d=a;b>d;d++)if(this._row[d]!==c)return!1;return!0},Object.defineProperty(a.prototype,"FORMAT",{value:"unknown",writeable:!1}),a.DIRECTION={FORWARD:1,REVERSE:-1},a.Exception={StartNotFoundException:"Start-Info was not found!",CodeNotFoundException:"Code could not be found!",PatternNotFoundException:"Pattern could not be found!"},a}),d("code_128_reader",["./barcode_reader"],function(a){"use strict";function b(){a.call(this)}var c={CODE_SHIFT:{value:98},CODE_C:{value:99},CODE_B:{value:100},CODE_A:{value:101},START_CODE_A:{value:103},START_CODE_B:{value:104},START_CODE_C:{value:105},STOP_CODE:{value:106},MODULO:{value:11},CODE_PATTERN:{value:[[2,1,2,2,2,2],[2,2,2,1,2,2],[2,2,2,2,2,1],[1,2,1,2,2,3],[1,2,1,3,2,2],[1,3,1,2,2,2],[1,2,2,2,1,3],[1,2,2,3,1,2],[1,3,2,2,1,2],[2,2,1,2,1,3],[2,2,1,3,1,2],[2,3,1,2,1,2],[1,1,2,2,3,2],[1,2,2,1,3,2],[1,2,2,2,3,1],[1,1,3,2,2,2],[1,2,3,1,2,2],[1,2,3,2,2,1],[2,2,3,2,1,1],[2,2,1,1,3,2],[2,2,1,2,3,1],[2,1,3,2,1,2],[2,2,3,1,1,2],[3,1,2,1,3,1],[3,1,1,2,2,2],[3,2,1,1,2,2],[3,2,1,2,2,1],[3,1,2,2,1,2],[3,2,2,1,1,2],[3,2,2,2,1,1],[2,1,2,1,2,3],[2,1,2,3,2,1],[2,3,2,1,2,1],[1,1,1,3,2,3],[1,3,1,1,2,3],[1,3,1,3,2,1],[1,1,2,3,1,3],[1,3,2,1,1,3],[1,3,2,3,1,1],[2,1,1,3,1,3],[2,3,1,1,1,3],[2,3,1,3,1,1],[1,1,2,1,3,3],[1,1,2,3,3,1],[1,3,2,1,3,1],[1,1,3,1,2,3],[1,1,3,3,2,1],[1,3,3,1,2,1],[3,1,3,1,2,1],[2,1,1,3,3,1],[2,3,1,1,3,1],[2,1,3,1,1,3],[2,1,3,3,1,1],[2,1,3,1,3,1],[3,1,1,1,2,3],[3,1,1,3,2,1],[3,3,1,1,2,1],[3,1,2,1,1,3],[3,1,2,3,1,1],[3,3,2,1,1,1],[3,1,4,1,1,1],[2,2,1,4,1,1],[4,3,1,1,1,1],[1,1,1,2,2,4],[1,1,1,4,2,2],[1,2,1,1,2,4],[1,2,1,4,2,1],[1,4,1,1,2,2],[1,4,1,2,2,1],[1,1,2,2,1,4],[1,1,2,4,1,2],[1,2,2,1,1,4],[1,2,2,4,1,1],[1,4,2,1,1,2],[1,4,2,2,1,1],[2,4,1,2,1,1],[2,2,1,1,1,4],[4,1,3,1,1,1],[2,4,1,1,1,2],[1,3,4,1,1,1],[1,1,1,2,4,2],[1,2,1,1,4,2],[1,2,1,2,4,1],[1,1,4,2,1,2],[1,2,4,1,1,2],[1,2,4,2,1,1],[4,1,1,2,1,2],[4,2,1,1,1,2],[4,2,1,2,1,1],[2,1,2,1,4,1],[2,1,4,1,2,1],[4,1,2,1,2,1],[1,1,1,1,4,3],[1,1,1,3,4,1],[1,3,1,1,4,1],[1,1,4,1,1,3],[1,1,4,3,1,1],[4,1,1,1,1,3],[4,1,1,3,1,1],[1,1,3,1,4,1],[1,1,4,1,3,1],[3,1,1,1,4,1],[4,1,1,1,3,1],[2,1,1,4,1,2],[2,1,1,2,1,4],[2,1,1,2,3,2],[2,3,3,1,1,1,2]]},SINGLE_CODE_ERROR:{value:1},AVG_CODE_ERROR:{value:.5},FORMAT:{value:"code_128",writeable:!1}};return b.prototype=Object.create(a.prototype,c),b.prototype.constructor=b,b.prototype._decodeCode=function(a){var b,c,d,e,f=[0,0,0,0,0,0],g=this,h=a,i=!g._row[h],j=0,k={error:Number.MAX_VALUE,code:-1,start:a,end:a};for(b=h;bd;d++)g[d]=g[d+2];g[4]=0,g[5]=0,k--}else k++;g[k]=1,j=!j}return null},b.prototype._decode=function(){var a,b,c,d=this,e=d._findStart(),f=null,g=!1,h=[],i=0,j=0,k=[],l=[],m=!1;if(null===e)return null;switch(f={code:e.code,start:e.start,end:e.end},l.push(f),j=f.code,f.code){case d.START_CODE_A:a=d.CODE_A;break;case d.START_CODE_B:a=d.CODE_B;break;case d.START_CODE_C:a=d.CODE_C;break;default:return null}for(;!g;){if(b=m,m=!1,f=d._decodeCode(f.end),null!==f)switch(f.code!==d.STOP_CODE&&(k.push(f.code),i++,j+=i*f.code),l.push(f),a){case d.CODE_A:if(f.code<64)h.push(String.fromCharCode(32+f.code));else if(f.code<96)h.push(String.fromCharCode(f.code-64));else switch(f.code){case d.CODE_SHIFT:m=!0,a=d.CODE_B;break;case d.CODE_B:a=d.CODE_B;break;case d.CODE_C:a=d.CODE_C;break;case d.STOP_CODE:g=!0}break;case d.CODE_B:if(f.code<96)h.push(String.fromCharCode(32+f.code));else switch(f.code!=d.STOP_CODE&&(c=!1),f.code){case d.CODE_SHIFT:m=!0,a=d.CODE_A;break;case d.CODE_A:a=d.CODE_A;break;case d.CODE_C:a=d.CODE_C;break;case d.STOP_CODE:g=!0}break;case d.CODE_C:switch(f.code<100&&h.push(f.code<10?"0"+f.code:f.code),f.code){case d.CODE_A:a=d.CODE_A;break;case d.CODE_B:a=d.CODE_B;break;case d.STOP_CODE:g=!0}}else g=!0;b&&(a=a==d.CODE_A?d.CODE_B:d.CODE_A)}return null===f?null:(f.end=d._nextUnset(d._row,f.end),d._verifyTrailingWhitespace(f)?(j-=i*k[k.length-1],j%103!=k[k.length-1]?null:h.length?(h.splice(h.length-1,1),{code:h.join(""),start:e.start,end:f.end,codeset:a,startInfo:e,decodedCodes:l,endInfo:f}):null):null)},a.prototype._verifyTrailingWhitespace=function(a){var b,c=this;return b=a.end+(a.end-a.start)/2,bd;d++)e=h._matchPattern(f,h.CODE_PATTERN[d]),eh.AVG_CODE_ERROR?null:l}}else k++;g[k]=1,j=!j}return null},b.prototype._findPattern=function(a,b,c,d,e){var f,g,h,i,j,k=[],l=this,m=0,n={error:Number.MAX_VALUE,code:-1,start:0,end:0};for(b||(b=l._nextSet(l._row)),void 0===c&&(c=!1),void 0===d&&(d=!0),void 0===e&&(e=l.AVG_CODE_ERROR),f=0;fg))return n.error=g,n.start=f-i,n.end=f,n;if(!d)return null;for(h=0;h=0&&c._matchRange(a,b.start,0))return b;d=b.end,b=null}},b.prototype._verifyTrailingWhitespace=function(a){var b,c=this;return b=a.end+(a.end-a.start),bd;d++){if(a=f._decodeCode(a.end),!a)return null;a.code>=f.CODE_G_START?(a.code=a.code-f.CODE_G_START,g|=1<<5-d):g|=0<<5-d,b.push(a.code),c.push(a)}if(e=f._calculateFirstDigit(g),null===e)return null;if(b.unshift(e),a=f._findPattern(f.MIDDLE_PATTERN,a.end,!0,!1),null===a)return null;for(c.push(a),d=0;6>d;d++){if(a=f._decodeCode(a.end,f.CODE_G_START),!a)return null;c.push(a),b.push(a.code)}return a},b.prototype._decode=function(){var a,b,c=this,d=[],e=[];return(a=c._findStart())?(b={code:a.code,start:a.start,end:a.end},e.push(b),(b=c._decodePayload(b,d,e))&&(b=c._findEnd(b.end,!1))?(e.push(b),c._checksum(d)?{code:d.join(""),start:a.start,end:b.end,codeset:"",startInfo:a,decodedCodes:e}:null):null):null},b.prototype._checksum=function(a){var b,c=0;for(b=a.length-2;b>=0;b-=2)c+=a[b];for(c*=3,b=a.length-1;b>=0;b-=2)c+=a[b];return c%10===0},b}),d("image_loader",[],function(){"use strict";function a(a,b){a.onload=function(){b.loaded(this)}}var b={};return b.load=function(b,c,d,e,f){var g,h,i,j=new Array(e),k=new Array(j.length);if(f===!1)j[0]=b;else for(g=0;g1?f.size:Math.floor(b/e*f.size):b,d=f.size?b/e>1?Math.floor(e/b*f.size):f.size:e,j.x=c,j.y=d}var c,d,e={},f=null,g=["canrecord","ended"],h={},i={x:0,y:0},j={x:0,y:0};return e.getRealWidth=function(){return a.videoWidth},e.getRealHeight=function(){return a.videoHeight},e.getWidth=function(){return c},e.getHeight=function(){return d},e.setWidth=function(a){c=a},e.setHeight=function(a){d=a},e.setInputStream=function(b){f=b,a.src="undefined"!=typeof b.src?b.src:""},e.ended=function(){return a.ended},e.getConfig=function(){return f},e.setAttribute=function(b,c){a.setAttribute(b,c)},e.pause=function(){a.pause()},e.play=function(){a.play()},e.setCurrentTime=function(b){"LiveStream"!==f.type&&(a.currentTime=b)},e.addEventListener=function(b,c,d){-1!==g.indexOf(b)?(h[b]||(h[b]=[]),h[b].push(c)):a.addEventListener(b,c,d)},e.clearEventHandlers=function(){g.forEach(function(b){var c=h[b];c&&c.length>0&&c.forEach(function(c){a.removeEventListener(b,c)})})},e.trigger=function(a,c){var d,f=h[a];if("canrecord"===a&&b(),f&&f.length>0)for(d=0;d1?g.size:Math.floor(h/i*g.size):h,e=g.size?h/i>1?Math.floor(i/h*g.size):g.size:i,u.x=d,u.y=e,l=!0,j=0,setTimeout(function(){c("canrecord",[])},0)},o,n,g.sequence)}function c(a,b){var c,d=s[a];if(d&&d.length>0)for(c=0;cj?j++:setTimeout(function(){q=!0,c("ended",[])},0)),a):null},f},b}),glMatrixArrayType=Float32Array,"undefined"!=typeof window&&(window.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){window.setTimeout(a,1e3/60)}}(),navigator.getUserMedia=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia||navigator.msGetUserMedia,window.URL=window.URL||window.webkitURL||window.mozURL||window.msURL),d("typedefs",function(a){return function(){var b;return b||a.typedefs}}(this)),d("subImage",["typedefs"],function(){"use strict";function a(a,b,c){c||(c={data:null,size:b}),this.data=c.data,this.originalSize=c.size,this.I=c,this.from=a,this.size=b}return a.prototype.show=function(a,b){var c,d,e,f,g,h,i;for(b||(b=1),c=a.getContext("2d"),a.width=this.size.x,a.height=this.size.y,d=c.getImageData(0,0,a.width,a.height),e=d.data,f=0,g=0;g0&&(e=1/Math.sqrt(e),a[0]=b[0]*e,a[1]=b[1]*e),a},e.dot=function(a,b){return a[0]*b[0]+a[1]*b[1]},e.cross=function(a,b,c){var d=b[0]*c[1]-b[1]*c[0];return a[0]=a[1]=0,a[2]=d,a},e.lerp=function(a,b,c,d){var e=b[0],f=b[1];return a[0]=e+d*(c[0]-e),a[1]=f+d*(c[1]-f),a},e.transformMat2=function(a,b,c){var d=b[0],e=b[1];return a[0]=c[0]*d+c[2]*e,a[1]=c[1]*d+c[3]*e,a},e.transformMat2d=function(a,b,c){var d=b[0],e=b[1];return a[0]=c[0]*d+c[2]*e+c[4],a[1]=c[1]*d+c[3]*e+c[5],a},e.transformMat3=function(a,b,c){var d=b[0],e=b[1];return a[0]=c[0]*d+c[3]*e+c[6],a[1]=c[1]*d+c[4]*e+c[7],a},e.transformMat4=function(a,b,c){var d=b[0],e=b[1];return a[0]=c[0]*d+c[4]*e+c[12],a[1]=c[1]*d+c[5]*e+c[13],a},e.forEach=function(){var a=e.create();return function(b,c,d,e,f,g){var h,i;for(c||(c=2),d||(d=0),i=e?Math.min(e*c+d,b.length):b.length,h=d;i>h;h+=c)a[0]=b[h],a[1]=b[h+1],f(a,a,g),b[h]=a[0],b[h+1]=a[1];return b}}(),e.str=function(a){return"vec2("+a[0]+", "+a[1]+")"},"undefined"!=typeof a&&(a.vec2=e);var f={};f.create=function(){var a=new c(3);return a[0]=0,a[1]=0,a[2]=0,a},f.clone=function(a){var b=new c(3);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b},f.fromValues=function(a,b,d){var e=new c(3);return e[0]=a,e[1]=b,e[2]=d,e},f.copy=function(a,b){return a[0]=b[0],a[1]=b[1],a[2]=b[2],a},f.set=function(a,b,c,d){return a[0]=b,a[1]=c,a[2]=d,a},f.add=function(a,b,c){return a[0]=b[0]+c[0],a[1]=b[1]+c[1],a[2]=b[2]+c[2],a},f.subtract=function(a,b,c){return a[0]=b[0]-c[0],a[1]=b[1]-c[1],a[2]=b[2]-c[2],a},f.sub=f.subtract,f.multiply=function(a,b,c){return a[0]=b[0]*c[0],a[1]=b[1]*c[1],a[2]=b[2]*c[2],a},f.mul=f.multiply,f.divide=function(a,b,c){return a[0]=b[0]/c[0],a[1]=b[1]/c[1],a[2]=b[2]/c[2],a},f.div=f.divide,f.min=function(a,b,c){return a[0]=Math.min(b[0],c[0]),a[1]=Math.min(b[1],c[1]),a[2]=Math.min(b[2],c[2]),a},f.max=function(a,b,c){return a[0]=Math.max(b[0],c[0]),a[1]=Math.max(b[1],c[1]),a[2]=Math.max(b[2],c[2]),a},f.scale=function(a,b,c){return a[0]=b[0]*c,a[1]=b[1]*c,a[2]=b[2]*c,a},f.distance=function(a,b){var c=b[0]-a[0],d=b[1]-a[1],e=b[2]-a[2];return Math.sqrt(c*c+d*d+e*e)},f.dist=f.distance,f.squaredDistance=function(a,b){var c=b[0]-a[0],d=b[1]-a[1],e=b[2]-a[2];return c*c+d*d+e*e},f.sqrDist=f.squaredDistance,f.length=function(a){var b=a[0],c=a[1],d=a[2];return Math.sqrt(b*b+c*c+d*d)},f.len=f.length,f.squaredLength=function(a){var b=a[0],c=a[1],d=a[2];return b*b+c*c+d*d},f.sqrLen=f.squaredLength,f.negate=function(a,b){return a[0]=-b[0],a[1]=-b[1],a[2]=-b[2],a},f.normalize=function(a,b){var c=b[0],d=b[1],e=b[2],f=c*c+d*d+e*e;return f>0&&(f=1/Math.sqrt(f),a[0]=b[0]*f,a[1]=b[1]*f,a[2]=b[2]*f),a},f.dot=function(a,b){return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]},f.cross=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=c[0],h=c[1],i=c[2];return a[0]=e*i-f*h,a[1]=f*g-d*i,a[2]=d*h-e*g,a},f.lerp=function(a,b,c,d){var e=b[0],f=b[1],g=b[2];return a[0]=e+d*(c[0]-e),a[1]=f+d*(c[1]-f),a[2]=g+d*(c[2]-g),a},f.transformMat4=function(a,b,c){var d=b[0],e=b[1],f=b[2];return a[0]=c[0]*d+c[4]*e+c[8]*f+c[12],a[1]=c[1]*d+c[5]*e+c[9]*f+c[13],a[2]=c[2]*d+c[6]*e+c[10]*f+c[14],a},f.transformQuat=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=c[0],h=c[1],i=c[2],j=c[3],k=j*d+h*f-i*e,l=j*e+i*d-g*f,m=j*f+g*e-h*d,n=-g*d-h*e-i*f;return a[0]=k*j+n*-g+l*-i-m*-h,a[1]=l*j+n*-h+m*-g-k*-i,a[2]=m*j+n*-i+k*-h-l*-g,a},f.forEach=function(){var a=f.create();return function(b,c,d,e,f,g){var h,i;for(c||(c=3),d||(d=0),i=e?Math.min(e*c+d,b.length):b.length,h=d;i>h;h+=c)a[0]=b[h],a[1]=b[h+1],a[2]=b[h+2],f(a,a,g),b[h]=a[0],b[h+1]=a[1],b[h+2]=a[2];return b}}(),f.str=function(a){return"vec3("+a[0]+", "+a[1]+", "+a[2]+")"},"undefined"!=typeof a&&(a.vec3=f);var g={};g.create=function(){var a=new c(4);return a[0]=0,a[1]=0,a[2]=0,a[3]=0,a},g.clone=function(a){var b=new c(4);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b},g.fromValues=function(a,b,d,e){var f=new c(4);return f[0]=a,f[1]=b,f[2]=d,f[3]=e,f},g.copy=function(a,b){return a[0]=b[0],a[1]=b[1],a[2]=b[2],a[3]=b[3],a},g.set=function(a,b,c,d,e){return a[0]=b,a[1]=c,a[2]=d,a[3]=e,a},g.add=function(a,b,c){return a[0]=b[0]+c[0],a[1]=b[1]+c[1],a[2]=b[2]+c[2],a[3]=b[3]+c[3],a},g.subtract=function(a,b,c){return a[0]=b[0]-c[0],a[1]=b[1]-c[1],a[2]=b[2]-c[2],a[3]=b[3]-c[3],a},g.sub=g.subtract,g.multiply=function(a,b,c){return a[0]=b[0]*c[0],a[1]=b[1]*c[1],a[2]=b[2]*c[2],a[3]=b[3]*c[3],a},g.mul=g.multiply,g.divide=function(a,b,c){return a[0]=b[0]/c[0],a[1]=b[1]/c[1],a[2]=b[2]/c[2],a[3]=b[3]/c[3],a},g.div=g.divide,g.min=function(a,b,c){return a[0]=Math.min(b[0],c[0]),a[1]=Math.min(b[1],c[1]),a[2]=Math.min(b[2],c[2]),a[3]=Math.min(b[3],c[3]),a},g.max=function(a,b,c){return a[0]=Math.max(b[0],c[0]),a[1]=Math.max(b[1],c[1]),a[2]=Math.max(b[2],c[2]),a[3]=Math.max(b[3],c[3]),a},g.scale=function(a,b,c){return a[0]=b[0]*c,a[1]=b[1]*c,a[2]=b[2]*c,a[3]=b[3]*c,a},g.distance=function(a,b){var c=b[0]-a[0],d=b[1]-a[1],e=b[2]-a[2],f=b[3]-a[3];return Math.sqrt(c*c+d*d+e*e+f*f)},g.dist=g.distance,g.squaredDistance=function(a,b){var c=b[0]-a[0],d=b[1]-a[1],e=b[2]-a[2],f=b[3]-a[3];return c*c+d*d+e*e+f*f},g.sqrDist=g.squaredDistance,g.length=function(a){var b=a[0],c=a[1],d=a[2],e=a[3];return Math.sqrt(b*b+c*c+d*d+e*e)},g.len=g.length,g.squaredLength=function(a){var b=a[0],c=a[1],d=a[2],e=a[3];return b*b+c*c+d*d+e*e},g.sqrLen=g.squaredLength,g.negate=function(a,b){return a[0]=-b[0],a[1]=-b[1],a[2]=-b[2],a[3]=-b[3],a},g.normalize=function(a,b){var c=b[0],d=b[1],e=b[2],f=b[3],g=c*c+d*d+e*e+f*f;return g>0&&(g=1/Math.sqrt(g),a[0]=b[0]*g,a[1]=b[1]*g,a[2]=b[2]*g,a[3]=b[3]*g),a},g.dot=function(a,b){return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+a[3]*b[3]},g.lerp=function(a,b,c,d){var e=b[0],f=b[1],g=b[2],h=b[3];return a[0]=e+d*(c[0]-e),a[1]=f+d*(c[1]-f),a[2]=g+d*(c[2]-g),a[3]=h+d*(c[3]-h),a},g.transformMat4=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=b[3];return a[0]=c[0]*d+c[4]*e+c[8]*f+c[12]*g,a[1]=c[1]*d+c[5]*e+c[9]*f+c[13]*g,a[2]=c[2]*d+c[6]*e+c[10]*f+c[14]*g,a[3]=c[3]*d+c[7]*e+c[11]*f+c[15]*g,a},g.transformQuat=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=c[0],h=c[1],i=c[2],j=c[3],k=j*d+h*f-i*e,l=j*e+i*d-g*f,m=j*f+g*e-h*d,n=-g*d-h*e-i*f;return a[0]=k*j+n*-g+l*-i-m*-h,a[1]=l*j+n*-h+m*-g-k*-i,a[2]=m*j+n*-i+k*-h-l*-g,a},g.forEach=function(){var a=g.create();return function(b,c,d,e,f,g){var h,i;for(c||(c=4),d||(d=0),i=e?Math.min(e*c+d,b.length):b.length,h=d;i>h;h+=c)a[0]=b[h],a[1]=b[h+1],a[2]=b[h+2],a[3]=b[h+3],f(a,a,g),b[h]=a[0],b[h+1]=a[1],b[h+2]=a[2],b[h+3]=a[3];return b}}(),g.str=function(a){return"vec4("+a[0]+", "+a[1]+", "+a[2]+", "+a[3]+")"},"undefined"!=typeof a&&(a.vec4=g);{var h={};new Float32Array([1,0,0,1])}h.create=function(){var a=new c(4);return a[0]=1,a[1]=0,a[2]=0,a[3]=1,a},h.clone=function(a){var b=new c(4);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b},h.copy=function(a,b){return a[0]=b[0],a[1]=b[1],a[2]=b[2],a[3]=b[3],a},h.identity=function(a){return a[0]=1,a[1]=0,a[2]=0,a[3]=1,a},h.transpose=function(a,b){if(a===b){var c=b[1];a[1]=b[2],a[2]=c}else a[0]=b[0],a[1]=b[2],a[2]=b[1],a[3]=b[3];return a},h.invert=function(a,b){var c=b[0],d=b[1],e=b[2],f=b[3],g=c*f-e*d;return g?(g=1/g,a[0]=f*g,a[1]=-d*g,a[2]=-e*g,a[3]=c*g,a):null},h.adjoint=function(a,b){var c=b[0];return a[0]=b[3],a[1]=-b[1],a[2]=-b[2],a[3]=c,a},h.determinant=function(a){return a[0]*a[3]-a[2]*a[1]},h.multiply=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=b[3],h=c[0],i=c[1],j=c[2],k=c[3];return a[0]=d*h+e*j,a[1]=d*i+e*k,a[2]=f*h+g*j,a[3]=f*i+g*k,a},h.mul=h.multiply,h.rotate=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=b[3],h=Math.sin(c),i=Math.cos(c);return a[0]=d*i+e*h,a[1]=d*-h+e*i,a[2]=f*i+g*h,a[3]=f*-h+g*i,a},h.scale=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=b[3],h=c[0],i=c[1];return a[0]=d*h,a[1]=e*i,a[2]=f*h,a[3]=g*i,a},h.str=function(a){return"mat2("+a[0]+", "+a[1]+", "+a[2]+", "+a[3]+")"},"undefined"!=typeof a&&(a.mat2=h);{var i={};new Float32Array([1,0,0,1,0,0])}i.create=function(){var a=new c(6);return a[0]=1,a[1]=0,a[2]=0,a[3]=1,a[4]=0,a[5]=0,a},i.clone=function(a){var b=new c(6);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b},i.copy=function(a,b){return a[0]=b[0],a[1]=b[1],a[2]=b[2],a[3]=b[3],a[4]=b[4],a[5]=b[5],a},i.identity=function(a){return a[0]=1,a[1]=0,a[2]=0,a[3]=1,a[4]=0,a[5]=0,a},i.invert=function(a,b){var c=b[0],d=b[1],e=b[2],f=b[3],g=b[4],h=b[5],i=c*f-d*e;return i?(i=1/i,a[0]=f*i,a[1]=-d*i,a[2]=-e*i,a[3]=c*i,a[4]=(e*h-f*g)*i,a[5]=(d*g-c*h)*i,a):null},i.determinant=function(a){return a[0]*a[3]-a[1]*a[2]},i.multiply=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=b[3],h=b[4],i=b[5],j=c[0],k=c[1],l=c[2],m=c[3],n=c[4],o=c[5];return a[0]=d*j+e*l,a[1]=d*k+e*m,a[2]=f*j+g*l,a[3]=f*k+g*m,a[4]=j*h+l*i+n,a[5]=k*h+m*i+o,a},i.mul=i.multiply,i.rotate=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=b[3],h=b[4],i=b[5],j=Math.sin(c),k=Math.cos(c);return a[0]=d*k+e*j,a[1]=-d*j+e*k,a[2]=f*k+g*j,a[3]=-f*j+k*g,a[4]=k*h+j*i,a[5]=k*i-j*h,a},i.scale=function(a,b,c){var d=c[0],e=c[1];return a[0]=b[0]*d,a[1]=b[1]*e,a[2]=b[2]*d,a[3]=b[3]*e,a[4]=b[4]*d,a[5]=b[5]*e,a},i.translate=function(a,b,c){return a[0]=b[0],a[1]=b[1],a[2]=b[2],a[3]=b[3],a[4]=b[4]+c[0],a[5]=b[5]+c[1],a},i.str=function(a){return"mat2d("+a[0]+", "+a[1]+", "+a[2]+", "+a[3]+", "+a[4]+", "+a[5]+")"},"undefined"!=typeof a&&(a.mat2d=i);{var j={};new Float32Array([1,0,0,0,1,0,0,0,1])}j.create=function(){var a=new c(9);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},j.clone=function(a){var b=new c(9);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b[6]=a[6],b[7]=a[7],b[8]=a[8],b},j.copy=function(a,b){return a[0]=b[0],a[1]=b[1],a[2]=b[2],a[3]=b[3],a[4]=b[4],a[5]=b[5],a[6]=b[6],a[7]=b[7],a[8]=b[8],a},j.identity=function(a){return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=1,a[5]=0,a[6]=0,a[7]=0,a[8]=1,a},j.transpose=function(a,b){if(a===b){var c=b[1],d=b[2],e=b[5];a[1]=b[3],a[2]=b[6],a[3]=c,a[5]=b[7],a[6]=d,a[7]=e}else a[0]=b[0],a[1]=b[3],a[2]=b[6],a[3]=b[1],a[4]=b[4],a[5]=b[7],a[6]=b[2],a[7]=b[5],a[8]=b[8];return a},j.invert=function(a,b){var c=b[0],d=b[1],e=b[2],f=b[3],g=b[4],h=b[5],i=b[6],j=b[7],k=b[8],l=k*g-h*j,m=-k*f+h*i,n=j*f-g*i,o=c*l+d*m+e*n;return o?(o=1/o,a[0]=l*o,a[1]=(-k*d+e*j)*o,a[2]=(h*d-e*g)*o,a[3]=m*o,a[4]=(k*c-e*i)*o,a[5]=(-h*c+e*f)*o,a[6]=n*o,a[7]=(-j*c+d*i)*o,a[8]=(g*c-d*f)*o,a):null},j.adjoint=function(a,b){var c=b[0],d=b[1],e=b[2],f=b[3],g=b[4],h=b[5],i=b[6],j=b[7],k=b[8];return a[0]=g*k-h*j,a[1]=e*j-d*k,a[2]=d*h-e*g,a[3]=h*i-f*k,a[4]=c*k-e*i,a[5]=e*f-c*h,a[6]=f*j-g*i,a[7]=d*i-c*j,a[8]=c*g-d*f,a},j.determinant=function(a){var b=a[0],c=a[1],d=a[2],e=a[3],f=a[4],g=a[5],h=a[6],i=a[7],j=a[8];return b*(j*f-g*i)+c*(-j*e+g*h)+d*(i*e-f*h)},j.multiply=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=b[3],h=b[4],i=b[5],j=b[6],k=b[7],l=b[8],m=c[0],n=c[1],o=c[2],p=c[3],q=c[4],r=c[5],s=c[6],t=c[7],u=c[8];return a[0]=m*d+n*g+o*j,a[1]=m*e+n*h+o*k,a[2]=m*f+n*i+o*l,a[3]=p*d+q*g+r*j,a[4]=p*e+q*h+r*k,a[5]=p*f+q*i+r*l,a[6]=s*d+t*g+u*j,a[7]=s*e+t*h+u*k,a[8]=s*f+t*i+u*l,a},j.mul=j.multiply,j.translate=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=b[3],h=b[4],i=b[5],j=b[6],k=b[7],l=b[8],m=c[0],n=c[1];return a[0]=d,a[1]=e,a[2]=f,a[3]=g,a[4]=h,a[5]=i,a[6]=m*d+n*g+j,a[7]=m*e+n*h+k,a[8]=m*f+n*i+l,a},j.rotate=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=b[3],h=b[4],i=b[5],j=b[6],k=b[7],l=b[8],m=Math.sin(c),n=Math.cos(c);return a[0]=n*d+m*g,a[1]=n*e+m*h,a[2]=n*f+m*i,a[3]=n*g-m*d,a[4]=n*h-m*e,a[5]=n*i-m*f,a[6]=j,a[7]=k,a[8]=l,a},j.scale=function(a,b,c){var d=c[0],e=c[2];return a[0]=d*b[0],a[1]=d*b[1],a[2]=d*b[2],a[3]=e*b[3],a[4]=e*b[4],a[5]=e*b[5],a[6]=b[6],a[7]=b[7],a[8]=b[8],a},j.fromMat2d=function(a,b){return a[0]=b[0],a[1]=b[1],a[2]=0,a[3]=b[2],a[4]=b[3],a[5]=0,a[6]=b[4],a[7]=b[5],a[8]=1,a},j.fromQuat=function(a,b){var c=b[0],d=b[1],e=b[2],f=b[3],g=c+c,h=d+d,i=e+e,j=c*g,k=c*h,l=c*i,m=d*h,n=d*i,o=e*i,p=f*g,q=f*h,r=f*i;return a[0]=1-(m+o),a[1]=k+r,a[2]=l-q,a[3]=k-r,a[4]=1-(j+o),a[5]=n+p,a[6]=l+q,a[7]=n-p,a[8]=1-(j+m),a},j.str=function(a){return"mat3("+a[0]+", "+a[1]+", "+a[2]+", "+a[3]+", "+a[4]+", "+a[5]+", "+a[6]+", "+a[7]+", "+a[8]+")"},"undefined"!=typeof a&&(a.mat3=j);{var k={};new Float32Array([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1])}k.create=function(){var a=new c(16);return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},k.clone=function(a){var b=new c(16);return b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b[6]=a[6],b[7]=a[7],b[8]=a[8],b[9]=a[9],b[10]=a[10],b[11]=a[11],b[12]=a[12],b[13]=a[13],b[14]=a[14],b[15]=a[15],b},k.copy=function(a,b){return a[0]=b[0],a[1]=b[1],a[2]=b[2],a[3]=b[3],a[4]=b[4],a[5]=b[5],a[6]=b[6],a[7]=b[7],a[8]=b[8],a[9]=b[9],a[10]=b[10],a[11]=b[11],a[12]=b[12],a[13]=b[13],a[14]=b[14],a[15]=b[15],a},k.identity=function(a){return a[0]=1,a[1]=0,a[2]=0,a[3]=0,a[4]=0,a[5]=1,a[6]=0,a[7]=0,a[8]=0,a[9]=0,a[10]=1,a[11]=0,a[12]=0,a[13]=0,a[14]=0,a[15]=1,a},k.transpose=function(a,b){if(a===b){var c=b[1],d=b[2],e=b[3],f=b[6],g=b[7],h=b[11];a[1]=b[4],a[2]=b[8],a[3]=b[12],a[4]=c,a[6]=b[9],a[7]=b[13],a[8]=d,a[9]=f,a[11]=b[14],a[12]=e,a[13]=g,a[14]=h +}else a[0]=b[0],a[1]=b[4],a[2]=b[8],a[3]=b[12],a[4]=b[1],a[5]=b[5],a[6]=b[9],a[7]=b[13],a[8]=b[2],a[9]=b[6],a[10]=b[10],a[11]=b[14],a[12]=b[3],a[13]=b[7],a[14]=b[11],a[15]=b[15];return a},k.invert=function(a,b){var c=b[0],d=b[1],e=b[2],f=b[3],g=b[4],h=b[5],i=b[6],j=b[7],k=b[8],l=b[9],m=b[10],n=b[11],o=b[12],p=b[13],q=b[14],r=b[15],s=c*h-d*g,t=c*i-e*g,u=c*j-f*g,v=d*i-e*h,w=d*j-f*h,x=e*j-f*i,y=k*p-l*o,z=k*q-m*o,A=k*r-n*o,B=l*q-m*p,C=l*r-n*p,D=m*r-n*q,E=s*D-t*C+u*B+v*A-w*z+x*y;return E?(E=1/E,a[0]=(h*D-i*C+j*B)*E,a[1]=(e*C-d*D-f*B)*E,a[2]=(p*x-q*w+r*v)*E,a[3]=(m*w-l*x-n*v)*E,a[4]=(i*A-g*D-j*z)*E,a[5]=(c*D-e*A+f*z)*E,a[6]=(q*u-o*x-r*t)*E,a[7]=(k*x-m*u+n*t)*E,a[8]=(g*C-h*A+j*y)*E,a[9]=(d*A-c*C-f*y)*E,a[10]=(o*w-p*u+r*s)*E,a[11]=(l*u-k*w-n*s)*E,a[12]=(h*z-g*B-i*y)*E,a[13]=(c*B-d*z+e*y)*E,a[14]=(p*t-o*v-q*s)*E,a[15]=(k*v-l*t+m*s)*E,a):null},k.adjoint=function(a,b){var c=b[0],d=b[1],e=b[2],f=b[3],g=b[4],h=b[5],i=b[6],j=b[7],k=b[8],l=b[9],m=b[10],n=b[11],o=b[12],p=b[13],q=b[14],r=b[15];return a[0]=h*(m*r-n*q)-l*(i*r-j*q)+p*(i*n-j*m),a[1]=-(d*(m*r-n*q)-l*(e*r-f*q)+p*(e*n-f*m)),a[2]=d*(i*r-j*q)-h*(e*r-f*q)+p*(e*j-f*i),a[3]=-(d*(i*n-j*m)-h*(e*n-f*m)+l*(e*j-f*i)),a[4]=-(g*(m*r-n*q)-k*(i*r-j*q)+o*(i*n-j*m)),a[5]=c*(m*r-n*q)-k*(e*r-f*q)+o*(e*n-f*m),a[6]=-(c*(i*r-j*q)-g*(e*r-f*q)+o*(e*j-f*i)),a[7]=c*(i*n-j*m)-g*(e*n-f*m)+k*(e*j-f*i),a[8]=g*(l*r-n*p)-k*(h*r-j*p)+o*(h*n-j*l),a[9]=-(c*(l*r-n*p)-k*(d*r-f*p)+o*(d*n-f*l)),a[10]=c*(h*r-j*p)-g*(d*r-f*p)+o*(d*j-f*h),a[11]=-(c*(h*n-j*l)-g*(d*n-f*l)+k*(d*j-f*h)),a[12]=-(g*(l*q-m*p)-k*(h*q-i*p)+o*(h*m-i*l)),a[13]=c*(l*q-m*p)-k*(d*q-e*p)+o*(d*m-e*l),a[14]=-(c*(h*q-i*p)-g*(d*q-e*p)+o*(d*i-e*h)),a[15]=c*(h*m-i*l)-g*(d*m-e*l)+k*(d*i-e*h),a},k.determinant=function(a){var b=a[0],c=a[1],d=a[2],e=a[3],f=a[4],g=a[5],h=a[6],i=a[7],j=a[8],k=a[9],l=a[10],m=a[11],n=a[12],o=a[13],p=a[14],q=a[15],r=b*g-c*f,s=b*h-d*f,t=b*i-e*f,u=c*h-d*g,v=c*i-e*g,w=d*i-e*h,x=j*o-k*n,y=j*p-l*n,z=j*q-m*n,A=k*p-l*o,B=k*q-m*o,C=l*q-m*p;return r*C-s*B+t*A+u*z-v*y+w*x},k.multiply=function(a,b,c){var d=b[0],e=b[1],f=b[2],g=b[3],h=b[4],i=b[5],j=b[6],k=b[7],l=b[8],m=b[9],n=b[10],o=b[11],p=b[12],q=b[13],r=b[14],s=b[15],t=c[0],u=c[1],v=c[2],w=c[3];return a[0]=t*d+u*h+v*l+w*p,a[1]=t*e+u*i+v*m+w*q,a[2]=t*f+u*j+v*n+w*r,a[3]=t*g+u*k+v*o+w*s,t=c[4],u=c[5],v=c[6],w=c[7],a[4]=t*d+u*h+v*l+w*p,a[5]=t*e+u*i+v*m+w*q,a[6]=t*f+u*j+v*n+w*r,a[7]=t*g+u*k+v*o+w*s,t=c[8],u=c[9],v=c[10],w=c[11],a[8]=t*d+u*h+v*l+w*p,a[9]=t*e+u*i+v*m+w*q,a[10]=t*f+u*j+v*n+w*r,a[11]=t*g+u*k+v*o+w*s,t=c[12],u=c[13],v=c[14],w=c[15],a[12]=t*d+u*h+v*l+w*p,a[13]=t*e+u*i+v*m+w*q,a[14]=t*f+u*j+v*n+w*r,a[15]=t*g+u*k+v*o+w*s,a},k.mul=k.multiply,k.translate=function(a,b,c){var d,e,f,g,h,i,j,k,l,m,n,o,p=c[0],q=c[1],r=c[2];return b===a?(a[12]=b[0]*p+b[4]*q+b[8]*r+b[12],a[13]=b[1]*p+b[5]*q+b[9]*r+b[13],a[14]=b[2]*p+b[6]*q+b[10]*r+b[14],a[15]=b[3]*p+b[7]*q+b[11]*r+b[15]):(d=b[0],e=b[1],f=b[2],g=b[3],h=b[4],i=b[5],j=b[6],k=b[7],l=b[8],m=b[9],n=b[10],o=b[11],a[0]=d,a[1]=e,a[2]=f,a[3]=g,a[4]=h,a[5]=i,a[6]=j,a[7]=k,a[8]=l,a[9]=m,a[10]=n,a[11]=o,a[12]=d*p+h*q+l*r+b[12],a[13]=e*p+i*q+m*r+b[13],a[14]=f*p+j*q+n*r+b[14],a[15]=g*p+k*q+o*r+b[15]),a},k.scale=function(a,b,c){var d=c[0],e=c[1],f=c[2];return a[0]=b[0]*d,a[1]=b[1]*d,a[2]=b[2]*d,a[3]=b[3]*d,a[4]=b[4]*e,a[5]=b[5]*e,a[6]=b[6]*e,a[7]=b[7]*e,a[8]=b[8]*f,a[9]=b[9]*f,a[10]=b[10]*f,a[11]=b[11]*f,a[12]=b[12],a[13]=b[13],a[14]=b[14],a[15]=b[15],a},k.rotate=function(a,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D=e[0],E=e[1],F=e[2],G=Math.sqrt(D*D+E*E+F*F);return Math.abs(G)=1?(a!==b&&(a[0]=i,a[1]=j,a[2]=k,a[3]=l),a):(e=Math.acos(q),f=Math.sqrt(1-q*q),Math.abs(f)<.001?(a[0]=.5*i+.5*m,a[1]=.5*j+.5*n,a[2]=.5*k+.5*o,a[3]=.5*l+.5*p,a):(g=Math.sin((1-d)*e)/f,h=Math.sin(d*e)/f,a[0]=i*g+m*h,a[1]=j*g+n*h,a[2]=k*g+o*h,a[3]=l*g+p*h,a))},l.invert=function(a,b){var c=b[0],d=b[1],e=b[2],f=b[3],g=c*c+d*d+e*e+f*f,h=g?1/g:0;return a[0]=-c*h,a[1]=-d*h,a[2]=-e*h,a[3]=f*h,a},l.conjugate=function(a,b){return a[0]=-b[0],a[1]=-b[1],a[2]=-b[2],a[3]=b[3],a},l.length=g.length,l.len=l.length,l.squaredLength=g.squaredLength,l.sqrLen=l.squaredLength,l.normalize=g.normalize,l.fromMat3=function(){var a=[1,2,0];return function(b,c){var d,e=c[0]+c[4]+c[8];if(e>0)d=Math.sqrt(e+1),b[3]=.5*d,d=.5/d,b[0]=(c[7]-c[5])*d,b[1]=(c[2]-c[6])*d,b[2]=(c[3]-c[1])*d;else{var f=0;c[4]>c[0]&&(f=1),c[8]>c[3*f+f]&&(f=2);var g=a[f],h=a[g];d=Math.sqrt(c[3*f+f]-c[3*g+g]-c[3*h+h]+1),b[f]=.5*d,d=.5/d,b[3]=(c[3*h+g]-c[3*g+h])*d,b[g]=(c[3*g+f]+c[3*f+g])*d,b[h]=(c[3*h+f]+c[3*f+h])*d}return b}}(),l.str=function(a){return"quat("+a[0]+", "+a[1]+", "+a[2]+", "+a[3]+")"},"undefined"!=typeof a&&(a.quat=l)}(a.exports)}(),d("cluster",["gl-matrix"],function(a){"use strict";var b=a.vec2,c={create:function(a,c){function d(){e(a),f()}function e(a){i[a.id]=a,g.push(a)}function f(){var a,c=0;for(a=0;ac?!0:!1},getPoints:function(){return g},getCenter:function(){return h}}},createPoint:function(a,b,c){return{rad:a[c],point:a,id:b}}};return c}),d("array_helper",[],function(){"use strict";return{init:function(a,b){for(var c=a.length;c--;)a[c]=b},shuffle:function(a){var b,c,d=a.length-1;for(d;d>=0;d--)b=Math.floor(Math.random()*d),c=a[d],a[d]=a[b],a[b]=c;return a},toPointList:function(a){var b,c,d=[],e=[];for(b=0;b=b&&e.push(a[d]);return e},maxIndex:function(a){var b,c=0;for(b=0;ba[c]&&(c=b);return c},max:function(a){var b,c=0;for(b=0;bc&&(c=a[b]);return c},sum:function(a){for(var b=a.length,c=0;b--;)c+=a[b];return c}}}),d("cv_utils",["cluster","array_helper","gl-matrix"],function(a,b,c){"use strict";var d={},e=c.vec2,f=c.vec3;return d.imageRef=function(a,b){var c={x:a,y:b,toVec2:function(){return e.clone([this.x,this.y])},toVec3:function(){return f.clone([this.x,this.y,1])},round:function(){return this.x=Math.floor(this.x>0?this.x+.5:this.x-.5),this.y=Math.floor(this.y>0?this.y+.5:this.y-.5),this}};return c},d.computeIntegralImage2=function(a,b){var c,d,e=a.data,f=a.size.x,g=a.size.y,h=b.data,i=0,j=0,k=0,l=0,m=0;for(k=f,i=0,d=1;g>d;d++)i+=e[j],h[k]+=i,j+=f,k+=f;for(j=0,k=1,i=0,c=1;f>c;c++)i+=e[j],h[k]+=i,j++,k++;for(d=1;g>d;d++)for(j=d*f+1,k=(d-1)*f+1,l=d*f,m=(d-1)*f,c=1;f>c;c++)h[j]+=e[j]+h[k]+h[l]-h[m],j++,k++,l++,m++},d.computeIntegralImage=function(a,b){for(var c=a.data,d=a.size.x,e=a.size.y,f=b.data,g=0,h=0;d>h;h++)g+=c[h],f[h]=g;for(var i=1;e>i;i++){g=0;for(var j=0;d>j;j++)g+=c[i*d+j],f[i*d+j]=g+f[(i-1)*d+j]}},d.thresholdImage=function(a,b,c){c||(c=a);for(var d=a.data,e=d.length,f=c.data;e--;)f[e]=d[e]>e]++;return g},d.sharpenLine=function(a){var b,c,d=a.length,e=a[0],f=a[1];for(b=1;d-1>b;b++)c=a[b+1],a[b-1]=2*f-e-c&255,e=f,f=c;return a},d.determineOtsuThreshold=function(a,c){function e(a,b){var c,d=0;for(c=a;b>=c;c++)d+=h[c];return d}function f(a,b){var c,d=0;for(c=a;b>=c;c++)d+=c*h[c];return d}function g(){var g,i,j,k,l,m,n,o=[0],p=(1<k;k++)g=e(0,k),i=e(k+1,p),j=g*i,0===j&&(j=1),l=f(0,k)*i,m=f(k+1,p)*g,n=l-m,o[k]=n*n/j;return b.maxIndex(o)}c||(c=8);var h,i,j=8-c;return i=g(),i<=e;e++)for(f=0;n>f;f++)m[e*n+f]=0,m[(o-1-e)*n+f]=0;for(e=r;o-r>e;e++)for(f=0;r>=f;f++)m[e*n+f]=0,m[e*n+(n-1-f)]=0;for(e=r+1;o-r-1>e;e++)for(f=r+1;n-r>f;f++)g=p[(e-r-1)*n+(f-r-1)],h=p[(e-r-1)*n+(f+r)],i=p[(e+r)*n+(f-r-1)],j=p[(e+r)*n+(f+r)],q=j-i-h+g,k=q/s,m[e*n+f]=l[e*n+f]>k+5?0:1},d.cluster=function(b,c,d){function e(a){var b=!1;for(g=0;gb.x-j&&a.xb.y-k&&a.yd;d++){for(h=Math.floor(Math.random()*a.length),f=[],i=h,f.push(a[i]);null!==(i=c(i,!0));)f.push(a[i]);if(h>0)for(i=h;null!==(i=c(i,!1));)f.push(a[i]);f.length>g.length&&(g=f)}return g}},d.DILATE=1,d.ERODE=2,d.dilate=function(a,b){var c,d,e,f,g,h,i,j=a.data,k=b.data,l=a.size.y,m=a.size.x;for(c=1;l-1>c;c++)for(d=1;m-1>d;d++)f=c-1,g=c+1,h=d-1,i=d+1,e=j[f*m+h]+j[f*m+i]+j[c*m+d]+j[g*m+h]+j[g*m+i],k[c*m+d]=e>0?1:0},d.erode=function(a,b){var c,d,e,f,g,h,i,j=a.data,k=b.data,l=a.size.y,m=a.size.x;for(c=1;l-1>c;c++)for(d=1;m-1>d;d++)f=c-1,g=c+1,h=d-1,i=d+1,e=j[f*m+h]+j[f*m+i]+j[c*m+d]+j[g*m+h]+j[g*m+i],k[c*m+d]=5===e?1:0},d.subtract=function(a,b,c){c||(c=a);for(var d=a.data.length,e=a.data,f=b.data,g=c.data;d--;)g[d]=e[d]-f[d]},d.bitwiseOr=function(a,b,c){c||(c=a);for(var d=a.data.length,e=a.data,f=b.data,g=c.data;d--;)g[d]=e[d]||f[d]},d.countNonZero=function(a){for(var b=a.data.length,c=a.data,d=0;b--;)d+=c[b];return d},d.topGeneric=function(a,b,c){var d,e,f,g,h=0,i=0,j=[];for(d=0;b>d;d++)j[d]={score:0,item:null};for(d=0;di)for(f=j[h],f.score=e,f.item=a[d],i=Number.MAX_VALUE,g=0;b>g;g++)j[g].scoref;){for(d=0;h>d;d++)c[i]=Math.floor((.299*a[4*e+0]+.587*a[4*e+1]+.114*a[4*e+2]+(.299*a[4*(e+1)+0]+.587*a[4*(e+1)+1]+.114*a[4*(e+1)+2])+(.299*a[4*f+0]+.587*a[4*f+1]+.114*a[4*f+2])+(.299*a[4*(f+1)+0]+.587*a[4*(f+1)+1]+.114*a[4*(f+1)+2]))/4),i++,e+=2,f+=2;e+=j,f+=j}},d.computeGray=function(a,b,c){var d,e=a.length/4|0,f=c&&c.singleChannel===!0;if(f)for(d=0;e>d;d++)b[d]=a[4*d+0];else for(d=0;e>d;d++)b[d]=Math.floor(.299*a[4*d+0]+.587*a[4*d+1]+.114*a[4*d+2])},d.loadImageArray=function(a,b,c){c||(c=document.createElement("canvas"));var e=new Image;e.callback=b,e.onload=function(){c.width=this.width,c.height=this.height;var a=c.getContext("2d");a.drawImage(this,0,0);var b=new Uint8Array(this.width*this.height);a.drawImage(this,0,0);var e=a.getImageData(0,0,this.width,this.height).data;d.computeGray(e,b),this.callback(b,{x:this.width,y:this.height},this)},e.src=a},d.halfSample=function(a,b){for(var c=a.data,d=a.size.x,e=b.data,f=0,g=d,h=c.length,i=d/2,j=0;h>g;){for(var k=0;i>k;k++)e[j]=Math.floor((c[f]+c[f+1]+c[g]+c[g+1])/4),j++,f+=2,g+=2;f+=d,g+=d}},d.hsv2rgb=function(a,b){var c=a[0],d=a[1],e=a[2],f=e*d,g=f*(1-Math.abs(c/60%2-1)),h=e-f,i=0,j=0,k=0;return b=b||[0,0,0],60>c?(i=f,j=g):120>c?(i=g,j=f):180>c?(j=f,k=g):240>c?(j=g,k=f):300>c?(i=g,k=f):360>c&&(i=f,k=g),b[0]=255*(i+h)|0,b[1]=255*(j+h)|0,b[2]=255*(k+h)|0,b},d._computeDivisors=function(a){var b,c=[],d=[];for(b=1;bb[d]?d++:c++;return e},d.calculatePatchSize=function(a,b){function c(a){for(var b=0,c=a[Math.floor(a.length/2)];b0&&(c=Math.abs(a[b]-m)>Math.abs(a[b-1]-m)?a[b-1]:a[b]),m/ci[k-1]/i[k]?{x:c,y:c}:null}var d,e=this._computeDivisors(b.x),f=this._computeDivisors(b.y),g=Math.max(b.x,b.y),h=this._computeIntersection(e,f),i=[8,10,15,20,32,60,80],j={"x-small":5,small:4,medium:3,large:2,"x-large":1},k=j[a]||j.medium,l=i[k],m=Math.floor(g/l);return d=c(h),d||(d=c(this._computeDivisors(g)),d||(d=c(this._computeDivisors(m*l)))),d},d._parseCSSDimensionValues=function(a){var b={value:parseFloat(a),unit:a.indexOf("%")===a.length-1?"%":"%"};return b},d._dimensionsConverters={top:function(a,b){return"%"===a.unit?Math.floor(b.height*(a.value/100)):void 0},right:function(a,b){return"%"===a.unit?Math.floor(b.width-b.width*(a.value/100)):void 0},bottom:function(a,b){return"%"===a.unit?Math.floor(b.height-b.height*(a.value/100)):void 0},left:function(a,b){return"%"===a.unit?Math.floor(b.width*(a.value/100)):void 0}},d.computeImageArea=function(a,b,c){var e={width:a,height:b},f=Object.keys(c).reduce(function(a,b){var f=c[b],g=d._parseCSSDimensionValues(f),h=d._dimensionsConverters[b](g,e);return a[b]=h,a},{});return{sx:f.left,sy:f.top,sw:f.right-f.left,sh:f.bottom-f.top}},d}),d("image_wrapper",["subImage","cv_utils","array_helper","gl-matrix"],function(a,b,c,d){"use strict";function e(a,b,d,e){b?this.data=b:d?(this.data=new d(a.x*a.y),d===Array&&e&&c.init(this.data,0)):(this.data=new Uint8Array(a.x*a.y),Uint8Array===Array&&e&&c.init(this.data,0)),this.size=a}var f=d.vec2,g=d.mat2;return e.prototype.inImageWithBorder=function(a,b){return a.x>=b&&a.y>=b&&a.x=0&&u>=0&&n-1>v&&o-1>w){for(i=s,j=0;m>j;++j,f.add(i,y))for(k=0;l>k;++k,f.add(i,p))b.set(k,j,x(a,i[0],i[1]));return 0}var z=n-1,A=o-1,B=0;for(i=s,j=0;m>j;++j,f.add(i,y))for(k=0;l>k;++k,f.add(i,p))0<=i[0]&&0<=i[1]&&i[0]c;c++)for(d=0;e>d;d++)a.data[d*f+c]=this.data[(b.y+d)*this.size.x+b.x+c]},e.prototype.copyTo=function(a){for(var b=this.data.length,c=this.data,d=a.data;b--;)d[b]=c[b]},e.prototype.get=function(a,b){return this.data[b*this.size.x+a]},e.prototype.getSafe=function(a,b){var c;if(!this.indexMapping){for(this.indexMapping={x:[],y:[]},c=0;ca;a++)d[a]=d[(c-1)*b+a]=0;for(a=1;c-1>a;a++)d[a*b]=d[a*b+(b-1)]=0},e.prototype.invert=function(){for(var a=this.data,b=a.length;b--;)a[b]=a[b]?0:1},e.prototype.convolve=function(a){var b,c,d,e,f=a.length/2|0,g=0;for(c=0;c=e;e++)for(d=-f;f>=d;d++)g+=a[e+f][d+f]*this.getSafe(b+d,c+e);this.data[c*this.size.x+b]=g}},e.prototype.moments=function(a){var b,c,d,e,g,h,i,j,k,l,m,n,o=this.data,p=this.size.y,q=this.size.x,r=[],s=[],t=Math.PI,u=t/4;if(0>=a)return s;for(g=0;a>g;g++)r[g]={m00:0,m01:0,m10:0,m11:0,m02:0,m20:0,theta:0,rad:0};for(c=0;p>c;c++)for(e=c*c,b=0;q>b;b++)d=o[c*q+b],d>0&&(h=r[d-1],h.m00+=1,h.m01+=c,h.m10+=b,h.m11+=b*c,h.m02+=e,h.m20+=b*b);for(g=0;a>g;g++)h=r[g],isNaN(h.m00)||0===h.m00||(l=h.m10/h.m00,m=h.m01/h.m00,i=h.m11/h.m00-l*m,j=h.m02/h.m00-m*m,k=h.m20/h.m00-l*l,n=(j-k)/(2*i),n=.5*Math.atan(n)+(i>=0?u:-u)+t,h.theta=(180*n/t+90)%180-90,h.theta<0&&(h.theta+=180),h.rad=n>t?n-t:n,h.vec=f.clone([Math.cos(n),Math.sin(n)]),s.push(h));return s},e.prototype.show=function(a,b){var c,d,e,f,g,h,i;for(b||(b=1),c=a.getContext("2d"),a.width=this.size.x,a.height=this.size.y,d=c.getImageData(0,0,a.width,a.height),e=d.data,f=0,i=0;ic||c>360)&&(c=360);for(var e=[0,1,1],f=[0,0,0],g=[255,255,255],h=[0,0,0],i=[],j=a.getContext("2d"),k=j.getImageData(d.x,d.y,this.size.x,this.size.y),l=k.data,m=this.data.length;m--;)e[0]=this.data[m]*c,i=e[0]<=0?g:e[0]>=360?h:b.hsv2rgb(e,f),l[4*m+0]=i[0],l[4*m+1]=i[1],l[4*m+2]=i[2],l[4*m+3]=255;j.putImageData(k,d.x,d.y)},e}),d("tracer",[],function(){"use strict";var a={searchDirections:[[0,1],[1,1],[1,0],[1,-1],[0,-1],[-1,-1],[-1,0],[-1,1]],create:function(a,b){function c(a,b,c,d){var e,k,l;for(e=0;7>e;e++){if(k=a.cy+i[a.dir][0],l=a.cx+i[a.dir][1],f=k*j+l,g[f]===b&&(0===h[f]||h[f]===c))return h[f]=c,a.cy=k,a.cx=l,!0;0===h[f]&&(h[f]=d),a.dir=(a.dir+1)%8}return!1}function d(a,b,c){return{dir:c,x:a,y:b,next:null,prev:null}}function e(a,b,e,f,g){var h,i,j,k=null,l={cx:b,cy:a,dir:0};if(c(l,f,e,g)){k=d(b,a,l.dir),h=k,j=l.dir,i=d(l.cx,l.cy,0),i.prev=h,h.next=i,i.next=null,h=i;do l.dir=(l.dir+6)%8,c(l,f,e,g),j!=l.dir?(h.dir=l.dir,i=d(l.cx,l.cy,0),i.prev=h,h.next=i,i.next=null,h=i):(h.dir=j,h.x=l.cx,h.y=l.cy),j=l.dir;while(l.cx!=b||l.cy!=a);k.prev=h.prev,h.prev.next=k}return k}var f,g=a.data,h=b.data,i=this.searchDirections,j=a.size.x;return{trace:function(a,b,d,e){return c(a,b,d,e)},contourTracing:function(a,b,c,d,f){return e(a,b,c,d,f)}}}};return a}),d("rasterizer",["tracer"],function(a){"use strict";var b={createContour2D:function(){return{dir:null,index:null,firstVertex:null,insideContours:null,nextpeer:null,prevpeer:null}},CONTOUR_DIR:{CW_DIR:0,CCW_DIR:1,UNKNOWN_DIR:2},DIR:{OUTSIDE_EDGE:-32767,INSIDE_EDGE:-32766},create:function(c,d){var e=c.data,f=d.data,g=c.size.x,h=c.size.y,i=a.create(c,d);return{rasterize:function(a){var c,d,j,k,l,m,n,o,p,q,r,s,t=[],u=0;for(s=0;400>s;s++)t[s]=0;for(t[0]=e[0],p=null,m=1;h-1>m;m++)for(k=0,d=t[0],l=1;g-1>l;l++)if(r=m*g+l,0===f[r])if(c=e[r],c!==d){if(0===k)j=u+1,t[j]=c,d=c,n=i.contourTracing(m,l,j,c,b.DIR.OUTSIDE_EDGE),null!==n&&(u++,k=j,o=b.createContour2D(),o.dir=b.CONTOUR_DIR.CW_DIR,o.index=k,o.firstVertex=n,o.nextpeer=p,o.insideContours=null,null!==p&&(p.prevpeer=o),p=o);else if(n=i.contourTracing(m,l,b.DIR.INSIDE_EDGE,c,k),null!==n){for(o=b.createContour2D(),o.firstVertex=n,o.insideContours=null,o.dir=0===a?b.CONTOUR_DIR.CCW_DIR:b.CONTOUR_DIR.CW_DIR,o.index=a,q=p;null!==q&&q.index!==k;)q=q.nextpeer;null!==q&&(o.nextpeer=q.insideContours,null!==q.insideContours&&(q.insideContours.prevpeer=o),q.insideContours=o)}}else f[r]=k;else f[r]===b.DIR.OUTSIDE_EDGE||f[r]===b.DIR.INSIDE_EDGE?(k=0,d=f[r]===b.DIR.INSIDE_EDGE?e[r]:t[0]):(k=f[r],d=t[k]);for(q=p;null!==q;)q.index=a,q=q.nextpeer;return{cc:p,count:u}},debug:{drawContour:function(a,c){var d,e,f,g=a.getContext("2d"),h=c;for(g.strokeStyle="red",g.fillStyle="red",g.lineWidth=1,d=null!==h?h.insideContours:null;null!==h;){switch(null!==d?(e=d,d=d.nextpeer):(e=h,h=h.nextpeer,d=null!==h?h.insideContours:null),e.dir){case b.CONTOUR_DIR.CW_DIR:g.strokeStyle="red";break;case b.CONTOUR_DIR.CCW_DIR:g.strokeStyle="blue";break;case b.CONTOUR_DIR.UNKNOWN_DIR:g.strokeStyle="green"}f=e.firstVertex,g.beginPath(),g.moveTo(f.x,f.y);do f=f.next,g.lineTo(f.x,f.y);while(f!==e.firstVertex);g.stroke()}}}}}};return b}),d("skeletonizer",[],function(){"use strict";function a(stdlib, foreign, buffer) {"use asm";var images=new stdlib.Uint8Array(buffer),size=foreign.size|0,imul=stdlib.Math.imul;function erode(inImagePtr, outImagePtr) {inImagePtr=inImagePtr|0;outImagePtr=outImagePtr|0;var v=0,u=0,sum=0,yStart1=0,yStart2=0,xStart1=0,xStart2=0,offset=0;for ( v=1; (v|0)<((size - 1)|0); v=(v+1)|0) {offset=(offset+size)|0;for ( u=1; (u|0)<((size - 1)|0); u=(u+1)|0) {yStart1=(offset - size)|0;yStart2=(offset+size)|0;xStart1=(u - 1)|0;xStart2=(u+1)|0;sum=((images[(inImagePtr+yStart1+xStart1)|0]|0)+(images[(inImagePtr+yStart1+xStart2)|0]|0)+(images[(inImagePtr+offset+u)|0]|0)+(images[(inImagePtr+yStart2+xStart1)|0]|0)+(images[(inImagePtr+yStart2+xStart2)|0]|0))|0;if ((sum|0) == (5|0)) {images[(outImagePtr+offset+u)|0]=1;} else {images[(outImagePtr+offset+u)|0]=0;}}}return;}function subtract(aImagePtr, bImagePtr, outImagePtr) {aImagePtr=aImagePtr|0;bImagePtr=bImagePtr|0;outImagePtr=outImagePtr|0;var length=0;length=imul(size, size)|0;while ((length|0)>0) {length=(length - 1)|0;images[(outImagePtr+length)|0]=((images[(aImagePtr+length)|0]|0) - (images[(bImagePtr+length)|0]|0))|0;}}function bitwiseOr(aImagePtr, bImagePtr, outImagePtr) {aImagePtr=aImagePtr|0;bImagePtr=bImagePtr|0;outImagePtr=outImagePtr|0;var length=0;length=imul(size, size)|0;while ((length|0)>0) {length=(length - 1)|0;images[(outImagePtr+length)|0]=((images[(aImagePtr+length)|0]|0)|(images[(bImagePtr+length)|0]|0))|0;}}function countNonZero(imagePtr) {imagePtr=imagePtr|0;var sum=0,length=0;length=imul(size, size)|0;while ((length|0)>0) {length=(length - 1)|0;sum=((sum|0)+(images[(imagePtr+length)|0]|0))|0;}return (sum|0);}function init(imagePtr, value) {imagePtr=imagePtr|0;value=value|0;var length=0;length=imul(size, size)|0;while ((length|0)>0) {length=(length - 1)|0;images[(imagePtr+length)|0]=value;}}function dilate(inImagePtr, outImagePtr) {inImagePtr=inImagePtr|0;outImagePtr=outImagePtr|0;var v=0,u=0,sum=0,yStart1=0,yStart2=0,xStart1=0,xStart2=0,offset=0;for ( v=1; (v|0)<((size - 1)|0); v=(v+1)|0) {offset=(offset+size)|0;for ( u=1; (u|0)<((size - 1)|0); u=(u+1)|0) {yStart1=(offset - size)|0;yStart2=(offset+size)|0;xStart1=(u - 1)|0;xStart2=(u+1)|0;sum=((images[(inImagePtr+yStart1+xStart1)|0]|0)+(images[(inImagePtr+yStart1+xStart2)|0]|0)+(images[(inImagePtr+offset+u)|0]|0)+(images[(inImagePtr+yStart2+xStart1)|0]|0)+(images[(inImagePtr+yStart2+xStart2)|0]|0))|0;if ((sum|0)>(0|0)) {images[(outImagePtr+offset+u)|0]=1;} else {images[(outImagePtr+offset+u)|0]=0;}}}return;}function memcpy(srcImagePtr, dstImagePtr) {srcImagePtr=srcImagePtr|0;dstImagePtr=dstImagePtr|0;var length=0;length=imul(size, size)|0;while ((length|0)>0) {length=(length - 1)|0;images[(dstImagePtr+length)|0]=(images[(srcImagePtr+length)|0]|0);}}function zeroBorder(imagePtr) {imagePtr=imagePtr|0;var x=0,y=0;for ( x=0; (x|0)<((size - 1)|0); x=(x+1)|0) {images[(imagePtr+x)|0]=0;images[(imagePtr+y)|0]=0;y=((y+size) - 1)|0;images[(imagePtr+y)|0]=0;y=(y+1)|0;}for ( x=0; (x|0)<(size|0); x=(x+1)|0) {images[(imagePtr+y)|0]=0;y=(y+1)|0;}}function skeletonize() {var subImagePtr=0,erodedImagePtr=0,tempImagePtr=0,skelImagePtr=0,sum=0,done=0;erodedImagePtr=imul(size, size)|0;tempImagePtr=(erodedImagePtr+erodedImagePtr)|0;skelImagePtr=(tempImagePtr+erodedImagePtr)|0;init(skelImagePtr, 0);zeroBorder(subImagePtr);do {erode(subImagePtr, erodedImagePtr);dilate(erodedImagePtr, tempImagePtr);subtract(subImagePtr, tempImagePtr, tempImagePtr);bitwiseOr(skelImagePtr, tempImagePtr, skelImagePtr);memcpy(erodedImagePtr, subImagePtr);sum=countNonZero(subImagePtr)|0;done=((sum|0) == 0|0);} while(!done);}return {skeletonize : skeletonize};} +return Math.imul=Math.imul||function(a,b){var c=a>>>16&65535,d=65535&a,e=b>>>16&65535,f=65535&b;return d*f+(c*f+d*e<<16>>>0)|0},a}),d("image_debug",[],function(){"use strict";return{drawRect:function(a,b,c,d){c.strokeStyle=d.color,c.fillStyle=d.color,c.lineWidth=1,c.beginPath(),c.strokeRect(a.x,a.y,b.x,b.y)},drawPath:function(a,b,c,d){c.strokeStyle=d.color,c.fillStyle=d.color,c.lineWidth=d.lineWidth,c.beginPath(),c.moveTo(a[0][b.x],a[0][b.y]);for(var e=1;eb&&(b+=180),b=(180-b)*Math.PI/180,f=I.clone([Math.cos(b),Math.sin(b),-Math.sin(b),Math.cos(b)]),c=0;cd;d++)H.transformMat2(e.box[d],e.box[d],f);t.boxFromPatches.showTransformed&&g.drawPath(e.box,{x:0,y:1},F.ctx.binary,{color:"#99ff00",lineWidth:2})}for(c=0;cd;d++)e.box[d][0]l&&(l=e.box[d][0]),e.box[d][1]m&&(m=e.box[d][1]);for(h=[[j,k],[l,k],[l,m],[j,m]],t.boxFromPatches.showTransformedBox&&g.drawPath(h,{x:0,y:1},F.ctx.binary,{color:"#ff0000",lineWidth:2}),i=t.halfSample?2:1,f=I.invert(f,f),d=0;4>d;d++)H.transformMat2(h[d],h[d],f);for(t.boxFromPatches.showBB&&g.drawPath(h,{x:0,y:1},F.ctx.binary,{color:"#ff0000",lineWidth:2}),d=0;4>d;d++)H.scale(h[d],h[d],i);return h}function l(){b.otsuThreshold(u,B),B.zeroBorder(),t.showCanvas&&B.show(F.dom.binary,255)}function m(){var a,b,d,e,h,i,j,k,l=[];for(a=0;ab;b++)d.push(0);for(c=z.data.length;c--;)z.data[c]>0&&d[z.data[c]-1]++;return d=d.map(function(a,b){return{val:a,label:b+1}}),d.sort(function(a,b){return b.val-a.val}),e=d.filter(function(a){return a.val>=5})}function o(a,c){var d,e,f,h,i,j=[],l=[],m=[0,1,1],n=[0,0,0];for(d=0;d=2){for(e=0;el&&j.push(a[e]);if(j.length>=2){for(i=j.length,g=p(j),f=0,e=0;e1&&g.length>=j.length/4*3&&g.length>a.length/4&&(f/=g.length,h={index:b[1]*G.x+b[0],pos:{x:c,y:d},box:[H.clone([c,d]),H.clone([c+w.size.x,d]),H.clone([c+w.size.x,d+w.size.y]),H.clone([c,d+w.size.y])],moments:g,rad:f,vec:H.clone([Math.cos(f),Math.sin(f)])},k.push(h))}}return k}function s(a){function c(){var a;for(a=0;ak&&e(h))):z.data[h]=Number.MAX_VALUE}var h,i,j=0,k=.95,l=0,m=[0,1,1],n=[0,0,0];for(f.init(y.data,0),f.init(z.data,0),f.init(A.data,null),h=0;h0&&z.data[h]<=j&&(i=A.data[h],m[0]=z.data[h]/(j+1)*360,b.hsv2rgb(m,n),g.drawRect(i.pos,w.size,F.ctx.binary,{color:"rgb("+n.join(",")+")",lineWidth:2}));return j}var t,u,v,w,x,y,z,A,B,C,D,E,F={ctx:{binary:null},dom:{binary:null}},G={x:0,y:0},H=h.vec2,I=h.mat2,J=this;return{init:function(a,b){t=b,D=a,i(),j()},locate:function(){var a,c,d;if(t.halfSample&&b.halfSample(D,u),l(),a=m(),a.lengthe?null:(c=n(e),0===c.length?null:d=o(c,e))},checkImageConstraints:function(a,c){var d,e,f,g=a.getWidth(),h=a.getHeight(),i=c.halfSample?.5:1;if(a.getConfig().area&&(f=b.computeImageArea(g,h,a.getConfig().area),a.setTopRight({x:f.sx,y:f.sy}),a.setCanvasSize({x:g,y:h}),g=f.sw,h=f.sh),e={x:Math.floor(g*i),y:Math.floor(h*i)},d=b.calculatePatchSize(c.patchSize,e),console.log("Patch-Size: "+JSON.stringify(d)),a.setWidth(Math.floor(Math.floor(e.x/d.x)*(1/i)*d.x)),a.setHeight(Math.floor(Math.floor(e.y/d.y)*(1/i)*d.y)),a.getWidth()%d.x===0&&a.getHeight()%d.y===0)return!0;throw new Error("Image dimensions do not comply with the current settings: Width ("+g+" )and height ("+h+") must a multiple of "+d.x)}}}),d("bresenham",["cv_utils","image_wrapper"],function(a,b){"use strict";var c={},d={DIR:{UP:1,DOWN:-1}};return c.getBarcodeLine=function(a,b,c){function d(a,b){l=s[b*t+a],u+=l,v=v>l?l:v,w=l>w?l:w,r.push(l)}var e,f,g,h,i,j,k,l,m=0|b.x,n=0|b.y,o=0|c.x,p=0|c.y,q=Math.abs(p-n)>Math.abs(o-m),r=[],s=a.data,t=a.size.x,u=0,v=255,w=0;for(q&&(j=m,m=n,n=j,j=o,o=p,p=j),m>o&&(j=m,m=o,o=j,j=n,n=p,p=j),e=o-m,f=Math.abs(p-n),g=e/2|0,i=n,h=p>n?1:-1,k=m;o>k;k++)q?d(i,k):d(k,i),g-=f,0>g&&(i+=h,g+=e);return{line:r,min:v,max:w}},c.toOtsuBinaryLine=function(c){var d=c.line,e=new b({x:d.length-1,y:1},d),f=a.determineOtsuThreshold(e,5);return d=a.sharpenLine(d),a.thresholdImage(e,f),{line:d,threshold:f}},c.toBinaryLine=function(a){var b,c,e,f,g,h,i=a.min,j=a.max,k=a.line,l=i+(j-i)/2,m=[],n=(j-i)/12,o=-n;for(e=k[0]>l?d.DIR.UP:d.DIR.DOWN,m.push({pos:0,val:k[0]}),g=0;gb+c&&k[g+1]<1.5*l?d.DIR.DOWN:b+c>n&&k[g+1]>.5*l?d.DIR.UP:e,e!==f&&(m.push({pos:g,val:k[g]}),e=f);for(m.push({pos:k.length,val:k[k.length-1]}),h=m[0].pos;hl?0:1;for(g=1;gm[g].val?m[g].val+(m[g+1].val-m[g].val)/3*2|0:m[g+1].val+(m[g].val-m[g+1].val)/3|0,h=m[g].pos;hn?0:1;return{line:k,threshold:n}},c.debug={printFrequency:function(a,b){var c,d=b.getContext("2d");for(b.width=a.length,b.height=256,d.beginPath(),d.strokeStyle="blue",c=0;cd;d++)if(e._row[d]^h)c[i]++;else{if(i++,i===f)break;c[i]=1,h=!h}return c},c.prototype._decode=function(){var a,c,d,e,f=this,g=[0,0,0,0,0,0,0,0,0],h=[],i=f._findStart();if(!i)return null;e=f._nextSet(f._row,i.end);do{if(g=f._toCounters(e,g),d=f._toPattern(g),0>d)return null;if(a=f._patternToChar(d),0>a)return null;h.push(a),c=e,e+=b.sum(g),e=f._nextSet(f._row,e)}while("*"!==a);return h.pop(),h.length&&f._verifyTrailingWhitespace(c,e,g)?{code:h.join(""),start:i.start,end:e,startInfo:i,decodedCodes:h}:null},c.prototype._verifyTrailingWhitespace=function(a,c,d){var e,f=b.sum(d);return e=c-a-f,3*e>=f?!0:!1},c.prototype._patternToChar=function(a){var b,c=this;for(b=0;bb&&(d=a[c]);return d},c.prototype._toPattern=function(a){for(var b,c,d=a.length,e=0,f=d,g=0,h=this;f>3;){for(e=h._findNextWidth(a,e),f=0,b=0,c=0;d>c;c++)a[c]>e&&(b|=1<c&&f>0;c++)if(a[c]>e&&(f--,2*a[c]>=g))return-1;return b}}return-1},c.prototype._findStart=function(){var a,b,c,d=this,e=d._nextSet(d._row),f=e,g=[0,0,0,0,0,0,0,0,0],h=0,i=!1;for(a=e;ab;b++)g[b]=g[b+2];g[7]=0,g[8]=0,h--}else h++;g[h]=1,i=!i}return null},c}),d("code_39_vin_reader",["./code_39_reader"],function(a){"use strict";function b(){a.call(this)}var c={IOQ:/[IOQ]/g,AZ09:/[A-Z0-9]{17}/};return b.prototype=Object.create(a.prototype),b.prototype.constructor=b,b.prototype._decode=function(){var b=a.prototype._decode.apply(this);if(!b)return null;var d=b.code;if(d)return d=d.replace(c.IOQ,""),d.match(c.AZ09)?this._checkChecksum(d)?(b.code=d,b):null:(console.log("Failed AZ09 pattern code:",d),null)},b.prototype._checkChecksum=function(a){return!!a},b}),d("codabar_reader",["./barcode_reader"],function(a){"use strict";function b(){a.call(this),this._counters=[]}var c={ALPHABETH_STRING:{value:"0123456789-$:/.+ABCD"},ALPHABET:{value:[48,49,50,51,52,53,54,55,56,57,45,36,58,47,46,43,65,66,67,68]},CHARACTER_ENCODINGS:{value:[3,6,9,96,18,66,33,36,48,72,12,24,69,81,84,21,26,41,11,14]},START_END:{value:[26,41,11,14]},MIN_ENCODED_CHARS:{value:4},MAX_ACCEPTABLE:{value:2},PADDING:{value:1.5},FORMAT:{value:"codabar",writeable:!1}};return b.prototype=Object.create(a.prototype,c),b.prototype.constructor=b,b.prototype._decode=function(){var a,b,c,d,e,f=this,g=[];if(f._fillCounters(),a=f._findStart(),!a)return null;d=a.startCounter;do{if(c=f._toPattern(d),0>c)return null;if(b=f._patternToChar(c),0>b)return null;if(g.push(b),d+=8,g.length>1&&f._isStartEnd(c))break}while(df._counters.length?f._counters.length:d,e=a.start+f._sumCounters(a.startCounter,d-8),{code:g.join(""),start:a.start,end:e,startInfo:a,decodedCodes:g}):null},b.prototype._verifyWhitespace=function(a,b){return(0>=a-1||this._counters[a-1]>=this._calculatePatternLength(a)/2)&&(b+8>=this._counters.length||this._counters[b+7]>=this._calculatePatternLength(b)/2)?!0:!1},b.prototype._calculatePatternLength=function(a){var b,c=0;for(b=a;a+7>b;b++)c+=this._counters[b];return c},b.prototype._thresholdResultPattern=function(a,b){var c,d,e,f,g,h=this,i={space:{narrow:{size:0,counts:0,min:0,max:Number.MAX_VALUE},wide:{size:0,counts:0,min:0,max:Number.MAX_VALUE}},bar:{narrow:{size:0,counts:0,min:0,max:Number.MAX_VALUE},wide:{size:0,counts:0,min:0,max:Number.MAX_VALUE}}},j=b;for(e=0;e=0;f--)c=2===(1&f)?i.bar:i.space,d=1===(1&g)?c.wide:c.narrow,d.size+=h._counters[j+f],d.counts++,g>>=1;j+=8}return["space","bar"].forEach(function(a){var b=i[a];b.wide.min=Math.floor((b.narrow.size/b.narrow.counts+b.wide.size/b.wide.counts)/2),b.narrow.max=Math.ceil(b.wide.min),b.wide.max=Math.ceil((b.wide.size*h.MAX_ACCEPTABLE+h.PADDING)/b.wide.counts)}),i},b.prototype._charToPattern=function(a){var b,c=this,d=a.charCodeAt(0);for(b=0;b=0;d--){if(e=0===(1&d)?j.bar:j.space,f=1===(1&h)?e.wide:e.narrow,g=i._counters[k+d],gf.max)return!1;h>>=1}k+=8}return!0},b.prototype._fillCounters=function(){var a,b=this,c=0,d=!0,e=b._nextUnset(b._row);for(b._counters.length=0,b._counters[c]=0,a=e;ac;c+=2)d=this._counters[c],d>f&&(f=d),e>d&&(e=d);return(e+f)/2|0},b.prototype._toPattern=function(a){var b,c,d,e,f=7,g=a+f,h=1<this._counters.length)return-1;for(b=this._computeAlternatingThreshold(a,g),c=this._computeAlternatingThreshold(a+1,g),d=0;f>d;d++)e=0===(1&d)?b:c,this._counters[a+d]>e&&(i|=h),h>>=1;return i},b.prototype._isStartEnd=function(a){var b;for(b=0;bc;c++)d+=this._counters[c];return d},b.prototype._findStart=function(){var a,b,c,d=this,e=d._nextUnset(d._row);for(a=1;ad;d++){if(a=e._decodeCode(a.end,e.CODE_G_START),!a)return null;b.push(a.code),c.push(a)}if(a=e._findPattern(e.MIDDLE_PATTERN,a.end,!0,!1),null===a)return null;for(c.push(a),d=0;4>d;d++){if(a=e._decodeCode(a.end,e.CODE_G_START),!a)return null;c.push(a),b.push(a.code)}return a},b}),d("upc_e_reader",["./ean_reader"],function(a){"use strict";function b(){a.call(this)}var c={CODE_FREQUENCY:{value:[[56,52,50,49,44,38,35,42,41,37],[7,11,13,14,19,25,28,21,22,26]]},STOP_PATTERN:{value:[1/6*7,1/6*7,1/6*7,1/6*7,1/6*7,1/6*7]},FORMAT:{value:"upc_e",writeable:!1}};return b.prototype=Object.create(a.prototype,c),b.prototype.constructor=b,b.prototype._decodePayload=function(a,b,c){var d,e=this,f=0;for(d=0;6>d;d++){if(a=e._decodeCode(a.end),!a)return null;a.code>=e.CODE_G_START&&(a.code=a.code-e.CODE_G_START,f|=1<<5-d),b.push(a.code),c.push(a)}return e._determineParity(f,b)?a:null},b.prototype._determineParity=function(a,b){var c,d,e=this;for(d=0;d=c?b.concat(a.slice(1,3)).concat([c,0,0,0,0]).concat(a.slice(3,6)):3===c?b.concat(a.slice(1,4)).concat([0,0,0,0,0]).concat(a.slice(4,6)):4===c?b.concat(a.slice(1,5)).concat([0,0,0,0,0,a[5]]):b.concat(a.slice(1,6)).concat([0,0,0,0,c]),b.push(a[a.length-1]),b},b.prototype._checksum=function(b){return a.prototype._checksum.call(this,this._convertToUPCA(b))},b.prototype._findEnd=function(b,c){return c=!0,a.prototype._findEnd.call(this,b,c)},b.prototype._verifyTrailingWhitespace=function(a){var b,c=this;return b=a.end+(a.end-a.start)/2,b1&&(!d.inImageWithBorder(a[0],0)||!d.inImageWithBorder(a[1],0));)c-=Math.ceil(c/2),e(-c);return a}function i(a){return[{x:(a[1][0]-a[0][0])/2+a[0][0],y:(a[1][1]-a[0][1])/2+a[0][1]},{x:(a[3][0]-a[2][0])/2+a[2][0],y:(a[3][1]-a[2][1])/2+a[2][1]}]}function j(e){var f,g=null,h=a.getBarcodeLine(d,e[0],e[1]);for(c.showFrequency&&(b.drawPath(e,{x:"x",y:"y"},o.ctx.overlay,{color:"red",lineWidth:3}),a.debug.printFrequency(h.line,o.dom.frequency)),a.toBinaryLine(h),c.showPattern&&a.debug.printPattern(h.line,o.dom.pattern),f=0;fd&&null===i;d++)e=g/h*d*(d%2===0?-1:1),f={y:e*k,x:e*l},b[0].y+=f.x,b[0].x-=f.y,b[1].y+=f.x,b[1].x-=f.y,i=j(b);return i}function m(a){return Math.sqrt(Math.pow(Math.abs(a[1].y-a[0].y),2)+Math.pow(Math.abs(a[1].x-a[0].x),2))}function n(a){var d,e,f,g,k=o.ctx.overlay;return c.drawBoundingBox&&k&&b.drawPath(a,{x:0,y:1},k,{color:"blue",lineWidth:2}),d=i(a),g=m(d),e=Math.atan2(d[1].y-d[0].y,d[1].x-d[0].x),d=h(d,e,Math.floor(.1*g)),null===d?null:(f=j(d),null===f&&(f=l(a,d,e)),null===f?null:(f&&c.drawScanline&&k&&b.drawPath(d,{x:"x",y:"y"},k,{color:"red",lineWidth:3}),{codeResult:f.codeResult,line:d,angle:e,pattern:f.barcodeLine.line,threshold:f.barcodeLine.threshold}))}var o={ctx:{frequency:null,pattern:null,overlay:null},dom:{frequency:null,pattern:null,overlay:null}},p=[];return e(),f(),g(),{decodeFromBoundingBox:function(a){return n(a)},decodeFromBoundingBoxes:function(a){var b,c;for(b=0;b0?a.videoWidth>0&&a.videoHeight>0?(console.log(a.videoWidth+"px x "+a.videoHeight+"px"),b()):window.setTimeout(c,500):b("Unable to play video stream. Is webcam working?"),d--}var d=10;c()}function d(a,d,e){b(a,function(a){d.src=a,h&&d.removeEventListener("loadeddata",h,!1),h=c.bind(null,d,e),d.addEventListener("loadeddata",h,!1),d.play()},function(a){e(a)})}function e(b,c){var d={audio:!1,video:!0},e=a.mergeObjects({width:640,height:480,minAspectRatio:0,maxAspectRatio:100,facing:"environment"},b);return"undefined"==typeof MediaStreamTrack||"undefined"==typeof MediaStreamTrack.getSources?(d.video={mediaSource:"camera",width:{min:e.width,max:e.width},height:{min:e.height,max:e.height},require:["width","height"]},c(d)):void MediaStreamTrack.getSources(function(a){for(var b,f=0;f!=a.length;++f){var g=a[f];"video"==g.kind&&g.facing==e.facing&&(b=g.id)}return d.video={mandatory:{minWidth:e.width,minHeight:e.height,minAspectRatio:e.minAspectRatio,maxAspectRatio:e.maxAspectRatio},optional:[{sourceId:b}]},c(d)})}function f(a,b,c){e(b,function(b){d(b,a,c)})}var g,h;return{request:function(a,b,c){f(a,b,c)},release:function(){var a=g&&g.getVideoTracks();a.length&&a[0].stop(),g=null}}}),d("result_collector",["image_debug"],function(a){"use strict";function b(a,b){return b?b.some(function(b){return Object.keys(b).every(function(c){return b[c]===a[c]})}):!1}function c(a,b){return"function"==typeof b?b(a):!0}return{create:function(d){function e(a){return i&&a&&!b(a,d.blacklist)&&c(a,d.filter)}var f=document.createElement("canvas"),g=f.getContext("2d"),h=[],i=d.capacity||20,j=d.capture===!0;return{addResult:function(b,c,d){var k={};e(d)&&(i--,k.codeResult=d,j&&(f.width=c.x,f.height=c.y,a.drawImage(b,c,g),k.frame=f.toDataURL()),h.push(k))},getResults:function(){return h}}}}}),d("quagga",["code_128_reader","ean_reader","input_stream","image_wrapper","barcode_locator","barcode_decoder","frame_grabber","html_utils","config","events","camera_access","image_debug","gl-matrix","result_collector"],function(b,c,d,e,f,g,h,i,j,k,l,m,n,o){"use strict";function p(a){v(a),M=g.create(j.decoder,K)}function q(){if("undefined"!=typeof document)for(var a=[{node:document.querySelector("div[data-controls]"),prop:j.controls},{node:O.dom.overlay,prop:j.visual.show}],b=0;b0?C(function(){console.log("Workers created"),t(a)}):(p(),t(a))}function t(a){H.play(),a()}function u(){if("undefined"!=typeof document){var a=document.querySelector("#interactive.viewport");if(O.dom.image=document.querySelector("canvas.imgBuffer"),O.dom.image||(O.dom.image=document.createElement("canvas"),O.dom.image.className="imgBuffer",a&&"ImageStream"==j.inputStream.type&&a.appendChild(O.dom.image)),O.ctx.image=O.dom.image.getContext("2d"),O.dom.image.width=H.getCanvasSize().x,O.dom.image.height=H.getCanvasSize().y,O.dom.overlay=document.querySelector("canvas.drawingBuffer"),!O.dom.overlay){O.dom.overlay=document.createElement("canvas"),O.dom.overlay.className="drawingBuffer",a&&a.appendChild(O.dom.overlay);var b=document.createElement("br");b.setAttribute("clear","all"),a&&a.appendChild(b)}O.ctx.overlay=O.dom.overlay.getContext("2d"),O.dom.overlay.width=H.getCanvasSize().x,O.dom.overlay.height=H.getCanvasSize().y}}function v(a){K=a?a:new e({x:H.getWidth(),y:H.getHeight()}),console.log(K.size),L=[R.clone([0,0]),R.clone([0,K.size.y]),R.clone([K.size.x,K.size.y]),R.clone([K.size.x,0])],f.init(K,j.locator)}function w(){return j.locate?f.locate():[[R.clone(L[0]),R.clone(L[1]),R.clone(L[2]),R.clone(L[3])]]}function x(a){function b(a){for(var b=a.length;b--;)a[b][0]+=f,a[b][1]+=g}function c(a){a[0].x+=f,a[0].y+=g,a[1].x+=f,a[1].y+=g}var d,e=H.getTopRight(),f=e.x,g=e.y;if(a&&(0!==f||0!==g)&&(a.line&&2===a.line.length&&c(a.line),a.boxes&&a.boxes.length>0))for(d=0;d0){if(a=P.filter(function(a){return!a.busy})[0],!a)return;I.attachData(a.imageData)}else I.attachData(K.data);I.grab()&&(a?(a.busy=!0,a.worker.postMessage({cmd:"process",imageData:a.imageData},[a.imageData.buffer])):z())}else z()}function B(){J=!1,function a(){J||(A(),Q&&"LiveStream"==j.inputStream.type&&window.requestAnimFrame(a))}()}function C(a){function b(b){P.push(b),P.length>=j.numOfWorkers&&a()}var c;for(P=[],c=0;c0&&P.forEach(function(b){b.worker.postMessage({cmd:"setReaders",readers:a})})}var H,I,J,K,L,M,N,O={ctx:{image:null,overlay:null},dom:{image:null,overlay:null}},P=[],Q=!0,R=n.vec2;return{init:function(a,b,c){return j=i.mergeObjects(j,a),c?(Q=!1,p(c),b()):void r(b)},start:function(){B()},stop:function(){J=!0,P.forEach(function(a){a.worker.terminate(),console.log("Worker terminated!")}),P.length=0,"LiveStream"===j.inputStream.type&&(l.release(),H.clearEventHandlers())},pause:function(){J=!0},onDetected:function(a){k.subscribe("detected",a)},onProcessed:function(a){k.subscribe("processed",a)},setReaders:function(a){G(a)},registerResultCollector:function(a){a&&"function"==typeof a.addResult&&(N=a)},canvas:O,decodeSingle:function(a,b){a=i.mergeObjects({inputStream:{type:"ImageStream",sequence:!1,size:800,src:a.src},numOfWorkers:1,locator:{halfSample:!1}},a),this.init(a,function(){k.once("processed",function(a){J=!0,b.call(null,a)},!0),B()})},Reader:{EANReader:c,Code128Reader:b},ImageWrapper:e,ImageDebug:m,ResultCollector:o}}),c("quagga")}); \ No newline at end of file diff --git a/example/css/styles.css b/example/css/styles.css index 16a76e6..a39a361 100644 --- a/example/css/styles.css +++ b/example/css/styles.css @@ -74,7 +74,7 @@ padding: 10px 0; } /* line 50, ../sass/_viewport.scss */ -#result_strip ul.thumbnails { +#result_strip > ul { padding: 0; margin: 0; list-style-type: none; @@ -84,34 +84,34 @@ white-space: nowrap; } /* line 59, ../sass/_viewport.scss */ -#result_strip ul.thumbnails > li { +#result_strip > ul > li { display: inline-block; vertical-align: middle; width: 160px; } /* line 63, ../sass/_viewport.scss */ -#result_strip ul.thumbnails > li .thumbnail { +#result_strip > ul > li .thumbnail { padding: 5px; margin: 4px; border: 1px dashed #CCC; } /* line 68, ../sass/_viewport.scss */ -#result_strip ul.thumbnails > li .thumbnail img { +#result_strip > ul > li .thumbnail img { max-width: 140px; } /* line 71, ../sass/_viewport.scss */ -#result_strip ul.thumbnails > li .thumbnail .caption { +#result_strip > ul > li .thumbnail .caption { white-space: normal; } /* line 73, ../sass/_viewport.scss */ -#result_strip ul.thumbnails > li .thumbnail .caption h4 { +#result_strip > ul > li .thumbnail .caption h4 { text-align: center; word-wrap: break-word; height: 40px; margin: 0px; } /* line 83, ../sass/_viewport.scss */ -#result_strip ul.thumbnails:after { +#result_strip > ul:after { content: ""; display: table; clear: both; diff --git a/example/file_input.html b/example/file_input.html index f8f7297..a157123 100644 --- a/example/file_input.html +++ b/example/file_input.html @@ -77,14 +77,15 @@ Half-Sample + diff --git a/example/file_input.js b/example/file_input.js index 18f37e4..dccbdcf 100644 --- a/example/file_input.js +++ b/example/file_input.js @@ -88,17 +88,16 @@ $(function() { }, state: { inputStream: { - size: 640 + size: 640, + singleChannel: false }, locator: { patchSize: "large", halfSample: false }, - numOfWorkers: 0, + numOfWorkers: 1, decoder: { - readers: ["code_128_reader"], - showFrequency: true, - showPattern: true + readers: ["code_128_reader"] }, locate: true, src: null diff --git a/example/file_input_require.html b/example/file_input_require.html index 5aeddaa..f597f97 100644 --- a/example/file_input_require.html +++ b/example/file_input_require.html @@ -68,24 +68,19 @@ diff --git a/example/file_input_require.js b/example/file_input_require.js index e2492c6..91569d1 100644 --- a/example/file_input_require.js +++ b/example/file_input_require.js @@ -112,11 +112,12 @@ define(['quagga'], function(Quagga) { }, state: { inputStream: { - size: 640 + size: 640, + singleChannel: false }, locator: { - patchSize: "large", - halfSample: false + patchSize: "medium", + halfSample: true }, numOfWorkers: 0, decoder: { @@ -162,7 +163,7 @@ define(['quagga'], function(Quagga) { $node = $('
  • '); $node.find("img").attr("src", canvas.toDataURL()); - $node.find("h4.code").html(code); + $node.find("h4.code").html(code + " (" + result.codeResult.format + ")"); $("#result_strip ul.thumbnails").prepend($node); }); }); \ No newline at end of file diff --git a/example/live_w_locator.html b/example/live_w_locator.html index c72eb5b..72c8d19 100644 --- a/example/live_w_locator.html +++ b/example/live_w_locator.html @@ -82,6 +82,7 @@
      +
        diff --git a/example/live_w_locator.js b/example/live_w_locator.js index 6394254..d66a21d 100644 --- a/example/live_w_locator.js +++ b/example/live_w_locator.js @@ -1,17 +1,37 @@ $(function() { + var resultCollector = Quagga.ResultCollector.create({ + capture: true, + capacity: 20, + blacklist: [{code: "3574660239843", format: "ean_13"}], + filter: function(codeResult) { + // only store results which match this constraint + // e.g.: codeResult + return true; + } + }); var App = { init : function() { - Quagga.init(this.state, function() { + var self = this; + + Quagga.init(this.state, function(err) { + if (err) { + return self.handleError(err); + } + Quagga.registerResultCollector(resultCollector); App.attachListeners(); Quagga.start(); }); }, + handleError: function(err) { + console.log(err); + }, attachListeners: function() { var self = this; $(".controls").on("click", "button.stop", function(e) { e.preventDefault(); Quagga.stop(); + self._printCollectedResults(); }); $(".controls .reader-config-group").on("change", "input, select", function(e) { @@ -25,6 +45,18 @@ $(function() { self.setState(state, value); }); }, + _printCollectedResults: function() { + var results = resultCollector.getResults(), + $ul = $("#result_strip ul.collector"); + + results.forEach(function(result) { + var $li = $('
      • '); + + $li.find("img").attr("src", result.frame); + $li.find("h4.code").html(result.codeResult.code + " (" + result.codeResult.format + ")"); + $ul.prepend($li); + }); + }, _accessByPath: function(obj, path, val) { var parts = path.split('.'), depth = parts.length, diff --git a/example/sass/_viewport.scss b/example/sass/_viewport.scss index fca73fa..f0d085b 100644 --- a/example/sass/_viewport.scss +++ b/example/sass/_viewport.scss @@ -47,7 +47,7 @@ border-bottom: 1px solid #EEE; padding: 10px 0; - ul.thumbnails{ + & > ul { padding: 0; margin: 0; list-style-type: none; diff --git a/package.json b/package.json index fa8104f..3290c10 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "quagga", - "version": "0.6.8", + "version": "0.6.13", "description": "An advanced barcode-scanner written in JavaScript", "main": "lib/quagga.js", "browser": "dist/quagga.js", @@ -43,6 +43,8 @@ "ean", "code128", "code39", + "codabar", + "upc", "getusermedia", "imageprocessing" ], diff --git a/spec/camera_access.spec.js b/spec/camera_access.spec.js index a47a711..1320606 100644 --- a/spec/camera_access.spec.js +++ b/spec/camera_access.spec.js @@ -1,17 +1,15 @@ define(['camera_access'], function(CameraAccess){ var originalURL, - originalUserMedia, originalMediaStreamTrack, video, stream; - + beforeEach(function() { var tracks = [{ stop: function() {} }]; originalURL = window.URL; - originalUserMedia = window.getUserMedia; originalMediaStreamTrack = window.MediaStreamTrack; window.MediaStreamTrack = {}; window.URL = null; @@ -23,10 +21,7 @@ define(['camera_access'], function(CameraAccess){ } }; sinon.spy(tracks[0], "stop"); - navigator.getUserMedia = function(constraints, cb) { - cb(stream); - }; - sinon.spy(navigator, "getUserMedia"); + video = { src: null, addEventListener: function() { @@ -48,29 +43,80 @@ define(['camera_access'], function(CameraAccess){ }); afterEach(function() { - navigator.getUserMedia = originalUserMedia; window.URL = originalURL; window.MediaStreamTrack = originalMediaStreamTrack; }); - describe('request', function() { - it('should request the camera', function(done) { - CameraAccess.request(video, {}, function() { - expect(navigator.getUserMedia.calledOnce).to.equal(true); - expect(video.src).to.deep.equal(stream); - done(); + describe('success', function() { + beforeEach(function() { + sinon.stub(navigator, "getUserMedia", function(constraints, success) { + success(stream); + }); + }); + + afterEach(function() { + navigator.getUserMedia.restore(); + }); + describe('request', function () { + it('should request the camera', function (done) { + CameraAccess.request(video, {}, function () { + expect(navigator.getUserMedia.calledOnce).to.equal(true); + expect(video.src).to.deep.equal(stream); + done(); + }); + }); + }); + + describe('release', function () { + it('should release the camera', function (done) { + CameraAccess.request(video, {}, function () { + expect(video.src).to.deep.equal(stream); + CameraAccess.release(); + expect(video.src.getVideoTracks()).to.have.length(1); + expect(video.src.getVideoTracks()[0].stop.calledOnce).to.equal(true); + done(); + }); }); }); }); - - describe('release', function() { - it('should release the camera', function(done) { - CameraAccess.request(video, {}, function() { - expect(video.src).to.deep.equal(stream); - CameraAccess.release(); - expect(video.src.getVideoTracks()).to.have.length(1); - expect(video.src.getVideoTracks()[0].stop.calledOnce).to.equal(true); - done(); + + describe('failure', function() { + describe("permission denied", function(){ + before(function() { + sinon.stub(navigator, "getUserMedia", function(constraints, success, failure) { + failure(new Error()); + }); + }); + + after(function() { + navigator.getUserMedia.restore(); + }); + + it('should throw if getUserMedia not available', function(done) { + CameraAccess.request(video, {}, function(err) { + expect(err).to.be.defined; + done(); + }); + }); + }); + + describe("not available", function(){ + var originalGetUserMedia; + + before(function() { + originalGetUserMedia = navigator.getUserMedia; + navigator.getUserMedia = undefined; + }); + + after(function() { + navigator.getUserMedia = originalGetUserMedia; + }); + + it('should throw if getUserMedia not available', function(done) { + CameraAccess.request(video, {}, function(err) { + expect(err).to.be.defined; + done(); + }); }); }); }); diff --git a/spec/integration.spec.js b/spec/integration.spec.js index db4136d..c9c4765 100644 --- a/spec/integration.spec.js +++ b/spec/integration.spec.js @@ -35,6 +35,7 @@ define(['quagga', 'async'], function(Quagga, async) { Quagga.decodeSingle(config, function(result) { console.log(sample.name); expect(result.codeResult.code).to.equal(sample.result); + expect(result.codeResult.format).to.equal(sample.format); callback(); }); }, function() { @@ -45,18 +46,22 @@ define(['quagga', 'async'], function(Quagga, async) { describe("EAN", function() { var config = generateConfig(), - testSet = [ - {"name": "image-001.jpg", "result": "3574660239843"}, - {"name": "image-002.jpg", "result": "8032754490297"}, - {"name": "image-003.jpg", "result": "4006209700068"}, - /* {"name": "image-004.jpg", "result": "9002233139084"}, */ - /* {"name": "image-005.jpg", "result": "8004030044005"}, */ - {"name": "image-006.jpg", "result": "4003626011159"}, - {"name": "image-007.jpg", "result": "2111220009686"}, - {"name": "image-008.jpg", "result": "9000275609022"}, - {"name": "image-009.jpg", "result": "9004593978587"}, - {"name": "image-010.jpg", "result": "9002244845578"} - ]; + testSet = [ + {"name": "image-001.jpg", "result": "3574660239843"}, + {"name": "image-002.jpg", "result": "8032754490297"}, + {"name": "image-003.jpg", "result": "4006209700068"}, + /* {"name": "image-004.jpg", "result": "9002233139084"}, */ + /* {"name": "image-005.jpg", "result": "8004030044005"}, */ + {"name": "image-006.jpg", "result": "4003626011159"}, + {"name": "image-007.jpg", "result": "2111220009686"}, + {"name": "image-008.jpg", "result": "9000275609022"}, + {"name": "image-009.jpg", "result": "9004593978587"}, + {"name": "image-010.jpg", "result": "9002244845578"} + ]; + + testSet.forEach(function(sample) { + sample.format = "ean_13"; + }); config.decoder.readers = ['ean_reader']; _runTestSet(testSet, config); @@ -65,17 +70,21 @@ define(['quagga', 'async'], function(Quagga, async) { describe("Code128", function() { var config = generateConfig(), testSet = [ - {"name": "image-001.jpg", "result": "0001285112001000040801"}, - {"name": "image-002.jpg", "result": "FANAVF1461710"}, - {"name": "image-003.jpg", "result": "673023"}, - // {"name": "image-004.jpg", "result": "010210150301625334"}, - {"name": "image-005.jpg", "result": "419055603900009001012999"}, - {"name": "image-006.jpg", "result": "419055603900009001012999"}, - {"name": "image-007.jpg", "result": "T 000003552345"}, - {"name": "image-008.jpg", "result": "FANAVF1461710"}, - {"name": "image-009.jpg", "result": "0001285112001000040801"}, - {"name": "image-010.jpg", "result": "673023"} - ]; + {"name": "image-001.jpg", "result": "0001285112001000040801"}, + {"name": "image-002.jpg", "result": "FANAVF1461710"}, + // {"name": "image-003.jpg", "result": "673023"}, + {"name": "image-004.jpg", "result": "010210150301625334"}, + {"name": "image-005.jpg", "result": "419055603900009001012999"}, + {"name": "image-006.jpg", "result": "419055603900009001012999"}, + {"name": "image-007.jpg", "result": "T 000003552345"}, + {"name": "image-008.jpg", "result": "FANAVF1461710"}, + {"name": "image-009.jpg", "result": "0001285112001000040801"}, + {"name": "image-010.jpg", "result": "673023"} + ]; + + testSet.forEach(function(sample) { + sample.format = "code_128"; + }); config.decoder.readers = ['code_128_reader']; _runTestSet(testSet, config); @@ -84,17 +93,20 @@ define(['quagga', 'async'], function(Quagga, async) { describe("Code39", function() { var config = generateConfig(), testSet = [ - {"name": "image-001.jpg", "result": "B3% $DAD$"}, - /*{"name": "image-002.jpg", "result": "QUAGGAJS"},*/ - {"name": "image-003.jpg", "result": "CODE39"}, - {"name": "image-004.jpg", "result": "QUAGGAJS"}, - /* {"name": "image-005.jpg", "result": "CODE39"}, */ - {"name": "image-006.jpg", "result": "2/4-8/16-32"}, - {"name": "image-007.jpg", "result": "2/4-8/16-32"}, - {"name": "image-008.jpg", "result": "CODE39"}, - {"name": "image-009.jpg", "result": "2/4-8/16-32"}, - {"name": "image-010.jpg", "result": "CODE39"} - ]; + {"name": "image-001.jpg", "result": "B3% $DAD$"}, + {"name": "image-003.jpg", "result": "CODE39"}, + {"name": "image-004.jpg", "result": "QUAGGAJS"}, + {"name": "image-005.jpg", "result": "CODE39"}, + {"name": "image-006.jpg", "result": "2/4-8/16-32"}, + {"name": "image-007.jpg", "result": "2/4-8/16-32"}, + {"name": "image-008.jpg", "result": "CODE39"}, + {"name": "image-009.jpg", "result": "2/4-8/16-32"}, + {"name": "image-010.jpg", "result": "CODE39"} + ]; + + testSet.forEach(function(sample) { + sample.format = "code_39"; + }); config.decoder.readers = ['code_39_reader']; _runTestSet(testSet, config); @@ -103,17 +115,21 @@ define(['quagga', 'async'], function(Quagga, async) { describe("EAN-8", function() { var config = generateConfig(), testSet = [ - {"name": "image-001.jpg", "result": "42191605"}, - {"name": "image-002.jpg", "result": "42191605"}, - {"name": "image-003.jpg", "result": "90311208"}, - {"name": "image-004.jpg", "result": "24057257"}, - {"name": "image-005.jpg", "result": "90162602"}, - {"name": "image-006.jpg", "result": "24036153"}, - {"name": "image-007.jpg", "result": "42176817"}, - /*{"name": "image-008.jpg", "result": "42191605"},*/ - {"name": "image-009.jpg", "result": "42242215"}, - {"name": "image-010.jpg", "result": "42184799"} - ]; + {"name": "image-001.jpg", "result": "42191605"}, + {"name": "image-002.jpg", "result": "42191605"}, + {"name": "image-003.jpg", "result": "90311208"}, + {"name": "image-004.jpg", "result": "24057257"}, + {"name": "image-005.jpg", "result": "90162602"}, + {"name": "image-006.jpg", "result": "24036153"}, + {"name": "image-007.jpg", "result": "42176817"}, + {"name": "image-008.jpg", "result": "42191605"}, + {"name": "image-009.jpg", "result": "42242215"}, + {"name": "image-010.jpg", "result": "42184799"} + ]; + + testSet.forEach(function(sample) { + sample.format = "ean_8"; + }); config.decoder.readers = ['ean_8_reader']; _runTestSet(testSet, config); @@ -127,13 +143,17 @@ define(['quagga', 'async'], function(Quagga, async) { {"name": "image-003.jpg", "result": "882428015084"}, {"name": "image-004.jpg", "result": "882428015343"}, {"name": "image-005.jpg", "result": "882428015343"}, - {"name": "image-006.jpg", "result": "882428015046"}, + /* {"name": "image-006.jpg", "result": "882428015046"}, */ {"name": "image-007.jpg", "result": "882428015084"}, {"name": "image-008.jpg", "result": "882428015046"}, {"name": "image-009.jpg", "result": "039047013551"}, {"name": "image-010.jpg", "result": "039047013551"} ]; + testSet.forEach(function(sample) { + sample.format = "upc_a"; + }); + config.decoder.readers = ['upc_reader']; _runTestSet(testSet, config); }); @@ -153,6 +173,10 @@ define(['quagga', 'async'], function(Quagga, async) { {"name": "image-010.jpg", "result": "01264904"} ]; + testSet.forEach(function(sample) { + sample.format = "upc_e"; + }); + config.decoder.readers = ['upc_e_reader']; _runTestSet(testSet, config); }); @@ -167,11 +191,15 @@ define(['quagga', 'async'], function(Quagga, async) { {"name": "image-005.jpg", "result": "C$399.95A"}, {"name": "image-006.jpg", "result": "B546745735B"}, {"name": "image-007.jpg", "result": "C$399.95A"}, - /* {"name": "image-008.jpg", "result": "01264904"}, */ + {"name": "image-008.jpg", "result": "A16:9/4:3/3:2D"}, {"name": "image-009.jpg", "result": "C$399.95A"}, {"name": "image-010.jpg", "result": "C$399.95A"} ]; + testSet.forEach(function(sample) { + sample.format = "codabar"; + }); + config.decoder.readers = ['codabar_reader']; _runTestSet(testSet, config); }); diff --git a/spec/result_collector.spec.js b/spec/result_collector.spec.js new file mode 100644 index 0000000..dcb927a --- /dev/null +++ b/spec/result_collector.spec.js @@ -0,0 +1,103 @@ + +define(['result_collector', 'image_debug'], function(ResultCollector, ImageDebug) { + var canvasMock, + imageSize, + config; + + beforeEach(function() { + imageSize = {x: 320, y: 240}; + config = { + capture: true, + capacity: 20, + blacklist: [{code: "3574660239843", format: "ean_13"}], + filter: function(codeResult) { + return true; + } + }; + canvasMock = { + getContext: function() { + return {}; + }, + toDataURL: sinon.spy(), + width: 0, + height: 0 + }; + sinon.stub(document, "createElement", function(type) { + if (type === "canvas") { + return canvasMock; + } + }); + }); + + afterEach(function() { + document.createElement.restore(); + }); + + + describe('create', function () { + it("should return a new collector", function() { + ResultCollector.create(config); + expect(document.createElement.calledOnce).to.be.equal(true); + expect(document.createElement.getCall(0).args[0]).to.equal("canvas"); + }); + }); + + describe('addResult', function() { + beforeEach(function() { + sinon.stub(ImageDebug, "drawImage", function() {}); + }); + + afterEach(function() { + ImageDebug.drawImage.restore(); + }); + + it("should not add result if capacity is full", function(){ + config.capacity = 1; + var collector = ResultCollector.create(config); + collector.addResult([], imageSize, {}); + collector.addResult([], imageSize, {}); + collector.addResult([], imageSize, {}); + expect(collector.getResults()).to.have.length(1); + }); + + it("should only add results which match constraints", function(){ + var collector = ResultCollector.create(config), + results; + + collector.addResult([], imageSize, {code: "423423443", format: "ean_13"}); + collector.addResult([], imageSize, {code: "3574660239843", format: "ean_13"}); + collector.addResult([], imageSize, {code: "3574660239843", format: "code_128"}); + + results = collector.getResults(); + expect(results).to.have.length(2); + + results.forEach(function(result) { + expect(result).not.to.deep.equal(config.blacklist[0]); + }); + }); + + it("should add result if no filter is set", function() { + delete config.filter; + var collector = ResultCollector.create(config); + + collector.addResult([], imageSize, {code: "423423443", format: "ean_13"}); + expect(collector.getResults()).to.have.length(1); + }); + + it("should not add results if filter returns false", function() { + config.filter = function(){ return false }; + var collector = ResultCollector.create(config); + + collector.addResult([], imageSize, {code: "423423443", format: "ean_13"}); + expect(collector.getResults()).to.have.length(0); + }); + + it("should add result if no blacklist is set", function() { + delete config.blacklist; + var collector = ResultCollector.create(config); + + collector.addResult([], imageSize, {code: "3574660239843", format: "ean_13"}); + expect(collector.getResults()).to.have.length(1); + }); + }); +}); \ No newline at end of file diff --git a/src/barcode_decoder.js b/src/barcode_decoder.js index 2e518d0..8f94f03 100644 --- a/src/barcode_decoder.js +++ b/src/barcode_decoder.js @@ -49,8 +49,7 @@ define([ overlay : null } }, - _barcodeReaders = [], - _barcodeReader = null; + _barcodeReaders = []; initCanvas(); initReaders(); @@ -135,13 +134,10 @@ define([ // check if inside image extendLine(ext); - while (ext > 1 && !inputImageWrapper.inImageWithBorder(line[0], 0) || !inputImageWrapper.inImageWithBorder(line[1], 0)) { - ext -= Math.floor(ext/2); + while (ext > 1 && (!inputImageWrapper.inImageWithBorder(line[0], 0) || !inputImageWrapper.inImageWithBorder(line[1], 0))) { + ext -= Math.ceil(ext/2); extendLine(-ext); } - if (ext <= 1) { - return null; - } return line; } @@ -171,9 +167,6 @@ define([ for ( i = 0; i < _barcodeReaders.length && result === null; i++) { result = _barcodeReaders[i].decodePattern(barcodeLine.line); - if (result !== null) { - _barcodeReader = _barcodeReaders[i]; - } } if(result === null){ return null; diff --git a/src/barcode_reader.js b/src/barcode_reader.js index aeea175..520d64e 100644 --- a/src/barcode_reader.js +++ b/src/barcode_reader.js @@ -166,6 +166,9 @@ define( } else { result.direction = BarcodeReader.DIRECTION.FORWARD; } + if (result) { + result.format = self.FORMAT; + } return result; }; @@ -180,6 +183,11 @@ define( } return true; }; + + Object.defineProperty(BarcodeReader.prototype, "FORMAT", { + value: 'unknown', + writeable: false + }); BarcodeReader.DIRECTION = { FORWARD : 1, diff --git a/src/bresenham.js b/src/bresenham.js index b9a789c..a59c163 100644 --- a/src/bresenham.js +++ b/src/bresenham.js @@ -117,6 +117,7 @@ define(["cv_utils", "image_wrapper"], function(CVUtils, ImageWrapper) { max = result.max, line = result.line, slope, + slope2, center = min + (max - min) / 2, extrema = [], currentDir, @@ -132,11 +133,12 @@ define(["cv_utils", "image_wrapper"], function(CVUtils, ImageWrapper) { pos : 0, val : line[0] }); - for ( i = 0; i < line.length - 1; i++) { + for ( i = 0; i < line.length - 2; i++) { slope = (line[i + 1] - line[i]); - if (slope < rThreshold && line[i + 1] < (center*1.5)) { + slope2 = (line[i + 2] - line[i + 1]); + if ((slope + slope2) < rThreshold && line[i + 1] < (center*1.5)) { dir = Slope.DIR.DOWN; - } else if (slope > threshold && line[i + 1] > (center*0.5)) { + } else if ((slope + slope2) > threshold && line[i + 1] > (center*0.5)) { dir = Slope.DIR.UP; } else { dir = currentDir; diff --git a/src/camera_access.js b/src/camera_access.js index 44baaaa..bf4e831 100644 --- a/src/camera_access.js +++ b/src/camera_access.js @@ -13,11 +13,15 @@ define(["html_utils"], function(HtmlUtils) { * @param {Object} failure Callback */ function getUserMedia(constraints, success, failure) { - navigator.getUserMedia(constraints, function(stream) { - streamRef = stream; - var videoSrc = (window.URL && window.URL.createObjectURL(stream)) || stream; - success.apply(null, [videoSrc]); - }, failure); + if (typeof navigator.getUserMedia !== 'undefined') { + navigator.getUserMedia(constraints, function (stream) { + streamRef = stream; + var videoSrc = (window.URL && window.URL.createObjectURL(stream)) || stream; + success.apply(null, [videoSrc]); + }, failure); + } else { + failure(new TypeError("getUserMedia not available")); + } } function loadedData(video, callback) { @@ -56,7 +60,7 @@ define(["html_utils"], function(HtmlUtils) { video.addEventListener('loadeddata', loadedDataHandler, false); video.play(); }, function(e) { - console.log(e); + callback(e); }); } @@ -79,7 +83,7 @@ define(["html_utils"], function(HtmlUtils) { facing: "environment" }, config); - if ( typeof MediaStreamTrack.getSources !== 'undefined') { + if ( typeof MediaStreamTrack !== 'undefined' && typeof MediaStreamTrack.getSources !== 'undefined') { MediaStreamTrack.getSources(function(sourceInfos) { var videoSourceId; for (var i = 0; i != sourceInfos.length; ++i) { diff --git a/src/codabar_reader.js b/src/codabar_reader.js index a094071..389e4df 100644 --- a/src/codabar_reader.js +++ b/src/codabar_reader.js @@ -20,7 +20,8 @@ define( START_END: {value: [0x01A, 0x029, 0x00B, 0x00E]}, MIN_ENCODED_CHARS: {value: 4}, MAX_ACCEPTABLE: {value: 2.0}, - PADDING: {value: 1.5} + PADDING: {value: 1.5}, + FORMAT: {value: "codabar", writeable: false} }; CodabarReader.prototype = Object.create(BarcodeReader.prototype, properties); diff --git a/src/code_128_reader.js b/src/code_128_reader.js index 4f5cef1..5327592 100644 --- a/src/code_128_reader.js +++ b/src/code_128_reader.js @@ -132,7 +132,8 @@ define( [2, 3, 3, 1, 1, 1, 2] ]}, SINGLE_CODE_ERROR: {value: 1}, - AVG_CODE_ERROR: {value: 0.5} + AVG_CODE_ERROR: {value: 0.5}, + FORMAT: {value: "code_128", writeable: false} }; Code128Reader.prototype = Object.create(BarcodeReader.prototype, properties); @@ -161,67 +162,17 @@ define( } else { if (counterPos === counter.length - 1) { normalized = self._normalize(counter); - for ( code = 0; code < self.CODE_PATTERN.length; code++) { - error = self._matchPattern(normalized, self.CODE_PATTERN[code]); - if (error < bestMatch.error) { - bestMatch.code = code; - bestMatch.error = error; + if (normalized) { + for (code = 0; code < self.CODE_PATTERN.length; code++) { + error = self._matchPattern(normalized, self.CODE_PATTERN[code]); + if (error < bestMatch.error) { + bestMatch.code = code; + bestMatch.error = error; + } } - } - bestMatch.end = i; - return bestMatch; - } else { - counterPos++; - } - counter[counterPos] = 1; - isWhite = !isWhite; - } - } - return null; - }; - - Code128Reader.prototype._findEnd = function() { - var counter = [0, 0, 0, 0, 0, 0, 0], - i, - self = this, - offset = self._nextSet(self._row), - isWhite = !self._row[offset], - counterPos = 0, - bestMatch = { - error : Number.MAX_VALUE, - code : -1, - start : 0, - end : 0 - }, - error, - j, - sum, - normalized; - - for ( i = offset; i < self._row.length; i++) { - if (self._row[i] ^ isWhite) { - counter[counterPos]++; - } else { - if (counterPos === counter.length - 1) { - sum = 0; - for ( j = 0; j < counter.length; j++) { - sum += counter[j]; - } - normalized = self._normalize(counter, 13); - error = self._matchPattern(normalized, self.CODE_PATTERN[self.STOP_CODE]); - if (error < self.AVG_CODE_ERROR) { - bestMatch.error = error; - bestMatch.start = i - sum; bestMatch.end = i; return bestMatch; } - - for ( j = 0; j < 5; j++) { - counter[j] = counter[j + 2]; - } - counter[5] = 0; - counter[6] = 0; - counterPos--; } else { counterPos++; } @@ -261,17 +212,19 @@ define( sum += counter[j]; } normalized = self._normalize(counter); - for ( code = self.START_CODE_A; code <= self.START_CODE_C; code++) { - error = self._matchPattern(normalized, self.CODE_PATTERN[code]); - if (error < bestMatch.error) { - bestMatch.code = code; - bestMatch.error = error; + if (normalized) { + for (code = self.START_CODE_A; code <= self.START_CODE_C; code++) { + error = self._matchPattern(normalized, self.CODE_PATTERN[code]); + if (error < bestMatch.error) { + bestMatch.code = code; + bestMatch.error = error; + } + } + if (bestMatch.error < self.AVG_CODE_ERROR) { + bestMatch.start = i - sum; + bestMatch.end = i; + return bestMatch; } - } - if (bestMatch.error < self.AVG_CODE_ERROR) { - bestMatch.start = i - sum; - bestMatch.end = i; - return bestMatch; } for ( j = 0; j < 4; j++) { @@ -420,7 +373,7 @@ define( // find end bar code.end = self._nextUnset(self._row, code.end); - if (code.end === self._row.length) { + if(!self._verifyTrailingWhitespace(code)){ return null; } @@ -431,9 +384,15 @@ define( return null; } + if (!result.length) { + return null; + } + // remove last code from result (checksum) result.splice(result.length - 1, 1); + + return { code : result.join(""), start : startInfo.start, @@ -444,6 +403,20 @@ define( endInfo : code }; }; + + + BarcodeReader.prototype._verifyTrailingWhitespace = function(endInfo) { + var self = this, + trailingWhitespaceEnd; + + trailingWhitespaceEnd = endInfo.end + ((endInfo.end - endInfo.start) / 2); + if (trailingWhitespaceEnd < self._row.length) { + if (self._matchRange(endInfo.end, trailingWhitespaceEnd, 0)) { + return endInfo; + } + } + return null; + }; return (Code128Reader); } diff --git a/src/code_39_reader.js b/src/code_39_reader.js index cb228fa..a02fee5 100644 --- a/src/code_39_reader.js +++ b/src/code_39_reader.js @@ -17,7 +17,8 @@ define( ALPHABETH_STRING: {value: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *$/+%"}, ALPHABET: {value: [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 45, 46, 32, 42, 36, 47, 43, 37]}, CHARACTER_ENCODINGS: {value: [0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, 0x124, 0x064, 0x109, 0x049, 0x148, 0x019, 0x118, 0x058, 0x00D, 0x10C, 0x04C, 0x01C, 0x103, 0x043, 0x142, 0x013, 0x112, 0x052, 0x007, 0x106, 0x046, 0x016, 0x181, 0x0C1, 0x1C0, 0x091, 0x190, 0x0D0, 0x085, 0x184, 0x0C4, 0x094, 0x0A8, 0x0A2, 0x08A, 0x02A]}, - ASTERISK: {value: 0x094} + ASTERISK: {value: 0x094}, + FORMAT: {value: "code_39", writeable: false} }; Code39Reader.prototype = Object.create(BarcodeReader.prototype, properties); diff --git a/src/config.js b/src/config.js index a394fcc..7236180 100644 --- a/src/config.js +++ b/src/config.js @@ -18,7 +18,8 @@ define(function(){ right: "0%", left: "0%", bottom: "0%" - } + }, + singleChannel: false // true: only the red color-channel is read }, tracking: false, debug: false, diff --git a/src/cv_utils.js b/src/cv_utils.js index 830c250..01155d5 100644 --- a/src/cv_utils.js +++ b/src/cv_utils.js @@ -486,13 +486,19 @@ define(['cluster', "array_helper", "gl-matrix"], function(Cluster2, ArrayHelper, }; - CVUtils.computeGray = function(imageData, outArray) { - var l = imageData.length / 4; - var i = 0; - for ( i = 0; i < l; i++) { - //outArray[i] = (0.299*imageData[i*4+0] + 0.587*imageData[i*4+1] + 0.114*imageData[i*4+2]); - - outArray[i] = Math.floor(0.299 * imageData[i * 4 + 0] + 0.587 * imageData[i * 4 + 1] + 0.114 * imageData[i * 4 + 2]); + CVUtils.computeGray = function(imageData, outArray, config) { + var l = (imageData.length / 4) | 0, + i, + singleChannel = config && config.singleChannel === true; + + if (singleChannel) { + for (i = 0; i < l; i++) { + outArray[i] = imageData[i * 4 + 0]; + } + } else { + for (i = 0; i < l; i++) { + outArray[i] = Math.floor(0.299 * imageData[i * 4 + 0] + 0.587 * imageData[i * 4 + 1] + 0.114 * imageData[i * 4 + 2]); + } } }; diff --git a/src/ean_8_reader.js b/src/ean_8_reader.js index b6b98da..f76642e 100644 --- a/src/ean_8_reader.js +++ b/src/ean_8_reader.js @@ -12,7 +12,11 @@ define( EANReader.call(this); } - EAN8Reader.prototype = Object.create(EANReader.prototype); + var properties = { + FORMAT: {value: "ean_8", writeable: false} + }; + + EAN8Reader.prototype = Object.create(EANReader.prototype, properties); EAN8Reader.prototype.constructor = EAN8Reader; EAN8Reader.prototype._decodePayload = function(code, result, decodedCodes) { @@ -28,7 +32,7 @@ define( decodedCodes.push(code); } - code = self._findPattern(self.MIDDLE_PATTERN, code.end, true); + code = self._findPattern(self.MIDDLE_PATTERN, code.end, true, false); if (code === null) { return null; } diff --git a/src/ean_reader.js b/src/ean_reader.js index 249ee54..f207055 100644 --- a/src/ean_reader.js +++ b/src/ean_reader.js @@ -42,8 +42,9 @@ define( [2, 1, 1, 3] ]}, CODE_FREQUENCY : {value: [0, 11, 13, 14, 19, 25, 28, 21, 22, 26]}, - SINGLE_CODE_ERROR: {value: 0.7}, - AVG_CODE_ERROR: {value: 0.3} + SINGLE_CODE_ERROR: {value: 0.67}, + AVG_CODE_ERROR: {value: 0.27}, + FORMAT: {value: "ean_13", writeable: false} }; EANReader.prototype = Object.create(BarcodeReader.prototype, properties); @@ -76,18 +77,20 @@ define( } else { if (counterPos === counter.length - 1) { normalized = self._normalize(counter); - for ( code = 0; code < coderange; code++) { - error = self._matchPattern(normalized, self.CODE_PATTERN[code]); - if (error < bestMatch.error) { - bestMatch.code = code; - bestMatch.error = error; + if (normalized) { + for (code = 0; code < coderange; code++) { + error = self._matchPattern(normalized, self.CODE_PATTERN[code]); + if (error < bestMatch.error) { + bestMatch.code = code; + bestMatch.error = error; + } } + bestMatch.end = i; + if (bestMatch.error > self.AVG_CODE_ERROR) { + return null; + } + return bestMatch; } - bestMatch.end = i; - if (bestMatch.error > self.AVG_CODE_ERROR) { - return null; - } - return bestMatch; } else { counterPos++; } @@ -144,13 +147,15 @@ define( sum += counter[j]; } normalized = self._normalize(counter); - error = self._matchPattern(normalized, pattern); + if (normalized) { + error = self._matchPattern(normalized, pattern); - if (error < epsilon) { - bestMatch.error = error; - bestMatch.start = i - sum; - bestMatch.end = i; - return bestMatch; + if (error < epsilon) { + bestMatch.error = error; + bestMatch.start = i - sum; + bestMatch.end = i; + return bestMatch; + } } if (tryHarder) { for ( j = 0; j < counter.length - 2; j++) { diff --git a/src/frame_grabber.js b/src/frame_grabber.js index 0892b2f..92dcd7a 100644 --- a/src/frame_grabber.js +++ b/src/frame_grabber.js @@ -59,7 +59,7 @@ define(["cv_utils"], function(CVUtils) { if(doHalfSample){ CVUtils.grayAndHalfSampleFromCanvasData(ctxData, _size, _data); } else { - CVUtils.computeGray(ctxData, _data); + CVUtils.computeGray(ctxData, _data, _streamConfig); } return true; } else { diff --git a/src/image_debug.js b/src/image_debug.js index e0fbde1..3eb9678 100644 --- a/src/image_debug.js +++ b/src/image_debug.js @@ -23,6 +23,26 @@ define(function() { } ctx.closePath(); ctx.stroke(); + }, + drawImage: function(imageData, size, ctx) { + var canvasData = ctx.getImageData(0, 0, size.x, size.y), + data = canvasData.data, + imageDataPos = imageData.length, + canvasDataPos = data.length, + value; + + if (canvasDataPos/imageDataPos !== 4) { + return false; + } + while(imageDataPos--){ + value = imageData[imageDataPos]; + data[--canvasDataPos] = 255; + data[--canvasDataPos] = value; + data[--canvasDataPos] = value; + data[--canvasDataPos] = value; + } + ctx.putImageData(canvasData, 0, 0); + return true; } }; diff --git a/src/quagga.js b/src/quagga.js index 2d84bdf..c9bc00e 100644 --- a/src/quagga.js +++ b/src/quagga.js @@ -1,7 +1,5 @@ /* jshint undef: true, unused: true, browser:true, devel: true, evil: true */ /* global define */ - - define([ "code_128_reader", "ean_reader", @@ -15,7 +13,8 @@ define([ "events", "camera_access", "image_debug", - "gl-matrix"], + "gl-matrix", + "result_collector"], function(Code128Reader, EANReader, InputStream, @@ -28,7 +27,8 @@ function(Code128Reader, Events, CameraAccess, ImageDebug, - glMatrix) { + glMatrix, + ResultCollector) { "use strict"; var _inputStream, @@ -49,7 +49,8 @@ function(Code128Reader, _decoder, _workerPool = [], _onUIThread = true, - vec2 = glMatrix.vec2; + vec2 = glMatrix.vec2, + _resultCollector; function initializeData(imageWrapper) { initBuffers(imageWrapper); @@ -99,7 +100,7 @@ function(Code128Reader, if (!err) { _inputStream.trigger("canrecord"); } else { - console.log(err); + return cb(err); } }); } @@ -111,9 +112,7 @@ function(Code128Reader, } function canRecord(cb) { - if (_config.locate) { - BarcodeLocator.checkImageConstraints(_inputStream, _config.locator); - } + BarcodeLocator.checkImageConstraints(_inputStream, _config.locator); initCanvas(); _framegrabber = FrameGrabber.create(_inputStream, _canvasContainer.dom.image); initConfig(); @@ -180,10 +179,10 @@ function(Code128Reader, console.log(_inputImageWrapper.size); _boxSize = [ - vec2.clone([20, _inputImageWrapper.size.y / 2 - 100]), - vec2.clone([20, _inputImageWrapper.size.y / 2 + 100]), - vec2.clone([_inputImageWrapper.size.x - 20, _inputImageWrapper.size.y / 2 + 100]), - vec2.clone([_inputImageWrapper.size.x - 20, _inputImageWrapper.size.y / 2 - 100]) + vec2.clone([0, 0]), + vec2.clone([0, _inputImageWrapper.size.y]), + vec2.clone([_inputImageWrapper.size.x, _inputImageWrapper.size.y]), + vec2.clone([_inputImageWrapper.size.x, 0]) ]; BarcodeLocator.init(_inputImageWrapper, _config.locator); } @@ -192,7 +191,11 @@ function(Code128Reader, if (_config.locate) { return BarcodeLocator.locate(); } else { - return [_boxSize]; + return [[ + vec2.clone(_boxSize[0]), + vec2.clone(_boxSize[1]), + vec2.clone(_boxSize[2]), + vec2.clone(_boxSize[3])]]; } } @@ -233,10 +236,16 @@ function(Code128Reader, } } - function publishResult(result) { + function publishResult(result, imageData) { if (_onUIThread) { transformResult(result); + if (imageData && result && result.codeResult) { + if (_resultCollector) { + _resultCollector.addResult(imageData, _inputStream.getCanvasSize(), result.codeResult); + } + } } + Events.publish("processed", result); if (result && result.codeResult) { Events.publish("detected", result); @@ -252,7 +261,7 @@ function(Code128Reader, result = _decoder.decodeFromBoundingBoxes(boxes); result = result || {}; result.boxes = boxes; - publishResult(result); + publishResult(result, _inputImageWrapper.data); } else { publishResult(); } @@ -321,7 +330,7 @@ function(Code128Reader, function initWorker(cb) { var blobURL, workerThread = { - worker: null, + worker: undefined, imageData: new Uint8Array(_inputStream.getWidth() * _inputStream.getHeight()), busy: true }; @@ -339,7 +348,7 @@ function(Code128Reader, } else if (e.data.event === 'processed') { workerThread.imageData = new Uint8Array(e.data.imageData); workerThread.busy = false; - publishResult(e.data.result); + publishResult(e.data.result, workerThread.imageData); } }; @@ -454,6 +463,11 @@ function(Code128Reader, setReaders: function(readers) { setReaders(readers); }, + registerResultCollector: function(resultCollector) { + if (resultCollector && typeof resultCollector.addResult === 'function') { + _resultCollector = resultCollector; + } + }, canvas : _canvasContainer, decodeSingle : function(config, resultCallback) { config = HtmlUtils.mergeObjects({ @@ -481,6 +495,7 @@ function(Code128Reader, Code128Reader : Code128Reader }, ImageWrapper: ImageWrapper, - ImageDebug: ImageDebug + ImageDebug: ImageDebug, + ResultCollector: ResultCollector }; }); diff --git a/src/result_collector.js b/src/result_collector.js new file mode 100644 index 0000000..f29bf95 --- /dev/null +++ b/src/result_collector.js @@ -0,0 +1,59 @@ +/* jshint undef: true, unused: true, browser:true, devel: true */ +/* global define */ + +define(["image_debug"], function(ImageDebug) { + "use strict"; + + function contains(codeResult, list) { + if (list) { + return list.some(function (item) { + return Object.keys(item).every(function (key) { + return item[key] === codeResult[key]; + }); + }); + } + return false; + } + + function passesFilter(codeResult, filter) { + if (typeof filter === 'function') { + return filter(codeResult); + } + return true; + } + + return { + create: function(config) { + var canvas = document.createElement("canvas"), + ctx = canvas.getContext("2d"), + results = [], + capacity = config.capacity || 20, + capture = config.capture === true; + + function matchesConstraints(codeResult) { + return capacity && codeResult && !contains(codeResult, config.blacklist) && passesFilter(codeResult, config.filter); + } + + return { + addResult: function(data, imageSize, codeResult) { + var result = {}; + + if (matchesConstraints(codeResult)) { + capacity--; + result.codeResult = codeResult; + if (capture) { + canvas.width = imageSize.x; + canvas.height = imageSize.y; + ImageDebug.drawImage(data, imageSize, ctx); + result.frame = canvas.toDataURL(); + } + results.push(result); + } + }, + getResults: function() { + return results; + } + }; + } + }; +}); diff --git a/src/upc_e_reader.js b/src/upc_e_reader.js index d32c4b8..d2dfaf0 100644 --- a/src/upc_e_reader.js +++ b/src/upc_e_reader.js @@ -16,7 +16,8 @@ define( CODE_FREQUENCY : {value: [ [ 56, 52, 50, 49, 44, 38, 35, 42, 41, 37 ], [7, 11, 13, 14, 19, 25, 28, 21, 22, 26]]}, - STOP_PATTERN: { value: [1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7]} + STOP_PATTERN: { value: [1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7]}, + FORMAT: {value: "upc_e", writeable: false} }; UPCEReader.prototype = Object.create(EANReader.prototype, properties); @@ -35,13 +36,13 @@ define( if (code.code >= self.CODE_G_START) { code.code = code.code - self.CODE_G_START; codeFrequency |= 1 << (5 - i); - } else { - codeFrequency |= 0 << (5 - i); } result.push(code.code); decodedCodes.push(code); } - self._determineParity(codeFrequency, result); + if (!self._determineParity(codeFrequency, result)) { + return null; + } return code; }; @@ -56,10 +57,11 @@ define( if (codeFrequency === self.CODE_FREQUENCY[nrSystem][i]) { result.unshift(nrSystem); result.push(i); - return; + return true; } } } + return false; }; UPCEReader.prototype._convertToUPCA = function(result) { diff --git a/src/upc_reader.js b/src/upc_reader.js index c09e863..cd6eef2 100644 --- a/src/upc_reader.js +++ b/src/upc_reader.js @@ -12,7 +12,11 @@ define( EANReader.call(this); } - UPCReader.prototype = Object.create(EANReader.prototype); + var properties = { + FORMAT: {value: "upc_a", writeable: false} + }; + + UPCReader.prototype = Object.create(EANReader.prototype, properties); UPCReader.prototype.constructor = UPCReader; UPCReader.prototype._decode = function() { diff --git a/test-main.js b/test-main.js index e5797ba..96dabf0 100644 --- a/test-main.js +++ b/test-main.js @@ -46,7 +46,8 @@ require.config({ 'upc_e_reader': 'src/upc_e_reader', 'upc_reader': 'src/upc_reader', 'async': 'node_modules/async/lib/async', - 'gl-matrix': 'node_modules/gl-matrix/dist/gl-matrix' + 'gl-matrix': 'node_modules/gl-matrix/dist/gl-matrix', + 'result_collector': 'src/result_collector' }, deps: allTestFiles, callback: window.__karma__.start