Initial commit for I2of5 reader; Relates to #49

pull/55/head
Christoph Oberhofer 10 years ago
parent 59e3466c25
commit 9c0248f1d7

10827
dist/quagga.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -116,12 +116,13 @@ define(['quagga'], function(Quagga) {
singleChannel: false singleChannel: false
}, },
locator: { locator: {
patchSize: "medium", patchSize: "large",
halfSample: true halfSample: true,
showCanvas: true
}, },
numOfWorkers: 0, numOfWorkers: 0,
decoder: { decoder: {
readers: ["code_128_reader"], readers: ["i2of5_reader"],
showFrequency: true, showFrequency: true,
showPattern: true showPattern: true
}, },

@ -11,7 +11,8 @@ define([
'codabar_reader', 'codabar_reader',
'upc_reader', 'upc_reader',
'ean_8_reader', 'ean_8_reader',
'upc_e_reader' 'upc_e_reader',
'i2of5_reader'
], function( ], function(
Bresenham, Bresenham,
ImageDebug, ImageDebug,
@ -22,7 +23,8 @@ define([
CodabarReader, CodabarReader,
UPCReader, UPCReader,
EAN8Reader, EAN8Reader,
UPCEReader) { UPCEReader,
I2of5Reader) {
"use strict"; "use strict";
var readers = { var readers = {
@ -33,7 +35,8 @@ define([
code_39_vin_reader: Code39VINReader, code_39_vin_reader: Code39VINReader,
codabar_reader: CodabarReader, codabar_reader: CodabarReader,
upc_reader: UPCReader, upc_reader: UPCReader,
upc_e_reader: UPCEReader upc_e_reader: UPCEReader,
i2of5_reader: I2of5Reader
}; };
var BarcodeDecoder = { var BarcodeDecoder = {
create : function(config, inputImageWrapper) { create : function(config, inputImageWrapper) {

@ -184,6 +184,29 @@ define(
return true; return true;
}; };
BarcodeReader.prototype._fillCounters = function(offset, end, isWhite) {
var self = this,
counterPos = 0,
i,
counters = [];
isWhite = (typeof isWhite !== 'undefined') ? isWhite : true;
offset = (typeof offset !== 'undefined') ? offset : self._nextUnset(self._row);
end = end || self._row.length;
counters[counterPos] = 0;
for (i = offset; i < end; i++) {
if (self._row[i] ^ isWhite) {
counters[counterPos]++;
} else {
counterPos++;
counters[counterPos] = 1;
isWhite = !isWhite;
}
}
return counters;
};
Object.defineProperty(BarcodeReader.prototype, "FORMAT", { Object.defineProperty(BarcodeReader.prototype, "FORMAT", {
value: 'unknown', value: 'unknown',
writeable: false writeable: false

@ -36,7 +36,7 @@ define(
nextStart, nextStart,
end; end;
self._fillCounters(); this._counters = self._fillCounters();
start = self._findStart(); start = self._findStart();
if (!start) { if (!start) {
return null; return null;
@ -186,26 +186,6 @@ define(
return true; 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) { CodabarReader.prototype._patternToChar = function(pattern) {
var i, var i,
self = this; self = this;

@ -0,0 +1,293 @@
/* jshint undef: true, unused: true, browser:true, devel: true */
/* global define */
define(
[
"./barcode_reader"
],
function(BarcodeReader) {
"use strict";
function I2of5Reader(opts) {
BarcodeReader.call(this, opts);
}
var N = 1,
W = 3,
properties = {
MODULO : {value: 10},
START_PATTERN : {value: [N*2.5, N*2.5, N*2.5, N*2.5]},
STOP_PATTERN : {value: [N*2, N*2, W*2]},
CODE_PATTERN : {value: [
[N, N, W, W, N],
[W, N, N, N, W],
[N, W, N, N, W],
[W, W, N, N, N],
[N, N, W, N, W],
[W, N, W, N, N],
[N, W, W, N, N],
[N, N, N, W, W],
[W, N, N, W, N],
[N, W, N, W, N]
]},
SINGLE_CODE_ERROR: {value: 1},
AVG_CODE_ERROR: {value: 0.38},
FORMAT: {value: "i2of5", writeable: false}
};
I2of5Reader.prototype = Object.create(BarcodeReader.prototype, properties);
I2of5Reader.prototype.constructor = I2of5Reader;
I2of5Reader.prototype._findPattern = function(pattern, offset) {
var counter = [],
self = this,
i,
counterPos = 0,
bestMatch = {
error : Number.MAX_VALUE,
code : -1,
start : 0,
end : 0
},
error,
j,
sum,
normalized,
isWhite = false,
epsilon = self.AVG_CODE_ERROR;
if (!offset) {
offset = self._nextSet(self._row);
}
for ( i = 0; i < pattern.length; i++) {
counter[i] = 0;
}
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);
if (normalized) {
error = self._matchPattern(normalized, pattern);
if (error < epsilon) {
bestMatch.error = error;
bestMatch.start = i - sum;
bestMatch.end = i;
return bestMatch;
}
}
for ( j = 0; j < counter.length - 2; j++) {
counter[j] = counter[j + 2];
}
counter[counter.length - 2] = 0;
counter[counter.length - 1] = 0;
counterPos--;
} else {
counterPos++;
}
counter[counterPos] = 1;
isWhite = !isWhite;
}
}
return null;
};
I2of5Reader.prototype._findStart = function() {
var self = this,
leadingWhitespaceStart,
offset = self._nextSet(self._row),
startInfo;
while(!startInfo) {
startInfo = self._findPattern(self.START_PATTERN, offset);
if (!startInfo) {
return null;
}
leadingWhitespaceStart = startInfo.start - (startInfo.end - startInfo.start);
if (leadingWhitespaceStart >= 0) {
if (self._matchRange(leadingWhitespaceStart, startInfo.start, 0)) {
startInfo.narrowBarWidth = Math.floor((startInfo.end - startInfo.start) / 4);
return startInfo;
}
}
offset = startInfo.end;
startInfo = null;
}
};
I2of5Reader.prototype._verifyTrailingWhitespace = function(endInfo) {
var self = this,
trailingWhitespaceEnd;
trailingWhitespaceEnd = endInfo.end + (endInfo.end - endInfo.start);
if (trailingWhitespaceEnd < self._row.length) {
if (self._matchRange(endInfo.end, trailingWhitespaceEnd, 0)) {
return endInfo;
}
}
return null;
};
I2of5Reader.prototype._findEnd = function() {
var self = this,
endInfo,
tmp;
self._row.reverse();
endInfo = self._findPattern(self.STOP_PATTERN);
self._row.reverse();
if (endInfo === null) {
return null;
}
// reverse numbers
tmp = endInfo.start;
endInfo.start = self._row.length - endInfo.end;
endInfo.end = self._row.length - tmp;
return endInfo !== null ? self._verifyTrailingWhitespace(endInfo) : null;
};
I2of5Reader.prototype._decodePair = function(counterPair) {
var i,
code,
codes = [],
self = this;
for (i = 0; i < counterPair.length; i++) {
code = self._decodeCode(counterPair[i]);
if (!code) {
return null;
}
codes.push(code);
}
return codes;
};
I2of5Reader.prototype._decodeCode = function(counter) {
var j,
self = this,
sum = 0,
normalized,
error,
epsilon = self.AVG_CODE_ERROR,
code,
bestMatch = {
error : Number.MAX_VALUE,
code : -1,
start : 0,
end : 0
};
for ( j = 0; j < counter.length; j++) {
sum += counter[j];
}
normalized = self._normalize(counter);
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;
}
}
if (bestMatch.error < epsilon) {
return bestMatch;
}
}
return null;
};
I2of5Reader.prototype._decodePayload = function(counters, result, decodedCodes) {
var i,
self = this,
pos = 0,
counterLength = counters.length,
counterPair = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0]],
codes;
while (pos < counterLength) {
for (i = 0; i < 5; i++) {
counterPair[0][i] = counters[pos];
counterPair[1][i] = counters[pos + 1];
pos += 2;
}
codes = self._decodePair(counterPair);
if (!codes) {
return null;
}
for (i = 0; i < codes.length; i++) {
result.push(codes[i].code + "");
decodedCodes.push(codes[i]);
}
}
return codes;
};
I2of5Reader.prototype._verifyCounterLength = function(counters) {
return (counters.length % 10 === 0);
};
I2of5Reader.prototype._decode = function() {
var startInfo,
endInfo,
self = this,
code,
result = [],
decodedCodes = [],
counters;
startInfo = self._findStart();
if (!startInfo) {
return null;
}
endInfo = self._findEnd();
if (!endInfo) {
return null;
}
console.log(startInfo);
console.log(endInfo);
code = {
code : startInfo.code,
start : startInfo.start,
end : startInfo.end
};
decodedCodes.push(code);
counters = self._fillCounters(startInfo.end, endInfo.start, false);
if (!self._verifyCounterLength(counters)) {
return null;
}
code = self._decodePayload(counters, result, decodedCodes);
if (!code) {
return null;
}
// Checksum
if (!self._checksum(result)) {
return null;
}
return {
code : result.join(""),
start : startInfo.start,
end : code.end,
startInfo : startInfo,
decodedCodes : decodedCodes
};
};
return (I2of5Reader);
}
);

@ -3,8 +3,6 @@
define([ define([
"code_128_reader",
"ean_reader",
"input_stream", "input_stream",
"image_wrapper", "image_wrapper",
"barcode_locator", "barcode_locator",
@ -16,9 +14,7 @@ define([
"camera_access", "camera_access",
"image_debug", "image_debug",
"result_collector"], "result_collector"],
function(Code128Reader, function(InputStream,
EANReader,
InputStream,
ImageWrapper, ImageWrapper,
BarcodeLocator, BarcodeLocator,
BarcodeDecoder, BarcodeDecoder,
@ -489,10 +485,6 @@ function(Code128Reader,
start(); start();
}); });
}, },
Reader: {
EANReader : EANReader,
Code128Reader : Code128Reader
},
ImageWrapper: ImageWrapper, ImageWrapper: ImageWrapper,
ImageDebug: ImageDebug, ImageDebug: ImageDebug,
ResultCollector: ResultCollector ResultCollector: ResultCollector

@ -47,7 +47,8 @@ require.config({
'upc_e_reader': 'src/upc_e_reader', 'upc_e_reader': 'src/upc_e_reader',
'upc_reader': 'src/upc_reader', 'upc_reader': 'src/upc_reader',
'async': 'node_modules/async/lib/async', 'async': 'node_modules/async/lib/async',
'result_collector': 'src/result_collector' 'result_collector': 'src/result_collector',
'i2of5_reader': 'src/i2of5_reader'
}, },
deps: allTestFiles, deps: allTestFiles,
callback: window.__karma__.start callback: window.__karma__.start

Loading…
Cancel
Save