diff --git a/examples/file_input.html b/examples/file_input.html index e28c91c..9452fc1 100644 --- a/examples/file_input.html +++ b/examples/file_input.html @@ -18,6 +18,8 @@ showInMenu: false + +
diff --git a/examples/js/quagga.js b/examples/js/quagga.js index 65aab97..e2497ab 100644 --- a/examples/js/quagga.js +++ b/examples/js/quagga.js @@ -470,10 +470,11 @@ define( return error; }; - BarcodeReader.prototype._nextSet = function(line) { + BarcodeReader.prototype._nextSet = function(line, offset) { var i; - - for (i = 0; i < line.length; i++) { + + offset = offset || 0; + for (i = offset; i < line.length; i++) { if (line[i]) { return i; } @@ -596,6 +597,18 @@ define( } return result; }; + + BarcodeReader.prototype._matchRange = function(start, end, value) { + var i; + + start = start < 0 ? 0 : start; + for (i = start; i < end; i++) { + if (this._row[i] !== value) { + return false; + } + } + return true; + }; BarcodeReader.DIRECTION = { FORWARD : 1, @@ -1409,7 +1422,7 @@ define('input_stream',["image_loader"], function(ImageLoader) { that.setInputStream = function(config) { _config = config; - video.src = config.src; + video.src = (typeof config.src !== 'undefined') ? config.src : ''; }; that.ended = function() { @@ -4180,6 +4193,16 @@ define('array_helper',[],function() { } } return max; + }, + + sum: function(arr) { + var length = arr.length, + sum = 0; + + while(length--) { + sum += arr[length]; + } + return sum; } }; }); @@ -6416,12 +6439,213 @@ define('bresenham',[],function() { /* jshint undef: true, unused: true, browser:true, devel: true */ /* global define */ -define('barcode_decoder',["bresenham", "image_debug", 'code_128_reader', 'ean_reader'], function(Bresenham, ImageDebug, Code128Reader, EANReader) { +define( + 'code_39_reader',[ + "./barcode_reader", + "./array_helper" + ], + function(BarcodeReader, ArrayHelper) { + + + function Code39Reader() { + BarcodeReader.call(this); + } + + var properties = { + 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} + }; + + Code39Reader.prototype = Object.create(BarcodeReader.prototype, properties); + Code39Reader.prototype.constructor = Code39Reader; + + Code39Reader.prototype._toCounters = function(start, counter) { + var self = this, + numCounters = counter.length, + end = self._row.length, + isWhite = !self._row[start], + i, + counterPos = 0; + + ArrayHelper.init(counter, 0); + + for ( i = start; i < end; i++) { + if (self._row[i] ^ isWhite) { + counter[counterPos]++; + } else { + counterPos++; + if (counterPos === numCounters) { + break; + } else { + counter[counterPos] = 1; + isWhite = !isWhite; + } + } + } + + return counter; + }; + + Code39Reader.prototype._decode = function() { + var self = this, + counters = [0,0,0,0,0,0,0,0,0], + result = [], + start = self._findStart(), + decodedChar, + lastStart, + pattern, + nextStart; + + if (!start) { + return null; + } + nextStart = self._nextSet(self._row, start.end); + + do { + counters = self._toCounters(nextStart, counters); + pattern = self._toPattern(counters); + if (pattern < 0) { + return null; + } + decodedChar = self._patternToChar(pattern); + result.push(decodedChar); + lastStart = nextStart; + nextStart += ArrayHelper.sum(counters); + nextStart = self._nextSet(self._row, nextStart); + } while(decodedChar !== '*'); + result.pop(); + + + + return { + code : result.join(""), + start : start.start, + end : nextStart, + startInfo : start, + decodedCodes : result + }; + }; + + Code39Reader.prototype._patternToChar = function(pattern) { + var i, + self = this; + + for (i = 0; i < self.CHARACTER_ENCODINGS.length; i++) { + if (self.CHARACTER_ENCODINGS[i] === pattern) { + return String.fromCharCode(self.ALPHABET[i]); + } + } + }; + + Code39Reader.prototype._findNextWidth = function(counters, current) { + var i, + minWidth = Number.MAX_VALUE; + + for (i = 0; i < counters.length; i++) { + if (counters[i] < minWidth && counters[i] > current) { + minWidth = counters[i]; + } + } + + return minWidth; + }; + + Code39Reader.prototype._toPattern = function(counters) { + var numCounters = counters.length, + maxNarrowWidth = 0, + numWideBars = numCounters, + wideBarWidth = 0, + self = this, + pattern, + i; + + while(numWideBars > 3) { + maxNarrowWidth = self._findNextWidth(counters, maxNarrowWidth); + numWideBars = 0; + pattern = 0; + for (i = 0; i < numCounters; i++) { + if (counters[i] > maxNarrowWidth) { + pattern |= 1 << (numCounters - 1 - i); + numWideBars++; + wideBarWidth += counters[i]; + } + } + + if (numWideBars === 3) { + for (i = 0; i < numCounters && numWideBars > 0; i++) { + if (counters[i] > maxNarrowWidth) { + numWideBars--; + if ((counters[i] * 3) >= wideBarWidth) { + return -1; + } + } + } + return pattern; + } + } + return -1; + }; + + Code39Reader.prototype._findStart = function() { + var self = this, + offset = self._nextSet(self._row), + patternStart = offset, + counter = [0,0,0,0,0,0,0,0,0], + counterPos = 0, + isWhite = false, + i, + j, + whiteSpaceMustStart; + + for ( i = offset; i < self._row.length; i++) { + if (self._row[i] ^ isWhite) { + counter[counterPos]++; + } else { + if (counterPos === counter.length - 1) { + + // find start pattern + if (self._toPattern(counter) === self.ASTERISK) { + whiteSpaceMustStart = Math.floor(Math.max(0, patternStart - ((i - patternStart) / 4))); + if (self._matchRange(whiteSpaceMustStart, patternStart, 0)) { + return { + start: patternStart, + end: i + }; + } + } + + patternStart += counter[0] + counter[1]; + for ( j = 0; j < 7; j++) { + counter[j] = counter[j + 2]; + } + counter[7] = 0; + counter[8] = 0; + counterPos--; + } else { + counterPos++; + } + counter[counterPos] = 1; + isWhite = !isWhite; + } + } + return null; + }; + + return (Code39Reader); + } +); +/* jshint undef: true, unused: true, browser:true, devel: true */ +/* global define */ + +define('barcode_decoder',["bresenham", "image_debug", 'code_128_reader', 'ean_reader', 'code_39_reader'], function(Bresenham, ImageDebug, Code128Reader, EANReader, Code39Reader) { var readers = { code_128_reader: Code128Reader, - ean_reader: EANReader + ean_reader: EANReader, + code_39_reader: Code39Reader }; var BarcodeDecoder = { create : function(config, inputImageWrapper) { @@ -6967,7 +7191,7 @@ define('camera_access',["html_utils"], function(HtmlUtils) { } /** - * Tries to attach the camer-stream to a given video-element + * Tries to attach the camera-stream to a given video-element * and calls the callback function when the content is ready * @param {Object} constraints * @param {Object} video @@ -7001,6 +7225,12 @@ define('camera_access',["html_utils"], function(HtmlUtils) { }); } + /** + * Normalizes the incoming constraints to satisfy the current browser + * @param config + * @param cb Callback which is called whenever constraints are created + * @returns {*} + */ function normalizeConstraints(config, cb) { var constraints = { audio: false, diff --git a/examples/live_w_locator.html b/examples/live_w_locator.html index c2a80ec..d3ef4c4 100644 --- a/examples/live_w_locator.html +++ b/examples/live_w_locator.html @@ -17,6 +17,8 @@ showInMenu: false + +
diff --git a/examples/static_images.html b/examples/static_images.html index ec131c8..4d7a905 100644 --- a/examples/static_images.html +++ b/examples/static_images.html @@ -20,6 +20,8 @@ showInMenu: false + +
diff --git a/index.md b/index.md index 8948a72..406b735 100644 --- a/index.md +++ b/index.md @@ -268,6 +268,10 @@ In case you want to take a deeper dive into the inner workings of Quagga, get to ## Changelog +### 2015-03-04 +- Features + - Added support for [Code 39][code39_wiki] barcodes + ### 2015-01-21 - Features - Added support for web-worker (using 4 workers as default, can be changed through `config.numOfWorkers`) @@ -289,3 +293,4 @@ In the course of implementing web-workers some breaking changes were introduced [chaiUrl]: http://chaijs.com/ [mochaUrl]: https://github.com/mochajs/mocha [karmaUrl]: http://karma-runner.github.io/ +[code39_wiki]: http://en.wikipedia.org/wiki/Code_39 diff --git a/test/fixtures/code_39/image-001.jpg b/test/fixtures/code_39/image-001.jpg new file mode 100644 index 0000000..02f9d08 Binary files /dev/null and b/test/fixtures/code_39/image-001.jpg differ diff --git a/test/fixtures/code_39/image-002.jpg b/test/fixtures/code_39/image-002.jpg new file mode 100644 index 0000000..23054bf Binary files /dev/null and b/test/fixtures/code_39/image-002.jpg differ diff --git a/test/fixtures/code_39/image-003.jpg b/test/fixtures/code_39/image-003.jpg new file mode 100644 index 0000000..e375f64 Binary files /dev/null and b/test/fixtures/code_39/image-003.jpg differ diff --git a/test/fixtures/code_39/image-004.jpg b/test/fixtures/code_39/image-004.jpg new file mode 100644 index 0000000..3166f7b Binary files /dev/null and b/test/fixtures/code_39/image-004.jpg differ diff --git a/test/fixtures/code_39/image-005.jpg b/test/fixtures/code_39/image-005.jpg new file mode 100644 index 0000000..3b87463 Binary files /dev/null and b/test/fixtures/code_39/image-005.jpg differ diff --git a/test/fixtures/code_39/image-006.jpg b/test/fixtures/code_39/image-006.jpg new file mode 100644 index 0000000..14fb03f Binary files /dev/null and b/test/fixtures/code_39/image-006.jpg differ diff --git a/test/fixtures/code_39/image-007.jpg b/test/fixtures/code_39/image-007.jpg new file mode 100644 index 0000000..baeddab Binary files /dev/null and b/test/fixtures/code_39/image-007.jpg differ diff --git a/test/fixtures/code_39/image-008.jpg b/test/fixtures/code_39/image-008.jpg new file mode 100644 index 0000000..4ba7c1e Binary files /dev/null and b/test/fixtures/code_39/image-008.jpg differ diff --git a/test/fixtures/code_39/image-009.jpg b/test/fixtures/code_39/image-009.jpg new file mode 100644 index 0000000..6a67ddc Binary files /dev/null and b/test/fixtures/code_39/image-009.jpg differ diff --git a/test/fixtures/code_39/image-010.jpg b/test/fixtures/code_39/image-010.jpg new file mode 100644 index 0000000..f6bf568 Binary files /dev/null and b/test/fixtures/code_39/image-010.jpg differ