Improving EAN-Reader, Barcode-Line extension, ToBinaryLine
@@ -1240,6 +1240,39 @@ define(
|
|||||||
throw BarcodeReader.PatternNotFoundException;
|
throw BarcodeReader.PatternNotFoundException;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EANReader.prototype._findStart = function() {
|
||||||
|
var self = this,
|
||||||
|
leadingWhitespaceStart,
|
||||||
|
offset = self._nextSet(self._row),
|
||||||
|
startInfo;
|
||||||
|
|
||||||
|
while(!startInfo) {
|
||||||
|
startInfo = self._findPattern(self.START_PATTERN, offset);
|
||||||
|
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._findEnd = function(offset) {
|
||||||
|
var self = this,
|
||||||
|
trailingWhitespaceEnd,
|
||||||
|
endInfo = self._findPattern(self.STOP_PATTERN, offset);
|
||||||
|
|
||||||
|
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._decode = function() {
|
EANReader.prototype._decode = function() {
|
||||||
var startInfo,
|
var startInfo,
|
||||||
self = this,
|
self = this,
|
||||||
@@ -1250,7 +1283,7 @@ define(
|
|||||||
decodedCodes = [];
|
decodedCodes = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
startInfo = self._findPattern(self.START_PATTERN);
|
startInfo = self._findStart();
|
||||||
code = {
|
code = {
|
||||||
code : startInfo.code,
|
code : startInfo.code,
|
||||||
start : startInfo.start,
|
start : startInfo.start,
|
||||||
@@ -1288,7 +1321,11 @@ define(
|
|||||||
result.push(code.code);
|
result.push(code.code);
|
||||||
}
|
}
|
||||||
|
|
||||||
code = self._findPattern(self.STOP_PATTERN, code.end);
|
code = self._findEnd(code.end);
|
||||||
|
if (code === null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
decodedCodes.push(code);
|
decodedCodes.push(code);
|
||||||
|
|
||||||
// Checksum
|
// Checksum
|
||||||
@@ -6384,23 +6421,23 @@ define('bresenham',[],function() {
|
|||||||
extrema = [],
|
extrema = [],
|
||||||
currentDir,
|
currentDir,
|
||||||
dir,
|
dir,
|
||||||
threshold = (max - min) / 8,
|
threshold = (max - min) / 12,
|
||||||
rThreshold = -threshold,
|
rThreshold = -threshold,
|
||||||
i,
|
i,
|
||||||
j;
|
j;
|
||||||
|
|
||||||
// 1. find extrema
|
// 1. find extrema
|
||||||
currentDir = line[0] > center ? Slope.DIR.DOWN : Slope.DIR.UP;
|
currentDir = line[0] > center ? Slope.DIR.UP : Slope.DIR.DOWN;
|
||||||
extrema.push({
|
extrema.push({
|
||||||
pos : 0,
|
pos : 0,
|
||||||
val : line[0]
|
val : line[0]
|
||||||
});
|
});
|
||||||
for ( i = 0; i < line.length - 1; i++) {
|
for ( i = 0; i < line.length - 1; i++) {
|
||||||
slope = (line[i + 1] - line[i]);
|
slope = (line[i + 1] - line[i]);
|
||||||
if (slope < rThreshold) {
|
if (slope < rThreshold && line[i + 1] < (center*1.5)) {
|
||||||
dir = Slope.DIR.UP;
|
|
||||||
} else if (slope > threshold) {
|
|
||||||
dir = Slope.DIR.DOWN;
|
dir = Slope.DIR.DOWN;
|
||||||
|
} else if (slope > threshold && line[i + 1] > (center*0.5)) {
|
||||||
|
dir = Slope.DIR.UP;
|
||||||
} else {
|
} else {
|
||||||
dir = currentDir;
|
dir = currentDir;
|
||||||
}
|
}
|
||||||
@@ -7090,18 +7127,25 @@ define('barcode_decoder',["bresenham", "image_debug", 'code_128_reader', 'ean_re
|
|||||||
* @param {Number} angle
|
* @param {Number} angle
|
||||||
*/
|
*/
|
||||||
function getExtendedLine(line, angle, ext) {
|
function getExtendedLine(line, angle, ext) {
|
||||||
var extension = {
|
function extendLine(amount) {
|
||||||
y : ext * Math.sin(angle),
|
var extension = {
|
||||||
x : ext * Math.cos(angle)
|
y : amount * Math.sin(angle),
|
||||||
|
x : amount * Math.cos(angle)
|
||||||
};
|
};
|
||||||
|
|
||||||
line[0].y -= extension.y;
|
line[0].y -= extension.y;
|
||||||
line[0].x -= extension.x;
|
line[0].x -= extension.x;
|
||||||
line[1].y += extension.y;
|
line[1].y += extension.y;
|
||||||
line[1].x += extension.x;
|
line[1].x += extension.x;
|
||||||
|
}
|
||||||
|
|
||||||
// check if inside image
|
// check if inside image
|
||||||
if (!inputImageWrapper.inImageWithBorder(line[0], 0) || !inputImageWrapper.inImageWithBorder(line[1], 0)) {
|
extendLine(ext);
|
||||||
|
while (ext > 1 && !inputImageWrapper.inImageWithBorder(line[0], 0) || !inputImageWrapper.inImageWithBorder(line[1], 0)) {
|
||||||
|
ext -= Math.floor(ext/2);
|
||||||
|
extendLine(-ext);
|
||||||
|
}
|
||||||
|
if (ext <= 1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return line;
|
return line;
|
||||||
@@ -7181,6 +7225,12 @@ define('barcode_decoder',["bresenham", "image_debug", 'code_128_reader', 'ean_re
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getLineLength(line) {
|
||||||
|
return Math.sqrt(
|
||||||
|
Math.pow(Math.abs(line[1].y - line[0].y), 2) +
|
||||||
|
Math.pow(Math.abs(line[1].x - line[0].x), 2));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* With the help of the configured readers (Code128 or EAN) this function tries to detect a
|
* With the help of the configured readers (Code128 or EAN) this function tries to detect a
|
||||||
* valid barcode pattern within the given area.
|
* valid barcode pattern within the given area.
|
||||||
@@ -7191,15 +7241,17 @@ define('barcode_decoder',["bresenham", "image_debug", 'code_128_reader', 'ean_re
|
|||||||
var line,
|
var line,
|
||||||
lineAngle,
|
lineAngle,
|
||||||
ctx = _canvas.ctx.overlay,
|
ctx = _canvas.ctx.overlay,
|
||||||
result;
|
result,
|
||||||
|
lineLength;
|
||||||
|
|
||||||
if (config.drawBoundingBox && ctx) {
|
if (config.drawBoundingBox && ctx) {
|
||||||
ImageDebug.drawPath(box, {x: 0, y: 1}, ctx, {color: "blue", lineWidth: 2});
|
ImageDebug.drawPath(box, {x: 0, y: 1}, ctx, {color: "blue", lineWidth: 2});
|
||||||
}
|
}
|
||||||
|
|
||||||
line = getLine(box);
|
line = getLine(box);
|
||||||
|
lineLength = getLineLength(line);
|
||||||
lineAngle = Math.atan2(line[1].y - line[0].y, line[1].x - line[0].x);
|
lineAngle = Math.atan2(line[1].y - line[0].y, line[1].x - line[0].x);
|
||||||
line = getExtendedLine(line, lineAngle, 10);
|
line = getExtendedLine(line, lineAngle, Math.floor(lineLength*0.07));
|
||||||
if(line === null){
|
if(line === null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -7402,7 +7454,7 @@ define('config',[],function(){
|
|||||||
debug: false,
|
debug: false,
|
||||||
controls: false,
|
controls: false,
|
||||||
locate: true,
|
locate: true,
|
||||||
numOfWorkers: 4,
|
numOfWorkers: 0,
|
||||||
visual: {
|
visual: {
|
||||||
show: true
|
show: true
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -42,9 +42,9 @@
|
|||||||
<label>
|
<label>
|
||||||
<span>Barcode-Type</span>
|
<span>Barcode-Type</span>
|
||||||
<select name="decoder_readers">
|
<select name="decoder_readers">
|
||||||
<option value="code_128" selected="selected">Code 128</option>
|
<option value="code_128">Code 128</option>
|
||||||
<option value="code_39">Code 39</option>
|
<option value="code_39">Code 39</option>
|
||||||
<option value="ean">EAN</option>
|
<option value="ean" selected="selected">EAN</option>
|
||||||
<option value="codabar">Codabar</option>
|
<option value="codabar">Codabar</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
@@ -52,8 +52,8 @@
|
|||||||
<span>Resolution (long side)</span>
|
<span>Resolution (long side)</span>
|
||||||
<select name="input-stream_size">
|
<select name="input-stream_size">
|
||||||
<option value="320">320px</option>
|
<option value="320">320px</option>
|
||||||
<option value="640">640px</option>
|
<option selected="selected" value="640">640px</option>
|
||||||
<option selected="selected" value="800">800px</option>
|
<option value="800">800px</option>
|
||||||
<option value="1280">1280px</option>
|
<option value="1280">1280px</option>
|
||||||
<option value="1600">1600px</option>
|
<option value="1600">1600px</option>
|
||||||
<option value="1920">1920px</option>
|
<option value="1920">1920px</option>
|
||||||
@@ -64,8 +64,8 @@
|
|||||||
<select name="locator_patch-size">
|
<select name="locator_patch-size">
|
||||||
<option value="x-small">x-small</option>
|
<option value="x-small">x-small</option>
|
||||||
<option value="small">small</option>
|
<option value="small">small</option>
|
||||||
<option selected="selected" value="medium">medium</option>
|
<option value="medium">medium</option>
|
||||||
<option value="large">large</option>
|
<option selected="selected" value="large">large</option>
|
||||||
<option value="x-large">x-large</option>
|
<option value="x-large">x-large</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
@@ -76,8 +76,8 @@
|
|||||||
<label>
|
<label>
|
||||||
<span>Workers</span>
|
<span>Workers</span>
|
||||||
<select name="numOfWorkers">
|
<select name="numOfWorkers">
|
||||||
<option value="0">0</option>
|
<option selected="selected" value="0">0</option>
|
||||||
<option value="1" selected="selected">1</option>
|
<option value="1">1</option>
|
||||||
<option value="2">2</option>
|
<option value="2">2</option>
|
||||||
<option value="4">4</option>
|
<option value="4">4</option>
|
||||||
<option value="8">8</option>
|
<option value="8">8</option>
|
||||||
|
|||||||
@@ -92,15 +92,17 @@ $(function() {
|
|||||||
},
|
},
|
||||||
state: {
|
state: {
|
||||||
inputStream: {
|
inputStream: {
|
||||||
size: 800
|
size: 640
|
||||||
},
|
},
|
||||||
locator: {
|
locator: {
|
||||||
patchSize: "medium",
|
patchSize: "large",
|
||||||
halfSample: false
|
halfSample: false
|
||||||
},
|
},
|
||||||
numOfWorkers: 1,
|
numOfWorkers: 0,
|
||||||
decoder: {
|
decoder: {
|
||||||
readers: ["code_128_reader"]
|
readers: ["ean_reader"],
|
||||||
|
showFrequency: true,
|
||||||
|
showPattern: true
|
||||||
},
|
},
|
||||||
locate: true,
|
locate: true,
|
||||||
src: null
|
src: null
|
||||||
|
|||||||
@@ -32,13 +32,13 @@
|
|||||||
<button class="next">Next</button>
|
<button class="next">Next</button>
|
||||||
<fieldset class="reader-group">
|
<fieldset class="reader-group">
|
||||||
<label>Codabar</label>
|
<label>Codabar</label>
|
||||||
<input type="radio" name="reader" value="codabar" checked />
|
<input type="radio" name="reader" value="codabar" />
|
||||||
<label>Code39</label>
|
<label>Code39</label>
|
||||||
<input type="radio" name="reader" value="code_39" />
|
<input type="radio" name="reader" value="code_39" />
|
||||||
<label>Code128</label>
|
<label>Code128</label>
|
||||||
<input type="radio" name="reader" value="code_128" />
|
<input type="radio" name="reader" value="code_128" />
|
||||||
<label>EAN</label>
|
<label>EAN</label>
|
||||||
<input type="radio" name="reader" value="ean" />
|
<input type="radio" name="reader" value="ean" checked />
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
<div id="result_strip">
|
<div id="result_strip">
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ $(function() {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
reader: "codabar",
|
reader: "ean",
|
||||||
length: 10
|
length: 10
|
||||||
},
|
},
|
||||||
attachListeners: function() {
|
attachListeners: function() {
|
||||||
|
|||||||
@@ -96,18 +96,25 @@ define(["bresenham", "image_debug", 'code_128_reader', 'ean_reader', 'code_39_re
|
|||||||
* @param {Number} angle
|
* @param {Number} angle
|
||||||
*/
|
*/
|
||||||
function getExtendedLine(line, angle, ext) {
|
function getExtendedLine(line, angle, ext) {
|
||||||
var extension = {
|
function extendLine(amount) {
|
||||||
y : ext * Math.sin(angle),
|
var extension = {
|
||||||
x : ext * Math.cos(angle)
|
y : amount * Math.sin(angle),
|
||||||
|
x : amount * Math.cos(angle)
|
||||||
};
|
};
|
||||||
|
|
||||||
line[0].y -= extension.y;
|
line[0].y -= extension.y;
|
||||||
line[0].x -= extension.x;
|
line[0].x -= extension.x;
|
||||||
line[1].y += extension.y;
|
line[1].y += extension.y;
|
||||||
line[1].x += extension.x;
|
line[1].x += extension.x;
|
||||||
|
}
|
||||||
|
|
||||||
// check if inside image
|
// check if inside image
|
||||||
if (!inputImageWrapper.inImageWithBorder(line[0], 0) || !inputImageWrapper.inImageWithBorder(line[1], 0)) {
|
extendLine(ext);
|
||||||
|
while (ext > 1 && !inputImageWrapper.inImageWithBorder(line[0], 0) || !inputImageWrapper.inImageWithBorder(line[1], 0)) {
|
||||||
|
ext -= Math.floor(ext/2);
|
||||||
|
extendLine(-ext);
|
||||||
|
}
|
||||||
|
if (ext <= 1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return line;
|
return line;
|
||||||
@@ -187,6 +194,12 @@ define(["bresenham", "image_debug", 'code_128_reader', 'ean_reader', 'code_39_re
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getLineLength(line) {
|
||||||
|
return Math.sqrt(
|
||||||
|
Math.pow(Math.abs(line[1].y - line[0].y), 2) +
|
||||||
|
Math.pow(Math.abs(line[1].x - line[0].x), 2));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* With the help of the configured readers (Code128 or EAN) this function tries to detect a
|
* With the help of the configured readers (Code128 or EAN) this function tries to detect a
|
||||||
* valid barcode pattern within the given area.
|
* valid barcode pattern within the given area.
|
||||||
@@ -197,15 +210,17 @@ define(["bresenham", "image_debug", 'code_128_reader', 'ean_reader', 'code_39_re
|
|||||||
var line,
|
var line,
|
||||||
lineAngle,
|
lineAngle,
|
||||||
ctx = _canvas.ctx.overlay,
|
ctx = _canvas.ctx.overlay,
|
||||||
result;
|
result,
|
||||||
|
lineLength;
|
||||||
|
|
||||||
if (config.drawBoundingBox && ctx) {
|
if (config.drawBoundingBox && ctx) {
|
||||||
ImageDebug.drawPath(box, {x: 0, y: 1}, ctx, {color: "blue", lineWidth: 2});
|
ImageDebug.drawPath(box, {x: 0, y: 1}, ctx, {color: "blue", lineWidth: 2});
|
||||||
}
|
}
|
||||||
|
|
||||||
line = getLine(box);
|
line = getLine(box);
|
||||||
|
lineLength = getLineLength(line);
|
||||||
lineAngle = Math.atan2(line[1].y - line[0].y, line[1].x - line[0].x);
|
lineAngle = Math.atan2(line[1].y - line[0].y, line[1].x - line[0].x);
|
||||||
line = getExtendedLine(line, lineAngle, 10);
|
line = getExtendedLine(line, lineAngle, Math.floor(lineLength*0.07));
|
||||||
if(line === null){
|
if(line === null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,23 +107,23 @@ define(function() {
|
|||||||
extrema = [],
|
extrema = [],
|
||||||
currentDir,
|
currentDir,
|
||||||
dir,
|
dir,
|
||||||
threshold = (max - min) / 8,
|
threshold = (max - min) / 12,
|
||||||
rThreshold = -threshold,
|
rThreshold = -threshold,
|
||||||
i,
|
i,
|
||||||
j;
|
j;
|
||||||
|
|
||||||
// 1. find extrema
|
// 1. find extrema
|
||||||
currentDir = line[0] > center ? Slope.DIR.DOWN : Slope.DIR.UP;
|
currentDir = line[0] > center ? Slope.DIR.UP : Slope.DIR.DOWN;
|
||||||
extrema.push({
|
extrema.push({
|
||||||
pos : 0,
|
pos : 0,
|
||||||
val : line[0]
|
val : line[0]
|
||||||
});
|
});
|
||||||
for ( i = 0; i < line.length - 1; i++) {
|
for ( i = 0; i < line.length - 1; i++) {
|
||||||
slope = (line[i + 1] - line[i]);
|
slope = (line[i + 1] - line[i]);
|
||||||
if (slope < rThreshold) {
|
if (slope < rThreshold && line[i + 1] < (center*1.5)) {
|
||||||
dir = Slope.DIR.UP;
|
|
||||||
} else if (slope > threshold) {
|
|
||||||
dir = Slope.DIR.DOWN;
|
dir = Slope.DIR.DOWN;
|
||||||
|
} else if (slope > threshold && line[i + 1] > (center*0.5)) {
|
||||||
|
dir = Slope.DIR.UP;
|
||||||
} else {
|
} else {
|
||||||
dir = currentDir;
|
dir = currentDir;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -167,6 +167,39 @@ define(
|
|||||||
throw BarcodeReader.PatternNotFoundException;
|
throw BarcodeReader.PatternNotFoundException;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EANReader.prototype._findStart = function() {
|
||||||
|
var self = this,
|
||||||
|
leadingWhitespaceStart,
|
||||||
|
offset = self._nextSet(self._row),
|
||||||
|
startInfo;
|
||||||
|
|
||||||
|
while(!startInfo) {
|
||||||
|
startInfo = self._findPattern(self.START_PATTERN, offset);
|
||||||
|
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._findEnd = function(offset) {
|
||||||
|
var self = this,
|
||||||
|
trailingWhitespaceEnd,
|
||||||
|
endInfo = self._findPattern(self.STOP_PATTERN, offset);
|
||||||
|
|
||||||
|
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._decode = function() {
|
EANReader.prototype._decode = function() {
|
||||||
var startInfo,
|
var startInfo,
|
||||||
self = this,
|
self = this,
|
||||||
@@ -177,7 +210,7 @@ define(
|
|||||||
decodedCodes = [];
|
decodedCodes = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
startInfo = self._findPattern(self.START_PATTERN);
|
startInfo = self._findStart();
|
||||||
code = {
|
code = {
|
||||||
code : startInfo.code,
|
code : startInfo.code,
|
||||||
start : startInfo.start,
|
start : startInfo.start,
|
||||||
@@ -215,7 +248,11 @@ define(
|
|||||||
result.push(code.code);
|
result.push(code.code);
|
||||||
}
|
}
|
||||||
|
|
||||||
code = self._findPattern(self.STOP_PATTERN, code.end);
|
code = self._findEnd(code.end);
|
||||||
|
if (code === null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
decodedCodes.push(code);
|
decodedCodes.push(code);
|
||||||
|
|
||||||
// Checksum
|
// Checksum
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 570 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 710 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 674 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 797 KiB After Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 736 KiB After Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 774 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 748 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 741 KiB After Width: | Height: | Size: 136 KiB |
|
Before Width: | Height: | Size: 570 KiB After Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 562 KiB After Width: | Height: | Size: 115 KiB |