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) {
initBuffers(imageWrapper);
_decoder = BarcodeDecoder.create(_config.decoder, _inputImageWrapper);
}
function initInputStream(cb) { function initInputStream(cb) {
var video; var video;
if (_config.inputStream.type === "VideoStream") { if (_config.inputStream.type === "VideoStream") {
video = document.createElement("video"); video = document.createElement("video");
_inputStream = InputStream.createVideoStream(video); _inputStream = InputStream.createVideoStream(video);
} else if (_config.inputStream.type === "ImageStream") { } else if (_config.inputStream.type === "ImageStream") {
_inputStream = InputStream.createImageStream(); _inputStream = InputStream.createImageStream();
} else if (_config.inputStream.type === "LiveStream") { } else if (_config.inputStream.type === "LiveStream") {
var $viewport = getViewPort(); var $viewport = getViewPort();
if ($viewport) { if ($viewport) {
video = $viewport.querySelector("video"); video = $viewport.querySelector("video");
if (!video) { if (!video) {
video = document.createElement("video"); video = document.createElement("video");
$viewport.appendChild(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)
.then(() => {
_inputStream.trigger("canrecord");
}).catch((err) => {
return cb(err);
});
}
_inputStream.setAttribute("preload", "auto"); _inputStream.setAttribute("preload", "auto");
_inputStream.setInputStream(_config.inputStream); _inputStream.setInputStream(_config.inputStream);
_inputStream.addEventListener("canrecord", canRecord.bind(undefined, cb)); _inputStream.addEventListener("canrecord", canRecord.bind(undefined, cb));
}
function getViewPort() {
var target = _config.inputStream.target;
// Check if target is already a DOM element
if (target && target.nodeName && target.nodeType === 1) {
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 getViewPort() {
BarcodeLocator.checkImageConstraints(_inputStream, _config.locator); var target = _config.inputStream.target;
initCanvas(_config); // Check if target is already a DOM element
_framegrabber = FrameGrabber.create(_inputStream, _canvasContainer.dom.image); if (target && target.nodeName && target.nodeType === 1) {
return target;
adjustWorkerPool(_config.numOfWorkers, function() { } else {
if (_config.numOfWorkers === 0) { // Use '#interactive.viewport' as a fallback selector (backwards compatibility)
initializeData(); var selector = typeof target === 'string' ? target : '#interactive.viewport';
return document.querySelector(selector);
} }
ready(cb); }
});
}
function ready(cb){ function canRecord(cb) {
_inputStream.play(); BarcodeLocator.checkImageConstraints(_inputStream, _config.locator);
cb(); initCanvas(_config);
} _framegrabber = FrameGrabber.create(_inputStream, _canvasContainer.dom.image);
function initCanvas() { adjustWorkerPool(_config.numOfWorkers, function () {
if (typeof document !== "undefined") { if (_config.numOfWorkers === 0) {
var $viewport = getViewPort(); initializeData();
_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;
function ready(cb) {
_canvasContainer.dom.overlay = document.querySelector("canvas.drawingBuffer"); _inputStream.play();
if (!_canvasContainer.dom.overlay) { cb();
_canvasContainer.dom.overlay = document.createElement("canvas"); }
_canvasContainer.dom.overlay.className = "drawingBuffer";
if ($viewport) { function initCanvas() {
$viewport.appendChild(_canvasContainer.dom.overlay); 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);
}
} }
var clearFix = document.createElement("br"); _canvasContainer.ctx.image = _canvasContainer.dom.image.getContext("2d");
clearFix.setAttribute("clear", "all"); _canvasContainer.dom.image.width = _inputStream.getCanvasSize().x;
if ($viewport) { _canvasContainer.dom.image.height = _inputStream.getCanvasSize().y;
$viewport.appendChild(clearFix);
_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;
} }
_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) { function initBuffers(imageWrapper) {
if (imageWrapper) { if (imageWrapper) {
_inputImageWrapper = imageWrapper; _inputImageWrapper = imageWrapper;
} else { } else {
_inputImageWrapper = new ImageWrapper({ _inputImageWrapper = new ImageWrapper({
x: _inputStream.getWidth(), x: _inputStream.getWidth(),
y: _inputStream.getHeight() y: _inputStream.getHeight()
}); });
} }
if (ENV.development) { if (ENV.development) {
console.log(_inputImageWrapper.size); 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);
} }
_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);
}
function getBoundingBoxes() { function getBoundingBoxes() {
if (_config.locate) { if (_config.locate) {
return BarcodeLocator.locate(); return BarcodeLocator.locate();
} else { } else {
return [[ return [[
vec2.clone(_boxSize[0]), vec2.clone(_boxSize[0]),
vec2.clone(_boxSize[1]), vec2.clone(_boxSize[1]),
vec2.clone(_boxSize[2]), vec2.clone(_boxSize[2]),
vec2.clone(_boxSize[3])]]; vec2.clone(_boxSize[3])]];
}
} }
}
function transformResult(result) { function transformResult(result) {
var topRight = _inputStream.getTopRight(), var topRight = _inputStream.getTopRight(),
xOffset = topRight.x, xOffset = topRight.x,
yOffset = topRight.y, yOffset = topRight.y,
i; i;
if (xOffset === 0 && yOffset === 0) { if (xOffset === 0 && yOffset === 0) {
return; return;
} }
if (result.barcodes) { if (result.barcodes) {
for (i = 0; i < result.barcodes.length; i++) { for (i = 0; i < result.barcodes.length; i++) {
transformResult(result.barcodes[i]); transformResult(result.barcodes[i]);
}
} }
}
if (result.line && result.line.length === 2) { if (result.line && result.line.length === 2) {
moveLine(result.line); moveLine(result.line);
} }
if (result.box) { if (result.box) {
moveBox(result.box); moveBox(result.box);
} }
if (result.boxes && result.boxes.length > 0) { if (result.boxes && result.boxes.length > 0) {
for (i = 0; i < result.boxes.length; i++) { for (i = 0; i < result.boxes.length; i++) {
moveBox(result.boxes[i]); moveBox(result.boxes[i]);
}
} }
}
function moveBox(box) { function moveBox(box) {
var corner = box.length; var corner = box.length;
while (corner--) { while (corner--) {
box[corner][0] += xOffset; box[corner][0] += xOffset;
box[corner][1] += yOffset; box[corner][1] += yOffset;
}
} }
}
function moveLine(line) { function moveLine(line) {
line[0].x += xOffset; line[0].x += xOffset;
line[0].y += yOffset; line[0].y += yOffset;
line[1].x += xOffset; line[1].x += xOffset;
line[1].y += yOffset; 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;
}
}
function locateAndDecode() { boxes = getBoundingBoxes();
var result, if (boxes) {
boxes; result = _decoder.decodeFromBoundingBoxes(boxes);
result = result || {};
boxes = getBoundingBoxes(); result.boxes = boxes;
if (boxes) { publishResult(result, _inputImageWrapper.data);
result = _decoder.decodeFromBoundingBoxes(boxes); } else {
result = result || {}; publishResult();
result.boxes = boxes; }
publishResult(result, _inputImageWrapper.data);
} else {
publishResult();
} }
}
function update() { function update() {
var availableWorker; var availableWorker;
if (_onUIThread) { if (_onUIThread) {
if (_workerPool.length > 0) { if (_workerPool.length > 0) {
availableWorker = _workerPool.filter(function(workerThread) { availableWorker = _workerPool.filter(function (workerThread) {
return !workerThread.busy; return !workerThread.busy;
})[0]; })[0];
if (availableWorker) { if (availableWorker) {
_framegrabber.attachData(availableWorker.imageData); _framegrabber.attachData(availableWorker.imageData);
} else {
return; // all workers are busy
}
} else { } else {
return; // all workers are busy _framegrabber.attachData(_inputImageWrapper.data);
} }
} else { if (_framegrabber.grab()) {
_framegrabber.attachData(_inputImageWrapper.data); if (availableWorker) {
} availableWorker.busy = true;
if (_framegrabber.grab()) { availableWorker.worker.postMessage({
if (availableWorker) { cmd: 'process',
availableWorker.busy = true; imageData: availableWorker.imageData
availableWorker.worker.postMessage({ }, [availableWorker.imageData.buffer]);
cmd: 'process', } else {
imageData: availableWorker.imageData locateAndDecode();
}, [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()));
} }
}(performance.now()));
}
function start() { function start() {
if (_onUIThread && _config.inputStream.type === "LiveStream") { if (_onUIThread && _config.inputStream.type === "LiveStream") {
startContinuousUpdate(); startContinuousUpdate();
} else { } else {
update(); 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) { function ready() { // eslint-disable-line
/* eslint-disable no-undef*/ self.postMessage({'event': 'initialized', imageData: imageWrapper.data}, [imageWrapper.data.buffer]);
if (factory) {
var Quagga = factory().default;
if (!Quagga) {
self.postMessage({'event': 'error', message: 'Quagga could not be created'});
return;
}
}
var imageWrapper;
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) {
} if (_decoder) {
_decoder.setReaders(readers);
function setReaders(readers) { } else if (_onUIThread && _workerPool.length > 0) {
if (_decoder) { _workerPool.forEach(function (workerThread) {
_decoder.setReaders(readers); workerThread.worker.postMessage({cmd: 'setReaders', readers: readers});
} else if (_onUIThread && _workerPool.length > 0) { });
_workerPool.forEach(function(workerThread) { }
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