Improving robustness of Code 128 decoder; Relates to #104

feature/104
Christoph Oberhofer 9 years ago
parent 9c212838cc
commit 7a9f146278

@ -47,41 +47,42 @@ BarcodeReader.prototype._nextSet = function(line, offset) {
return line.length; return line.length;
}; };
BarcodeReader.prototype._normalize = function(counter, modulo) { BarcodeReader.prototype._normalize = function(counter, correction) {
var i, var i,
self = this, self = this,
sum = 0, sum = 0,
ratio, ratio,
numOnes = 0, numOnes = 0,
normalized = [], normalized = new Array(counter.length),
norm = 0; norm = 0,
if (!modulo) {
modulo = self.MODULO; modulo = self.MODULO;
if (correction) {
correct(counter, correction.bar, [0, 2, 4]);
correct(counter, correction.space, [1, 3, 5]);
} }
for (i = 0; i < counter.length; i++) { for (i = 0; i < counter.length; i++) {
if (counter[i] === 1) {
numOnes++;
} else {
sum += counter[i]; sum += counter[i];
} }
}
ratio = sum / (modulo - numOnes); ratio = sum / (modulo - numOnes);
if (ratio > 1.0) {
for (i = 0; i < counter.length; i++) { for (i = 0; i < counter.length; i++) {
norm = counter[i] === 1 ? counter[i] : counter[i] / ratio; norm = counter[i] === 1 ? counter[i] : counter[i] / ratio;
normalized.push(norm); normalized[i] = norm;
}
} else {
ratio = (sum + numOnes) / modulo;
for (i = 0; i < counter.length; i++) {
norm = counter[i] / ratio;
normalized.push(norm);
}
} }
return normalized; return normalized;
}; };
function correct(counter, correction, indices) {
var length = indices.length,
tmp = 0;
while(length--) {
tmp = counter[indices[length]] * (1 - ((1 - correction) / 2));
if (tmp > 1) {
counter[indices[length]] = tmp;
}
}
}
BarcodeReader.prototype._matchTrace = function(cmpCounter, epsilon) { BarcodeReader.prototype._matchTrace = function(cmpCounter, epsilon) {
var counter = [], var counter = [],
i, i,

@ -123,15 +123,15 @@ var properties = {
[2, 1, 1, 2, 3, 2], [2, 1, 1, 2, 3, 2],
[2, 3, 3, 1, 1, 1, 2] [2, 3, 3, 1, 1, 1, 2]
]}, ]},
SINGLE_CODE_ERROR: {value: 1}, SINGLE_CODE_ERROR: {value: 0.64},
AVG_CODE_ERROR: {value: 0.5}, AVG_CODE_ERROR: {value: 0.30},
FORMAT: {value: "code_128", writeable: false} FORMAT: {value: "code_128", writeable: false}
}; };
Code128Reader.prototype = Object.create(BarcodeReader.prototype, properties); Code128Reader.prototype = Object.create(BarcodeReader.prototype, properties);
Code128Reader.prototype.constructor = Code128Reader; Code128Reader.prototype.constructor = Code128Reader;
Code128Reader.prototype._decodeCode = function(start) { Code128Reader.prototype._decodeCode = function(start, correction) {
var counter = [0, 0, 0, 0, 0, 0], var counter = [0, 0, 0, 0, 0, 0],
i, i,
self = this, self = this,
@ -142,7 +142,11 @@ Code128Reader.prototype._decodeCode = function(start) {
error: Number.MAX_VALUE, error: Number.MAX_VALUE,
code: -1, code: -1,
start: start, start: start,
end: start end: start,
correction: {
bar: 1,
space: 1
}
}, },
code, code,
error, error,
@ -153,7 +157,7 @@ Code128Reader.prototype._decodeCode = function(start) {
counter[counterPos]++; counter[counterPos]++;
} else { } else {
if (counterPos === counter.length - 1) { if (counterPos === counter.length - 1) {
normalized = self._normalize(counter); normalized = self._normalize(counter, correction);
if (normalized) { if (normalized) {
for (code = 0; code < self.CODE_PATTERN.length; code++) { for (code = 0; code < self.CODE_PATTERN.length; code++) {
error = self._matchPattern(normalized, self.CODE_PATTERN[code]); error = self._matchPattern(normalized, self.CODE_PATTERN[code]);
@ -163,6 +167,15 @@ Code128Reader.prototype._decodeCode = function(start) {
} }
} }
bestMatch.end = i; bestMatch.end = i;
if (bestMatch.code === -1) {
return null;
}
if (self.CODE_PATTERN[bestMatch.code]) {
bestMatch.correction.bar = calculateCorrection(
self.CODE_PATTERN[bestMatch.code], normalized, [0, 2, 4]);
bestMatch.correction.space = calculateCorrection(
self.CODE_PATTERN[bestMatch.code], normalized, [1, 3, 5]);
}
return bestMatch; return bestMatch;
} }
} else { } else {
@ -175,6 +188,18 @@ Code128Reader.prototype._decodeCode = function(start) {
return null; return null;
}; };
function calculateCorrection(expected, normalized, indices) {
var length = indices.length,
sumNormalized = 0,
sumExpected = 0;
while(length--) {
sumExpected += expected[indices[length]];
sumNormalized += normalized[indices[length]];
}
return sumExpected/sumNormalized;
}
Code128Reader.prototype._findStart = function() { Code128Reader.prototype._findStart = function() {
var counter = [0, 0, 0, 0, 0, 0], var counter = [0, 0, 0, 0, 0, 0],
i, i,
@ -186,7 +211,11 @@ Code128Reader.prototype._findStart = function() {
error: Number.MAX_VALUE, error: Number.MAX_VALUE,
code: -1, code: -1,
start: 0, start: 0,
end: 0 end: 0,
correction: {
bar: 1,
space: 1
}
}, },
code, code,
error, error,
@ -215,6 +244,10 @@ Code128Reader.prototype._findStart = function() {
if (bestMatch.error < self.AVG_CODE_ERROR) { if (bestMatch.error < self.AVG_CODE_ERROR) {
bestMatch.start = i - sum; bestMatch.start = i - sum;
bestMatch.end = i; bestMatch.end = i;
bestMatch.correction.bar = calculateCorrection(
self.CODE_PATTERN[code], normalized, [0, 2, 4]);
bestMatch.correction.space = calculateCorrection(
self.CODE_PATTERN[code], normalized, [1, 3, 5]);
return bestMatch; return bestMatch;
} }
} }
@ -256,7 +289,11 @@ Code128Reader.prototype._decode = function() {
code = { code = {
code: startInfo.code, code: startInfo.code,
start: startInfo.start, start: startInfo.start,
end: startInfo.end end: startInfo.end,
correction: {
bar: startInfo.correction.bar,
space: startInfo.correction.space
}
}; };
decodedCodes.push(code); decodedCodes.push(code);
checksum = code.code; checksum = code.code;
@ -277,7 +314,7 @@ Code128Reader.prototype._decode = function() {
while (!done) { while (!done) {
unshift = shiftNext; unshift = shiftNext;
shiftNext = false; shiftNext = false;
code = self._decodeCode(code.end); code = self._decodeCode(code.end, code.correction);
if (code !== null) { if (code !== null) {
if (code.code !== self.STOP_CODE) { if (code.code !== self.STOP_CODE) {
removeLastCharacter = true; removeLastCharacter = true;

Loading…
Cancel
Save