Fix parallel image processing

pull/319/head
Adam Dobrawy 7 years ago
parent a4de46f9a9
commit fe6a2e8be1

1534
dist/quagga.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

10421
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -14,530 +14,532 @@ const vec2 = {
clone: require('gl-vec2/clone') clone: require('gl-vec2/clone')
}; };
var _inputStream, exports.default = function() {
_framegrabber, var _inputStream,
_stopped, _framegrabber,
_canvasContainer = { _stopped,
ctx: { _canvasContainer = {
image: null, ctx: {
overlay: null image: null,
overlay: null
},
dom: {
image: null,
overlay: null
}
}, },
dom: { _inputImageWrapper,
image: null, _boxSize,
overlay: null _decoder,
} _workerPool = [],
}, _onUIThread = true,
_inputImageWrapper, _resultCollector,
_boxSize, _config = {};
_decoder,
_workerPool = [], function initializeData(imageWrapper) {
_onUIThread = true, initBuffers(imageWrapper);
_resultCollector, _decoder = BarcodeDecoder.create(_config.decoder, _inputImageWrapper);
_config = {}; }
function initializeData(imageWrapper) { function initInputStream(cb) {
initBuffers(imageWrapper); var video;
_decoder = BarcodeDecoder.create(_config.decoder, _inputImageWrapper); if (_config.inputStream.type === "VideoStream") {
} video = document.createElement("video");
_inputStream = InputStream.createVideoStream(video);
function initInputStream(cb) { } else if (_config.inputStream.type === "ImageStream") {
var video; _inputStream = InputStream.createImageStream();
if (_config.inputStream.type === "VideoStream") { } else if (_config.inputStream.type === "LiveStream") {
video = document.createElement("video"); var $viewport = getViewPort();
_inputStream = InputStream.createVideoStream(video); if ($viewport) {
} else if (_config.inputStream.type === "ImageStream") { video = $viewport.querySelector("video");
_inputStream = InputStream.createImageStream(); if (!video) {
} else if (_config.inputStream.type === "LiveStream") { video = document.createElement("video");
var $viewport = getViewPort(); $viewport.appendChild(video);
if ($viewport) { }
video = $viewport.querySelector("video");
if (!video) {
video = document.createElement("video");
$viewport.appendChild(video);
} }
_inputStream = InputStream.createLiveStream(video);
CameraAccess.request(video, _config.inputStream.constraints)
.then(() => {
_inputStream.trigger("canrecord");
}).catch((err) => {
return cb(err);
});
} }
_inputStream = InputStream.createLiveStream(video);
CameraAccess.request(video, _config.inputStream.constraints) _inputStream.setAttribute("preload", "auto");
.then(() => { _inputStream.setInputStream(_config.inputStream);
_inputStream.trigger("canrecord"); _inputStream.addEventListener("canrecord", canRecord.bind(undefined, cb));
}).catch((err) => {
return cb(err);
});
} }
_inputStream.setAttribute("preload", "auto"); function getViewPort() {
_inputStream.setInputStream(_config.inputStream); var target = _config.inputStream.target;
_inputStream.addEventListener("canrecord", canRecord.bind(undefined, cb)); // Check if target is already a DOM element
} if (target && target.nodeName && target.nodeType === 1) {
return target;
function getViewPort() { } else {
var target = _config.inputStream.target; // Use '#interactive.viewport' as a fallback selector (backwards compatibility)
// Check if target is already a DOM element var selector = typeof target === 'string' ? target : '#interactive.viewport';
if (target && target.nodeName && target.nodeType === 1) { return document.querySelector(selector);
return target; }
} else {
// Use '#interactive.viewport' as a fallback selector (backwards compatibility)
var selector = typeof target === 'string' ? target : '#interactive.viewport';
return document.querySelector(selector);
} }
}
function canRecord(cb) { function canRecord(cb) {
BarcodeLocator.checkImageConstraints(_inputStream, _config.locator); BarcodeLocator.checkImageConstraints(_inputStream, _config.locator);
initCanvas(_config); initCanvas(_config);
_framegrabber = FrameGrabber.create(_inputStream, _canvasContainer.dom.image); _framegrabber = FrameGrabber.create(_inputStream, _canvasContainer.dom.image);
adjustWorkerPool(_config.numOfWorkers, function() { adjustWorkerPool(_config.numOfWorkers, function () {
if (_config.numOfWorkers === 0) { if (_config.numOfWorkers === 0) {
initializeData(); initializeData();
}
ready(cb);
});
}
function ready(cb){
_inputStream.play();
cb();
}
function initCanvas() {
if (typeof document !== "undefined") {
var $viewport = getViewPort();
_canvasContainer.dom.image = document.querySelector("canvas.imgBuffer");
if (!_canvasContainer.dom.image) {
_canvasContainer.dom.image = document.createElement("canvas");
_canvasContainer.dom.image.className = "imgBuffer";
if ($viewport && _config.inputStream.type === "ImageStream") {
$viewport.appendChild(_canvasContainer.dom.image);
} }
} ready(cb);
_canvasContainer.ctx.image = _canvasContainer.dom.image.getContext("2d");
_canvasContainer.dom.image.width = _inputStream.getCanvasSize().x;
_canvasContainer.dom.image.height = _inputStream.getCanvasSize().y;
_canvasContainer.dom.overlay = document.querySelector("canvas.drawingBuffer");
if (!_canvasContainer.dom.overlay) {
_canvasContainer.dom.overlay = document.createElement("canvas");
_canvasContainer.dom.overlay.className = "drawingBuffer";
if ($viewport) {
$viewport.appendChild(_canvasContainer.dom.overlay);
}
var clearFix = document.createElement("br");
clearFix.setAttribute("clear", "all");
if ($viewport) {
$viewport.appendChild(clearFix);
}
}
_canvasContainer.ctx.overlay = _canvasContainer.dom.overlay.getContext("2d");
_canvasContainer.dom.overlay.width = _inputStream.getCanvasSize().x;
_canvasContainer.dom.overlay.height = _inputStream.getCanvasSize().y;
}
}
function initBuffers(imageWrapper) {
if (imageWrapper) {
_inputImageWrapper = imageWrapper;
} else {
_inputImageWrapper = new ImageWrapper({
x: _inputStream.getWidth(),
y: _inputStream.getHeight()
}); });
} }
if (ENV.development) { function ready(cb) {
console.log(_inputImageWrapper.size); _inputStream.play();
cb();
} }
_boxSize = [
vec2.clone([0, 0]), function initCanvas() {
vec2.clone([0, _inputImageWrapper.size.y]), if (typeof document !== "undefined") {
vec2.clone([_inputImageWrapper.size.x, _inputImageWrapper.size.y]), var $viewport = getViewPort();
vec2.clone([_inputImageWrapper.size.x, 0]) _canvasContainer.dom.image = document.querySelector("canvas.imgBuffer");
]; if (!_canvasContainer.dom.image) {
BarcodeLocator.init(_inputImageWrapper, _config.locator); _canvasContainer.dom.image = document.createElement("canvas");
} _canvasContainer.dom.image.className = "imgBuffer";
if ($viewport && _config.inputStream.type === "ImageStream") {
function getBoundingBoxes() { $viewport.appendChild(_canvasContainer.dom.image);
if (_config.locate) { }
return BarcodeLocator.locate(); }
} else { _canvasContainer.ctx.image = _canvasContainer.dom.image.getContext("2d");
return [[ _canvasContainer.dom.image.width = _inputStream.getCanvasSize().x;
vec2.clone(_boxSize[0]), _canvasContainer.dom.image.height = _inputStream.getCanvasSize().y;
vec2.clone(_boxSize[1]),
vec2.clone(_boxSize[2]), _canvasContainer.dom.overlay = document.querySelector("canvas.drawingBuffer");
vec2.clone(_boxSize[3])]]; if (!_canvasContainer.dom.overlay) {
_canvasContainer.dom.overlay = document.createElement("canvas");
_canvasContainer.dom.overlay.className = "drawingBuffer";
if ($viewport) {
$viewport.appendChild(_canvasContainer.dom.overlay);
}
var clearFix = document.createElement("br");
clearFix.setAttribute("clear", "all");
if ($viewport) {
$viewport.appendChild(clearFix);
}
}
_canvasContainer.ctx.overlay = _canvasContainer.dom.overlay.getContext("2d");
_canvasContainer.dom.overlay.width = _inputStream.getCanvasSize().x;
_canvasContainer.dom.overlay.height = _inputStream.getCanvasSize().y;
}
} }
}
function transformResult(result) { function initBuffers(imageWrapper) {
var topRight = _inputStream.getTopRight(), if (imageWrapper) {
xOffset = topRight.x, _inputImageWrapper = imageWrapper;
yOffset = topRight.y, } else {
i; _inputImageWrapper = new ImageWrapper({
x: _inputStream.getWidth(),
y: _inputStream.getHeight()
});
}
if (xOffset === 0 && yOffset === 0) { if (ENV.development) {
return; console.log(_inputImageWrapper.size);
}
_boxSize = [
vec2.clone([0, 0]),
vec2.clone([0, _inputImageWrapper.size.y]),
vec2.clone([_inputImageWrapper.size.x, _inputImageWrapper.size.y]),
vec2.clone([_inputImageWrapper.size.x, 0])
];
BarcodeLocator.init(_inputImageWrapper, _config.locator);
} }
if (result.barcodes) { function getBoundingBoxes() {
for (i = 0; i < result.barcodes.length; i++) { if (_config.locate) {
transformResult(result.barcodes[i]); return BarcodeLocator.locate();
} else {
return [[
vec2.clone(_boxSize[0]),
vec2.clone(_boxSize[1]),
vec2.clone(_boxSize[2]),
vec2.clone(_boxSize[3])]];
} }
} }
if (result.line && result.line.length === 2) { function transformResult(result) {
moveLine(result.line); var topRight = _inputStream.getTopRight(),
} xOffset = topRight.x,
yOffset = topRight.y,
i;
if (result.box) { if (xOffset === 0 && yOffset === 0) {
moveBox(result.box); return;
} }
if (result.boxes && result.boxes.length > 0) { if (result.barcodes) {
for (i = 0; i < result.boxes.length; i++) { for (i = 0; i < result.barcodes.length; i++) {
moveBox(result.boxes[i]); transformResult(result.barcodes[i]);
}
} }
}
function moveBox(box) { if (result.line && result.line.length === 2) {
var corner = box.length; moveLine(result.line);
}
while (corner--) { if (result.box) {
box[corner][0] += xOffset; moveBox(result.box);
box[corner][1] += yOffset;
} }
}
function moveLine(line) { if (result.boxes && result.boxes.length > 0) {
line[0].x += xOffset; for (i = 0; i < result.boxes.length; i++) {
line[0].y += yOffset; moveBox(result.boxes[i]);
line[1].x += xOffset; }
line[1].y += yOffset; }
function moveBox(box) {
var corner = box.length;
while (corner--) {
box[corner][0] += xOffset;
box[corner][1] += yOffset;
}
}
function moveLine(line) {
line[0].x += xOffset;
line[0].y += yOffset;
line[1].x += xOffset;
line[1].y += yOffset;
}
} }
}
function addResult (result, imageData) { function addResult(result, imageData) {
if (!imageData || !_resultCollector) { if (!imageData || !_resultCollector) {
return; return;
}
if (result.barcodes) {
result.barcodes.filter(barcode => barcode.codeResult)
.forEach(barcode => addResult(barcode, imageData));
} else if (result.codeResult) {
_resultCollector.addResult(imageData, _inputStream.getCanvasSize(), result.codeResult);
}
} }
if (result.barcodes) { function hasCodeResult(result) {
result.barcodes.filter(barcode => barcode.codeResult) return result && (result.barcodes ?
.forEach(barcode => addResult(barcode, imageData)); result.barcodes.some(barcode => barcode.codeResult) :
} else if (result.codeResult) { result.codeResult);
_resultCollector.addResult(imageData, _inputStream.getCanvasSize(), result.codeResult);
} }
}
function hasCodeResult (result) { function publishResult(result, imageData) {
return result && (result.barcodes ? let resultToPublish = result;
result.barcodes.some(barcode => barcode.codeResult) :
result.codeResult);
}
function publishResult(result, imageData) { if (result && _onUIThread) {
let resultToPublish = result; transformResult(result);
addResult(result, imageData);
resultToPublish = result.barcodes || result;
}
if (result && _onUIThread) { Events.publish("processed", resultToPublish);
transformResult(result); if (hasCodeResult(result)) {
addResult(result, imageData); Events.publish("detected", resultToPublish);
resultToPublish = result.barcodes || result; }
} }
Events.publish("processed", resultToPublish); function locateAndDecode() {
if (hasCodeResult(result)) { var result,
Events.publish("detected", resultToPublish); boxes;
}
} boxes = getBoundingBoxes();
if (boxes) {
function locateAndDecode() { result = _decoder.decodeFromBoundingBoxes(boxes);
var result, result = result || {};
boxes; result.boxes = boxes;
publishResult(result, _inputImageWrapper.data);
boxes = getBoundingBoxes();
if (boxes) {
result = _decoder.decodeFromBoundingBoxes(boxes);
result = result || {};
result.boxes = boxes;
publishResult(result, _inputImageWrapper.data);
} else {
publishResult();
}
}
function update() {
var availableWorker;
if (_onUIThread) {
if (_workerPool.length > 0) {
availableWorker = _workerPool.filter(function(workerThread) {
return !workerThread.busy;
})[0];
if (availableWorker) {
_framegrabber.attachData(availableWorker.imageData);
} else {
return; // all workers are busy
}
} else { } else {
_framegrabber.attachData(_inputImageWrapper.data); publishResult();
} }
if (_framegrabber.grab()) { }
if (availableWorker) {
availableWorker.busy = true; function update() {
availableWorker.worker.postMessage({ var availableWorker;
cmd: 'process',
imageData: availableWorker.imageData if (_onUIThread) {
}, [availableWorker.imageData.buffer]); if (_workerPool.length > 0) {
availableWorker = _workerPool.filter(function (workerThread) {
return !workerThread.busy;
})[0];
if (availableWorker) {
_framegrabber.attachData(availableWorker.imageData);
} else {
return; // all workers are busy
}
} else { } else {
locateAndDecode(); _framegrabber.attachData(_inputImageWrapper.data);
}
if (_framegrabber.grab()) {
if (availableWorker) {
availableWorker.busy = true;
availableWorker.worker.postMessage({
cmd: 'process',
imageData: availableWorker.imageData
}, [availableWorker.imageData.buffer]);
} else {
locateAndDecode();
}
} }
} else {
locateAndDecode();
} }
} else {
locateAndDecode();
} }
}
function startContinuousUpdate() {
function startContinuousUpdate() { var next = null,
var next = null, delay = 1000 / (_config.frequency || 60);
delay = 1000 / (_config.frequency || 60);
_stopped = false;
_stopped = false; (function frame(timestamp) {
(function frame(timestamp) { next = next || timestamp;
next = next || timestamp; if (!_stopped) {
if (!_stopped) { if (timestamp >= next) {
if (timestamp >= next) { next += delay;
next += delay; update();
update(); }
window.requestAnimFrame(frame);
} }
window.requestAnimFrame(frame); }(performance.now()));
}
function start() {
if (_onUIThread && _config.inputStream.type === "LiveStream") {
startContinuousUpdate();
} else {
update();
} }
}(performance.now()));
}
function start() {
if (_onUIThread && _config.inputStream.type === "LiveStream") {
startContinuousUpdate();
} else {
update();
} }
}
function initWorker(cb) {
function initWorker(cb) { var blobURL,
var blobURL, workerThread = {
workerThread = { worker: undefined,
worker: undefined, imageData: new Uint8Array(_inputStream.getWidth() * _inputStream.getHeight()),
imageData: new Uint8Array(_inputStream.getWidth() * _inputStream.getHeight()), busy: true
busy: true };
blobURL = generateWorkerBlob();
workerThread.worker = new Worker(blobURL);
workerThread.worker.onmessage = function (e) {
if (e.data.event === 'initialized') {
URL.revokeObjectURL(blobURL);
workerThread.busy = false;
workerThread.imageData = new Uint8Array(e.data.imageData);
if (ENV.development) {
console.log("Worker initialized");
}
return cb(workerThread);
} else if (e.data.event === 'processed') {
workerThread.imageData = new Uint8Array(e.data.imageData);
workerThread.busy = false;
publishResult(e.data.result, workerThread.imageData);
} else if (e.data.event === 'error') {
if (ENV.development) {
console.log("Worker error: " + e.data.message);
}
}
}; };
blobURL = generateWorkerBlob(); workerThread.worker.postMessage({
workerThread.worker = new Worker(blobURL); cmd: 'init',
size: {x: _inputStream.getWidth(), y: _inputStream.getHeight()},
imageData: workerThread.imageData,
config: configForWorker(_config)
}, [workerThread.imageData.buffer]);
}
workerThread.worker.onmessage = function(e) { function configForWorker(config) {
if (e.data.event === 'initialized') { return {
URL.revokeObjectURL(blobURL); ...config,
workerThread.busy = false; inputStream: {
workerThread.imageData = new Uint8Array(e.data.imageData); ...config.inputStream,
if (ENV.development) { target: null
console.log("Worker initialized");
} }
return cb(workerThread); };
} else if (e.data.event === 'processed') { }
workerThread.imageData = new Uint8Array(e.data.imageData);
workerThread.busy = false; function workerInterface(factory) {
publishResult(e.data.result, workerThread.imageData); /* eslint-disable no-undef*/
} else if (e.data.event === 'error') { if (factory) {
if (ENV.development) { var Quagga = factory().default;
console.log("Worker error: " + e.data.message); if (!Quagga) {
self.postMessage({'event': 'error', message: 'Quagga could not be created'});
return;
} }
} }
}; var imageWrapper;
workerThread.worker.postMessage({ self.onmessage = function (e) {
cmd: 'init', if (e.data.cmd === 'init') {
size: {x: _inputStream.getWidth(), y: _inputStream.getHeight()}, var config = e.data.config;
imageData: workerThread.imageData, config.numOfWorkers = 0;
config: configForWorker(_config) imageWrapper = new Quagga.ImageWrapper({
}, [workerThread.imageData.buffer]); x: e.data.size.x,
} y: e.data.size.y
}, new Uint8Array(e.data.imageData));
Quagga.init(config, ready, imageWrapper);
Quagga.onProcessed(onProcessed);
} else if (e.data.cmd === 'process') {
imageWrapper.data = new Uint8Array(e.data.imageData);
Quagga.start();
} else if (e.data.cmd === 'setReaders') {
Quagga.setReaders(e.data.readers);
}
};
function configForWorker(config) { function onProcessed(result) {
return { self.postMessage({
...config, 'event': 'processed',
inputStream: { imageData: imageWrapper.data,
...config.inputStream, result: result
target: null }, [imageWrapper.data.buffer]);
}
};
}
function workerInterface(factory) {
/* eslint-disable no-undef*/
if (factory) {
var Quagga = factory().default;
if (!Quagga) {
self.postMessage({'event': 'error', message: 'Quagga could not be created'});
return;
} }
}
var imageWrapper; function ready() { // eslint-disable-line
self.postMessage({'event': 'initialized', imageData: imageWrapper.data}, [imageWrapper.data.buffer]);
self.onmessage = function(e) {
if (e.data.cmd === 'init') {
var config = e.data.config;
config.numOfWorkers = 0;
imageWrapper = new Quagga.ImageWrapper({
x: e.data.size.x,
y: e.data.size.y
}, new Uint8Array(e.data.imageData));
Quagga.init(config, ready, imageWrapper);
Quagga.onProcessed(onProcessed);
} else if (e.data.cmd === 'process') {
imageWrapper.data = new Uint8Array(e.data.imageData);
Quagga.start();
} else if (e.data.cmd === 'setReaders') {
Quagga.setReaders(e.data.readers);
} }
};
function onProcessed(result) { /* eslint-enable */
self.postMessage({
'event': 'processed',
imageData: imageWrapper.data,
result: result
}, [imageWrapper.data.buffer]);
} }
function ready() { // eslint-disable-line function generateWorkerBlob() {
self.postMessage({'event': 'initialized', imageData: imageWrapper.data}, [imageWrapper.data.buffer]); var blob,
} factorySource;
/* eslint-enable */ /* jshint ignore:start */
} if (typeof __factorySource__ !== 'undefined') {
factorySource = __factorySource__; // eslint-disable-line no-undef
}
/* jshint ignore:end */
function generateWorkerBlob() { blob = new Blob(['(' + workerInterface.toString() + ')(' + factorySource + ');'],
var blob, {type: 'text/javascript'});
factorySource;
/* jshint ignore:start */ return window.URL.createObjectURL(blob);
if (typeof __factorySource__ !== 'undefined') {
factorySource = __factorySource__; // eslint-disable-line no-undef
} }
/* jshint ignore:end */
blob = new Blob(['(' + workerInterface.toString() + ')(' + factorySource + ');'],
{type: 'text/javascript'});
return window.URL.createObjectURL(blob);
}
function setReaders(readers) { function setReaders(readers) {
if (_decoder) { if (_decoder) {
_decoder.setReaders(readers); _decoder.setReaders(readers);
} else if (_onUIThread && _workerPool.length > 0) { } else if (_onUIThread && _workerPool.length > 0) {
_workerPool.forEach(function(workerThread) { _workerPool.forEach(function (workerThread) {
workerThread.worker.postMessage({cmd: 'setReaders', readers: readers}); workerThread.worker.postMessage({cmd: 'setReaders', readers: readers});
}); });
}
} }
}
function adjustWorkerPool(capacity, cb) { function adjustWorkerPool(capacity, cb) {
const increaseBy = capacity - _workerPool.length; const increaseBy = capacity - _workerPool.length;
if (increaseBy === 0) { if (increaseBy === 0) {
return cb && cb(); return cb && cb();
}
if (increaseBy < 0) {
const workersToTerminate = _workerPool.slice(increaseBy);
workersToTerminate.forEach(function(workerThread) {
workerThread.worker.terminate();
if (ENV.development) {
console.log("Worker terminated!");
}
});
_workerPool = _workerPool.slice(0, increaseBy);
return cb && cb();
} else {
for (var i = 0; i < increaseBy; i++) {
initWorker(workerInitialized);
} }
if (increaseBy < 0) {
const workersToTerminate = _workerPool.slice(increaseBy);
workersToTerminate.forEach(function (workerThread) {
workerThread.worker.terminate();
if (ENV.development) {
console.log("Worker terminated!");
}
});
_workerPool = _workerPool.slice(0, increaseBy);
return cb && cb();
} else {
for (var i = 0; i < increaseBy; i++) {
initWorker(workerInitialized);
}
function workerInitialized(workerThread) { function workerInitialized(workerThread) {
_workerPool.push(workerThread); _workerPool.push(workerThread);
if (_workerPool.length >= capacity){ if (_workerPool.length >= capacity) {
cb && cb(); cb && cb();
}
} }
} }
} }
}
export default { return {
init: function(config, cb, imageWrapper) { init: function (config, cb, imageWrapper) {
_config = merge({}, Config, config); _config = merge({}, Config, config);
if (imageWrapper) { if (imageWrapper) {
_onUIThread = false; _onUIThread = false;
initializeData(imageWrapper); initializeData(imageWrapper);
return cb(); return cb();
} else { } else {
initInputStream(cb); initInputStream(cb);
}
},
start: function() {
start();
},
stop: function() {
_stopped = true;
adjustWorkerPool(0);
if (_config.inputStream.type === "LiveStream") {
CameraAccess.release();
_inputStream.clearEventHandlers();
}
},
pause: function() {
_stopped = true;
},
onDetected: function(callback) {
Events.subscribe("detected", callback);
},
offDetected: function(callback) {
Events.unsubscribe("detected", callback);
},
onProcessed: function(callback) {
Events.subscribe("processed", callback);
},
offProcessed: function(callback) {
Events.unsubscribe("processed", callback);
},
setReaders: function(readers) {
setReaders(readers);
},
registerResultCollector: function(resultCollector) {
if (resultCollector && typeof resultCollector.addResult === 'function') {
_resultCollector = resultCollector;
}
},
canvas: _canvasContainer,
decodeSingle: function(config, resultCallback) {
config = merge({
inputStream: {
type: "ImageStream",
sequence: false,
size: 800,
src: config.src
},
numOfWorkers: (ENV.development && config.debug) ? 0 : 1,
locator: {
halfSample: false
} }
}, config); },
this.init(config, () => { start: function () {
Events.once("processed", (result) => {
this.stop();
resultCallback.call(null, result);
}, true);
start(); start();
}); },
}, stop: function () {
ImageWrapper: ImageWrapper, _stopped = true;
ImageDebug: ImageDebug, adjustWorkerPool(0);
ResultCollector: ResultCollector, if (_config.inputStream.type === "LiveStream") {
CameraAccess: CameraAccess, CameraAccess.release();
}; _inputStream.clearEventHandlers();
}
},
pause: function () {
_stopped = true;
},
onDetected: function (callback) {
Events.subscribe("detected", callback);
},
offDetected: function (callback) {
Events.unsubscribe("detected", callback);
},
onProcessed: function (callback) {
Events.subscribe("processed", callback);
},
offProcessed: function (callback) {
Events.unsubscribe("processed", callback);
},
setReaders: function (readers) {
setReaders(readers);
},
registerResultCollector: function (resultCollector) {
if (resultCollector && typeof resultCollector.addResult === 'function') {
_resultCollector = resultCollector;
}
},
canvas: _canvasContainer,
decodeSingle: function (config, resultCallback) {
config = merge({
inputStream: {
type: "ImageStream",
sequence: false,
size: 800,
src: config.src
},
numOfWorkers: (ENV.development && config.debug) ? 0 : 1,
locator: {
halfSample: false
}
}, config);
this.init(config, () => {
Events.once("processed", (result) => {
this.stop();
resultCallback.call(null, result);
}, true);
start();
});
},
ImageWrapper: ImageWrapper,
ImageDebug: ImageDebug,
ResultCollector: ResultCollector,
CameraAccess: CameraAccess,
};
}
Loading…
Cancel
Save