Merge pull request #28 from serratus/issue-26
Issue 26 - Support for Codabar Barcodes
@@ -1,13 +1,13 @@
|
|||||||
quaggaJS
|
quaggaJS
|
||||||
========
|
========
|
||||||
|
|
||||||
- [Changelog](#changelog) (2015-03-16)
|
- [Changelog](#changelog) (2015-04-16)
|
||||||
|
|
||||||
## What is QuaggaJS?
|
## What is QuaggaJS?
|
||||||
|
|
||||||
QuaggaJS is a barcode-scanner entirely written in JavaScript supporting real-
|
QuaggaJS is a barcode-scanner entirely written in JavaScript supporting real-
|
||||||
time localization and decoding of various types of barcodes such as __EAN__,
|
time localization and decoding of various types of barcodes such as __EAN__,
|
||||||
__CODE128__ and __CODE39__. The library is also capable of using `getUserMedia`
|
__CODE128__, __CODE39__ and __CODABAR__. The library is also capable of using `getUserMedia`
|
||||||
to get direct access to the user's camera stream. Although the code relies on
|
to get direct access to the user's camera stream. Although the code relies on
|
||||||
heavy image-processing even recent smartphones are capable of locating and
|
heavy image-processing even recent smartphones are capable of locating and
|
||||||
decoding barcodes in real-time.
|
decoding barcodes in real-time.
|
||||||
@@ -291,6 +291,10 @@ work.
|
|||||||
|
|
||||||
## <a name="changelog">Changelog</a>
|
## <a name="changelog">Changelog</a>
|
||||||
|
|
||||||
|
### 2015-04-16
|
||||||
|
- Features
|
||||||
|
- Added support for [Codabar][codabar_wiki] barcodes
|
||||||
|
|
||||||
### 2015-03-16
|
### 2015-03-16
|
||||||
- Improvements
|
- Improvements
|
||||||
- now includes minified version (23.3KB gzipped)
|
- now includes minified version (23.3KB gzipped)
|
||||||
@@ -334,5 +338,6 @@ introduced to the API.
|
|||||||
[mochaUrl]: https://github.com/mochajs/mocha
|
[mochaUrl]: https://github.com/mochajs/mocha
|
||||||
[karmaUrl]: http://karma-runner.github.io/
|
[karmaUrl]: http://karma-runner.github.io/
|
||||||
[code39_wiki]: http://en.wikipedia.org/wiki/Code_39
|
[code39_wiki]: http://en.wikipedia.org/wiki/Code_39
|
||||||
|
[codabar_wiki]: http://en.wikipedia.org/wiki/Codabar
|
||||||
[oberhofer_co_how]: http://www.oberhofer.co/how-barcode-localization-works-in-quaggajs/
|
[oberhofer_co_how]: http://www.oberhofer.co/how-barcode-localization-works-in-quaggajs/
|
||||||
[github_examples]: http://serratus.github.io/quaggaJS/examples
|
[github_examples]: http://serratus.github.io/quaggaJS/examples
|
||||||
|
|||||||
@@ -437,7 +437,7 @@ define("almond", function(){});
|
|||||||
|
|
||||||
define(
|
define(
|
||||||
'barcode_reader',[],function() {
|
'barcode_reader',[],function() {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
function BarcodeReader() {
|
function BarcodeReader() {
|
||||||
this._row = [];
|
this._row = [];
|
||||||
@@ -631,7 +631,7 @@ define(
|
|||||||
"./barcode_reader"
|
"./barcode_reader"
|
||||||
],
|
],
|
||||||
function(BarcodeReader) {
|
function(BarcodeReader) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
function Code128Reader() {
|
function Code128Reader() {
|
||||||
BarcodeReader.call(this);
|
BarcodeReader.call(this);
|
||||||
@@ -1079,7 +1079,7 @@ define(
|
|||||||
"./barcode_reader"
|
"./barcode_reader"
|
||||||
],
|
],
|
||||||
function(BarcodeReader) {
|
function(BarcodeReader) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
function EANReader() {
|
function EANReader() {
|
||||||
BarcodeReader.call(this);
|
BarcodeReader.call(this);
|
||||||
@@ -1329,7 +1329,7 @@ define(
|
|||||||
/* global define */
|
/* global define */
|
||||||
|
|
||||||
define('image_loader',[],function() {
|
define('image_loader',[],function() {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
var ImageLoader = {};
|
var ImageLoader = {};
|
||||||
ImageLoader.load = function(directory, callback, offset, size, sequence) {
|
ImageLoader.load = function(directory, callback, offset, size, sequence) {
|
||||||
@@ -1393,7 +1393,7 @@ define('image_loader',[],function() {
|
|||||||
/* global define */
|
/* global define */
|
||||||
|
|
||||||
define('input_stream',["image_loader"], function(ImageLoader) {
|
define('input_stream',["image_loader"], function(ImageLoader) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
var InputStream = {};
|
var InputStream = {};
|
||||||
InputStream.createVideoStream = function(video) {
|
InputStream.createVideoStream = function(video) {
|
||||||
@@ -1659,7 +1659,7 @@ define("typedefs", (function (global) {
|
|||||||
/* global define */
|
/* global define */
|
||||||
|
|
||||||
define('subImage',["typedefs"], function() {
|
define('subImage',["typedefs"], function() {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct representing a part of another {ImageWrapper}. Shares data
|
* Construct representing a part of another {ImageWrapper}. Shares data
|
||||||
@@ -1756,7 +1756,7 @@ define('subImage',["typedefs"], function() {
|
|||||||
/* global define, vec2 */
|
/* global define, vec2 */
|
||||||
|
|
||||||
define('cluster',[],function() {
|
define('cluster',[],function() {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a cluster for grouping similar orientations of datapoints
|
* Creates a cluster for grouping similar orientations of datapoints
|
||||||
@@ -4101,7 +4101,7 @@ define("glMatrixAddon", ["glMatrix"], (function (global) {
|
|||||||
/* global define */
|
/* global define */
|
||||||
|
|
||||||
define('array_helper',[],function() {
|
define('array_helper',[],function() {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
return {
|
return {
|
||||||
init : function(arr, val) {
|
init : function(arr, val) {
|
||||||
@@ -4188,7 +4188,7 @@ define('array_helper',[],function() {
|
|||||||
|
|
||||||
define('cv_utils',['cluster', 'glMatrixAddon', "array_helper"], function(Cluster2, glMatrixAddon, ArrayHelper) {
|
define('cv_utils',['cluster', 'glMatrixAddon', "array_helper"], function(Cluster2, glMatrixAddon, ArrayHelper) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
/*
|
/*
|
||||||
* cv_utils.js
|
* cv_utils.js
|
||||||
* Collection of CV functions and libraries
|
* Collection of CV functions and libraries
|
||||||
@@ -4738,7 +4738,7 @@ define('image_wrapper',[
|
|||||||
],
|
],
|
||||||
function(SubImage, CVUtils, ArrayHelper) {
|
function(SubImage, CVUtils, ArrayHelper) {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a basic image combining the data and size.
|
* Represents a basic image combining the data and size.
|
||||||
@@ -5159,7 +5159,7 @@ define('image_wrapper',[
|
|||||||
* http://www.codeproject.com/Tips/407172/Connected-Component-Labeling-and-Vectorization
|
* http://www.codeproject.com/Tips/407172/Connected-Component-Labeling-and-Vectorization
|
||||||
*/
|
*/
|
||||||
define('tracer',[],function() {
|
define('tracer',[],function() {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
var Tracer = {
|
var Tracer = {
|
||||||
searchDirections : [[0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0], [-1, 1]],
|
searchDirections : [[0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0], [-1, 1]],
|
||||||
@@ -5268,7 +5268,7 @@ define('tracer',[],function() {
|
|||||||
* http://www.codeproject.com/Tips/407172/Connected-Component-Labeling-and-Vectorization
|
* http://www.codeproject.com/Tips/407172/Connected-Component-Labeling-and-Vectorization
|
||||||
*/
|
*/
|
||||||
define('rasterizer',["tracer"], function(Tracer) {
|
define('rasterizer',["tracer"], function(Tracer) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
var Rasterizer = {
|
var Rasterizer = {
|
||||||
createContour2D : function() {
|
createContour2D : function() {
|
||||||
@@ -5464,7 +5464,7 @@ define('rasterizer',["tracer"], function(Tracer) {
|
|||||||
/* global define */
|
/* global define */
|
||||||
|
|
||||||
define('skeletonizer',[],function() {
|
define('skeletonizer',[],function() {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
/* @preserve ASM BEGIN */
|
/* @preserve ASM BEGIN */
|
||||||
function Skeletonizer(stdlib, foreign, buffer) {
|
function Skeletonizer(stdlib, foreign, buffer) {
|
||||||
@@ -5669,7 +5669,7 @@ define('skeletonizer',[],function() {
|
|||||||
/* global define */
|
/* global define */
|
||||||
|
|
||||||
define('image_debug',[],function() {
|
define('image_debug',[],function() {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
return {
|
return {
|
||||||
drawRect: function(pos, size, ctx, style){
|
drawRect: function(pos, size, ctx, style){
|
||||||
@@ -5698,10 +5698,9 @@ define('image_debug',[],function() {
|
|||||||
/* jshint undef: true, unused: true, browser:true, devel: true */
|
/* jshint undef: true, unused: true, browser:true, devel: true */
|
||||||
/* global define, mat2, vec2 */
|
/* global define, mat2, vec2 */
|
||||||
|
|
||||||
define('barcode_locator',["image_wrapper", "cv_utils", "rasterizer", "tracer", "skeletonizer", "array_helper", "image_debug"],
|
define("barcode_locator", ["image_wrapper", "cv_utils", "rasterizer", "tracer", "skeletonizer", "array_helper", "image_debug"],
|
||||||
function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, ImageDebug) {
|
function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, ImageDebug) {
|
||||||
|
|
||||||
|
|
||||||
var _config,
|
var _config,
|
||||||
_currentImageWrapper,
|
_currentImageWrapper,
|
||||||
_skelImageWrapper,
|
_skelImageWrapper,
|
||||||
@@ -6197,7 +6196,7 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
|
|||||||
|
|
||||||
// rasterrize area by comparing angular similarity;
|
// rasterrize area by comparing angular similarity;
|
||||||
var maxLabel = rasterizeAngularSimilarity(patchesFound);
|
var maxLabel = rasterizeAngularSimilarity(patchesFound);
|
||||||
if (maxLabel <= 1) {
|
if (maxLabel < 1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6218,7 +6217,7 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
|
|||||||
/* global define */
|
/* global define */
|
||||||
|
|
||||||
define('bresenham',[],function() {
|
define('bresenham',[],function() {
|
||||||
|
"use strict";
|
||||||
var Bresenham = {};
|
var Bresenham = {};
|
||||||
|
|
||||||
var Slope = {
|
var Slope = {
|
||||||
@@ -6424,7 +6423,7 @@ define(
|
|||||||
"./array_helper"
|
"./array_helper"
|
||||||
],
|
],
|
||||||
function(BarcodeReader, ArrayHelper) {
|
function(BarcodeReader, ArrayHelper) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
function Code39Reader() {
|
function Code39Reader() {
|
||||||
BarcodeReader.call(this);
|
BarcodeReader.call(this);
|
||||||
@@ -6489,6 +6488,9 @@ define(
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
decodedChar = self._patternToChar(pattern);
|
decodedChar = self._patternToChar(pattern);
|
||||||
|
if (decodedChar < 0){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
result.push(decodedChar);
|
result.push(decodedChar);
|
||||||
lastStart = nextStart;
|
lastStart = nextStart;
|
||||||
nextStart += ArrayHelper.sum(counters);
|
nextStart += ArrayHelper.sum(counters);
|
||||||
@@ -6618,13 +6620,327 @@ define(
|
|||||||
/* jshint undef: true, unused: true, browser:true, devel: true */
|
/* jshint undef: true, unused: true, browser:true, devel: true */
|
||||||
/* global define */
|
/* global define */
|
||||||
|
|
||||||
define('barcode_decoder',["bresenham", "image_debug", 'code_128_reader', 'ean_reader', 'code_39_reader'], function(Bresenham, ImageDebug, Code128Reader, EANReader, Code39Reader) {
|
define(
|
||||||
|
'codabar_reader',[
|
||||||
|
"./barcode_reader"
|
||||||
|
],
|
||||||
|
function(BarcodeReader) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
function CodabarReader() {
|
||||||
|
BarcodeReader.call(this);
|
||||||
|
this._counters = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
var properties = {
|
||||||
|
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: [0x003, 0x006, 0x009, 0x060, 0x012, 0x042, 0x021, 0x024, 0x030, 0x048, 0x00c, 0x018, 0x045, 0x051, 0x054, 0x015, 0x01A, 0x029, 0x00B, 0x00E]},
|
||||||
|
START_END: {value: [0x01A, 0x029, 0x00B, 0x00E]},
|
||||||
|
MIN_ENCODED_CHARS: {value: 4},
|
||||||
|
MAX_ACCEPTABLE: {value: 2.0},
|
||||||
|
PADDING: {value: 1.5}
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype = Object.create(BarcodeReader.prototype, properties);
|
||||||
|
CodabarReader.prototype.constructor = CodabarReader;
|
||||||
|
|
||||||
|
CodabarReader.prototype._decode = function() {
|
||||||
|
var self = this,
|
||||||
|
result = [],
|
||||||
|
start,
|
||||||
|
decodedChar,
|
||||||
|
pattern,
|
||||||
|
nextStart,
|
||||||
|
end;
|
||||||
|
|
||||||
|
self._fillCounters();
|
||||||
|
start = self._findStart();
|
||||||
|
if (!start) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
nextStart = start.startCounter;
|
||||||
|
|
||||||
|
do {
|
||||||
|
pattern = self._toPattern(nextStart);
|
||||||
|
if (pattern < 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
decodedChar = self._patternToChar(pattern);
|
||||||
|
if (decodedChar < 0){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
result.push(decodedChar);
|
||||||
|
nextStart += 8;
|
||||||
|
if (result.length > 1 && self._isStartEnd(pattern)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while(nextStart < self._counters.length);
|
||||||
|
|
||||||
|
// verify end
|
||||||
|
if ((result.length - 2) < self.MIN_ENCODED_CHARS || !self._isStartEnd(pattern)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify end white space
|
||||||
|
if (!self._verifyWhitespace(start.startCounter, nextStart - 8)){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!self._validateResult(result, start.startCounter)){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
nextStart = nextStart > self._counters.length ? self._counters.length : nextStart;
|
||||||
|
end = start.start + self._sumCounters(start.startCounter, nextStart - 8);
|
||||||
|
|
||||||
|
return {
|
||||||
|
code : result.join(""),
|
||||||
|
start : start.start,
|
||||||
|
end : end,
|
||||||
|
startInfo : start,
|
||||||
|
decodedCodes : result
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype._verifyWhitespace = function(startCounter, endCounter) {
|
||||||
|
if ((startCounter - 1 <= 0) || this._counters[startCounter-1] >= (this._calculatePatternLength(startCounter) / 2.0)) {
|
||||||
|
if ((endCounter + 8 >= this._counters.length) || this._counters[endCounter+7] >= (this._calculatePatternLength(endCounter) / 2.0)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype._calculatePatternLength = function(offset) {
|
||||||
|
var i,
|
||||||
|
sum = 0;
|
||||||
|
|
||||||
|
for (i = offset; i < offset + 7; i++) {
|
||||||
|
sum += this._counters[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype._thresholdResultPattern = function(result, startCounter){
|
||||||
|
var self = this,
|
||||||
|
categorization = {
|
||||||
|
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}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
kind,
|
||||||
|
cat,
|
||||||
|
i,
|
||||||
|
j,
|
||||||
|
pos = startCounter,
|
||||||
|
pattern;
|
||||||
|
|
||||||
|
for (i = 0; i < result.length; i++){
|
||||||
|
pattern = self._charToPattern(result[i]);
|
||||||
|
for (j = 6; j >= 0; j--) {
|
||||||
|
kind = (j & 1) === 2 ? categorization.bar : categorization.space;
|
||||||
|
cat = (pattern & 1) === 1 ? kind.wide : kind.narrow;
|
||||||
|
cat.size += self._counters[pos + j];
|
||||||
|
cat.counts++;
|
||||||
|
pattern >>= 1;
|
||||||
|
}
|
||||||
|
pos += 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
["space", "bar"].forEach(function(key) {
|
||||||
|
var kind = categorization[key];
|
||||||
|
kind.wide.min = Math.floor((kind.narrow.size/kind.narrow.counts + kind.wide.size / kind.wide.counts) / 2);
|
||||||
|
kind.narrow.max = Math.ceil(kind.wide.min);
|
||||||
|
kind.wide.max = Math.ceil((kind.wide.size * self.MAX_ACCEPTABLE + self.PADDING) / kind.wide.counts);
|
||||||
|
});
|
||||||
|
|
||||||
|
return categorization;
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype._charToPattern = function(char) {
|
||||||
|
var self = this,
|
||||||
|
charCode = char.charCodeAt(0),
|
||||||
|
i;
|
||||||
|
|
||||||
|
for (i = 0; i < self.ALPHABET.length; i++) {
|
||||||
|
if (self.ALPHABET[i] === charCode){
|
||||||
|
return self.CHARACTER_ENCODINGS[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0x0;
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype._validateResult = function(result, startCounter) {
|
||||||
|
var self = this,
|
||||||
|
thresholds = self._thresholdResultPattern(result, startCounter),
|
||||||
|
i,
|
||||||
|
j,
|
||||||
|
kind,
|
||||||
|
cat,
|
||||||
|
size,
|
||||||
|
pos = startCounter,
|
||||||
|
pattern;
|
||||||
|
|
||||||
|
for (i = 0; i < result.length; i++) {
|
||||||
|
pattern = self._charToPattern(result[i]);
|
||||||
|
for (j = 6; j >= 0; j--) {
|
||||||
|
kind = (j & 1) === 0 ? thresholds.bar : thresholds.space;
|
||||||
|
cat = (pattern & 1) === 1 ? kind.wide : kind.narrow;
|
||||||
|
size = self._counters[pos + j];
|
||||||
|
if (size < cat.min || size > cat.max) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pattern >>= 1;
|
||||||
|
}
|
||||||
|
pos += 8;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype._fillCounters = function() {
|
||||||
|
var self = this,
|
||||||
|
counterPos = 0,
|
||||||
|
isWhite = true,
|
||||||
|
offset = self._nextUnset(self._row),
|
||||||
|
i;
|
||||||
|
|
||||||
|
self._counters.length = 0;
|
||||||
|
self._counters[counterPos] = 0;
|
||||||
|
for (i = offset; i < self._row.length; i++) {
|
||||||
|
if (self._row[i] ^ isWhite) {
|
||||||
|
this._counters[counterPos]++;
|
||||||
|
} else {
|
||||||
|
counterPos++;
|
||||||
|
this._counters[counterPos] = 1;
|
||||||
|
isWhite = !isWhite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype._computeAlternatingThreshold = function(offset, end) {
|
||||||
|
var i,
|
||||||
|
min = Number.MAX_VALUE,
|
||||||
|
max = 0,
|
||||||
|
counter;
|
||||||
|
|
||||||
|
for (i = offset; i < end; i += 2){
|
||||||
|
counter = this._counters[i];
|
||||||
|
if (counter > max) {
|
||||||
|
max = counter;
|
||||||
|
}
|
||||||
|
if (counter < min) {
|
||||||
|
min = counter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((min + max) / 2.0) | 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype._toPattern = function(offset) {
|
||||||
|
var numCounters = 7,
|
||||||
|
end = offset + numCounters,
|
||||||
|
barThreshold,
|
||||||
|
spaceThreshold,
|
||||||
|
bitmask = 1 << (numCounters - 1),
|
||||||
|
pattern = 0,
|
||||||
|
i,
|
||||||
|
threshold;
|
||||||
|
|
||||||
|
if (end > this._counters.length) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
barThreshold = this._computeAlternatingThreshold(offset, end);
|
||||||
|
spaceThreshold = this._computeAlternatingThreshold(offset + 1, end);
|
||||||
|
|
||||||
|
for (i = 0; i < numCounters; i++){
|
||||||
|
threshold = (i & 1) === 0 ? barThreshold : spaceThreshold;
|
||||||
|
if (this._counters[offset + i] > threshold) {
|
||||||
|
pattern |= bitmask;
|
||||||
|
}
|
||||||
|
bitmask >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pattern;
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype._isStartEnd = function(pattern) {
|
||||||
|
var i;
|
||||||
|
|
||||||
|
for (i = 0; i < this.START_END.length; i++) {
|
||||||
|
if (this.START_END[i] === pattern) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype._sumCounters = function(start, end) {
|
||||||
|
var i,
|
||||||
|
sum = 0;
|
||||||
|
|
||||||
|
for (i = start; i < end; i++) {
|
||||||
|
sum += this._counters[i];
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype._findStart = function() {
|
||||||
|
var self = this,
|
||||||
|
i,
|
||||||
|
pattern,
|
||||||
|
start = self._nextUnset(self._row),
|
||||||
|
end;
|
||||||
|
|
||||||
|
for (i = 1; i < this._counters.length; i++) {
|
||||||
|
pattern = self._toPattern(i);
|
||||||
|
if (pattern !== -1 && self._isStartEnd(pattern)) {
|
||||||
|
// TODO: Look for whitespace ahead
|
||||||
|
start += self._sumCounters(0, i);
|
||||||
|
end = start + self._sumCounters(i, i + 8);
|
||||||
|
return {
|
||||||
|
start: start,
|
||||||
|
end: end,
|
||||||
|
startCounter: i,
|
||||||
|
endCounter: i + 8
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (CodabarReader);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
/* 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', 'codabar_reader'], function(Bresenham, ImageDebug, Code128Reader, EANReader, Code39Reader, CodabarReader) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
var readers = {
|
var readers = {
|
||||||
code_128_reader: Code128Reader,
|
code_128_reader: Code128Reader,
|
||||||
ean_reader: EANReader,
|
ean_reader: EANReader,
|
||||||
code_39_reader: Code39Reader
|
code_39_reader: Code39Reader,
|
||||||
|
codabar_reader: CodabarReader
|
||||||
};
|
};
|
||||||
var BarcodeDecoder = {
|
var BarcodeDecoder = {
|
||||||
create : function(config, inputImageWrapper) {
|
create : function(config, inputImageWrapper) {
|
||||||
@@ -6877,7 +7193,7 @@ define('barcode_decoder',["bresenham", "image_debug", 'code_128_reader', 'ean_re
|
|||||||
/* global define */
|
/* global define */
|
||||||
|
|
||||||
define('frame_grabber',["cv_utils"], function(CVUtils) {
|
define('frame_grabber',["cv_utils"], function(CVUtils) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
var FrameGrabber = {};
|
var FrameGrabber = {};
|
||||||
|
|
||||||
@@ -6970,7 +7286,7 @@ define('frame_grabber',["cv_utils"], function(CVUtils) {
|
|||||||
/* global define */
|
/* global define */
|
||||||
|
|
||||||
define('html_utils',[], function() {
|
define('html_utils',[], function() {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
function createNode(htmlStr) {
|
function createNode(htmlStr) {
|
||||||
var temp = document.createElement('div');
|
var temp = document.createElement('div');
|
||||||
@@ -7060,7 +7376,7 @@ define('config',[],function(){
|
|||||||
/* global define */
|
/* global define */
|
||||||
|
|
||||||
define('events',[],function() {
|
define('events',[],function() {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
var _events = function() {
|
var _events = function() {
|
||||||
var events = {};
|
var events = {};
|
||||||
@@ -7151,7 +7467,7 @@ define('events',[],function() {
|
|||||||
/* global define, MediaStreamTrack */
|
/* global define, MediaStreamTrack */
|
||||||
|
|
||||||
define('camera_access',["html_utils"], function(HtmlUtils) {
|
define('camera_access',["html_utils"], function(HtmlUtils) {
|
||||||
|
"use strict";
|
||||||
var streamRef;
|
var streamRef;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -7282,7 +7598,7 @@ define('camera_access',["html_utils"], function(HtmlUtils) {
|
|||||||
|
|
||||||
define('quagga',["code_128_reader", "ean_reader", "input_stream", "image_wrapper", "barcode_locator", "barcode_decoder", "frame_grabber", "html_utils", "config", "events", "camera_access", "image_debug"],
|
define('quagga',["code_128_reader", "ean_reader", "input_stream", "image_wrapper", "barcode_locator", "barcode_decoder", "frame_grabber", "html_utils", "config", "events", "camera_access", "image_debug"],
|
||||||
function(Code128Reader, EANReader, InputStream, ImageWrapper, BarcodeLocator, BarcodeDecoder, FrameGrabber, HtmlUtils, _config, Events, CameraAccess, ImageDebug) {
|
function(Code128Reader, EANReader, InputStream, ImageWrapper, BarcodeLocator, BarcodeDecoder, FrameGrabber, HtmlUtils, _config, Events, CameraAccess, ImageDebug) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
var _inputStream,
|
var _inputStream,
|
||||||
_framegrabber,
|
_framegrabber,
|
||||||
|
|||||||
@@ -31,8 +31,10 @@
|
|||||||
<div class="controls">
|
<div class="controls">
|
||||||
<button class="next">Next</button>
|
<button class="next">Next</button>
|
||||||
<fieldset class="reader-group">
|
<fieldset class="reader-group">
|
||||||
|
<label>Codabar</label>
|
||||||
|
<input type="radio" name="reader" value="codabar" checked />
|
||||||
<label>Code39</label>
|
<label>Code39</label>
|
||||||
<input type="radio" name="reader" value="code_39" checked />
|
<input type="radio" name="reader" value="code_39" />
|
||||||
<label>Code128</label>
|
<label>Code128</label>
|
||||||
<input type="radio" name="reader" value="code_128" />
|
<input type="radio" name="reader" value="code_128" />
|
||||||
<label>EAN</label>
|
<label>EAN</label>
|
||||||
@@ -51,7 +53,7 @@
|
|||||||
</p>
|
</p>
|
||||||
</footer>
|
</footer>
|
||||||
<script src="../src/vendor/jquery-1.9.0.min.js" type="text/javascript"></script>
|
<script src="../src/vendor/jquery-1.9.0.min.js" type="text/javascript"></script>
|
||||||
<script src="../dist/quagga.min.js" type="text/javascript"></script>
|
<script src="../dist/quagga.js" type="text/javascript"></script>
|
||||||
<script src="static_images.js" type="text/javascript"></script>
|
<script src="static_images.js" type="text/javascript"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ $(function() {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
reader: "code_39",
|
reader: "codabar",
|
||||||
length: 10
|
length: 10
|
||||||
},
|
},
|
||||||
attachListeners: function() {
|
attachListeners: function() {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "quagga",
|
"name": "quagga",
|
||||||
"version": "0.5.2",
|
"version": "0.5.3",
|
||||||
"description": "An advanced barcode-scanner written in JavaScript",
|
"description": "An advanced barcode-scanner written in JavaScript",
|
||||||
"main": "dist/quagga.js",
|
"main": "dist/quagga.js",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
/* jshint undef: true, unused: true, browser:true, devel: true */
|
/* jshint undef: true, unused: true, browser:true, devel: true */
|
||||||
/* global define */
|
/* global define */
|
||||||
|
|
||||||
define(["bresenham", "image_debug", 'code_128_reader', 'ean_reader', 'code_39_reader'], function(Bresenham, ImageDebug, Code128Reader, EANReader, Code39Reader) {
|
define(["bresenham", "image_debug", 'code_128_reader', 'ean_reader', 'code_39_reader', 'codabar_reader'], function(Bresenham, ImageDebug, Code128Reader, EANReader, Code39Reader, CodabarReader) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var readers = {
|
var readers = {
|
||||||
code_128_reader: Code128Reader,
|
code_128_reader: Code128Reader,
|
||||||
ean_reader: EANReader,
|
ean_reader: EANReader,
|
||||||
code_39_reader: Code39Reader
|
code_39_reader: Code39Reader,
|
||||||
|
codabar_reader: CodabarReader
|
||||||
};
|
};
|
||||||
var BarcodeDecoder = {
|
var BarcodeDecoder = {
|
||||||
create : function(config, inputImageWrapper) {
|
create : function(config, inputImageWrapper) {
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
/* jshint undef: true, unused: true, browser:true, devel: true */
|
/* jshint undef: true, unused: true, browser:true, devel: true */
|
||||||
/* global define, mat2, vec2 */
|
/* global define, mat2, vec2 */
|
||||||
|
|
||||||
define(["image_wrapper", "cv_utils", "rasterizer", "tracer", "skeletonizer", "array_helper", "image_debug"],
|
define("barcode_locator", ["image_wrapper", "cv_utils", "rasterizer", "tracer", "skeletonizer", "array_helper", "image_debug"],
|
||||||
function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, ImageDebug) {
|
function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, ImageDebug) {
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var _config,
|
var _config,
|
||||||
_currentImageWrapper,
|
_currentImageWrapper,
|
||||||
_skelImageWrapper,
|
_skelImageWrapper,
|
||||||
@@ -500,7 +499,7 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
|
|||||||
|
|
||||||
// rasterrize area by comparing angular similarity;
|
// rasterrize area by comparing angular similarity;
|
||||||
var maxLabel = rasterizeAngularSimilarity(patchesFound);
|
var maxLabel = rasterizeAngularSimilarity(patchesFound);
|
||||||
if (maxLabel <= 1) {
|
if (maxLabel < 1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,313 @@
|
|||||||
|
/* jshint undef: true, unused: true, browser:true, devel: true */
|
||||||
|
/* global define */
|
||||||
|
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
"./barcode_reader"
|
||||||
|
],
|
||||||
|
function(BarcodeReader) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
function CodabarReader() {
|
||||||
|
BarcodeReader.call(this);
|
||||||
|
this._counters = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
var properties = {
|
||||||
|
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: [0x003, 0x006, 0x009, 0x060, 0x012, 0x042, 0x021, 0x024, 0x030, 0x048, 0x00c, 0x018, 0x045, 0x051, 0x054, 0x015, 0x01A, 0x029, 0x00B, 0x00E]},
|
||||||
|
START_END: {value: [0x01A, 0x029, 0x00B, 0x00E]},
|
||||||
|
MIN_ENCODED_CHARS: {value: 4},
|
||||||
|
MAX_ACCEPTABLE: {value: 2.0},
|
||||||
|
PADDING: {value: 1.5}
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype = Object.create(BarcodeReader.prototype, properties);
|
||||||
|
CodabarReader.prototype.constructor = CodabarReader;
|
||||||
|
|
||||||
|
CodabarReader.prototype._decode = function() {
|
||||||
|
var self = this,
|
||||||
|
result = [],
|
||||||
|
start,
|
||||||
|
decodedChar,
|
||||||
|
pattern,
|
||||||
|
nextStart,
|
||||||
|
end;
|
||||||
|
|
||||||
|
self._fillCounters();
|
||||||
|
start = self._findStart();
|
||||||
|
if (!start) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
nextStart = start.startCounter;
|
||||||
|
|
||||||
|
do {
|
||||||
|
pattern = self._toPattern(nextStart);
|
||||||
|
if (pattern < 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
decodedChar = self._patternToChar(pattern);
|
||||||
|
if (decodedChar < 0){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
result.push(decodedChar);
|
||||||
|
nextStart += 8;
|
||||||
|
if (result.length > 1 && self._isStartEnd(pattern)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while(nextStart < self._counters.length);
|
||||||
|
|
||||||
|
// verify end
|
||||||
|
if ((result.length - 2) < self.MIN_ENCODED_CHARS || !self._isStartEnd(pattern)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify end white space
|
||||||
|
if (!self._verifyWhitespace(start.startCounter, nextStart - 8)){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!self._validateResult(result, start.startCounter)){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
nextStart = nextStart > self._counters.length ? self._counters.length : nextStart;
|
||||||
|
end = start.start + self._sumCounters(start.startCounter, nextStart - 8);
|
||||||
|
|
||||||
|
return {
|
||||||
|
code : result.join(""),
|
||||||
|
start : start.start,
|
||||||
|
end : end,
|
||||||
|
startInfo : start,
|
||||||
|
decodedCodes : result
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype._verifyWhitespace = function(startCounter, endCounter) {
|
||||||
|
if ((startCounter - 1 <= 0) || this._counters[startCounter-1] >= (this._calculatePatternLength(startCounter) / 2.0)) {
|
||||||
|
if ((endCounter + 8 >= this._counters.length) || this._counters[endCounter+7] >= (this._calculatePatternLength(endCounter) / 2.0)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype._calculatePatternLength = function(offset) {
|
||||||
|
var i,
|
||||||
|
sum = 0;
|
||||||
|
|
||||||
|
for (i = offset; i < offset + 7; i++) {
|
||||||
|
sum += this._counters[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype._thresholdResultPattern = function(result, startCounter){
|
||||||
|
var self = this,
|
||||||
|
categorization = {
|
||||||
|
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}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
kind,
|
||||||
|
cat,
|
||||||
|
i,
|
||||||
|
j,
|
||||||
|
pos = startCounter,
|
||||||
|
pattern;
|
||||||
|
|
||||||
|
for (i = 0; i < result.length; i++){
|
||||||
|
pattern = self._charToPattern(result[i]);
|
||||||
|
for (j = 6; j >= 0; j--) {
|
||||||
|
kind = (j & 1) === 2 ? categorization.bar : categorization.space;
|
||||||
|
cat = (pattern & 1) === 1 ? kind.wide : kind.narrow;
|
||||||
|
cat.size += self._counters[pos + j];
|
||||||
|
cat.counts++;
|
||||||
|
pattern >>= 1;
|
||||||
|
}
|
||||||
|
pos += 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
["space", "bar"].forEach(function(key) {
|
||||||
|
var kind = categorization[key];
|
||||||
|
kind.wide.min = Math.floor((kind.narrow.size/kind.narrow.counts + kind.wide.size / kind.wide.counts) / 2);
|
||||||
|
kind.narrow.max = Math.ceil(kind.wide.min);
|
||||||
|
kind.wide.max = Math.ceil((kind.wide.size * self.MAX_ACCEPTABLE + self.PADDING) / kind.wide.counts);
|
||||||
|
});
|
||||||
|
|
||||||
|
return categorization;
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype._charToPattern = function(char) {
|
||||||
|
var self = this,
|
||||||
|
charCode = char.charCodeAt(0),
|
||||||
|
i;
|
||||||
|
|
||||||
|
for (i = 0; i < self.ALPHABET.length; i++) {
|
||||||
|
if (self.ALPHABET[i] === charCode){
|
||||||
|
return self.CHARACTER_ENCODINGS[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0x0;
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype._validateResult = function(result, startCounter) {
|
||||||
|
var self = this,
|
||||||
|
thresholds = self._thresholdResultPattern(result, startCounter),
|
||||||
|
i,
|
||||||
|
j,
|
||||||
|
kind,
|
||||||
|
cat,
|
||||||
|
size,
|
||||||
|
pos = startCounter,
|
||||||
|
pattern;
|
||||||
|
|
||||||
|
for (i = 0; i < result.length; i++) {
|
||||||
|
pattern = self._charToPattern(result[i]);
|
||||||
|
for (j = 6; j >= 0; j--) {
|
||||||
|
kind = (j & 1) === 0 ? thresholds.bar : thresholds.space;
|
||||||
|
cat = (pattern & 1) === 1 ? kind.wide : kind.narrow;
|
||||||
|
size = self._counters[pos + j];
|
||||||
|
if (size < cat.min || size > cat.max) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pattern >>= 1;
|
||||||
|
}
|
||||||
|
pos += 8;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype._fillCounters = function() {
|
||||||
|
var self = this,
|
||||||
|
counterPos = 0,
|
||||||
|
isWhite = true,
|
||||||
|
offset = self._nextUnset(self._row),
|
||||||
|
i;
|
||||||
|
|
||||||
|
self._counters.length = 0;
|
||||||
|
self._counters[counterPos] = 0;
|
||||||
|
for (i = offset; i < self._row.length; i++) {
|
||||||
|
if (self._row[i] ^ isWhite) {
|
||||||
|
this._counters[counterPos]++;
|
||||||
|
} else {
|
||||||
|
counterPos++;
|
||||||
|
this._counters[counterPos] = 1;
|
||||||
|
isWhite = !isWhite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype._computeAlternatingThreshold = function(offset, end) {
|
||||||
|
var i,
|
||||||
|
min = Number.MAX_VALUE,
|
||||||
|
max = 0,
|
||||||
|
counter;
|
||||||
|
|
||||||
|
for (i = offset; i < end; i += 2){
|
||||||
|
counter = this._counters[i];
|
||||||
|
if (counter > max) {
|
||||||
|
max = counter;
|
||||||
|
}
|
||||||
|
if (counter < min) {
|
||||||
|
min = counter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((min + max) / 2.0) | 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype._toPattern = function(offset) {
|
||||||
|
var numCounters = 7,
|
||||||
|
end = offset + numCounters,
|
||||||
|
barThreshold,
|
||||||
|
spaceThreshold,
|
||||||
|
bitmask = 1 << (numCounters - 1),
|
||||||
|
pattern = 0,
|
||||||
|
i,
|
||||||
|
threshold;
|
||||||
|
|
||||||
|
if (end > this._counters.length) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
barThreshold = this._computeAlternatingThreshold(offset, end);
|
||||||
|
spaceThreshold = this._computeAlternatingThreshold(offset + 1, end);
|
||||||
|
|
||||||
|
for (i = 0; i < numCounters; i++){
|
||||||
|
threshold = (i & 1) === 0 ? barThreshold : spaceThreshold;
|
||||||
|
if (this._counters[offset + i] > threshold) {
|
||||||
|
pattern |= bitmask;
|
||||||
|
}
|
||||||
|
bitmask >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pattern;
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype._isStartEnd = function(pattern) {
|
||||||
|
var i;
|
||||||
|
|
||||||
|
for (i = 0; i < this.START_END.length; i++) {
|
||||||
|
if (this.START_END[i] === pattern) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype._sumCounters = function(start, end) {
|
||||||
|
var i,
|
||||||
|
sum = 0;
|
||||||
|
|
||||||
|
for (i = start; i < end; i++) {
|
||||||
|
sum += this._counters[i];
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
};
|
||||||
|
|
||||||
|
CodabarReader.prototype._findStart = function() {
|
||||||
|
var self = this,
|
||||||
|
i,
|
||||||
|
pattern,
|
||||||
|
start = self._nextUnset(self._row),
|
||||||
|
end;
|
||||||
|
|
||||||
|
for (i = 1; i < this._counters.length; i++) {
|
||||||
|
pattern = self._toPattern(i);
|
||||||
|
if (pattern !== -1 && self._isStartEnd(pattern)) {
|
||||||
|
// TODO: Look for whitespace ahead
|
||||||
|
start += self._sumCounters(0, i);
|
||||||
|
end = start + self._sumCounters(i, i + 8);
|
||||||
|
return {
|
||||||
|
start: start,
|
||||||
|
end: end,
|
||||||
|
startCounter: i,
|
||||||
|
endCounter: i + 8
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (CodabarReader);
|
||||||
|
}
|
||||||
|
);
|
||||||
@@ -72,6 +72,9 @@ define(
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
decodedChar = self._patternToChar(pattern);
|
decodedChar = self._patternToChar(pattern);
|
||||||
|
if (decodedChar < 0){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
result.push(decodedChar);
|
result.push(decodedChar);
|
||||||
lastStart = nextStart;
|
lastStart = nextStart;
|
||||||
nextStart += ArrayHelper.sum(counters);
|
nextStart += ArrayHelper.sum(counters);
|
||||||
|
|||||||
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 83 KiB |