Updated version to 0.6.0

gh-pages
Christoph Oberhofer 10 years ago
parent 902dc369d7
commit 380c4b6ff8

@ -7,12 +7,15 @@ showInMenu: false
<section id="container" class="container"> <section id="container" class="container">
<h3>Working with file-input</h3> <h3>Working with file-input</h3>
<p>This example let's you select an image from your local filesystem. QuaggaJS then tries to decode the barcode using <p>This example let's you select an image from your local filesystem.
the preferred method (<strong>Code128</strong>, <strong>EAN There is no server interaction needed as the file is
</strong>, <strong>Code 39</strong> or <strong>Codabar</strong>) simply accessed through the
There is no server interaction needed as the file is simply <a href="http://www.w3.org/TR/file-upload/">File API</a>.
accessed through the <a href="http://www.w3.org/TR/file-upload/">File API</a>.</p> <p>This also works great on a wide range of mobile-phones where the
<p>This also works great on a wide range of mobile-phones where the camera access through <code>getUserMedia</code> is still very limited.</p> camera access through <code>getUserMedia</code> is still very
limited. </p>
<p>If the default configuration does not suit your use-case, you can
adjust various parameters of the localization and decoding process.</p>
<div class="controls"> <div class="controls">
<fieldset class="input-group"> <fieldset class="input-group">
<input type="file" accept="image/*;capture=camera"/> <input type="file" accept="image/*;capture=camera"/>
@ -25,6 +28,9 @@ showInMenu: false
<option value="code_128" selected="selected">Code 128</option> <option value="code_128" selected="selected">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">EAN</option>
<option value="ean_8">EAN-8</option>
<option value="upc">UPC</option>
<option value="upc_e">UPC-E</option>
<option value="codabar">Codabar</option> <option value="codabar">Codabar</option>
</select> </select>
</label> </label>

@ -1240,55 +1240,105 @@ 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._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 self._verifyTrailingWhitespace(endInfo);
};
EANReader.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.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);
}
for ( i = 0; i < self.CODE_FREQUENCY.length; i++) {
if (codeFrequency === self.CODE_FREQUENCY[i]) {
result.unshift(i);
break;
}
}
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);
decodedCodes.push(code);
result.push(code.code);
}
return code;
};
EANReader.prototype._decode = function() { EANReader.prototype._decode = function() {
var startInfo, var startInfo,
self = this, self = this,
code = null, code = null,
result = [], result = [],
i,
codeFrequency = 0x0,
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,
end : startInfo.end end : startInfo.end
}; };
decodedCodes.push(code); decodedCodes.push(code);
for ( i = 0; i < 6; i++) { code = self._decodePayload(code, result, decodedCodes);
code = self._decodeCode(code.end); code = self._findEnd(code.end, false);
if (code.code >= self.CODE_G_START) { if (!code){
code.code = code.code - self.CODE_G_START;
codeFrequency |= 1 << (5 - i);
} else {
codeFrequency |= 0 << (5 - i);
}
result.push(code.code);
decodedCodes.push(code);
}
for ( i = 0; i < self.CODE_FREQUENCY.length; i++) {
if (codeFrequency === self.CODE_FREQUENCY[i]) {
result.unshift(i);
break;
}
}
code = self._findPattern(self.MIDDLE_PATTERN, code.end, true);
if (code === null) {
return null; return null;
} }
decodedCodes.push(code);
for ( i = 0; i < 6; i++) {
code = self._decodeCode(code.end, self.CODE_G_START);
decodedCodes.push(code);
result.push(code.code);
}
code = self._findPattern(self.STOP_PATTERN, code.end);
decodedCodes.push(code); decodedCodes.push(code);
// Checksum // Checksum
@ -1459,6 +1509,17 @@ define('input_stream',["image_loader"], function(ImageLoader) {
} }
}; };
that.clearEventHandlers = function() {
_eventNames.forEach(function(eventName) {
var handlers = _eventHandlers[eventName];
if (handlers && handlers.length > 0) {
handlers.forEach(function(handler) {
video.removeEventListener(eventName, handler);
});
}
});
};
that.trigger = function(eventName, args) { that.trigger = function(eventName, args) {
var j, var j,
handlers = _eventHandlers[eventName]; handlers = _eventHandlers[eventName];
@ -6384,23 +6445,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;
} }
@ -6995,14 +7056,221 @@ define(
/* jshint undef: true, unused: true, browser:true, devel: true */ /* jshint undef: true, unused: true, browser:true, devel: true */
/* global define */ /* global define */
define('barcode_decoder',["bresenham", "image_debug", 'code_128_reader', 'ean_reader', 'code_39_reader', 'codabar_reader'], function(Bresenham, ImageDebug, Code128Reader, EANReader, Code39Reader, CodabarReader) { define(
'upc_reader',[
"./ean_reader"
],
function(EANReader) {
function UPCReader() {
EANReader.call(this);
}
UPCReader.prototype = Object.create(EANReader.prototype);
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;
};
return (UPCReader);
}
);
/* jshint undef: true, unused: true, browser:true, devel: true */
/* global define */
define(
'ean_8_reader',[
"./ean_reader"
],
function(EANReader) {
function EAN8Reader() {
EANReader.call(this);
}
EAN8Reader.prototype = Object.create(EANReader.prototype);
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);
result.push(code.code);
decodedCodes.push(code);
}
code = self._findPattern(self.MIDDLE_PATTERN, code.end, true);
if (code === null) {
return null;
}
decodedCodes.push(code);
for ( i = 0; i < 4; i++) {
code = self._decodeCode(code.end, self.CODE_G_START);
decodedCodes.push(code);
result.push(code.code);
}
return code;
};
return (EAN8Reader);
}
);
/* jshint undef: true, unused: true, browser:true, devel: true */
/* global define */
define(
'upc_e_reader',[
"./ean_reader"
],
function(EANReader) {
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]}
};
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.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);
}
self._determineParity(codeFrequency, result);
return code;
};
UPCEReader.prototype._determineParity = function(codeFrequency, result) {
var self =this,
i,
nrSystem;
for (nrSystem = 0; nrSystem < self.CODE_FREQUENCY.length; nrSystem++){
for ( i = 0; i < self.CODE_FREQUENCY[nrSystem].length; i++) {
if (codeFrequency === self.CODE_FREQUENCY[nrSystem][i]) {
result.unshift(nrSystem);
result.push(i);
return;
}
}
}
};
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;
}
}
};
return (UPCEReader);
}
);
/* jshint undef: true, unused: true, browser:true, devel: true */
/* global define */
define('barcode_decoder',[
"bresenham",
"image_debug",
'code_128_reader',
'ean_reader',
'code_39_reader',
'codabar_reader',
'upc_reader',
'ean_8_reader',
'upc_e_reader'
], function(
Bresenham,
ImageDebug,
Code128Reader,
EANReader,
Code39Reader,
CodabarReader,
UPCReader,
EAN8Reader,
UPCEReader) {
var readers = { var readers = {
code_128_reader: Code128Reader, code_128_reader: Code128Reader,
ean_reader: EANReader, ean_reader: EANReader,
ean_8_reader: EAN8Reader,
code_39_reader: Code39Reader, code_39_reader: Code39Reader,
codabar_reader: CodabarReader codabar_reader: CodabarReader,
upc_reader: UPCReader,
upc_e_reader: UPCEReader
}; };
var BarcodeDecoder = { var BarcodeDecoder = {
create : function(config, inputImageWrapper) { create : function(config, inputImageWrapper) {
@ -7090,18 +7358,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 +7456,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 +7472,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.1));
if(line === null){ if(line === null){
return null; return null;
} }
@ -7531,7 +7814,8 @@ define('events',[],function() {
define('camera_access',["html_utils"], function(HtmlUtils) { define('camera_access',["html_utils"], function(HtmlUtils) {
var streamRef; var streamRef,
loadedDataHandler;
/** /**
* Wraps browser-specific getUserMedia * Wraps browser-specific getUserMedia
@ -7547,6 +7831,25 @@ define('camera_access',["html_utils"], function(HtmlUtils) {
}, failure); }, failure);
} }
function loadedData(video, callback) {
var attempts = 10;
function checkVideo() {
if (attempts > 0) {
if (video.videoWidth > 0 && video.videoHeight > 0) {
console.log(video.videoWidth + "px x " + video.videoHeight + "px");
callback();
} else {
window.setTimeout(checkVideo, 500);
}
} else {
callback('Unable to play video stream. Is webcam working?');
}
attempts--;
}
checkVideo();
}
/** /**
* Tries to attach the camera-stream to a given video-element * Tries to attach the camera-stream to a given video-element
* and calls the callback function when the content is ready * and calls the callback function when the content is ready
@ -7557,25 +7860,11 @@ define('camera_access',["html_utils"], function(HtmlUtils) {
function initCamera(constraints, video, callback) { function initCamera(constraints, video, callback) {
getUserMedia(constraints, function(src) { getUserMedia(constraints, function(src) {
video.src = src; video.src = src;
video.addEventListener('loadeddata', function() { if (loadedDataHandler) {
var attempts = 10; video.removeEventListener("loadeddata", loadedDataHandler, false);
}
function checkVideo() { loadedDataHandler = loadedData.bind(null, video, callback);
if (attempts > 0) { video.addEventListener('loadeddata', loadedDataHandler, false);
if (video.videoWidth > 0 && video.videoHeight > 0) {
console.log(video.videoWidth + "px x " + video.videoHeight + "px");
callback();
} else {
window.setTimeout(checkVideo, 500);
}
} else {
callback('Unable to play video stream. Is webcam working?');
}
attempts--;
}
checkVideo();
}, false);
video.play(); video.play();
}, function(e) { }, function(e) {
console.log(e); console.log(e);
@ -8064,8 +8353,14 @@ function(Code128Reader,
}, },
stop : function() { stop : function() {
_stopped = true; _stopped = true;
_workerPool.forEach(function(workerThread) {
workerThread.worker.terminate();
console.log("Worker terminated!");
});
_workerPool.length = 0;
if (_config.inputStream.type === "LiveStream") { if (_config.inputStream.type === "LiveStream") {
CameraAccess.release(); CameraAccess.release();
_inputStream.clearEventHandlers();
} }
}, },
pause: function() { pause: function() {

File diff suppressed because one or more lines are too long

@ -6,28 +6,69 @@ showInMenu: false
<section id="container" class="container"> <section id="container" class="container">
<h3>The user's camera</h3> <h3>The user's camera</h3>
<p>If your platform supports the <strong>getUserMedia</strong> API call, you can try the real-time locating and decoding features. <p>If your platform supports the <strong>getUserMedia</strong> API call, you
Simply allow the page to access your web-cam and point it to a barcode. You can switch between <strong>Code128</strong> can try the real-time locating and decoding features.
and <strong>EAN</strong> to test different scenarios. Simply allow the page to access your web-cam and point it to a barcode.</p>
It works best if your camera has built-in auto-focus. <p>The various options available allow you to adjust the decoding
</p> process to your needs (Type of barcode, resolution, ...)</p>
<div class="controls"> <div class="controls">
<fieldset class="reader-group"> <fieldset class="input-group">
<label>Code128</label> <button class="stop">Stop</button>
<input type="radio" name="reader" value="code_128" checked /> </fieldset>
<label>EAN</label> <fieldset class="reader-config-group">
<input type="radio" name="reader" value="ean" /> <label>
<label>Code39</label> <span>Barcode-Type</span>
<input type="radio" name="reader" value="code_39" /> <select name="decoder_readers">
<label>Codabar</label> <option value="code_128" selected="selected">Code 128</option>
<input type="radio" name="reader" value="codabar" /> <option value="code_39">Code 39</option>
</fieldset> <option value="ean">EAN</option>
<br clear="all" /> <option value="ean_8">EAN-8</option>
</div> <option value="upc">UPC</option>
<div id="result_strip"> <option value="upc_e">UPC-E</option>
<ul class="thumbnails"></ul> <option value="codabar">Codabar</option>
</div> </select>
<div id="interactive" class="viewport"></div> </label>
<label>
<span>Resolution (long side)</span>
<select name="input-stream_constraints">
<option value="320x240">320px</option>
<option selected="selected" value="640x480">640px</option>
<option value="800x600">800px</option>
<option value="1280x720">1280px</option>
<option value="1600x960">1600px</option>
<option value="1920x1080">1920px</option>
</select>
</label>
<label>
<span>Patch-Size</span>
<select name="locator_patch-size">
<option value="x-small">x-small</option>
<option value="small">small</option>
<option selected="selected" value="medium">medium</option>
<option value="large">large</option>
<option value="x-large">x-large</option>
</select>
</label>
<label>
<span>Half-Sample</span>
<input type="checkbox" checked="checked" name="locator_half-sample" />
</label>
<label>
<span>Workers</span>
<select name="numOfWorkers">
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option selected="selected" value="4">4</option>
<option value="8">8</option>
</select>
</label>
</fieldset>
</div>
<div id="result_strip">
<ul class="thumbnails"></ul>
</div>
<div id="interactive" class="viewport"></div>
</section> </section>
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script> <script src="//code.jquery.com/jquery-1.11.0.min.js"></script>

@ -1,27 +1,103 @@
$(function() { $(function() {
var App = { var App = {
init : function() { init : function() {
Quagga.init({ Quagga.init(this.state, function() {
inputStream : {
name : "Live",
type : "LiveStream"
},
decoder : {
readers : ["code_128_reader"]
}
}, function() {
App.attachListeners(); App.attachListeners();
Quagga.start(); Quagga.start();
}); });
}, },
attachListeners : function() { attachListeners: function() {
$(".controls .reader-group").on("change", "input", function(e) { var self = this;
$(".controls").on("click", "button.stop", function(e) {
e.preventDefault();
Quagga.stop();
});
$(".controls .reader-config-group").on("change", "input, select", function(e) {
e.preventDefault(); e.preventDefault();
Quagga.setReaders([e.target.value + "_reader"]); var $target = $(e.target),
value = $target.attr("type") === "checkbox" ? $target.prop("checked") : $target.val(),
name = $target.attr("name"),
state = self._convertNameToState(name);
console.log("Value of "+ state + " changed to " + value);
self.setState(state, value);
});
},
_accessByPath: function(obj, path, val) {
var parts = path.split('.'),
depth = parts.length,
setter = (typeof val !== "undefined") ? true : false;
return parts.reduce(function(o, key, i) {
if (setter && (i + 1) === depth) {
o[key] = val;
}
return key in o ? o[key] : {};
}, obj);
},
_convertNameToState: function(name) {
return name.replace("_", ".").split("-").reduce(function(result, value) {
return result + value.charAt(0).toUpperCase() + value.substring(1);
}); });
}, },
detachListeners : function() { detachListeners: function() {
$(".controls .reader-group").off("change", "input"); $(".controls").off("click", "button.stop");
$(".controls .reader-config-group").off("change", "input, select");
},
setState: function(path, value) {
var self = this;
if (typeof self._accessByPath(self.inputMapper, path) === "function") {
value = self._accessByPath(self.inputMapper, path)(value);
}
self._accessByPath(self.state, path, value);
console.log(JSON.stringify(self.state));
App.detachListeners();
Quagga.stop();
App.init();
},
inputMapper: {
inputStream: {
constraints: function(value){
var values = value.split('x');
return {
width: parseInt(values[0]),
height: parseInt(values[1]),
facing: "environment"
}
}
},
numOfWorkers: function(value) {
return parseInt(value);
},
decoder: {
readers: function(value) {
return [value + "_reader"];
}
}
},
state: {
inputStream: {
type : "LiveStream",
constraints: {
width: 640,
height: 480,
facing: "environment" // or user
}
},
locator: {
patchSize: "medium",
halfSample: true
},
numOfWorkers: 4,
decoder: {
readers : ["code_128_reader"]
},
locate: true
}, },
lastResult : null lastResult : null
}; };

@ -7,25 +7,29 @@ showInMenu: false
<section id="container" class="container"> <section id="container" class="container">
<h3>Working with static images</h3> <h3>Working with static images</h3>
<p>This examples uses static image files as input which are loaded from the server on startup. <p>This examples uses static image files as input which are loaded from
The locating and decoding process takes place inside the browser. the server on startup. The locating and decoding process takes place
Hit the <strong>next</strong> button to try a different image. You can also switch between inside the browser. Hit the <strong>next</strong> button to try a
two different test-sets. Each of those contains 10 images, demonstrating the capabilities of decoding different image. You can also switch between different test-sets,
<strong>Code128</strong> and <strong>EAN</strong> encoded barcodes. depending on the barcode-type.
</p> </p>
<div class="controls"> <div class="controls">
<button class="next">Next</button> <fieldset class="input-group">
<fieldset class="reader-group"> <button class="next">Next</button>
<label>Code128</label> </fieldset>
<input type="radio" name="reader" value="code_128" checked /> <fieldset class="reader-config-group">
<label>EAN</label> <span>Barcode-Type</span>
<input type="radio" name="reader" value="ean" /> <select name="decoder_readers;input-stream_src">
<label>Code39</label> <option value="code_128" selected="selected">Code 128</option>
<input type="radio" name="reader" value="code_39" /> <option value="code_39">Code 39</option>
<label>Codabar</label> <option value="ean">EAN</option>
<input type="radio" name="reader" value="codabar" /> <option value="ean_8">EAN-8</option>
</fieldset> <option value="upc">UPC</option>
</div> <option value="upc_e">UPC-E</option>
<option value="codabar">Codabar</option>
</select>
</fieldset>
</div>
<div id="result_strip"> <div id="result_strip">
<ul class="thumbnails"></ul> <ul class="thumbnails"></ul>
</div> </div>

@ -1,16 +1,7 @@
$(function() { $(function() {
var App = { var App = {
init: function() { init: function() {
Quagga.init({ Quagga.init(this.state, function() {
inputStream: { name: "Test",
type: "ImageStream",
src: site.baseurl + "/test/fixtures/" + App.config.reader + "/",
length: App.config.length
},
decoder : {
readers : [App.config.reader + "_reader"]
}
}, function() {
App.attachListeners(); App.attachListeners();
Quagga.start(); Quagga.start();
}); });
@ -20,22 +11,85 @@ $(function() {
length: 10 length: 10
}, },
attachListeners: function() { attachListeners: function() {
var self = this;
$(".controls").on("click", "button.next", function(e) { $(".controls").on("click", "button.next", function(e) {
e.preventDefault(); e.preventDefault();
Quagga.start(); Quagga.start();
}); });
$(".controls .reader-group").on("change", "input", function(e) { $(".controls .reader-config-group").on("change", "input, select", function(e) {
e.preventDefault(); e.preventDefault();
App.detachListeners(); var $target = $(e.target),
Quagga.stop(); value = $target.attr("type") === "checkbox" ? $target.prop("checked") : $target.val(),
App.config.reader = e.target.value; name = $target.attr("name"),
App.init(); states = self._convertNameToStates(name);
console.log("Value of "+ states + " changed to " + value);
self.setState(states, value);
}); });
}, },
detachListeners: function() { detachListeners: function() {
$(".controls").off("click", "button.next"); $(".controls").off("click", "button.next");
$(".controls .reader-group").off("change", "input"); $(".controls .reader-config-group").off("change", "input, select");
},
_accessByPath: function(obj, path, val) {
var parts = path.split('.'),
depth = parts.length,
setter = (typeof val !== "undefined") ? true : false;
return parts.reduce(function(o, key, i) {
if (setter && (i + 1) === depth) {
o[key] = val;
}
return key in o ? o[key] : {};
}, obj);
},
_convertNameToStates: function(names) {
return names.split(";").map(this._convertNameToState.bind(this));
},
_convertNameToState: function(name) {
return name.replace("_", ".").split("-").reduce(function(result, value) {
return result + value.charAt(0).toUpperCase() + value.substring(1);
});
},
setState: function(paths, value) {
var self = this;
paths.forEach(function(path) {
var mappedValue;
if (typeof self._accessByPath(self.inputMapper, path) === "function") {
mappedValue = self._accessByPath(self.inputMapper, path)(value);
}
self._accessByPath(self.state, path, mappedValue);
});
console.log(JSON.stringify(self.state));
App.detachListeners();
Quagga.stop();
App.init();
},
inputMapper: {
decoder: {
readers: function(value) {
return [value + "_reader"];
}
},
inputStream: {
src: function(value) {
return site.baseurl + "/test/fixtures/" + value + "/"
}
}
},
state: {
inputStream: { name: "Test",
type: "ImageStream",
src: site.baseurl + "/test/fixtures/code_128/",
length: 10
},
decoder : {
readers : ["code_128_reader"]
}
} }
}; };

@ -7,16 +7,17 @@ showInMenu: true
quaggaJS quaggaJS
======== ========
- [Changelog](#changelog) (2015-04-25) - [Changelog](#changelog) (2015-04-30)
## What is QuaggaJS? ## What is QuaggaJS?
QuaggaJS is a barcode-scanner entirely written in JavaScript supporting real- QuaggaJS is a barcode-scanner entirely written in JavaScript supporting real-
time localization and decoding of various types of barcodes such as __EAN__, time localization and decoding of various types of barcodes such as __EAN__,
__CODE128__, __CODE39__ and __CODABAR__. The library is also capable of using __CODE 128__, __CODE 39__, __EAN 8__, __UPC-A__, __UPC-C__ and __CODABAR__.
`getUserMedia` to get direct access to the user's camera stream. Although the The library is also capable of using `getUserMedia` to get direct access to
code relies on heavy image-processing even recent smartphones are capable of the user's camera stream. Although the code relies on heavy image-processing
locating and decoding barcodes in real-time. even recent smartphones are capable of locating and decoding barcodes in
real-time.
Try some [examples](http://serratus.github.io/quaggaJS/examples) and check out Try some [examples](http://serratus.github.io/quaggaJS/examples) and check out
the blog post ([How barcode-localization works in QuaggaJS][oberhofer_co_how]) the blog post ([How barcode-localization works in QuaggaJS][oberhofer_co_how])
@ -298,6 +299,15 @@ work.
## <a name="changelog">Changelog</a> ## <a name="changelog">Changelog</a>
### 2015-04-30
- Features
- Added support for [UPC-A and UPC-E][upc_wiki] barcodes
- Added support for [EAN-8][ean_8_wiki] barcodes
- Improvements
- Added extended configuration to the
[live-video example]({{ site.baseurl }}/examples/live_w_locator.html)
- Releasing resources when calling ``Quagga.stop()``
### 2015-04-25 ### 2015-04-25
- Improvements - Improvements
- Added extended configuration to the - Added extended configuration to the
@ -353,5 +363,7 @@ introduced to the API.
[karmaUrl]: http://karma-runner.github.io/ [karmaUrl]: http://karma-runner.github.io/
[code39_wiki]: http://en.wikipedia.org/wiki/Code_39 [code39_wiki]: http://en.wikipedia.org/wiki/Code_39
[codabar_wiki]: http://en.wikipedia.org/wiki/Codabar [codabar_wiki]: http://en.wikipedia.org/wiki/Codabar
[upc_wiki]: http://en.wikipedia.org/wiki/Universal_Product_Code
[ean_8_wiki]: http://en.wikipedia.org/wiki/EAN-8
[oberhofer_co_how]: http://www.oberhofer.co/how-barcode-localization-works-in-quaggajs/ [oberhofer_co_how]: http://www.oberhofer.co/how-barcode-localization-works-in-quaggajs/
[github_examples]: http://serratus.github.io/quaggaJS/examples [github_examples]: http://serratus.github.io/quaggaJS/examples

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Loading…
Cancel
Save