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;
|
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) {
|
sum += counter[i];
|
||||||
numOnes++;
|
|
||||||
} else {
|
|
||||||
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[i] = norm;
|
||||||
normalized.push(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;
|
||||||
|
|||||||
Reference in New Issue
Block a user