mirror of
https://github.com/serratus/quaggaJS.git
synced 2026-08-12 21:21:42 +08:00
Improving robustness of Code 128 decoder; Relates to #104
This commit is contained in:
@@ -47,41 +47,42 @@ BarcodeReader.prototype._nextSet = function(line, offset) {
|
||||
return line.length;
|
||||
};
|
||||
|
||||
BarcodeReader.prototype._normalize = function(counter, modulo) {
|
||||
BarcodeReader.prototype._normalize = function(counter, correction) {
|
||||
var i,
|
||||
self = this,
|
||||
sum = 0,
|
||||
ratio,
|
||||
numOnes = 0,
|
||||
normalized = [],
|
||||
norm = 0;
|
||||
|
||||
if (!modulo) {
|
||||
normalized = new Array(counter.length),
|
||||
norm = 0,
|
||||
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++) {
|
||||
if (counter[i] === 1) {
|
||||
numOnes++;
|
||||
} else {
|
||||
sum += counter[i];
|
||||
}
|
||||
}
|
||||
ratio = sum / (modulo - numOnes);
|
||||
if (ratio > 1.0) {
|
||||
for (i = 0; i < counter.length; i++) {
|
||||
norm = counter[i] === 1 ? counter[i] : counter[i] / ratio;
|
||||
normalized.push(norm);
|
||||
}
|
||||
} else {
|
||||
ratio = (sum + numOnes) / modulo;
|
||||
for (i = 0; i < counter.length; i++) {
|
||||
norm = counter[i] / ratio;
|
||||
normalized.push(norm);
|
||||
}
|
||||
normalized[i] = norm;
|
||||
}
|
||||
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) {
|
||||
var counter = [],
|
||||
i,
|
||||
|
||||
@@ -123,15 +123,15 @@ var properties = {
|
||||
[2, 1, 1, 2, 3, 2],
|
||||
[2, 3, 3, 1, 1, 1, 2]
|
||||
]},
|
||||
SINGLE_CODE_ERROR: {value: 1},
|
||||
AVG_CODE_ERROR: {value: 0.5},
|
||||
SINGLE_CODE_ERROR: {value: 0.64},
|
||||
AVG_CODE_ERROR: {value: 0.30},
|
||||
FORMAT: {value: "code_128", writeable: false}
|
||||
};
|
||||
|
||||
Code128Reader.prototype = Object.create(BarcodeReader.prototype, properties);
|
||||
Code128Reader.prototype.constructor = Code128Reader;
|
||||
|
||||
Code128Reader.prototype._decodeCode = function(start) {
|
||||
Code128Reader.prototype._decodeCode = function(start, correction) {
|
||||
var counter = [0, 0, 0, 0, 0, 0],
|
||||
i,
|
||||
self = this,
|
||||
@@ -142,7 +142,11 @@ Code128Reader.prototype._decodeCode = function(start) {
|
||||
error: Number.MAX_VALUE,
|
||||
code: -1,
|
||||
start: start,
|
||||
end: start
|
||||
end: start,
|
||||
correction: {
|
||||
bar: 1,
|
||||
space: 1
|
||||
}
|
||||
},
|
||||
code,
|
||||
error,
|
||||
@@ -153,7 +157,7 @@ Code128Reader.prototype._decodeCode = function(start) {
|
||||
counter[counterPos]++;
|
||||
} else {
|
||||
if (counterPos === counter.length - 1) {
|
||||
normalized = self._normalize(counter);
|
||||
normalized = self._normalize(counter, correction);
|
||||
if (normalized) {
|
||||
for (code = 0; code < self.CODE_PATTERN.length; code++) {
|
||||
error = self._matchPattern(normalized, self.CODE_PATTERN[code]);
|
||||
@@ -163,6 +167,15 @@ Code128Reader.prototype._decodeCode = function(start) {
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
@@ -175,6 +188,18 @@ Code128Reader.prototype._decodeCode = function(start) {
|
||||
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() {
|
||||
var counter = [0, 0, 0, 0, 0, 0],
|
||||
i,
|
||||
@@ -186,7 +211,11 @@ Code128Reader.prototype._findStart = function() {
|
||||
error: Number.MAX_VALUE,
|
||||
code: -1,
|
||||
start: 0,
|
||||
end: 0
|
||||
end: 0,
|
||||
correction: {
|
||||
bar: 1,
|
||||
space: 1
|
||||
}
|
||||
},
|
||||
code,
|
||||
error,
|
||||
@@ -215,6 +244,10 @@ Code128Reader.prototype._findStart = function() {
|
||||
if (bestMatch.error < self.AVG_CODE_ERROR) {
|
||||
bestMatch.start = i - sum;
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -256,7 +289,11 @@ Code128Reader.prototype._decode = function() {
|
||||
code = {
|
||||
code: startInfo.code,
|
||||
start: startInfo.start,
|
||||
end: startInfo.end
|
||||
end: startInfo.end,
|
||||
correction: {
|
||||
bar: startInfo.correction.bar,
|
||||
space: startInfo.correction.space
|
||||
}
|
||||
};
|
||||
decodedCodes.push(code);
|
||||
checksum = code.code;
|
||||
@@ -277,7 +314,7 @@ Code128Reader.prototype._decode = function() {
|
||||
while (!done) {
|
||||
unshift = shiftNext;
|
||||
shiftNext = false;
|
||||
code = self._decodeCode(code.end);
|
||||
code = self._decodeCode(code.end, code.correction);
|
||||
if (code !== null) {
|
||||
if (code.code !== self.STOP_CODE) {
|
||||
removeLastCharacter = true;
|
||||
|
||||
Reference in New Issue
Block a user