mirror of
https://github.com/serratus/quaggaJS.git
synced 2026-08-12 21:21:42 +08:00
Implemented applyConfig for ImageSource; Refactored ImageSource to fit into a class
This commit is contained in:
+33
-20
@@ -53,34 +53,47 @@ $(function() {
|
|||||||
$(".controls .reader-config-group").off("change", "input, select");
|
$(".controls .reader-config-group").off("change", "input, select");
|
||||||
$(".controls button").off("click");
|
$(".controls button").off("click");
|
||||||
},
|
},
|
||||||
|
detect: function() {
|
||||||
|
var scanner = this.scanner;
|
||||||
|
scanner.detect()
|
||||||
|
.then(function(result) {
|
||||||
|
console.log(result);
|
||||||
|
addToResults(scanner, result);
|
||||||
|
return result;
|
||||||
|
})
|
||||||
|
.catch(function(result) {
|
||||||
|
console.log('Not found', result);
|
||||||
|
return result;
|
||||||
|
})
|
||||||
|
.then(function(result) {
|
||||||
|
drawResult(scanner, result);
|
||||||
|
this.attachListeners();
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
decode: function(file) {
|
decode: function(file) {
|
||||||
this.detachListeners();
|
this.detachListeners();
|
||||||
var size = this.state.inputStream.size;
|
var size = this.state.inputStream.size;
|
||||||
console.log("decode...");
|
console.log("decode...");
|
||||||
|
|
||||||
Quagga.fromImage(file, {
|
if (!this.scanner) {
|
||||||
constraints: {width: size, height: size},
|
Quagga.fromImage({
|
||||||
locator: this.state.locator,
|
constraints: {src: file, width: size, height: size},
|
||||||
decoder: this.state.decoder,
|
locator: this.state.locator,
|
||||||
})
|
decoder: this.state.decoder,
|
||||||
.then(function(scanner) {
|
|
||||||
scanner.detect()
|
|
||||||
.then(function(result) {
|
|
||||||
console.log(result);
|
|
||||||
addToResults(scanner, result);
|
|
||||||
return result;
|
|
||||||
})
|
})
|
||||||
.catch(function(result) {
|
.then(function(scanner) {
|
||||||
console.log('Not found', result);
|
this.scanner = scanner;
|
||||||
return result;
|
this.detect();
|
||||||
})
|
|
||||||
.then(function(result) {
|
|
||||||
drawResult(scanner, result);
|
|
||||||
this.attachListeners();
|
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
}.bind(this));
|
} else {
|
||||||
|
this.scanner.applyConfig({
|
||||||
|
constraints: {src: file, width: size, height: size},
|
||||||
|
locator: this.state.locator,
|
||||||
|
decoder: this.state.decoder,
|
||||||
|
})
|
||||||
|
.then(this.detect.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
// Quagga.fromCamera(constraints)
|
|
||||||
// Quagga.fromSource();
|
// Quagga.fromSource();
|
||||||
// Quagga.fromPixelCapture();
|
// Quagga.fromPixelCapture();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -101,7 +101,8 @@ $(function() {
|
|||||||
|
|
||||||
console.log(JSON.stringify(this.state));
|
console.log(JSON.stringify(this.state));
|
||||||
|
|
||||||
this.scanner.applyConfig({
|
this.scanner
|
||||||
|
.applyConfig({
|
||||||
constraints: this.state.inputStream.constraints,
|
constraints: this.state.inputStream.constraints,
|
||||||
locator: this.state.locator,
|
locator: this.state.locator,
|
||||||
decoder: this.state.decoder,
|
decoder: this.state.decoder,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {determineOrientation} from '../common/device';
|
|||||||
import CameraAccess from './camera_access';
|
import CameraAccess from './camera_access';
|
||||||
import {getViewport} from '../common/utils';
|
import {getViewport} from '../common/utils';
|
||||||
import {generateSourceInterface} from './SourceInterface';
|
import {generateSourceInterface} from './SourceInterface';
|
||||||
import {Scope} from './input/SourceScope';
|
import {Scope} from './SourceScope';
|
||||||
|
|
||||||
const ConstraintPresets = [
|
const ConstraintPresets = [
|
||||||
{
|
{
|
||||||
|
|||||||
+88
-68
@@ -1,82 +1,102 @@
|
|||||||
import {findTagsInObjectURL} from './exif_helper';
|
import {findTagsInObjectURL} from './exif_helper';
|
||||||
import {generateSourceInterface} from './SourceInterface';
|
import {Source} from './SourceInterface';
|
||||||
|
|
||||||
export function fromImage(input, constraints = {width: 800, height: 800, channels: 3}) {
|
class ImageSource extends Source {
|
||||||
var $image = null;
|
constructor() {
|
||||||
var src = null;
|
super("IMAGE");
|
||||||
if (typeof input === 'string') {
|
this._$image = null;
|
||||||
// data or url, or queryString
|
this._src = null;
|
||||||
$image = new Image();
|
this.tags = null;
|
||||||
src = input;
|
this.colorChannels = 3;
|
||||||
} else if (input instanceof HTMLImageElement) {
|
|
||||||
$image = input;
|
|
||||||
} else if (input instanceof File) {
|
|
||||||
$image = new Image();
|
|
||||||
src = URL.createObjectURL(input);
|
|
||||||
} else {
|
|
||||||
return Promise.reject("fromImage needs a src, HTMLImageElement or File");
|
|
||||||
}
|
}
|
||||||
return new Promise(function(resolve, reject) {
|
|
||||||
if (src || !$image.complete) {
|
applyConstraints(newConstraints) {
|
||||||
console.log('Adding eventlistener');
|
this.constraints = newConstraints;
|
||||||
$image.addEventListener('load', function() {
|
this.colorChannels = this.constraints.channels || this.colorChannels;
|
||||||
resolve();
|
return this._applyInput(this.constraints.src)
|
||||||
}, false);
|
._loadResource()
|
||||||
$image.addEventListener('error', function(e) {
|
.then(() => findTagsInObjectURL(this._src, ['orientation']))
|
||||||
reject(e);
|
.then((tags) => {this.tags = tags;})
|
||||||
}, false);
|
.then(this._determineDimensions.bind(this))
|
||||||
if (src) {
|
.then(() => this);
|
||||||
console.log(`Setting src = ${src}`);
|
}
|
||||||
$image.src = src;
|
|
||||||
|
_loadResource() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (this._src || !this._$image.complete) {
|
||||||
|
this._$image.addEventListener('load', resolve, false);
|
||||||
|
this._$image.addEventListener('error', reject, false);
|
||||||
|
if (this._src) {
|
||||||
|
console.log(`Setting src = ${this._src}`);
|
||||||
|
this._$image.src = this._src;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return resolve();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_applyInput(input) {
|
||||||
|
if (typeof input === 'string') {
|
||||||
|
// data or url, or queryString
|
||||||
|
this._$image = new Image();
|
||||||
|
this._src = input;
|
||||||
|
} else if (input instanceof HTMLImageElement) {
|
||||||
|
this._$image = input;
|
||||||
|
} else if (input instanceof File) {
|
||||||
|
this._$image = new Image();
|
||||||
|
this._src = URL.createObjectURL(input);
|
||||||
} else {
|
} else {
|
||||||
return resolve();
|
throw new Error("fromImage needs a src, HTMLImageElement or File");
|
||||||
}
|
}
|
||||||
})
|
return this;
|
||||||
.then(() => findTagsInObjectURL(src, ['orientation']))
|
}
|
||||||
.then((tags) => {
|
|
||||||
let width = $image.naturalWidth;
|
_determineDimensions() {
|
||||||
let height = $image.naturalHeight;
|
let width = this._$image.naturalWidth;
|
||||||
if (tags && tags.orientation) {
|
let height = this._$image.naturalHeight;
|
||||||
switch (tags.orientation) {
|
let desiredWidth = this.constraints.width;
|
||||||
|
if (this.tags && this.tags.orientation) {
|
||||||
|
switch (this.tags.orientation) {
|
||||||
case 6:
|
case 6:
|
||||||
case 8:
|
case 8:
|
||||||
width = $image.naturalHeight;
|
width = this._$image.naturalHeight;
|
||||||
height = $image.naturalWidth;
|
height = this._$image.naturalWidth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const imageAR = width / height;
|
|
||||||
const calculatedWidth = imageAR > 1 ? constraints.width : Math.floor((imageAR) * constraints.width);
|
|
||||||
const calculatedHeight = imageAR > 1 ? Math.floor((1 / imageAR) * constraints.width) : constraints.width;
|
|
||||||
const colorChannels = constraints.channels || 3;
|
|
||||||
|
|
||||||
return Object.assign(generateSourceInterface(), {
|
const imageAR = width / height;
|
||||||
type: "IMAGE",
|
const calculatedWidth = imageAR > 1 ? desiredWidth : Math.floor((imageAR) * desiredWidth);
|
||||||
colorChannels,
|
const calculatedHeight = imageAR > 1 ? Math.floor((1 / imageAR) * desiredWidth) : desiredWidth;
|
||||||
tags,
|
|
||||||
getDimensions() {
|
this._dimensions = {
|
||||||
return {
|
viewport: {
|
||||||
viewport: {
|
width, // AR
|
||||||
width: $image.naturalWidth, // AR
|
height, // AR
|
||||||
height: $image.naturalHeight, // AR
|
x: 0, // AR
|
||||||
x: 0, // AR
|
y: 0, // AR
|
||||||
y: 0, // AR
|
|
||||||
},
|
|
||||||
canvas: {
|
|
||||||
width: calculatedWidth, // AR
|
|
||||||
height: calculatedHeight, // AR
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
getDrawable: function() {
|
canvas: {
|
||||||
return $image;
|
width: calculatedWidth, // AR
|
||||||
|
height: calculatedHeight, // AR
|
||||||
},
|
},
|
||||||
getLabel: function() {
|
};
|
||||||
return $image.src;
|
}
|
||||||
},
|
|
||||||
getConstraints: function() {
|
getDimensions() {
|
||||||
return constraints;
|
return this._dimensions;
|
||||||
},
|
}
|
||||||
});
|
|
||||||
});
|
getDrawable() {
|
||||||
|
return this._$image;
|
||||||
|
}
|
||||||
|
|
||||||
|
getLabel() {
|
||||||
|
return this._$image.src;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fromImage(constraints = {width: 800, height: 800, channels: 3}) {
|
||||||
|
const imageSource = new ImageSource();
|
||||||
|
return imageSource.applyConstraints(constraints);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ export function fromSource(source, {target = "#interactive.viewport"} = {}) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
grabFrameData: function grabFrameData({clipping} = {}) {
|
grabFrameData: function grabFrameData({clipping} = {}) {
|
||||||
|
const frame = source.getDrawable();
|
||||||
const {viewport, canvas: canvasSize} = source.getDimensions();
|
const {viewport, canvas: canvasSize} = source.getDimensions();
|
||||||
const sx = viewport.x;
|
const sx = viewport.x;
|
||||||
const sy = viewport.y;
|
const sy = viewport.y;
|
||||||
@@ -121,12 +122,12 @@ export function fromSource(source, {target = "#interactive.viewport"} = {}) {
|
|||||||
return sleep(100).then(grabFrameData);
|
return sleep(100).then(grabFrameData);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(drawable instanceof HTMLCanvasElement)) {
|
if (!(frame instanceof HTMLCanvasElement)) {
|
||||||
drawImage(
|
drawImage(
|
||||||
canvasSize,
|
canvasSize,
|
||||||
ctx,
|
ctx,
|
||||||
source,
|
source,
|
||||||
drawable,
|
frame,
|
||||||
sx,
|
sx,
|
||||||
sy,
|
sy,
|
||||||
sWidth,
|
sWidth,
|
||||||
|
|||||||
@@ -1,24 +1,22 @@
|
|||||||
const viewport = {
|
class Source {
|
||||||
x: 0,
|
constructor(type) {
|
||||||
y: 0,
|
this.type = type;
|
||||||
width: 0,
|
}
|
||||||
height: 0,
|
getDimensions() {}
|
||||||
};
|
getConstraints() {}
|
||||||
|
getDrawable() {}
|
||||||
|
applyConstraints() {}
|
||||||
|
getLabel() {}
|
||||||
|
stop() {}
|
||||||
|
getScope() {}
|
||||||
|
}
|
||||||
|
|
||||||
const canvas = {
|
export {Source};
|
||||||
height: 0,
|
|
||||||
width: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
export function generateSourceInterface() {
|
export function generateSourceInterface() {
|
||||||
return {
|
return {
|
||||||
type: "INTERFACE",
|
type: "INTERFACE",
|
||||||
getDimensions() {
|
getDimensions() {},
|
||||||
return {
|
|
||||||
viewport,
|
|
||||||
canvas,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
getConstraints() {},
|
getConstraints() {},
|
||||||
getDrawable() {},
|
getDrawable() {},
|
||||||
applyConstraints() {},
|
applyConstraints() {},
|
||||||
@@ -26,4 +24,4 @@ export function generateSourceInterface() {
|
|||||||
stop() {},
|
stop() {},
|
||||||
getScope() {},
|
getScope() {},
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
|
|||||||
+22
-21
@@ -43,17 +43,11 @@ function fromConfig(pixelCapturer, config) {
|
|||||||
scanner.start();
|
scanner.start();
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
}
|
}
|
||||||
pendingStart = new Promise((resolve, reject) => {
|
pendingStart = scanner.init(currentConfig)
|
||||||
scanner.init(currentConfig, (error) => {
|
.then(() => {
|
||||||
if (error) {
|
initialized = true;
|
||||||
console.log(error);
|
scanner.start();
|
||||||
reject(error);
|
pendingStart = null;
|
||||||
}
|
|
||||||
initialized = true;
|
|
||||||
scanner.start();
|
|
||||||
resolve();
|
|
||||||
pendingStart = null;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
return pendingStart;
|
return pendingStart;
|
||||||
},
|
},
|
||||||
@@ -88,14 +82,14 @@ function fromConfig(pixelCapturer, config) {
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return new Promise((resolve, reject) => {
|
let pendingDecodeSingle = Promise.resolve();
|
||||||
scanner.decodeSingle(currentConfig, (result) => {
|
if (!initialized) {
|
||||||
if (result && result.codeResult && result.codeResult.code) {
|
pendingDecodeSingle = pendingDecodeSingle
|
||||||
return resolve(result);
|
.then(scanner.init.bind(scanner, currentConfig))
|
||||||
}
|
.then(() => {initialized = true;});
|
||||||
return reject(result);
|
}
|
||||||
});
|
return pendingDecodeSingle
|
||||||
});
|
.then(scanner.decodeSingle.bind(scanner));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
registerResultCollector(resultCollector) {
|
registerResultCollector(resultCollector) {
|
||||||
@@ -106,6 +100,7 @@ function fromConfig(pixelCapturer, config) {
|
|||||||
},
|
},
|
||||||
applyConfig(newConfig) {
|
applyConfig(newConfig) {
|
||||||
const normalizedConfig = merge({}, Config, currentConfig, newConfig);
|
const normalizedConfig = merge({}, Config, currentConfig, newConfig);
|
||||||
|
const wasRunning = scanner.isRunning();
|
||||||
let promise = Promise.resolve();
|
let promise = Promise.resolve();
|
||||||
if (hasConfigChanged(currentConfig, normalizedConfig, "constraints")) {
|
if (hasConfigChanged(currentConfig, normalizedConfig, "constraints")) {
|
||||||
console.log("constraints changed!", currentConfig.constraints, normalizedConfig.constraints);
|
console.log("constraints changed!", currentConfig.constraints, normalizedConfig.constraints);
|
||||||
@@ -117,6 +112,9 @@ function fromConfig(pixelCapturer, config) {
|
|||||||
if (hasConfigChanged(currentConfig, normalizedConfig)) {
|
if (hasConfigChanged(currentConfig, normalizedConfig)) {
|
||||||
console.log("config changed!");
|
console.log("config changed!");
|
||||||
promise = promise.then(() => scanner.applyConfig(normalizedConfig));
|
promise = promise.then(() => scanner.applyConfig(normalizedConfig));
|
||||||
|
if (wasRunning) {
|
||||||
|
promise = promise.then(scanner.start.bind(scanner));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
currentConfig = normalizedConfig;
|
currentConfig = normalizedConfig;
|
||||||
return promise;
|
return promise;
|
||||||
@@ -134,10 +132,13 @@ function fromSource(config, source) {
|
|||||||
|
|
||||||
function createApi() {
|
function createApi() {
|
||||||
return {
|
return {
|
||||||
fromImage(image, options) {
|
fromImage(options) {
|
||||||
const config = merge({}, Config, options);
|
const config = merge({}, Config, options);
|
||||||
return Source
|
return Source
|
||||||
.fromImage(image, config.constraints)
|
.fromImage(config.constraints, {
|
||||||
|
target: config.target,
|
||||||
|
scope: Source.Scope.INTERNAL,
|
||||||
|
})
|
||||||
.then(fromSource.bind(null, config));
|
.then(fromSource.bind(null, config));
|
||||||
},
|
},
|
||||||
fromCamera(options) {
|
fromCamera(options) {
|
||||||
|
|||||||
+13
-11
@@ -346,7 +346,7 @@ function createScanner(pixelCapturer) {
|
|||||||
x: e.data.size.x,
|
x: e.data.size.x,
|
||||||
y: e.data.size.y
|
y: e.data.size.y
|
||||||
}, new Uint8Array(e.data.imageData));
|
}, new Uint8Array(e.data.imageData));
|
||||||
scanner.init(config, ready, imageWrapper);
|
scanner.init(config, imageWrapper).then(ready);
|
||||||
scanner.subscribe("processed", onProcessed);
|
scanner.subscribe("processed", onProcessed);
|
||||||
} else if (e.data.cmd === 'process') {
|
} else if (e.data.cmd === 'process') {
|
||||||
imageWrapper.data = new Uint8Array(e.data.imageData);
|
imageWrapper.data = new Uint8Array(e.data.imageData);
|
||||||
@@ -417,15 +417,17 @@ function createScanner(pixelCapturer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
init: function(config, cb, imageWrapper) {
|
init: function(config, imageWrapper) {
|
||||||
|
_stopped = true;
|
||||||
_config = merge({}, Config, config);
|
_config = merge({}, Config, config);
|
||||||
|
|
||||||
if (imageWrapper) {
|
if (imageWrapper) {
|
||||||
_onUIThread = false;
|
_onUIThread = false;
|
||||||
initBuffers(imageWrapper);
|
initBuffers(imageWrapper);
|
||||||
return cb();
|
return Promise.resolve();
|
||||||
} else {
|
} else {
|
||||||
return setup(_config).then(cb);
|
adjustWorkerPool(0);
|
||||||
|
return setup(_config);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
start: function() {
|
start: function() {
|
||||||
@@ -443,10 +445,7 @@ function createScanner(pixelCapturer) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
applyConfig(newConfig) {
|
applyConfig(newConfig) {
|
||||||
_stopped = true;
|
return this.init(newConfig);
|
||||||
adjustWorkerPool(0);
|
|
||||||
_config = merge({}, Config, _config, newConfig);
|
|
||||||
return setup(_config).then(start);
|
|
||||||
},
|
},
|
||||||
pause: function() {
|
pause: function() {
|
||||||
_stopped = true;
|
_stopped = true;
|
||||||
@@ -462,11 +461,14 @@ function createScanner(pixelCapturer) {
|
|||||||
_resultCollector = resultCollector;
|
_resultCollector = resultCollector;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
decodeSingle: function(config, resultCallback) {
|
decodeSingle() {
|
||||||
this.init(config, () => {
|
return new Promise((resolve, reject) => {
|
||||||
_events.once("processed", (result) => {
|
_events.once("processed", (result) => {
|
||||||
this.stop();
|
this.stop();
|
||||||
resultCallback.call(null, result);
|
if (result && result.codeResult && result.codeResult.code) {
|
||||||
|
return resolve(result);
|
||||||
|
}
|
||||||
|
return reject(result);
|
||||||
}, true);
|
}, true);
|
||||||
start();
|
start();
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user