Moved files into meaningful folders

This commit is contained in:
Christoph Oberhofer
2016-02-24 21:37:46 +01:00
parent 6343a235f8
commit b7ffeec6db
34 changed files with 841 additions and 632 deletions
+222
View File
@@ -0,0 +1,222 @@
function BarcodeReader(config) {
this._row = [];
this.config = config || {};
return this;
}
BarcodeReader.prototype._nextUnset = function(line, start) {
var i;
if (start === undefined) {
start = 0;
}
for (i = start; i < line.length; i++) {
if (!line[i]) {
return i;
}
}
return line.length;
};
BarcodeReader.prototype._matchPattern = function(counter, code) {
var i,
error = 0,
singleError = 0,
modulo = this.MODULO,
maxSingleError = this.SINGLE_CODE_ERROR || 1;
for (i = 0; i < counter.length; i++) {
singleError = Math.abs(code[i] - counter[i]);
if (singleError > maxSingleError) {
return Number.MAX_VALUE;
}
error += singleError;
}
return error / modulo;
};
BarcodeReader.prototype._nextSet = function(line, offset) {
var i;
offset = offset || 0;
for (i = offset; i < line.length; i++) {
if (line[i]) {
return i;
}
}
return line.length;
};
BarcodeReader.prototype._normalize = function(counter, modulo) {
var i,
self = this,
sum = 0,
ratio,
numOnes = 0,
normalized = [],
norm = 0;
if (!modulo) {
modulo = self.MODULO;
}
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);
}
}
return normalized;
};
BarcodeReader.prototype._matchTrace = function(cmpCounter, epsilon) {
var counter = [],
i,
self = this,
offset = self._nextSet(self._row),
isWhite = !self._row[offset],
counterPos = 0,
bestMatch = {
error: Number.MAX_VALUE,
code: -1,
start: 0
},
error;
if (cmpCounter) {
for ( i = 0; i < cmpCounter.length; i++) {
counter.push(0);
}
for ( i = offset; i < self._row.length; i++) {
if (self._row[i] ^ isWhite) {
counter[counterPos]++;
} else {
if (counterPos === counter.length - 1) {
error = self._matchPattern(counter, cmpCounter);
if (error < epsilon) {
bestMatch.start = i - offset;
bestMatch.end = i;
bestMatch.counter = counter;
return bestMatch;
} else {
return null;
}
} else {
counterPos++;
}
counter[counterPos] = 1;
isWhite = !isWhite;
}
}
} else {
counter.push(0);
for ( i = offset; i < self._row.length; i++) {
if (self._row[i] ^ isWhite) {
counter[counterPos]++;
} else {
counterPos++;
counter.push(0);
counter[counterPos] = 1;
isWhite = !isWhite;
}
}
}
// if cmpCounter was not given
bestMatch.start = offset;
bestMatch.end = self._row.length - 1;
bestMatch.counter = counter;
return bestMatch;
};
BarcodeReader.prototype.decodePattern = function(pattern) {
var self = this,
result;
self._row = pattern;
result = self._decode();
if (result === null) {
self._row.reverse();
result = self._decode();
if (result) {
result.direction = BarcodeReader.DIRECTION.REVERSE;
result.start = self._row.length - result.start;
result.end = self._row.length - result.end;
}
} else {
result.direction = BarcodeReader.DIRECTION.FORWARD;
}
if (result) {
result.format = self.FORMAT;
}
return result;
};
BarcodeReader.prototype._matchRange = function(start, end, value) {
var i;
start = start < 0 ? 0 : start;
for (i = start; i < end; i++) {
if (this._row[i] !== value) {
return false;
}
}
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", {
value: 'unknown',
writeable: false
});
BarcodeReader.DIRECTION = {
FORWARD: 1,
REVERSE: -1
};
BarcodeReader.Exception = {
StartNotFoundException: "Start-Info was not found!",
CodeNotFoundException: "Code could not be found!",
PatternNotFoundException: "Pattern could not be found!"
};
BarcodeReader.CONFIG_KEYS = {};
export default BarcodeReader;
+288
View File
@@ -0,0 +1,288 @@
import BarcodeReader from './barcode_reader';
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},
FORMAT: {value: "codabar", writeable: false}
};
CodabarReader.prototype = Object.create(BarcodeReader.prototype, properties);
CodabarReader.prototype.constructor = CodabarReader;
CodabarReader.prototype._decode = function() {
var self = this,
result = [],
start,
decodedChar,
pattern,
nextStart,
end;
this._counters = 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 newkind = categorization[key];
newkind.wide.min =
Math.floor((newkind.narrow.size / newkind.narrow.counts + newkind.wide.size / newkind.wide.counts) / 2);
newkind.narrow.max = Math.ceil(newkind.wide.min);
newkind.wide.max = Math.ceil((newkind.wide.size * self.MAX_ACCEPTABLE + self.PADDING) / newkind.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._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
};
}
}
};
export default CodabarReader;
+422
View File
@@ -0,0 +1,422 @@
import BarcodeReader from './barcode_reader';
function Code128Reader() {
BarcodeReader.call(this);
}
var properties = {
CODE_SHIFT: {value: 98},
CODE_C: {value: 99},
CODE_B: {value: 100},
CODE_A: {value: 101},
START_CODE_A: {value: 103},
START_CODE_B: {value: 104},
START_CODE_C: {value: 105},
STOP_CODE: {value: 106},
MODULO: {value: 11},
CODE_PATTERN: {value: [
[2, 1, 2, 2, 2, 2],
[2, 2, 2, 1, 2, 2],
[2, 2, 2, 2, 2, 1],
[1, 2, 1, 2, 2, 3],
[1, 2, 1, 3, 2, 2],
[1, 3, 1, 2, 2, 2],
[1, 2, 2, 2, 1, 3],
[1, 2, 2, 3, 1, 2],
[1, 3, 2, 2, 1, 2],
[2, 2, 1, 2, 1, 3],
[2, 2, 1, 3, 1, 2],
[2, 3, 1, 2, 1, 2],
[1, 1, 2, 2, 3, 2],
[1, 2, 2, 1, 3, 2],
[1, 2, 2, 2, 3, 1],
[1, 1, 3, 2, 2, 2],
[1, 2, 3, 1, 2, 2],
[1, 2, 3, 2, 2, 1],
[2, 2, 3, 2, 1, 1],
[2, 2, 1, 1, 3, 2],
[2, 2, 1, 2, 3, 1],
[2, 1, 3, 2, 1, 2],
[2, 2, 3, 1, 1, 2],
[3, 1, 2, 1, 3, 1],
[3, 1, 1, 2, 2, 2],
[3, 2, 1, 1, 2, 2],
[3, 2, 1, 2, 2, 1],
[3, 1, 2, 2, 1, 2],
[3, 2, 2, 1, 1, 2],
[3, 2, 2, 2, 1, 1],
[2, 1, 2, 1, 2, 3],
[2, 1, 2, 3, 2, 1],
[2, 3, 2, 1, 2, 1],
[1, 1, 1, 3, 2, 3],
[1, 3, 1, 1, 2, 3],
[1, 3, 1, 3, 2, 1],
[1, 1, 2, 3, 1, 3],
[1, 3, 2, 1, 1, 3],
[1, 3, 2, 3, 1, 1],
[2, 1, 1, 3, 1, 3],
[2, 3, 1, 1, 1, 3],
[2, 3, 1, 3, 1, 1],
[1, 1, 2, 1, 3, 3],
[1, 1, 2, 3, 3, 1],
[1, 3, 2, 1, 3, 1],
[1, 1, 3, 1, 2, 3],
[1, 1, 3, 3, 2, 1],
[1, 3, 3, 1, 2, 1],
[3, 1, 3, 1, 2, 1],
[2, 1, 1, 3, 3, 1],
[2, 3, 1, 1, 3, 1],
[2, 1, 3, 1, 1, 3],
[2, 1, 3, 3, 1, 1],
[2, 1, 3, 1, 3, 1],
[3, 1, 1, 1, 2, 3],
[3, 1, 1, 3, 2, 1],
[3, 3, 1, 1, 2, 1],
[3, 1, 2, 1, 1, 3],
[3, 1, 2, 3, 1, 1],
[3, 3, 2, 1, 1, 1],
[3, 1, 4, 1, 1, 1],
[2, 2, 1, 4, 1, 1],
[4, 3, 1, 1, 1, 1],
[1, 1, 1, 2, 2, 4],
[1, 1, 1, 4, 2, 2],
[1, 2, 1, 1, 2, 4],
[1, 2, 1, 4, 2, 1],
[1, 4, 1, 1, 2, 2],
[1, 4, 1, 2, 2, 1],
[1, 1, 2, 2, 1, 4],
[1, 1, 2, 4, 1, 2],
[1, 2, 2, 1, 1, 4],
[1, 2, 2, 4, 1, 1],
[1, 4, 2, 1, 1, 2],
[1, 4, 2, 2, 1, 1],
[2, 4, 1, 2, 1, 1],
[2, 2, 1, 1, 1, 4],
[4, 1, 3, 1, 1, 1],
[2, 4, 1, 1, 1, 2],
[1, 3, 4, 1, 1, 1],
[1, 1, 1, 2, 4, 2],
[1, 2, 1, 1, 4, 2],
[1, 2, 1, 2, 4, 1],
[1, 1, 4, 2, 1, 2],
[1, 2, 4, 1, 1, 2],
[1, 2, 4, 2, 1, 1],
[4, 1, 1, 2, 1, 2],
[4, 2, 1, 1, 1, 2],
[4, 2, 1, 2, 1, 1],
[2, 1, 2, 1, 4, 1],
[2, 1, 4, 1, 2, 1],
[4, 1, 2, 1, 2, 1],
[1, 1, 1, 1, 4, 3],
[1, 1, 1, 3, 4, 1],
[1, 3, 1, 1, 4, 1],
[1, 1, 4, 1, 1, 3],
[1, 1, 4, 3, 1, 1],
[4, 1, 1, 1, 1, 3],
[4, 1, 1, 3, 1, 1],
[1, 1, 3, 1, 4, 1],
[1, 1, 4, 1, 3, 1],
[3, 1, 1, 1, 4, 1],
[4, 1, 1, 1, 3, 1],
[2, 1, 1, 4, 1, 2],
[2, 1, 1, 2, 1, 4],
[2, 1, 1, 2, 3, 2],
[2, 3, 3, 1, 1, 1, 2]
]},
SINGLE_CODE_ERROR: {value: 1},
AVG_CODE_ERROR: {value: 0.5},
FORMAT: {value: "code_128", writeable: false}
};
Code128Reader.prototype = Object.create(BarcodeReader.prototype, properties);
Code128Reader.prototype.constructor = Code128Reader;
Code128Reader.prototype._decodeCode = function(start) {
var counter = [0, 0, 0, 0, 0, 0],
i,
self = this,
offset = start,
isWhite = !self._row[offset],
counterPos = 0,
bestMatch = {
error: Number.MAX_VALUE,
code: -1,
start: start,
end: start
},
code,
error,
normalized;
for ( i = offset; i < self._row.length; i++) {
if (self._row[i] ^ isWhite) {
counter[counterPos]++;
} else {
if (counterPos === counter.length - 1) {
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;
}
}
bestMatch.end = i;
return bestMatch;
}
} else {
counterPos++;
}
counter[counterPos] = 1;
isWhite = !isWhite;
}
}
return null;
};
Code128Reader.prototype._findStart = function() {
var counter = [0, 0, 0, 0, 0, 0],
i,
self = this,
offset = self._nextSet(self._row),
isWhite = false,
counterPos = 0,
bestMatch = {
error: Number.MAX_VALUE,
code: -1,
start: 0,
end: 0
},
code,
error,
j,
sum,
normalized;
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) {
for (code = self.START_CODE_A; code <= self.START_CODE_C; code++) {
error = self._matchPattern(normalized, self.CODE_PATTERN[code]);
if (error < bestMatch.error) {
bestMatch.code = code;
bestMatch.error = error;
}
}
if (bestMatch.error < self.AVG_CODE_ERROR) {
bestMatch.start = i - sum;
bestMatch.end = i;
return bestMatch;
}
}
for ( j = 0; j < 4; j++) {
counter[j] = counter[j + 2];
}
counter[4] = 0;
counter[5] = 0;
counterPos--;
} else {
counterPos++;
}
counter[counterPos] = 1;
isWhite = !isWhite;
}
}
return null;
};
Code128Reader.prototype._decode = function() {
var self = this,
startInfo = self._findStart(),
code = null,
done = false,
result = [],
multiplier = 0,
checksum = 0,
codeset,
rawResult = [],
decodedCodes = [],
shiftNext = false,
unshift,
removeLastCharacter = true;
if (startInfo === null) {
return null;
}
code = {
code: startInfo.code,
start: startInfo.start,
end: startInfo.end
};
decodedCodes.push(code);
checksum = code.code;
switch (code.code) {
case self.START_CODE_A:
codeset = self.CODE_A;
break;
case self.START_CODE_B:
codeset = self.CODE_B;
break;
case self.START_CODE_C:
codeset = self.CODE_C;
break;
default:
return null;
}
while (!done) {
unshift = shiftNext;
shiftNext = false;
code = self._decodeCode(code.end);
if (code !== null) {
if (code.code !== self.STOP_CODE) {
removeLastCharacter = true;
}
if (code.code !== self.STOP_CODE) {
rawResult.push(code.code);
multiplier++;
checksum += multiplier * code.code;
}
decodedCodes.push(code);
switch (codeset) {
case self.CODE_A:
if (code.code < 64) {
result.push(String.fromCharCode(32 + code.code));
} else if (code.code < 96) {
result.push(String.fromCharCode(code.code - 64));
} else {
if (code.code !== self.STOP_CODE) {
removeLastCharacter = false;
}
switch (code.code) {
case self.CODE_SHIFT:
shiftNext = true;
codeset = self.CODE_B;
break;
case self.CODE_B:
codeset = self.CODE_B;
break;
case self.CODE_C:
codeset = self.CODE_C;
break;
case self.STOP_CODE:
done = true;
break;
}
}
break;
case self.CODE_B:
if (code.code < 96) {
result.push(String.fromCharCode(32 + code.code));
} else {
if (code.code !== self.STOP_CODE) {
removeLastCharacter = false;
}
switch (code.code) {
case self.CODE_SHIFT:
shiftNext = true;
codeset = self.CODE_A;
break;
case self.CODE_A:
codeset = self.CODE_A;
break;
case self.CODE_C:
codeset = self.CODE_C;
break;
case self.STOP_CODE:
done = true;
break;
}
}
break;
case self.CODE_C:
if (code.code < 100) {
result.push(code.code < 10 ? "0" + code.code : code.code);
} else {
if (code.code !== self.STOP_CODE) {
removeLastCharacter = false;
}
switch (code.code) {
case self.CODE_A:
codeset = self.CODE_A;
break;
case self.CODE_B:
codeset = self.CODE_B;
break;
case self.STOP_CODE:
done = true;
break;
}
}
break;
}
} else {
done = true;
}
if (unshift) {
codeset = codeset === self.CODE_A ? self.CODE_B : self.CODE_A;
}
}
if (code === null) {
return null;
}
code.end = self._nextUnset(self._row, code.end);
if (!self._verifyTrailingWhitespace(code)){
return null;
}
checksum -= multiplier * rawResult[rawResult.length - 1];
if (checksum % 103 !== rawResult[rawResult.length - 1]) {
return null;
}
if (!result.length) {
return null;
}
// remove last code from result (checksum)
if (removeLastCharacter) {
result.splice(result.length - 1, 1);
}
return {
code: result.join(""),
start: startInfo.start,
end: code.end,
codeset: codeset,
startInfo: startInfo,
decodedCodes: decodedCodes,
endInfo: code
};
};
BarcodeReader.prototype._verifyTrailingWhitespace = function(endInfo) {
var self = this,
trailingWhitespaceEnd;
trailingWhitespaceEnd = endInfo.end + ((endInfo.end - endInfo.start) / 2);
if (trailingWhitespaceEnd < self._row.length) {
if (self._matchRange(endInfo.end, trailingWhitespaceEnd, 0)) {
return endInfo;
}
}
return null;
};
export default Code128Reader;
+215
View File
@@ -0,0 +1,215 @@
import BarcodeReader from './barcode_reader';
import ArrayHelper from '../common/array_helper';
function Code39Reader() {
BarcodeReader.call(this);
}
var properties = {
ALPHABETH_STRING: {value: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *$/+%"},
ALPHABET: {value: [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 45, 46, 32, 42, 36, 47, 43, 37]},
CHARACTER_ENCODINGS: {value: [0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, 0x124, 0x064, 0x109, 0x049,
0x148, 0x019, 0x118, 0x058, 0x00D, 0x10C, 0x04C, 0x01C, 0x103, 0x043, 0x142, 0x013, 0x112, 0x052, 0x007, 0x106,
0x046, 0x016, 0x181, 0x0C1, 0x1C0, 0x091, 0x190, 0x0D0, 0x085, 0x184, 0x0C4, 0x094, 0x0A8, 0x0A2, 0x08A, 0x02A
]},
ASTERISK: {value: 0x094},
FORMAT: {value: "code_39", writeable: false}
};
Code39Reader.prototype = Object.create(BarcodeReader.prototype, properties);
Code39Reader.prototype.constructor = Code39Reader;
Code39Reader.prototype._toCounters = function(start, counter) {
var self = this,
numCounters = counter.length,
end = self._row.length,
isWhite = !self._row[start],
i,
counterPos = 0;
ArrayHelper.init(counter, 0);
for ( i = start; i < end; i++) {
if (self._row[i] ^ isWhite) {
counter[counterPos]++;
} else {
counterPos++;
if (counterPos === numCounters) {
break;
} else {
counter[counterPos] = 1;
isWhite = !isWhite;
}
}
}
return counter;
};
Code39Reader.prototype._decode = function() {
var self = this,
counters = [0, 0, 0, 0, 0, 0, 0, 0, 0],
result = [],
start = self._findStart(),
decodedChar,
lastStart,
pattern,
nextStart;
if (!start) {
return null;
}
nextStart = self._nextSet(self._row, start.end);
do {
counters = self._toCounters(nextStart, counters);
pattern = self._toPattern(counters);
if (pattern < 0) {
return null;
}
decodedChar = self._patternToChar(pattern);
if (decodedChar < 0){
return null;
}
result.push(decodedChar);
lastStart = nextStart;
nextStart += ArrayHelper.sum(counters);
nextStart = self._nextSet(self._row, nextStart);
} while (decodedChar !== '*');
result.pop();
if (!result.length) {
return null;
}
if (!self._verifyTrailingWhitespace(lastStart, nextStart, counters)) {
return null;
}
return {
code: result.join(""),
start: start.start,
end: nextStart,
startInfo: start,
decodedCodes: result
};
};
Code39Reader.prototype._verifyTrailingWhitespace = function(lastStart, nextStart, counters) {
var trailingWhitespaceEnd,
patternSize = ArrayHelper.sum(counters);
trailingWhitespaceEnd = nextStart - lastStart - patternSize;
if ((trailingWhitespaceEnd * 3) >= patternSize) {
return true;
}
return false;
};
Code39Reader.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;
};
Code39Reader.prototype._findNextWidth = function(counters, current) {
var i,
minWidth = Number.MAX_VALUE;
for (i = 0; i < counters.length; i++) {
if (counters[i] < minWidth && counters[i] > current) {
minWidth = counters[i];
}
}
return minWidth;
};
Code39Reader.prototype._toPattern = function(counters) {
var numCounters = counters.length,
maxNarrowWidth = 0,
numWideBars = numCounters,
wideBarWidth = 0,
self = this,
pattern,
i;
while (numWideBars > 3) {
maxNarrowWidth = self._findNextWidth(counters, maxNarrowWidth);
numWideBars = 0;
pattern = 0;
for (i = 0; i < numCounters; i++) {
if (counters[i] > maxNarrowWidth) {
pattern |= 1 << (numCounters - 1 - i);
numWideBars++;
wideBarWidth += counters[i];
}
}
if (numWideBars === 3) {
for (i = 0; i < numCounters && numWideBars > 0; i++) {
if (counters[i] > maxNarrowWidth) {
numWideBars--;
if ((counters[i] * 2) >= wideBarWidth) {
return -1;
}
}
}
return pattern;
}
}
return -1;
};
Code39Reader.prototype._findStart = function() {
var self = this,
offset = self._nextSet(self._row),
patternStart = offset,
counter = [0, 0, 0, 0, 0, 0, 0, 0, 0],
counterPos = 0,
isWhite = false,
i,
j,
whiteSpaceMustStart;
for ( i = offset; i < self._row.length; i++) {
if (self._row[i] ^ isWhite) {
counter[counterPos]++;
} else {
if (counterPos === counter.length - 1) {
// find start pattern
if (self._toPattern(counter) === self.ASTERISK) {
whiteSpaceMustStart = Math.floor(Math.max(0, patternStart - ((i - patternStart) / 4)));
if (self._matchRange(whiteSpaceMustStart, patternStart, 0)) {
return {
start: patternStart,
end: i
};
}
}
patternStart += counter[0] + counter[1];
for ( j = 0; j < 7; j++) {
counter[j] = counter[j + 2];
}
counter[7] = 0;
counter[8] = 0;
counterPos--;
} else {
counterPos++;
}
counter[counterPos] = 1;
isWhite = !isWhite;
}
}
return null;
};
export default Code39Reader;
+49
View File
@@ -0,0 +1,49 @@
import Code39Reader from './code_39_reader';
function Code39VINReader() {
Code39Reader.call(this);
}
var patterns = {
IOQ: /[IOQ]/g,
AZ09: /[A-Z0-9]{17}/
};
Code39VINReader.prototype = Object.create(Code39Reader.prototype);
Code39VINReader.prototype.constructor = Code39VINReader;
// Cribbed from:
// https://github.com/zxing/zxing/blob/master/core/src/main/java/com/google/zxing/client/result/VINResultParser.java
Code39VINReader.prototype._decode = function() {
var result = Code39Reader.prototype._decode.apply(this);
if (!result) {
return null;
}
var code = result.code;
if (!code) {
return null;
}
code = code.replace(patterns.IOQ, '');
if (!code.match(patterns.AZ09)) {
console.log('Failed AZ09 pattern code:', code);
return null;
}
if (!this._checkChecksum(code)) {
return null;
}
result.code = code;
return result;
};
Code39VINReader.prototype._checkChecksum = function(code) {
// TODO
return !!code;
};
export default Code39VINReader;
+45
View File
@@ -0,0 +1,45 @@
import EANReader from './ean_reader';
function EAN8Reader() {
EANReader.call(this);
}
var properties = {
FORMAT: {value: "ean_8", writeable: false}
};
EAN8Reader.prototype = Object.create(EANReader.prototype, properties);
EAN8Reader.prototype.constructor = EAN8Reader;
EAN8Reader.prototype._decodePayload = function(code, result, decodedCodes) {
var i,
self = this;
for ( i = 0; i < 4; i++) {
code = self._decodeCode(code.end, self.CODE_G_START);
if (!code) {
return null;
}
result.push(code.code);
decodedCodes.push(code);
}
code = self._findPattern(self.MIDDLE_PATTERN, code.end, true, false);
if (code === null) {
return null;
}
decodedCodes.push(code);
for ( i = 0; i < 4; i++) {
code = self._decodeCode(code.end, self.CODE_G_START);
if (!code) {
return null;
}
decodedCodes.push(code);
result.push(code.code);
}
return code;
};
export default EAN8Reader;
+327
View File
@@ -0,0 +1,327 @@
import BarcodeReader from './barcode_reader';
function EANReader(opts) {
BarcodeReader.call(this, opts);
}
var properties = {
CODE_L_START: {value: 0},
MODULO: {value: 7},
CODE_G_START: {value: 10},
START_PATTERN: {value: [1 / 3 * 7, 1 / 3 * 7, 1 / 3 * 7]},
STOP_PATTERN: {value: [1 / 3 * 7, 1 / 3 * 7, 1 / 3 * 7]},
MIDDLE_PATTERN: {value: [1 / 5 * 7, 1 / 5 * 7, 1 / 5 * 7, 1 / 5 * 7, 1 / 5 * 7]},
CODE_PATTERN: {value: [
[3, 2, 1, 1],
[2, 2, 2, 1],
[2, 1, 2, 2],
[1, 4, 1, 1],
[1, 1, 3, 2],
[1, 2, 3, 1],
[1, 1, 1, 4],
[1, 3, 1, 2],
[1, 2, 1, 3],
[3, 1, 1, 2],
[1, 1, 2, 3],
[1, 2, 2, 2],
[2, 2, 1, 2],
[1, 1, 4, 1],
[2, 3, 1, 1],
[1, 3, 2, 1],
[4, 1, 1, 1],
[2, 1, 3, 1],
[3, 1, 2, 1],
[2, 1, 1, 3]
]},
CODE_FREQUENCY: {value: [0, 11, 13, 14, 19, 25, 28, 21, 22, 26]},
SINGLE_CODE_ERROR: {value: 0.67},
AVG_CODE_ERROR: {value: 0.27},
FORMAT: {value: "ean_13", writeable: false}
};
EANReader.prototype = Object.create(BarcodeReader.prototype, properties);
EANReader.prototype.constructor = EANReader;
EANReader.prototype._decodeCode = function(start, coderange) {
var counter = [0, 0, 0, 0],
i,
self = this,
offset = start,
isWhite = !self._row[offset],
counterPos = 0,
bestMatch = {
error: Number.MAX_VALUE,
code: -1,
start: start,
end: start
},
code,
error,
normalized;
if (!coderange) {
coderange = self.CODE_PATTERN.length;
}
for ( i = offset; i < self._row.length; i++) {
if (self._row[i] ^ isWhite) {
counter[counterPos]++;
} else {
if (counterPos === counter.length - 1) {
normalized = self._normalize(counter);
if (normalized) {
for (code = 0; code < coderange; code++) {
error = self._matchPattern(normalized, self.CODE_PATTERN[code]);
if (error < bestMatch.error) {
bestMatch.code = code;
bestMatch.error = error;
}
}
bestMatch.end = i;
if (bestMatch.error > self.AVG_CODE_ERROR) {
return null;
}
return bestMatch;
}
} else {
counterPos++;
}
counter[counterPos] = 1;
isWhite = !isWhite;
}
}
return null;
};
EANReader.prototype._findPattern = function(pattern, offset, isWhite, tryHarder, epsilon) {
var counter = [],
self = this,
i,
counterPos = 0,
bestMatch = {
error: Number.MAX_VALUE,
code: -1,
start: 0,
end: 0
},
error,
j,
sum,
normalized;
if (!offset) {
offset = self._nextSet(self._row);
}
if (isWhite === undefined) {
isWhite = false;
}
if (tryHarder === undefined) {
tryHarder = true;
}
if ( epsilon === undefined) {
epsilon = self.AVG_CODE_ERROR;
}
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;
}
}
if (tryHarder) {
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 {
return null;
}
} else {
counterPos++;
}
counter[counterPos] = 1;
isWhite = !isWhite;
}
}
return null;
};
EANReader.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)) {
return startInfo;
}
}
offset = startInfo.end;
startInfo = null;
}
};
EANReader.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;
};
EANReader.prototype._findEnd = function(offset, isWhite) {
var self = this,
endInfo = self._findPattern(self.STOP_PATTERN, offset, isWhite, false);
return endInfo !== null ? self._verifyTrailingWhitespace(endInfo) : null;
};
EANReader.prototype._calculateFirstDigit = function(codeFrequency) {
var i,
self = this;
for ( i = 0; i < self.CODE_FREQUENCY.length; i++) {
if (codeFrequency === self.CODE_FREQUENCY[i]) {
return i;
}
}
return null;
};
EANReader.prototype._decodePayload = function(code, result, decodedCodes) {
var i,
self = this,
codeFrequency = 0x0,
firstDigit;
for ( i = 0; i < 6; i++) {
code = self._decodeCode(code.end);
if (!code) {
return null;
}
if (code.code >= self.CODE_G_START) {
code.code = code.code - self.CODE_G_START;
codeFrequency |= 1 << (5 - i);
} else {
codeFrequency |= 0 << (5 - i);
}
result.push(code.code);
decodedCodes.push(code);
}
firstDigit = self._calculateFirstDigit(codeFrequency);
if (firstDigit === null) {
return null;
}
result.unshift(firstDigit);
code = self._findPattern(self.MIDDLE_PATTERN, code.end, true, false);
if (code === null) {
return null;
}
decodedCodes.push(code);
for ( i = 0; i < 6; i++) {
code = self._decodeCode(code.end, self.CODE_G_START);
if (!code) {
return null;
}
decodedCodes.push(code);
result.push(code.code);
}
return code;
};
EANReader.prototype._decode = function() {
var startInfo,
self = this,
code,
result = [],
decodedCodes = [];
startInfo = self._findStart();
if (!startInfo) {
return null;
}
code = {
code: startInfo.code,
start: startInfo.start,
end: startInfo.end
};
decodedCodes.push(code);
code = self._decodePayload(code, result, decodedCodes);
if (!code) {
return null;
}
code = self._findEnd(code.end, false);
if (!code){
return null;
}
decodedCodes.push(code);
// Checksum
if (!self._checksum(result)) {
return null;
}
return {
code: result.join(""),
start: startInfo.start,
end: code.end,
codeset: "",
startInfo: startInfo,
decodedCodes: decodedCodes
};
};
EANReader.prototype._checksum = function(result) {
var sum = 0, i;
for ( i = result.length - 2; i >= 0; i -= 2) {
sum += result[i];
}
sum *= 3;
for ( i = result.length - 1; i >= 0; i -= 2) {
sum += result[i];
}
return sum % 10 === 0;
};
export default (EANReader);
+334
View File
@@ -0,0 +1,334 @@
import BarcodeReader from './barcode_reader';
const merge = require('lodash/object/merge');
function I2of5Reader(opts) {
opts = merge(getDefaulConfig(), opts);
BarcodeReader.call(this, opts);
this.barSpaceRatio = [1, 1];
if (opts.normalizeBarSpaceWidth) {
this.SINGLE_CODE_ERROR = 0.38;
this.AVG_CODE_ERROR = 0.09;
}
}
function getDefaulConfig() {
var config = {};
Object.keys(I2of5Reader.CONFIG_KEYS).forEach(function(key) {
config[key] = I2of5Reader.CONFIG_KEYS[key].default;
});
return config;
}
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: 0.78, writable: true},
AVG_CODE_ERROR: {value: 0.38, writable: true},
MAX_CORRECTION_FACTOR: {value: 5},
FORMAT: {value: "i2of5"}
};
I2of5Reader.prototype = Object.create(BarcodeReader.prototype, properties);
I2of5Reader.prototype.constructor = I2of5Reader;
I2of5Reader.prototype._matchPattern = function(counter, code) {
if (this.config.normalizeBarSpaceWidth) {
var i,
counterSum = [0, 0],
codeSum = [0, 0],
correction = [0, 0],
correctionRatio = this.MAX_CORRECTION_FACTOR,
correctionRatioInverse = 1 / correctionRatio;
for (i = 0; i < counter.length; i++) {
counterSum[i % 2] += counter[i];
codeSum[i % 2] += code[i];
}
correction[0] = codeSum[0] / counterSum[0];
correction[1] = codeSum[1] / counterSum[1];
correction[0] = Math.max(Math.min(correction[0], correctionRatio), correctionRatioInverse);
correction[1] = Math.max(Math.min(correction[1], correctionRatio), correctionRatioInverse);
this.barSpaceRatio = correction;
for (i = 0; i < counter.length; i++) {
counter[i] *= this.barSpaceRatio[i % 2];
}
}
return BarcodeReader.prototype._matchPattern.call(this, counter, code);
};
I2of5Reader.prototype._findPattern = function(pattern, offset, isWhite, tryHarder) {
var counter = [],
self = this,
i,
counterPos = 0,
bestMatch = {
error: Number.MAX_VALUE,
code: -1,
start: 0,
end: 0
},
error,
j,
sum,
normalized,
epsilon = self.AVG_CODE_ERROR;
isWhite = isWhite || false;
tryHarder = tryHarder || false;
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;
}
}
if (tryHarder) {
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 {
return null;
}
} else {
counterPos++;
}
counter[counterPos] = 1;
isWhite = !isWhite;
}
}
return null;
};
I2of5Reader.prototype._findStart = function() {
var self = this,
leadingWhitespaceStart,
offset = self._nextSet(self._row),
startInfo,
narrowBarWidth = 1;
while (!startInfo) {
startInfo = self._findPattern(self.START_PATTERN, offset, false, true);
if (!startInfo) {
return null;
}
narrowBarWidth = Math.floor((startInfo.end - startInfo.start) / 4);
leadingWhitespaceStart = startInfo.start - narrowBarWidth * 10;
if (leadingWhitespaceStart >= 0) {
if (self._matchRange(leadingWhitespaceStart, startInfo.start, 0)) {
return startInfo;
}
}
offset = startInfo.end;
startInfo = null;
}
};
I2of5Reader.prototype._verifyTrailingWhitespace = function(endInfo) {
var self = this,
trailingWhitespaceEnd;
trailingWhitespaceEnd = endInfo.end + ((endInfo.end - endInfo.start) / 2);
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] * this.barSpaceRatio[0];
counterPair[1][i] = counters[pos + 1] * this.barSpaceRatio[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;
}
decodedCodes.push(startInfo);
endInfo = self._findEnd();
if (!endInfo) {
return null;
}
counters = self._fillCounters(startInfo.end, endInfo.start, false);
if (!self._verifyCounterLength(counters)) {
return null;
}
code = self._decodePayload(counters, result, decodedCodes);
if (!code) {
return null;
}
if (result.length % 2 !== 0 ||
result.length < 6) {
return null;
}
decodedCodes.push(endInfo);
return {
code: result.join(""),
start: startInfo.start,
end: endInfo.end,
startInfo: startInfo,
decodedCodes: decodedCodes
};
};
I2of5Reader.CONFIG_KEYS = {
normalizeBarSpaceWidth: {
'type': 'boolean',
'default': false,
'description': 'If true, the reader tries to normalize the' +
'width-difference between bars and spaces'
}
};
export default I2of5Reader;
+103
View File
@@ -0,0 +1,103 @@
import EANReader from './ean_reader';
function UPCEReader() {
EANReader.call(this);
}
var properties = {
CODE_FREQUENCY: {value: [
[ 56, 52, 50, 49, 44, 38, 35, 42, 41, 37 ],
[7, 11, 13, 14, 19, 25, 28, 21, 22, 26]]},
STOP_PATTERN: { value: [1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7]},
FORMAT: {value: "upc_e", writeable: false}
};
UPCEReader.prototype = Object.create(EANReader.prototype, properties);
UPCEReader.prototype.constructor = UPCEReader;
UPCEReader.prototype._decodePayload = function(code, result, decodedCodes) {
var i,
self = this,
codeFrequency = 0x0;
for ( i = 0; i < 6; i++) {
code = self._decodeCode(code.end);
if (!code) {
return null;
}
if (code.code >= self.CODE_G_START) {
code.code = code.code - self.CODE_G_START;
codeFrequency |= 1 << (5 - i);
}
result.push(code.code);
decodedCodes.push(code);
}
if (!self._determineParity(codeFrequency, result)) {
return null;
}
return code;
};
UPCEReader.prototype._determineParity = function(codeFrequency, result) {
var i,
nrSystem;
for (nrSystem = 0; nrSystem < this.CODE_FREQUENCY.length; nrSystem++){
for ( i = 0; i < this.CODE_FREQUENCY[nrSystem].length; i++) {
if (codeFrequency === this.CODE_FREQUENCY[nrSystem][i]) {
result.unshift(nrSystem);
result.push(i);
return true;
}
}
}
return false;
};
UPCEReader.prototype._convertToUPCA = function(result) {
var upca = [result[0]],
lastDigit = result[result.length - 2];
if (lastDigit <= 2) {
upca = upca.concat(result.slice(1, 3))
.concat([lastDigit, 0, 0, 0, 0])
.concat(result.slice(3, 6));
} else if (lastDigit === 3) {
upca = upca.concat(result.slice(1, 4))
.concat([0, 0, 0, 0, 0])
.concat(result.slice(4, 6));
} else if (lastDigit === 4) {
upca = upca.concat(result.slice(1, 5))
.concat([0, 0, 0, 0, 0, result[5]]);
} else {
upca = upca.concat(result.slice(1, 6))
.concat([0, 0, 0, 0, lastDigit]);
}
upca.push(result[result.length - 1]);
return upca;
};
UPCEReader.prototype._checksum = function(result) {
return EANReader.prototype._checksum.call(this, this._convertToUPCA(result));
};
UPCEReader.prototype._findEnd = function(offset, isWhite) {
isWhite = true;
return EANReader.prototype._findEnd.call(this, offset, isWhite);
};
UPCEReader.prototype._verifyTrailingWhitespace = function(endInfo) {
var self = this,
trailingWhitespaceEnd;
trailingWhitespaceEnd = endInfo.end + ((endInfo.end - endInfo.start) / 2);
if (trailingWhitespaceEnd < self._row.length) {
if (self._matchRange(endInfo.end, trailingWhitespaceEnd, 0)) {
return endInfo;
}
}
};
export default UPCEReader;
+24
View File
@@ -0,0 +1,24 @@
import EANReader from './ean_reader';
function UPCReader() {
EANReader.call(this);
}
var properties = {
FORMAT: {value: "upc_a", writeable: false}
};
UPCReader.prototype = Object.create(EANReader.prototype, properties);
UPCReader.prototype.constructor = UPCReader;
UPCReader.prototype._decode = function() {
var result = EANReader.prototype._decode.call(this);
if (result && result.code && result.code.length === 13 && result.code.charAt(0) === "0") {
result.code = result.code.substring(1);
return result;
}
return null;
};
export default UPCReader;