File-Input working with Source & PixelCaputure
parent
5173ffc8fd
commit
242c275571
@ -0,0 +1,23 @@
|
||||
export const PORTRAIT = "portrait";
|
||||
export const LANDSCAPE = "landscape";
|
||||
|
||||
const matchingScreens = {
|
||||
[PORTRAIT]: /portrait/i,
|
||||
[LANDSCAPE]: /landscape/i,
|
||||
};
|
||||
|
||||
export function determineOrientation() {
|
||||
var orientationType = screen.msOrientation || screen.mozOrientation;
|
||||
if (typeof orientationType !== 'string') {
|
||||
orientationType = screen.orientation;
|
||||
if (typeof orientationType === 'object' && orientationType.type) {
|
||||
orientationType = orientationType.type;
|
||||
}
|
||||
}
|
||||
if (orientationType) {
|
||||
return Object.keys(matchingScreens)
|
||||
.filter(orientation => matchingScreens[orientation].test(orientationType))[0];
|
||||
}
|
||||
console.log(`Failed to determine orientation, defaults to ${PORTRAIT}`);
|
||||
return PORTRAIT;
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
|
||||
export function sleep(millis) {
|
||||
return new Promise(function(resolve) {
|
||||
window.setTimeout(resolve, millis);
|
||||
});
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
import {
|
||||
computeGray
|
||||
} from '../common/cv_utils';
|
||||
import {sleep} from '../common/utils';
|
||||
|
||||
function adjustCanvasSize(input, canvas) {
|
||||
if (input instanceof HTMLVideoElement) {
|
||||
if (canvas.height !== input.videoHeight || canvas.width !== input.videoWidth) {
|
||||
console.log('adjusting canvas size', input.videoHeight, input.videoWidth);
|
||||
canvas.height = input.videoHeight;
|
||||
canvas.width = input.videoWidth;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} else if (typeof input.width !== 'undefined') {
|
||||
if (canvas.height !== input.height || canvas.width !== input.width) {
|
||||
console.log('adjusting canvas size', input.height, input.width);
|
||||
canvas.height = input.height;
|
||||
canvas.width = input.width;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
throw new Error('Not a video element!');
|
||||
}
|
||||
}
|
||||
|
||||
function getViewPort(target) {
|
||||
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 getOrCreateCanvas(source, target) {
|
||||
const $viewport = getViewPort(target);
|
||||
let $canvas = $viewport.querySelector("canvas.imgBuffer");
|
||||
if (!$canvas) {
|
||||
$canvas = document.createElement("canvas");
|
||||
$canvas.className = "imgBuffer";
|
||||
if ($viewport && source.type === "IMAGE") {
|
||||
$viewport.appendChild($canvas);
|
||||
}
|
||||
}
|
||||
return $canvas;
|
||||
}
|
||||
|
||||
export function fromSource(source, {target = "#interactive.viewport"} = {}) {
|
||||
var drawable = source.getDrawable();
|
||||
var $canvas = null;
|
||||
var ctx = null;
|
||||
var bytePool = [];
|
||||
|
||||
if (drawable instanceof HTMLVideoElement
|
||||
|| drawable instanceof HTMLImageElement) {
|
||||
$canvas = getOrCreateCanvas(source, target);
|
||||
ctx = $canvas.getContext('2d');
|
||||
}
|
||||
|
||||
if (drawable instanceof HTMLCanvasElement) {
|
||||
$canvas = drawable;
|
||||
ctx = drawable.getContext('2d');
|
||||
}
|
||||
|
||||
function nextAvailableBuffer() {
|
||||
var i;
|
||||
var buffer;
|
||||
var bytesRequired = ($canvas.height * $canvas.width);
|
||||
for (i = 0; i < bytePool.length; i++) {
|
||||
buffer = bytePool[i];
|
||||
if (buffer && buffer.buffer.byteLength === bytesRequired) {
|
||||
return bytePool[i];
|
||||
}
|
||||
}
|
||||
buffer = new Uint8Array(bytesRequired);
|
||||
bytePool.push(buffer);
|
||||
console.log("Added new entry to bufferPool", bytesRequired);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
return {
|
||||
grabFrameData: function grabFrameData() {
|
||||
const {viewport, canvas: canvasSize} = source.getDimensions();
|
||||
const sx = viewport.x;
|
||||
const sy = viewport.y;
|
||||
const sWidth = viewport.width;
|
||||
const sHeight = viewport.height;
|
||||
const dx = 0;
|
||||
const dy = 0;
|
||||
const dWidth = canvasSize.width;
|
||||
const dHeight = canvasSize.height;
|
||||
|
||||
adjustCanvasSize(canvasSize, $canvas);
|
||||
if ($canvas.height < 10 || $canvas.width < 10) {
|
||||
console.log('$canvas not initialized. Waiting 100ms and then continuing');
|
||||
return sleep(100).then(grabFrameData);
|
||||
}
|
||||
if (!(drawable instanceof HTMLCanvasElement)) {
|
||||
ctx.drawImage(drawable, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
|
||||
}
|
||||
var imageData = ctx.getImageData(0, 0, $canvas.width, $canvas.height).data;
|
||||
var buffer = nextAvailableBuffer();
|
||||
computeGray(imageData, buffer);
|
||||
return Promise.resolve({
|
||||
width: $canvas.width,
|
||||
height: $canvas.height,
|
||||
data: buffer,
|
||||
});
|
||||
},
|
||||
getSource: function() {
|
||||
return source;
|
||||
},
|
||||
getCanvas: function() {
|
||||
return $canvas;
|
||||
},
|
||||
};
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
import {determineOrientation, PORTRAIT} from '../common/device';
|
||||
import CameraAccess from './camera_access';
|
||||
|
||||
export function fromCamera(constraints) {
|
||||
if (!constraints) {
|
||||
constraints = {width: {ideal: 540}, height: {ideal: 540}, aspectRatio: {ideal: 1}, facingMode: 'environment'};
|
||||
}
|
||||
var orientation = determineOrientation();
|
||||
var videoConstraints = constraints;
|
||||
if (orientation === PORTRAIT) {
|
||||
constraints = Object.assign({}, constraints, {
|
||||
width: constraints.height,
|
||||
height: constraints.width,
|
||||
});
|
||||
}
|
||||
|
||||
const video = document.querySelector('video');
|
||||
CameraAccess.request(videoConstraints, video)
|
||||
.then(function(mediastream) {
|
||||
const track = mediastream.getVideoTracks()[0];
|
||||
return {
|
||||
type: "CAMERA",
|
||||
getDimensions() {
|
||||
const viewport = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: video.videoWidth,
|
||||
height: video.videoHeight,
|
||||
};
|
||||
|
||||
if (constraints.zoom && constraints.zoom.exact > 1) {
|
||||
const zoom = constraints.zoom.exact;
|
||||
viewport.width = Math.floor(video.videoWidth / zoom);
|
||||
viewport.height = Math.floor(video.videoHeight / zoom);
|
||||
viewport.x = Math.floor((video.videoWidth - viewport.width) / 2);
|
||||
viewport.y = Math.floor((video.videoHeight - viewport.height) / 2);
|
||||
}
|
||||
|
||||
return {
|
||||
viewport,
|
||||
canvas: {
|
||||
width: constraints.width, // AR
|
||||
height: constraints.height, // AR
|
||||
},
|
||||
};
|
||||
},
|
||||
getConstraints: function() {
|
||||
return videoConstraints;
|
||||
},
|
||||
getDrawable: function() {
|
||||
return video;
|
||||
},
|
||||
applyConstraints: function(constraints) {
|
||||
track.stop();
|
||||
videoConstraints = Object.assign({}, constraints);
|
||||
if (determineOrientation() === PORTRAIT) {
|
||||
constraints = Object.assign({}, constraints, {
|
||||
width: constraints.height,
|
||||
height: constraints.width,
|
||||
});
|
||||
}
|
||||
console.log(videoConstraints, constraints);
|
||||
if (constraints.zoom && constraints.zoom.exact > 1) {
|
||||
constraints.width.ideal = Math.floor(constraints.width.ideal * constraints.zoom.exact);
|
||||
constraints.height.ideal = Math.floor(constraints.height.ideal * constraints.zoom.exact);
|
||||
delete constraints.zoom;
|
||||
}
|
||||
return CameraAccess.request(videoConstraints, video);
|
||||
},
|
||||
getLabel: function() {
|
||||
return track.label;
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function fromCanvas(input) {
|
||||
var $canvas = null;
|
||||
if (typeof input === 'string') {
|
||||
$canvas = document.querySelector(input);
|
||||
} else if (input instanceof HTMLCanvasElement) {
|
||||
$canvas = input;
|
||||
} else {
|
||||
return Promise.reject("fromCanvas needs a selector or HTMLCanvasElement");
|
||||
}
|
||||
|
||||
return Promise.resolve({
|
||||
type: "CANVAS",
|
||||
getWidth: function() {
|
||||
return $canvas.width;
|
||||
},
|
||||
getHeight: function() {
|
||||
return $canvas.height;
|
||||
},
|
||||
getDrawable: function() {
|
||||
return $canvas;
|
||||
},
|
||||
getLabel: function() {
|
||||
return $canvas.getAttribute('id');
|
||||
},
|
||||
getConstraints: function() {
|
||||
return {};
|
||||
},
|
||||
applyConstraints: function() {
|
||||
console.log('CanvasSource.applyConstraints not implemented');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function fromImage(input, constraints = {width: 800, height: 800}) {
|
||||
var $image = null;
|
||||
var src = null;
|
||||
if (typeof input === 'string') {
|
||||
// data or url, or queryString
|
||||
$image = new Image();
|
||||
src = input;
|
||||
} 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) {
|
||||
console.log('Adding eventlistener');
|
||||
$image.addEventListener('load', function() {
|
||||
resolve();
|
||||
}, false);
|
||||
$image.addEventListener('error', function(e) {
|
||||
reject(e);
|
||||
}, false);
|
||||
if (src) {
|
||||
console.log(`Setting src = ${src}`);
|
||||
$image.src = src;
|
||||
}
|
||||
} else {
|
||||
return resolve();
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
const width = $image.naturalWidth;
|
||||
const height = $image.naturalHeight;
|
||||
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;
|
||||
|
||||
return {
|
||||
type: "IMAGE",
|
||||
getDimensions() {
|
||||
return {
|
||||
viewport: {
|
||||
width: $image.naturalWidth, // AR
|
||||
height: $image.naturalHeight, // AR
|
||||
x: 0, // AR
|
||||
y: 0, // AR
|
||||
},
|
||||
canvas: {
|
||||
width: calculatedWidth, // AR
|
||||
height: calculatedHeight, // AR
|
||||
},
|
||||
};
|
||||
},
|
||||
getDrawable: function() {
|
||||
return $image;
|
||||
},
|
||||
getLabel: function() {
|
||||
return $image.src;
|
||||
},
|
||||
getConstraints: function() {
|
||||
return constraints;
|
||||
},
|
||||
applyConstraints: function() {
|
||||
console.log('ImageSource.applyConstraints not implemented');
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue