Added orientation-dependent constraints; extended constrain-matching;

feature/image-source
Christoph Oberhofer 8 years ago
parent 22f48ea541
commit afcaa580b1

@ -146,12 +146,21 @@ $(function() {
inputStream: {
type : "LiveStream",
constraints: {
width: {ideal: 480},
height: {ideal: 480},
zoom: {exact: 2},
width: {ideal: 800},
height: {ideal: 800},
facingMode: "environment",
landscape: {
width: {ideal: 640},
height: {ideal: 480},
zoom: 1.5,
},
portrait: {
width: {ideal: 640},
height: {ideal: 640},
zoom: 1.5,
aspectRatio: 1,
}
}
},
locator: {
patchSize: "medium",

@ -1,5 +1,6 @@
export const PORTRAIT = "portrait";
export const LANDSCAPE = "landscape";
export const SQUARE = "square";
const matchingScreens = {
[PORTRAIT]: /portrait/i,

@ -1,8 +1,81 @@
import {clone} from 'lodash';
import {determineOrientation, PORTRAIT} from '../common/device';
import {determineOrientation, PORTRAIT, LANDSCAPE, SQUARE} from '../common/device';
import CameraAccess from './camera_access';
import {getViewport} from '../common/utils';
const ConstraintPresets = [
{
width: 720,
height: 1280,
}, {
width: 540,
height: 960,
}, {
width: 600,
height: 800,
}, {
width: 480,
height: 640,
}, {
width: 1280,
height: 720,
}, {
width: 960,
height: 540,
}, {
width: 800,
height: 600,
}, {
width: 640,
height: 480,
}, {
width: 1280,
height: 1280,
}, {
width: 1080,
height: 1080,
}, {
width: 960,
height: 960,
}, {
width: 800,
height: 800,
}, {
width: 640,
height: 640,
},
].map((preset) => Object.assign({}, preset, {aspectRatio: preset.width / preset.height}));
function getFilter(aspectRatio) {
if (aspectRatio === 1) {
return pre => pre.aspectRatio === aspectRatio;
} else if (aspectRatio > 1) {
return pre => pre.aspectRatio > 1;
}
return pre => pre.aspectRatio < 1;
}
function resolveMinWidthToAdvanced({aspectRatio, minPixels}) {
return [...ConstraintPresets]
.filter(getFilter(aspectRatio))
.map((pre) => {
return {
error: Math.abs((pre.width * pre.height) - minPixels),
pre,
};
})
.sort(({error: errorA}, {error: errorB}) => {
if (errorB > errorA) {
return -1;
}
if (errorB < errorA) {
return 1;
}
return 0;
})
.map(({pre}) => pre);
}
function getOrCreateVideo(source, target) {
const $viewport = getViewport(target);
if ($viewport) {
@ -16,21 +89,70 @@ function getOrCreateVideo(source, target) {
return document.createElement("video");
}
export function fromCamera(constraints) {
var orientation = determineOrientation();
var videoConstraints = clone(constraints);
if (orientation === PORTRAIT) {
videoConstraints = Object.assign({}, videoConstraints, {
width: videoConstraints.height,
height: videoConstraints.width,
});
function constraintToNumber(constraint) {
if (!constraint) {
return null;
}
if (typeof constraint === 'number') {
return constraint;
}
const {ideal, exact, min, max} = constraint;
if (typeof exact !== 'undefined') {
return exact;
}
if (typeof ideal !== 'undefined') {
return ideal;
}
if (typeof min !== 'undefined') {
return min;
}
if (typeof max !== 'undefined') {
return max;
}
return null;
}
function adjustWithZoom(videoConstraints) {
const constraints = clone(videoConstraints);
const orientation = determineOrientation();
let zoom = constraintToNumber(constraints.zoom) || 1,
width = constraintToNumber(constraints.width),
height = constraintToNumber(constraints.height),
aspectRatio = constraintToNumber(constraints.aspectRatio) || (width / height);
if (constraints[orientation]) {
zoom = constraintToNumber(constraints[orientation].zoom) || zoom;
width = constraintToNumber(constraints[orientation].width) || width;
height = constraintToNumber(constraints[orientation].height) || height;
aspectRatio = constraintToNumber(constraints[orientation].aspectRatio) || (width / height);
}
if (zoom > 1) {
width = Math.floor(width * zoom);
height = Math.floor(height * zoom);
}
delete constraints.zoom;
delete constraints.orientation;
delete constraints.landscape;
delete constraints.portrait;
if (videoConstraints.zoom && videoConstraints.zoom.exact > 1) {
videoConstraints.width.ideal = Math.floor(videoConstraints.width.ideal * videoConstraints.zoom.exact);
videoConstraints.height.ideal = Math.floor(videoConstraints.height.ideal * videoConstraints.zoom.exact);
delete videoConstraints.zoom;
const advanced = resolveMinWidthToAdvanced({minPixels: (width * height), aspectRatio});
return {
zoom,
video: Object.assign({}, constraints, {
width: {ideal: advanced[0].width},
height: {ideal: advanced[0].height},
aspectRatio: {exact: advanced[0].aspectRatio || aspectRatio},
advanced,
}),
};
}
export function fromCamera(constraints) {
var {video: videoConstraints, zoom} = adjustWithZoom(constraints);
console.log(videoConstraints);
const video = getOrCreateVideo();
@ -46,9 +168,7 @@ export function fromCamera(constraints) {
width: video.videoWidth,
height: video.videoHeight,
};
if (constraints.zoom && constraints.zoom.exact > 1) {
const zoom = constraints.zoom.exact;
if (zoom > 1) {
viewport.width = Math.floor(video.videoWidth / zoom);
viewport.height = Math.floor(video.videoHeight / zoom);
viewport.x = Math.floor((video.videoWidth - viewport.width) / 2);

@ -8,6 +8,7 @@ import {merge} from 'lodash';
import CameraAccess from './input/camera_access';
import * as PixelCapture from './input/PixelCapture';
import * as Source from './input/Source';
import {PORTRAIT, LANDSCAPE, SQUARE} from './common/device';
function fromConfig(pixelCapturer, config) {
const scanner = createScanner(pixelCapturer);
@ -162,6 +163,11 @@ function createApi() {
ResultCollector,
_worker: {
createScanner
},
Orientation: {
PORTRAIT,
LANDSCAPE,
SQUARE,
}
};
}

Loading…
Cancel
Save