From f0edd499d5a90779e58c36a1bc63b49886ea6922 Mon Sep 17 00:00:00 2001 From: Christoph Oberhofer Date: Mon, 16 Mar 2015 22:35:44 +0100 Subject: [PATCH] Updated quagga to 0.5.0 --- examples/file_input.html | 2 +- examples/js/quagga.js | 1221 ++-------------------------------- examples/js/quagga.min.js | 9 + examples/live_w_locator.html | 2 +- examples/static_images.html | 2 +- index.md | 178 +++-- 6 files changed, 166 insertions(+), 1248 deletions(-) create mode 100644 examples/js/quagga.min.js diff --git a/examples/file_input.html b/examples/file_input.html index 9452fc1..e49efc2 100644 --- a/examples/file_input.html +++ b/examples/file_input.html @@ -28,5 +28,5 @@ showInMenu: false
- + diff --git a/examples/js/quagga.js b/examples/js/quagga.js index e2497ab..3f27ade 100644 --- a/examples/js/quagga.js +++ b/examples/js/quagga.js @@ -1,16 +1,14 @@ (function (root, factory) { - if (typeof define === 'function' && define.amd) { - //Allow using this built library as an AMD module - //in another project. That other project will only - //see this AMD call, not the internal modules in - //the closure below. - define([], factory); + var factorySource = factory.toString(); + + if (typeof module !== 'undefined') { + module.exports = factory(factorySource); } else { //Browser globals case. Just assign the //result to a property on the global. - root.Quagga = factory(); + root.Quagga = factory(factorySource); } -}(this, function () {/** +}(this, function (__factorySource__) {/** * @license almond 0.2.9 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved. * Available via the MIT or new BSD license. * see: http://github.com/jrburke/almond for details @@ -3684,27 +3682,6 @@ define("glMatrix", ["typedefs"], (function (global) { }; }(this))); -/* - -Copyright (C) 2011 - - Christoph Oberhofer (ar.oberhofer@gmail.com) - - Jens Grubert (jg@jensgrubert.de) - - Gerhard Reitmayr (reitmayr@icg.tugraz.at) -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - - /* * glMatrixAddon.js * Extension to the glMatrix library. The original glMatrix library @@ -5489,6 +5466,7 @@ define('rasterizer',["tracer"], function(Tracer) { define('skeletonizer',[],function() { + /* @preserve ASM BEGIN */ function Skeletonizer(stdlib, foreign, buffer) { "use asm"; @@ -5682,6 +5660,7 @@ define('skeletonizer',[],function() { skeletonize : skeletonize }; } + /* @preserve ASM END */ return Skeletonizer; }); @@ -7046,7 +7025,6 @@ define('config',[],function(){ controls: false, locate: true, numOfWorkers: 4, - scriptName: 'quagga.js', visual: { show: true }, @@ -7298,1135 +7276,12 @@ define('camera_access',["html_utils"], function(HtmlUtils) { } }; }); -/*! - * async - * https://github.com/caolan/async - * - * Copyright 2010-2014 Caolan McMahon - * Released under the MIT license - */ -/*jshint onevar: false, indent:4 */ -/*global setImmediate: false, setTimeout: false, console: false */ -(function () { - - var async = {}; - - // global on the server, window in the browser - var root, previous_async; - - root = this; - if (root != null) { - previous_async = root.async; - } - - async.noConflict = function () { - root.async = previous_async; - return async; - }; - - function only_once(fn) { - var called = false; - return function() { - if (called) throw new Error("Callback was already called."); - called = true; - fn.apply(root, arguments); - } - } - - //// cross-browser compatiblity functions //// - - var _toString = Object.prototype.toString; - - var _isArray = Array.isArray || function (obj) { - return _toString.call(obj) === '[object Array]'; - }; - - var _each = function (arr, iterator) { - for (var i = 0; i < arr.length; i += 1) { - iterator(arr[i], i, arr); - } - }; - - var _map = function (arr, iterator) { - if (arr.map) { - return arr.map(iterator); - } - var results = []; - _each(arr, function (x, i, a) { - results.push(iterator(x, i, a)); - }); - return results; - }; - - var _reduce = function (arr, iterator, memo) { - if (arr.reduce) { - return arr.reduce(iterator, memo); - } - _each(arr, function (x, i, a) { - memo = iterator(memo, x, i, a); - }); - return memo; - }; - - var _keys = function (obj) { - if (Object.keys) { - return Object.keys(obj); - } - var keys = []; - for (var k in obj) { - if (obj.hasOwnProperty(k)) { - keys.push(k); - } - } - return keys; - }; - - //// exported async module functions //// - - //// nextTick implementation with browser-compatible fallback //// - if (typeof process === 'undefined' || !(process.nextTick)) { - if (typeof setImmediate === 'function') { - async.nextTick = function (fn) { - // not a direct alias for IE10 compatibility - setImmediate(fn); - }; - async.setImmediate = async.nextTick; - } - else { - async.nextTick = function (fn) { - setTimeout(fn, 0); - }; - async.setImmediate = async.nextTick; - } - } - else { - async.nextTick = process.nextTick; - if (typeof setImmediate !== 'undefined') { - async.setImmediate = function (fn) { - // not a direct alias for IE10 compatibility - setImmediate(fn); - }; - } - else { - async.setImmediate = async.nextTick; - } - } - - async.each = function (arr, iterator, callback) { - callback = callback || function () {}; - if (!arr.length) { - return callback(); - } - var completed = 0; - _each(arr, function (x) { - iterator(x, only_once(done) ); - }); - function done(err) { - if (err) { - callback(err); - callback = function () {}; - } - else { - completed += 1; - if (completed >= arr.length) { - callback(); - } - } - } - }; - async.forEach = async.each; - - async.eachSeries = function (arr, iterator, callback) { - callback = callback || function () {}; - if (!arr.length) { - return callback(); - } - var completed = 0; - var iterate = function () { - iterator(arr[completed], function (err) { - if (err) { - callback(err); - callback = function () {}; - } - else { - completed += 1; - if (completed >= arr.length) { - callback(); - } - else { - iterate(); - } - } - }); - }; - iterate(); - }; - async.forEachSeries = async.eachSeries; - - async.eachLimit = function (arr, limit, iterator, callback) { - var fn = _eachLimit(limit); - fn.apply(null, [arr, iterator, callback]); - }; - async.forEachLimit = async.eachLimit; - - var _eachLimit = function (limit) { - - return function (arr, iterator, callback) { - callback = callback || function () {}; - if (!arr.length || limit <= 0) { - return callback(); - } - var completed = 0; - var started = 0; - var running = 0; - - (function replenish () { - if (completed >= arr.length) { - return callback(); - } - - while (running < limit && started < arr.length) { - started += 1; - running += 1; - iterator(arr[started - 1], function (err) { - if (err) { - callback(err); - callback = function () {}; - } - else { - completed += 1; - running -= 1; - if (completed >= arr.length) { - callback(); - } - else { - replenish(); - } - } - }); - } - })(); - }; - }; - - - var doParallel = function (fn) { - return function () { - var args = Array.prototype.slice.call(arguments); - return fn.apply(null, [async.each].concat(args)); - }; - }; - var doParallelLimit = function(limit, fn) { - return function () { - var args = Array.prototype.slice.call(arguments); - return fn.apply(null, [_eachLimit(limit)].concat(args)); - }; - }; - var doSeries = function (fn) { - return function () { - var args = Array.prototype.slice.call(arguments); - return fn.apply(null, [async.eachSeries].concat(args)); - }; - }; - - - var _asyncMap = function (eachfn, arr, iterator, callback) { - arr = _map(arr, function (x, i) { - return {index: i, value: x}; - }); - if (!callback) { - eachfn(arr, function (x, callback) { - iterator(x.value, function (err) { - callback(err); - }); - }); - } else { - var results = []; - eachfn(arr, function (x, callback) { - iterator(x.value, function (err, v) { - results[x.index] = v; - callback(err); - }); - }, function (err) { - callback(err, results); - }); - } - }; - async.map = doParallel(_asyncMap); - async.mapSeries = doSeries(_asyncMap); - async.mapLimit = function (arr, limit, iterator, callback) { - return _mapLimit(limit)(arr, iterator, callback); - }; - - var _mapLimit = function(limit) { - return doParallelLimit(limit, _asyncMap); - }; - - // reduce only has a series version, as doing reduce in parallel won't - // work in many situations. - async.reduce = function (arr, memo, iterator, callback) { - async.eachSeries(arr, function (x, callback) { - iterator(memo, x, function (err, v) { - memo = v; - callback(err); - }); - }, function (err) { - callback(err, memo); - }); - }; - // inject alias - async.inject = async.reduce; - // foldl alias - async.foldl = async.reduce; - - async.reduceRight = function (arr, memo, iterator, callback) { - var reversed = _map(arr, function (x) { - return x; - }).reverse(); - async.reduce(reversed, memo, iterator, callback); - }; - // foldr alias - async.foldr = async.reduceRight; - - var _filter = function (eachfn, arr, iterator, callback) { - var results = []; - arr = _map(arr, function (x, i) { - return {index: i, value: x}; - }); - eachfn(arr, function (x, callback) { - iterator(x.value, function (v) { - if (v) { - results.push(x); - } - callback(); - }); - }, function (err) { - callback(_map(results.sort(function (a, b) { - return a.index - b.index; - }), function (x) { - return x.value; - })); - }); - }; - async.filter = doParallel(_filter); - async.filterSeries = doSeries(_filter); - // select alias - async.select = async.filter; - async.selectSeries = async.filterSeries; - - var _reject = function (eachfn, arr, iterator, callback) { - var results = []; - arr = _map(arr, function (x, i) { - return {index: i, value: x}; - }); - eachfn(arr, function (x, callback) { - iterator(x.value, function (v) { - if (!v) { - results.push(x); - } - callback(); - }); - }, function (err) { - callback(_map(results.sort(function (a, b) { - return a.index - b.index; - }), function (x) { - return x.value; - })); - }); - }; - async.reject = doParallel(_reject); - async.rejectSeries = doSeries(_reject); - - var _detect = function (eachfn, arr, iterator, main_callback) { - eachfn(arr, function (x, callback) { - iterator(x, function (result) { - if (result) { - main_callback(x); - main_callback = function () {}; - } - else { - callback(); - } - }); - }, function (err) { - main_callback(); - }); - }; - async.detect = doParallel(_detect); - async.detectSeries = doSeries(_detect); - - async.some = function (arr, iterator, main_callback) { - async.each(arr, function (x, callback) { - iterator(x, function (v) { - if (v) { - main_callback(true); - main_callback = function () {}; - } - callback(); - }); - }, function (err) { - main_callback(false); - }); - }; - // any alias - async.any = async.some; - - async.every = function (arr, iterator, main_callback) { - async.each(arr, function (x, callback) { - iterator(x, function (v) { - if (!v) { - main_callback(false); - main_callback = function () {}; - } - callback(); - }); - }, function (err) { - main_callback(true); - }); - }; - // all alias - async.all = async.every; - - async.sortBy = function (arr, iterator, callback) { - async.map(arr, function (x, callback) { - iterator(x, function (err, criteria) { - if (err) { - callback(err); - } - else { - callback(null, {value: x, criteria: criteria}); - } - }); - }, function (err, results) { - if (err) { - return callback(err); - } - else { - var fn = function (left, right) { - var a = left.criteria, b = right.criteria; - return a < b ? -1 : a > b ? 1 : 0; - }; - callback(null, _map(results.sort(fn), function (x) { - return x.value; - })); - } - }); - }; - - async.auto = function (tasks, callback) { - callback = callback || function () {}; - var keys = _keys(tasks); - var remainingTasks = keys.length - if (!remainingTasks) { - return callback(); - } - - var results = {}; - - var listeners = []; - var addListener = function (fn) { - listeners.unshift(fn); - }; - var removeListener = function (fn) { - for (var i = 0; i < listeners.length; i += 1) { - if (listeners[i] === fn) { - listeners.splice(i, 1); - return; - } - } - }; - var taskComplete = function () { - remainingTasks-- - _each(listeners.slice(0), function (fn) { - fn(); - }); - }; - - addListener(function () { - if (!remainingTasks) { - var theCallback = callback; - // prevent final callback from calling itself if it errors - callback = function () {}; - - theCallback(null, results); - } - }); - - _each(keys, function (k) { - var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]]; - var taskCallback = function (err) { - var args = Array.prototype.slice.call(arguments, 1); - if (args.length <= 1) { - args = args[0]; - } - if (err) { - var safeResults = {}; - _each(_keys(results), function(rkey) { - safeResults[rkey] = results[rkey]; - }); - safeResults[k] = args; - callback(err, safeResults); - // stop subsequent errors hitting callback multiple times - callback = function () {}; - } - else { - results[k] = args; - async.setImmediate(taskComplete); - } - }; - var requires = task.slice(0, Math.abs(task.length - 1)) || []; - var ready = function () { - return _reduce(requires, function (a, x) { - return (a && results.hasOwnProperty(x)); - }, true) && !results.hasOwnProperty(k); - }; - if (ready()) { - task[task.length - 1](taskCallback, results); - } - else { - var listener = function () { - if (ready()) { - removeListener(listener); - task[task.length - 1](taskCallback, results); - } - }; - addListener(listener); - } - }); - }; - - async.retry = function(times, task, callback) { - var DEFAULT_TIMES = 5; - var attempts = []; - // Use defaults if times not passed - if (typeof times === 'function') { - callback = task; - task = times; - times = DEFAULT_TIMES; - } - // Make sure times is a number - times = parseInt(times, 10) || DEFAULT_TIMES; - var wrappedTask = function(wrappedCallback, wrappedResults) { - var retryAttempt = function(task, finalAttempt) { - return function(seriesCallback) { - task(function(err, result){ - seriesCallback(!err || finalAttempt, {err: err, result: result}); - }, wrappedResults); - }; - }; - while (times) { - attempts.push(retryAttempt(task, !(times-=1))); - } - async.series(attempts, function(done, data){ - data = data[data.length - 1]; - (wrappedCallback || callback)(data.err, data.result); - }); - } - // If a callback is passed, run this as a controll flow - return callback ? wrappedTask() : wrappedTask - }; - - async.waterfall = function (tasks, callback) { - callback = callback || function () {}; - if (!_isArray(tasks)) { - var err = new Error('First argument to waterfall must be an array of functions'); - return callback(err); - } - if (!tasks.length) { - return callback(); - } - var wrapIterator = function (iterator) { - return function (err) { - if (err) { - callback.apply(null, arguments); - callback = function () {}; - } - else { - var args = Array.prototype.slice.call(arguments, 1); - var next = iterator.next(); - if (next) { - args.push(wrapIterator(next)); - } - else { - args.push(callback); - } - async.setImmediate(function () { - iterator.apply(null, args); - }); - } - }; - }; - wrapIterator(async.iterator(tasks))(); - }; - - var _parallel = function(eachfn, tasks, callback) { - callback = callback || function () {}; - if (_isArray(tasks)) { - eachfn.map(tasks, function (fn, callback) { - if (fn) { - fn(function (err) { - var args = Array.prototype.slice.call(arguments, 1); - if (args.length <= 1) { - args = args[0]; - } - callback.call(null, err, args); - }); - } - }, callback); - } - else { - var results = {}; - eachfn.each(_keys(tasks), function (k, callback) { - tasks[k](function (err) { - var args = Array.prototype.slice.call(arguments, 1); - if (args.length <= 1) { - args = args[0]; - } - results[k] = args; - callback(err); - }); - }, function (err) { - callback(err, results); - }); - } - }; - - async.parallel = function (tasks, callback) { - _parallel({ map: async.map, each: async.each }, tasks, callback); - }; - - async.parallelLimit = function(tasks, limit, callback) { - _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback); - }; - - async.series = function (tasks, callback) { - callback = callback || function () {}; - if (_isArray(tasks)) { - async.mapSeries(tasks, function (fn, callback) { - if (fn) { - fn(function (err) { - var args = Array.prototype.slice.call(arguments, 1); - if (args.length <= 1) { - args = args[0]; - } - callback.call(null, err, args); - }); - } - }, callback); - } - else { - var results = {}; - async.eachSeries(_keys(tasks), function (k, callback) { - tasks[k](function (err) { - var args = Array.prototype.slice.call(arguments, 1); - if (args.length <= 1) { - args = args[0]; - } - results[k] = args; - callback(err); - }); - }, function (err) { - callback(err, results); - }); - } - }; - - async.iterator = function (tasks) { - var makeCallback = function (index) { - var fn = function () { - if (tasks.length) { - tasks[index].apply(null, arguments); - } - return fn.next(); - }; - fn.next = function () { - return (index < tasks.length - 1) ? makeCallback(index + 1): null; - }; - return fn; - }; - return makeCallback(0); - }; - - async.apply = function (fn) { - var args = Array.prototype.slice.call(arguments, 1); - return function () { - return fn.apply( - null, args.concat(Array.prototype.slice.call(arguments)) - ); - }; - }; - - var _concat = function (eachfn, arr, fn, callback) { - var r = []; - eachfn(arr, function (x, cb) { - fn(x, function (err, y) { - r = r.concat(y || []); - cb(err); - }); - }, function (err) { - callback(err, r); - }); - }; - async.concat = doParallel(_concat); - async.concatSeries = doSeries(_concat); - - async.whilst = function (test, iterator, callback) { - if (test()) { - iterator(function (err) { - if (err) { - return callback(err); - } - async.whilst(test, iterator, callback); - }); - } - else { - callback(); - } - }; - - async.doWhilst = function (iterator, test, callback) { - iterator(function (err) { - if (err) { - return callback(err); - } - var args = Array.prototype.slice.call(arguments, 1); - if (test.apply(null, args)) { - async.doWhilst(iterator, test, callback); - } - else { - callback(); - } - }); - }; - - async.until = function (test, iterator, callback) { - if (!test()) { - iterator(function (err) { - if (err) { - return callback(err); - } - async.until(test, iterator, callback); - }); - } - else { - callback(); - } - }; - - async.doUntil = function (iterator, test, callback) { - iterator(function (err) { - if (err) { - return callback(err); - } - var args = Array.prototype.slice.call(arguments, 1); - if (!test.apply(null, args)) { - async.doUntil(iterator, test, callback); - } - else { - callback(); - } - }); - }; - - async.queue = function (worker, concurrency) { - if (concurrency === undefined) { - concurrency = 1; - } - function _insert(q, data, pos, callback) { - if (!q.started){ - q.started = true; - } - if (!_isArray(data)) { - data = [data]; - } - if(data.length == 0) { - // call drain immediately if there are no tasks - return async.setImmediate(function() { - if (q.drain) { - q.drain(); - } - }); - } - _each(data, function(task) { - var item = { - data: task, - callback: typeof callback === 'function' ? callback : null - }; - - if (pos) { - q.tasks.unshift(item); - } else { - q.tasks.push(item); - } - - if (q.saturated && q.tasks.length === q.concurrency) { - q.saturated(); - } - async.setImmediate(q.process); - }); - } - - var workers = 0; - var q = { - tasks: [], - concurrency: concurrency, - saturated: null, - empty: null, - drain: null, - started: false, - paused: false, - push: function (data, callback) { - _insert(q, data, false, callback); - }, - kill: function () { - q.drain = null; - q.tasks = []; - }, - unshift: function (data, callback) { - _insert(q, data, true, callback); - }, - process: function () { - if (!q.paused && workers < q.concurrency && q.tasks.length) { - var task = q.tasks.shift(); - if (q.empty && q.tasks.length === 0) { - q.empty(); - } - workers += 1; - var next = function () { - workers -= 1; - if (task.callback) { - task.callback.apply(task, arguments); - } - if (q.drain && q.tasks.length + workers === 0) { - q.drain(); - } - q.process(); - }; - var cb = only_once(next); - worker(task.data, cb); - } - }, - length: function () { - return q.tasks.length; - }, - running: function () { - return workers; - }, - idle: function() { - return q.tasks.length + workers === 0; - }, - pause: function () { - if (q.paused === true) { return; } - q.paused = true; - }, - resume: function () { - if (q.paused === false) { return; } - q.paused = false; - // Need to call q.process once per concurrent - // worker to preserve full concurrency after pause - for (var w = 1; w <= q.concurrency; w++) { - async.setImmediate(q.process); - } - } - }; - return q; - }; - - async.priorityQueue = function (worker, concurrency) { - - function _compareTasks(a, b){ - return a.priority - b.priority; - }; - - function _binarySearch(sequence, item, compare) { - var beg = -1, - end = sequence.length - 1; - while (beg < end) { - var mid = beg + ((end - beg + 1) >>> 1); - if (compare(item, sequence[mid]) >= 0) { - beg = mid; - } else { - end = mid - 1; - } - } - return beg; - } - - function _insert(q, data, priority, callback) { - if (!q.started){ - q.started = true; - } - if (!_isArray(data)) { - data = [data]; - } - if(data.length == 0) { - // call drain immediately if there are no tasks - return async.setImmediate(function() { - if (q.drain) { - q.drain(); - } - }); - } - _each(data, function(task) { - var item = { - data: task, - priority: priority, - callback: typeof callback === 'function' ? callback : null - }; - - q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item); +/* jshint undef: true, unused: true, browser:true, devel: true, evil: true */ +/* global define, vec2 */ - if (q.saturated && q.tasks.length === q.concurrency) { - q.saturated(); - } - async.setImmediate(q.process); - }); - } - - // Start with a normal queue - var q = async.queue(worker, concurrency); - - // Override push to accept second parameter representing priority - q.push = function (data, priority, callback) { - _insert(q, data, priority, callback); - }; - - // Remove unshift function - delete q.unshift; - - return q; - }; - - async.cargo = function (worker, payload) { - var working = false, - tasks = []; - - var cargo = { - tasks: tasks, - payload: payload, - saturated: null, - empty: null, - drain: null, - drained: true, - push: function (data, callback) { - if (!_isArray(data)) { - data = [data]; - } - _each(data, function(task) { - tasks.push({ - data: task, - callback: typeof callback === 'function' ? callback : null - }); - cargo.drained = false; - if (cargo.saturated && tasks.length === payload) { - cargo.saturated(); - } - }); - async.setImmediate(cargo.process); - }, - process: function process() { - if (working) return; - if (tasks.length === 0) { - if(cargo.drain && !cargo.drained) cargo.drain(); - cargo.drained = true; - return; - } - - var ts = typeof payload === 'number' - ? tasks.splice(0, payload) - : tasks.splice(0, tasks.length); - - var ds = _map(ts, function (task) { - return task.data; - }); - - if(cargo.empty) cargo.empty(); - working = true; - worker(ds, function () { - working = false; - - var args = arguments; - _each(ts, function (data) { - if (data.callback) { - data.callback.apply(null, args); - } - }); - - process(); - }); - }, - length: function () { - return tasks.length; - }, - running: function () { - return working; - } - }; - return cargo; - }; - - var _console_fn = function (name) { - return function (fn) { - var args = Array.prototype.slice.call(arguments, 1); - fn.apply(null, args.concat([function (err) { - var args = Array.prototype.slice.call(arguments, 1); - if (typeof console !== 'undefined') { - if (err) { - if (console.error) { - console.error(err); - } - } - else if (console[name]) { - _each(args, function (x) { - console[name](x); - }); - } - } - }])); - }; - }; - async.log = _console_fn('log'); - async.dir = _console_fn('dir'); - /*async.info = _console_fn('info'); - async.warn = _console_fn('warn'); - async.error = _console_fn('error');*/ - - async.memoize = function (fn, hasher) { - var memo = {}; - var queues = {}; - hasher = hasher || function (x) { - return x; - }; - var memoized = function () { - var args = Array.prototype.slice.call(arguments); - var callback = args.pop(); - var key = hasher.apply(null, args); - if (key in memo) { - async.nextTick(function () { - callback.apply(null, memo[key]); - }); - } - else if (key in queues) { - queues[key].push(callback); - } - else { - queues[key] = [callback]; - fn.apply(null, args.concat([function () { - memo[key] = arguments; - var q = queues[key]; - delete queues[key]; - for (var i = 0, l = q.length; i < l; i++) { - q[i].apply(null, arguments); - } - }])); - } - }; - memoized.memo = memo; - memoized.unmemoized = fn; - return memoized; - }; - - async.unmemoize = function (fn) { - return function () { - return (fn.unmemoized || fn).apply(null, arguments); - }; - }; - - async.times = function (count, iterator, callback) { - var counter = []; - for (var i = 0; i < count; i++) { - counter.push(i); - } - return async.map(counter, iterator, callback); - }; - async.timesSeries = function (count, iterator, callback) { - var counter = []; - for (var i = 0; i < count; i++) { - counter.push(i); - } - return async.mapSeries(counter, iterator, callback); - }; - - async.seq = function (/* functions... */) { - var fns = arguments; - return function () { - var that = this; - var args = Array.prototype.slice.call(arguments); - var callback = args.pop(); - async.reduce(fns, args, function (newargs, fn, cb) { - fn.apply(that, newargs.concat([function () { - var err = arguments[0]; - var nextargs = Array.prototype.slice.call(arguments, 1); - cb(err, nextargs); - }])) - }, - function (err, results) { - callback.apply(that, [err].concat(results)); - }); - }; - }; - - async.compose = function (/* functions... */) { - return async.seq.apply(null, Array.prototype.reverse.call(arguments)); - }; - - var _applyEach = function (eachfn, fns /*args...*/) { - var go = function () { - var that = this; - var args = Array.prototype.slice.call(arguments); - var callback = args.pop(); - return eachfn(fns, function (fn, cb) { - fn.apply(that, args.concat([cb])); - }, - callback); - }; - if (arguments.length > 2) { - var args = Array.prototype.slice.call(arguments, 2); - return go.apply(this, args); - } - else { - return go; - } - }; - async.applyEach = doParallel(_applyEach); - async.applyEachSeries = doSeries(_applyEach); - - async.forever = function (fn, callback) { - function next(err) { - if (err) { - if (callback) { - return callback(err); - } - throw err; - } - fn(next); - } - next(); - }; - - // Node.js - if (typeof module !== 'undefined' && module.exports) { - module.exports = async; - } - // AMD / RequireJS - else if (typeof define !== 'undefined' && define.amd) { - define('async',[], function () { - return async; - }); - } - // included directly via - + diff --git a/examples/static_images.html b/examples/static_images.html index 4d7a905..12bb896 100644 --- a/examples/static_images.html +++ b/examples/static_images.html @@ -30,7 +30,7 @@ showInMenu: false
- + diff --git a/index.md b/index.md index 2b9eba8..3dd642b 100644 --- a/index.md +++ b/index.md @@ -7,15 +7,19 @@ showInMenu: true quaggaJS ======== -- [Changelog](#changelog) (2015-03-12) +- [Changelog](#changelog) (2015-03-16) -QuaggaJS is a barcode-scanner entirely written in JavaScript supporting real-time localization and decoding of -various types of barcodes such as __EAN__ and __CODE128__. The library is also capable of using `getUserMedia` to get direct -access to the user's camera stream. Although the code relies on heavy image-processing even recent smartphones are -capable of locating and decoding barcodes in real-time. +## What is QuaggaJS? -Try some [examples]({{ site.baseurl }}/examples) and check out the blog post -([How barcode-localization works in QuaggaJS](http://www.oberhofer.co/how-barcode-localization-works-in-quaggajs/)) +QuaggaJS is a barcode-scanner entirely written in JavaScript supporting real- +time localization and decoding of various types of barcodes such as __EAN__, +__CODE128__ and __CODE39__. The library is also capable of using `getUserMedia` +to get direct access to the user's camera stream. Although the code relies on +heavy image-processing 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 +the blog post ([How barcode-localization works in QuaggaJS][oberhofer_co_how]) if you want to dive deeper into this topic. ![teaser][teaser_left]![teaser][teaser_right] @@ -23,63 +27,70 @@ if you want to dive deeper into this topic. ## Yet another barcode library? -This is not yet another port of the great [zxing][zxing_github] library, but more of an extension to it. -This implementation features a barcode locator which is capable of finding a barcode-like pattern in an -image resulting in an estimated bounding box including the rotation. Simply speaking, this reader is invariant -to scale and rotation, whereas other libraries require the barcode to be aligned with the viewport. +This is not yet another port of the great [zxing][zxing_github] library, but +more of an extension to it. This implementation features a barcode locator which +is capable of finding a barcode-like pattern in an image resulting in an +estimated bounding box including the rotation. Simply speaking, this reader is +invariant to scale and rotation, whereas other libraries require the barcode to +be aligned with the viewport. ## Requirements -In order to take full advantage of quaggaJS, the browser needs to support the `getUserMedia` API which is -already implemented in recent versions of Firefox, Chrome and Opera. The API is also available on their -mobile counterparts installed on Android. Safari and IE do not allow the access to the camera yet, neither -on desktop, nor on mobile. You can check [caniuse][caniuse_getusermedia] for updates. +In order to take full advantage of quaggaJS, the browser needs to support the +`getUserMedia` API which is already implemented in recent versions of Firefox, +Chrome and Opera. The API is also available on their mobile counterparts +installed on Android. Safari and IE do not allow the access to the camera yet, +neither on desktop, nor on mobile. You can check [caniuse][caniuse_getusermedia] +for updates. + +In cases where real-time decoding is not needed, or the platform does not +support `getUserMedia` QuaggaJS is also capable of decoding image-files using +the File API or other URL sources. -In cases where real-time decoding is not needed, or the platform does not support `getUserMedia` QuaggaJS is -also capable of decoding image-files using the File API or other URL sources. +## Getting Started -## Installation +You can simply include `dist/quagga.min.js` in your project and you are ready +to go. -Just clone the repository and include `dist/quagga.js` in your project. You can also build the library yourself -by simply typing: +If you want to keep your project modular, you can also install QuaggaJS via npm: ```console -> npm install -> grunt +> npm install quagga +``` + +And then import it as dependency in your project: + +```javascript +var quagga = require('quagga'); ``` -### Minification +For starters, have a look at the [examples][github_examples] to get an idea +where to go from here. -Currently, I strongly disapprove using `grunt uglify` since it does not handle asm.js code correctly -(see [issue](https://github.com/mishoo/UglifyJS2/issues/167)). The resulting code still works, but -the performance might suffer, especially in Firefox. Additionally it triggers some ugly log-warnings -in the console. +## Building -This is how you create a minified version of quaggaJS (saved in `dist/quagga.min.js`): +You can build the library yourself by simply cloning the repo and typing: ```console -> grunt uglify +> npm install +> grunt dist ``` -Special care has to be taken if a minimized/uglified version of the code is needed. Basically the grunt task -`grunt uglify` takes the `dist/quagga.js` as input and saves the minified code in `dist/quagga.min.js`. -Since the introduction of web-workers in quaggaJS, the filename of the script is important, because -the instantiation of the workers rely on it. This script-name defaults to `quagga.js` and can be changed -in the config with the key `config.scriptName`. The supplied string must match the filename of the -file being served by the webserver. Now, in the case of a minified version, the config must be adapted -so that `config.scriptName` points to `quagga.min.js`. - -See the [config](#configobject) for all supported options. +This grunt task builds a non optimized version `quagga.js` and a minified +version `quagga.min.js` and places both files in the `dist` folder. -## Usage +## API -You can check out the [examples]({{ site.baseurl }}/examples) to get an idea of how to use QuaggaJS. -Basically the library exposes the following API: +You can check out the [examples][github_examples] to get an idea of how to +use QuaggaJS. Basically the library exposes the following API: ### Quagga.init(config, callback) -This method initializes the library for a given configuration `config` (see below) and invokes the `callback` when Quagga is ready to start. The initialization process also requests for camera access if real-time detection is configured. +This method initializes the library for a given configuration `config` (see +below) and invokes the `callback` when Quagga is ready to start. The +initialization process also requests for camera access if real-time detection is +configured. ```javascript Quagga.init({ @@ -98,31 +109,41 @@ Quagga.init({ ### Quagga.start() -When the library is initialized, the `start()` method starts the video-stream and begins locating and decoding -the images. +When the library is initialized, the `start()` method starts the video-stream +and begins locating and decoding the images. ### Quagga.stop() -If the decoder is currently running, after calling `stop()` the decoder does not process any more images. Additionally, if a camera-stream was requested upon initialization, this operation also disconnects the camera. +If the decoder is currently running, after calling `stop()` the decoder does not +process any more images. Additionally, if a camera-stream was requested upon +initialization, this operation also disconnects the camera. ### Quagga.onProcessed(callback) -This method registers a `callback(data)` function that is called for each frame after the processing is done. The `data` object contains detailed information about the success/failure of the operation. The output varies, depending whether the detection and/or decoding were successful or not. +This method registers a `callback(data)` function that is called for each frame +after the processing is done. The `data` object contains detailed information +about the success/failure of the operation. The output varies, depending whether +the detection and/or decoding were successful or not. ### Quagga.onDetected(callback) -Registers a `callback(data)` function which is triggered whenever a barcode-pattern has been located and decoded -successfully. The passed `data` object contains information about the decoding process including the detected code which can be obtained by calling `data.codeResult.code`. +Registers a `callback(data)` function which is triggered whenever a barcode- +pattern has been located and decoded successfully. The passed `data` object +contains information about the decoding process including the detected code +which can be obtained by calling `data.codeResult.code`. ### Quagga.decodeSingle(config, callback) -In contrast to the calls described above, this method does not rely on `getUserMedia` and operates on a -single image instead. The provided callback is the same as in `onDetected` and contains the result `data` -object. +In contrast to the calls described above, this method does not rely on +`getUserMedia` and operates on a single image instead. The provided callback +is the same as in `onDetected` and contains the result `data` object. ## The result object -The callbacks passed into `onProcessed`, `onDetected` and `decodeSingle` receive a `data` object upon execution. The `data` object contains the following information. Depending on the success, some fields may be `undefined` or just empty. +The callbacks passed into `onProcessed`, `onDetected` and `decodeSingle` +receive a `data` object upon execution. The `data` object contains the following +information. Depending on the success, some fields may be `undefined` or just +empty. ```javascript { @@ -208,7 +229,6 @@ The default `config` object is set as followed: controls: false, locate: true, numOfWorkers: 4, - scriptName: 'quagga.js', visual: { show: true }, @@ -241,8 +261,9 @@ The default `config` object is set as followed: ## Examples -The following example takes an image `src` as input and prints the result on the console. -The decoder is configured to detect _Code128_ barcodes and enables the locating-mechanism for more robust results. +The following example takes an image `src` as input and prints the result on the +console. The decoder is configured to detect _Code128_ barcodes and enables the +locating-mechanism for more robust results. ```javascript Quagga.decodeSingle({ @@ -256,7 +277,9 @@ Quagga.decodeSingle({ ## Tests -Unit Tests can be run with [Karma][karmaUrl] and written using [Mocha][mochaUrl], [Chai][chaiUrl] and [SinonJS][sinonUrl]. Coverage reports are automatically generated in the coverage/ folder. +Unit Tests can be run with [Karma][karmaUrl] and written using +[Mocha][mochaUrl], [Chai][chaiUrl] and [SinonJS][sinonUrl]. Coverage reports are +automatically generated in the coverage/ folder. ```console > npm install @@ -264,10 +287,21 @@ Unit Tests can be run with [Karma][karmaUrl] and written using [Mocha][mochaUrl] ``` ## Image Debugging -In case you want to take a deeper dive into the inner workings of Quagga, get to know the _debugging_ capabilities of the current implementation. The various flags exposed through the `config` object give you the abilily to visualize almost every step in the processing. Because of the introduction of the web-workers, and their restriction not to have access to the DOM, the configuration must be explicitly set to `config.numOfWorkers = 0` in order to work. +In case you want to take a deeper dive into the inner workings of Quagga, get to +know the _debugging_ capabilities of the current implementation. The various +flags exposed through the `config` object give you the abilily to visualize +almost every step in the processing. Because of the introduction of the +web-workers, and their restriction not to have access to the DOM, the +configuration must be explicitly set to `config.numOfWorkers = 0` in order to +work. ## Changelog +### 2015-03-16 +- Improvements + - now includes minified version (23.3KB gzipped) + - No need for configuration of script-name any more + ### 2015-03-12 - Improvements - removed dependency on async.js @@ -278,17 +312,25 @@ In case you want to take a deeper dive into the inner workings of Quagga, get to ### 2015-01-21 - Features - - Added support for web-worker (using 4 workers as default, can be changed through `config.numOfWorkers`) - - Due to the way how web-workers are created, the name of the script file (`config.scriptName`) should be kept in sync with your actual filename - - Removed canvas-overlay for decoding (boxes & scanline) which can now be easily implemented using the existing API (see example) + - Added support for web-worker (using 4 workers as default, can be changed + through `config.numOfWorkers`) + - Due to the way how web-workers are created, the name of the script file + (`config.scriptName`) should be kept in sync with your actual filename + - Removed canvas-overlay for decoding (boxes & scanline) which can now be + easily implemented using the existing API (see example) - API Changes -In the course of implementing web-workers some breaking changes were introduced to the API. - - The `Quagga.init` function no longer receives the callback as part of the config but rather as a second argument: `Quagga.init(config, cb)` - - The callback to `Quagga.onDetected` now receives an object containing much more information in addition to the decoded code. (see [data](#resultobject)) - - Added `Quagga.onProcessed(callback)` which provides a way to get information for each image processed. - The callback receives the same `data` object as `Quagga.onDetected` does. Depending on the success of the process the `data` object - might not contain any `resultCode` and/or `box` properties. - +In the course of implementing web-workers some breaking changes were +introduced to the API. + - The `Quagga.init` function no longer receives the callback as part of the + config but rather as a second argument: `Quagga.init(config, cb)` + - The callback to `Quagga.onDetected` now receives an object containing + much more information in addition to the decoded code.(see + [data](#resultobject)) + - Added `Quagga.onProcessed(callback)` which provides a way to get information + for each image processed. The callback receives the same `data` object as + `Quagga.onDetected` does. Depending on the success of the process the `data` + object might not contain any `resultCode` and/or `box` properties. + [zxing_github]: https://github.com/zxing/zxing [teaser_left]: {{ site.baseurl }}/assets/mobile-located.jpg [teaser_right]: {{ site.baseurl }}/assets/mobile-detected.jpg @@ -298,3 +340,5 @@ In the course of implementing web-workers some breaking changes were introduced [mochaUrl]: https://github.com/mochajs/mocha [karmaUrl]: http://karma-runner.github.io/ [code39_wiki]: http://en.wikipedia.org/wiki/Code_39 +[oberhofer_co_how]: http://www.oberhofer.co/how-barcode-localization-works-in-quaggajs/ +[github_examples]: http://serratus.github.io/quaggaJS/examples