mirror of
https://github.com/serratus/quaggaJS.git
synced 2026-08-13 13:51:37 +08:00
Moved files into meaningful folders
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
const merge = require('lodash/object/merge');
|
||||
|
||||
var streamRef,
|
||||
loadedDataHandler;
|
||||
|
||||
/**
|
||||
* Wraps browser-specific getUserMedia
|
||||
* @param {Object} constraints
|
||||
* @param {Object} success Callback
|
||||
* @param {Object} failure Callback
|
||||
*/
|
||||
function getUserMedia(constraints, success, failure) {
|
||||
if (typeof navigator.getUserMedia !== 'undefined') {
|
||||
navigator.getUserMedia(constraints, function (stream) {
|
||||
streamRef = stream;
|
||||
var videoSrc = (window.URL && window.URL.createObjectURL(stream)) || stream;
|
||||
success.apply(null, [videoSrc]);
|
||||
}, failure);
|
||||
} else {
|
||||
failure(new TypeError("getUserMedia not available"));
|
||||
}
|
||||
}
|
||||
|
||||
function loadedData(video, callback) {
|
||||
var attempts = 10;
|
||||
|
||||
function checkVideo() {
|
||||
if (attempts > 0) {
|
||||
if (video.videoWidth > 0 && video.videoHeight > 0) {
|
||||
console.log(video.videoWidth + "px x " + video.videoHeight + "px");
|
||||
callback();
|
||||
} else {
|
||||
window.setTimeout(checkVideo, 500);
|
||||
}
|
||||
} else {
|
||||
callback('Unable to play video stream. Is webcam working?');
|
||||
}
|
||||
attempts--;
|
||||
}
|
||||
checkVideo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to attach the camera-stream to a given video-element
|
||||
* and calls the callback function when the content is ready
|
||||
* @param {Object} constraints
|
||||
* @param {Object} video
|
||||
* @param {Object} callback
|
||||
*/
|
||||
function initCamera(constraints, video, callback) {
|
||||
getUserMedia(constraints, function(src) {
|
||||
video.src = src;
|
||||
if (loadedDataHandler) {
|
||||
video.removeEventListener("loadeddata", loadedDataHandler, false);
|
||||
}
|
||||
loadedDataHandler = loadedData.bind(null, video, callback);
|
||||
video.addEventListener('loadeddata', loadedDataHandler, false);
|
||||
video.play();
|
||||
}, function(e) {
|
||||
callback(e);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the incoming constraints to satisfy the current browser
|
||||
* @param config
|
||||
* @param cb Callback which is called whenever constraints are created
|
||||
* @returns {*}
|
||||
*/
|
||||
function normalizeConstraints(config, cb) {
|
||||
var constraints = {
|
||||
audio: false,
|
||||
video: true
|
||||
},
|
||||
videoConstraints = merge({
|
||||
width: 640,
|
||||
height: 480,
|
||||
minAspectRatio: 0,
|
||||
maxAspectRatio: 100,
|
||||
facing: "environment"
|
||||
}, config);
|
||||
|
||||
if ( typeof MediaStreamTrack !== 'undefined' && typeof MediaStreamTrack.getSources !== 'undefined') {
|
||||
MediaStreamTrack.getSources(function(sourceInfos) {
|
||||
var videoSourceId;
|
||||
for (var i = 0; i < sourceInfos.length; ++i) {
|
||||
var sourceInfo = sourceInfos[i];
|
||||
if (sourceInfo.kind === "video" && sourceInfo.facing === videoConstraints.facing) {
|
||||
videoSourceId = sourceInfo.id;
|
||||
}
|
||||
}
|
||||
constraints.video = {
|
||||
mandatory: {
|
||||
minWidth: videoConstraints.width,
|
||||
minHeight: videoConstraints.height,
|
||||
minAspectRatio: videoConstraints.minAspectRatio,
|
||||
maxAspectRatio: videoConstraints.maxAspectRatio
|
||||
},
|
||||
optional: [{
|
||||
sourceId: videoSourceId
|
||||
}]
|
||||
};
|
||||
return cb(constraints);
|
||||
});
|
||||
} else {
|
||||
constraints.video = {
|
||||
mediaSource: "camera",
|
||||
width: { min: videoConstraints.width, max: videoConstraints.width },
|
||||
height: { min: videoConstraints.height, max: videoConstraints.height },
|
||||
require: ["width", "height"]
|
||||
};
|
||||
return cb(constraints);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the back-facing camera of the user. The callback is called
|
||||
* whenever the stream is ready to be consumed, or if an error occures.
|
||||
* @param {Object} video
|
||||
* @param {Object} callback
|
||||
*/
|
||||
function request(video, videoConstraints, callback) {
|
||||
normalizeConstraints(videoConstraints, function(constraints) {
|
||||
initCamera(constraints, video, callback);
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
request: function(video, constraints, callback) {
|
||||
request(video, constraints, callback);
|
||||
},
|
||||
release: function() {
|
||||
var tracks = streamRef && streamRef.getVideoTracks();
|
||||
if (tracks.length) {
|
||||
tracks[0].stop();
|
||||
}
|
||||
streamRef = null;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,73 @@
|
||||
import CVUtils from '../common/cv_utils';
|
||||
|
||||
var FrameGrabber = {};
|
||||
|
||||
FrameGrabber.create = function(inputStream, canvas) {
|
||||
var _that = {},
|
||||
_streamConfig = inputStream.getConfig(),
|
||||
_video_size = CVUtils.imageRef(inputStream.getRealWidth(), inputStream.getRealHeight()),
|
||||
_canvasSize = inputStream.getCanvasSize(),
|
||||
_size = CVUtils.imageRef(inputStream.getWidth(), inputStream.getHeight()),
|
||||
topRight = inputStream.getTopRight(),
|
||||
_sx = topRight.x,
|
||||
_sy = topRight.y,
|
||||
_canvas,
|
||||
_ctx = null,
|
||||
_data = null;
|
||||
|
||||
_canvas = canvas ? canvas : document.createElement("canvas");
|
||||
_canvas.width = _canvasSize.x;
|
||||
_canvas.height = _canvasSize.y;
|
||||
_ctx = _canvas.getContext("2d");
|
||||
_data = new Uint8Array(_size.x * _size.y);
|
||||
console.log("FrameGrabber", JSON.stringify({
|
||||
size: _size,
|
||||
topRight: topRight,
|
||||
videoSize: _video_size,
|
||||
canvasSize: _canvasSize
|
||||
}));
|
||||
|
||||
/**
|
||||
* Uses the given array as frame-buffer
|
||||
*/
|
||||
_that.attachData = function(data) {
|
||||
_data = data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the used frame-buffer
|
||||
*/
|
||||
_that.getData = function() {
|
||||
return _data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetches a frame from the input-stream and puts into the frame-buffer.
|
||||
* The image-data is converted to gray-scale and then half-sampled if configured.
|
||||
*/
|
||||
_that.grab = function() {
|
||||
var doHalfSample = _streamConfig.halfSample,
|
||||
frame = inputStream.getFrame(),
|
||||
ctxData;
|
||||
if (frame) {
|
||||
_ctx.drawImage(frame, 0, 0, _canvasSize.x, _canvasSize.y);
|
||||
ctxData = _ctx.getImageData(_sx, _sy, _size.x, _size.y).data;
|
||||
if (doHalfSample){
|
||||
CVUtils.grayAndHalfSampleFromCanvasData(ctxData, _size, _data);
|
||||
} else {
|
||||
CVUtils.computeGray(ctxData, _data, _streamConfig);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
_that.getSize = function() {
|
||||
return _size;
|
||||
};
|
||||
|
||||
return _that;
|
||||
};
|
||||
|
||||
export default FrameGrabber;
|
||||
@@ -0,0 +1,56 @@
|
||||
var ImageLoader = {};
|
||||
ImageLoader.load = function(directory, callback, offset, size, sequence) {
|
||||
var htmlImagesSrcArray = new Array(size),
|
||||
htmlImagesArray = new Array(htmlImagesSrcArray.length),
|
||||
i,
|
||||
img,
|
||||
num;
|
||||
|
||||
if (sequence === false) {
|
||||
htmlImagesSrcArray[0] = directory;
|
||||
} else {
|
||||
for ( i = 0; i < htmlImagesSrcArray.length; i++) {
|
||||
num = (offset + i);
|
||||
htmlImagesSrcArray[i] = directory + "image-" + ("00" + num).slice(-3) + ".jpg";
|
||||
}
|
||||
}
|
||||
htmlImagesArray.notLoaded = [];
|
||||
htmlImagesArray.addImage = function(image) {
|
||||
htmlImagesArray.notLoaded.push(image);
|
||||
};
|
||||
htmlImagesArray.loaded = function(loadedImg) {
|
||||
var notloadedImgs = htmlImagesArray.notLoaded;
|
||||
for (var x = 0; x < notloadedImgs.length; x++) {
|
||||
if (notloadedImgs[x] === loadedImg) {
|
||||
notloadedImgs.splice(x, 1);
|
||||
for (var y = 0; y < htmlImagesSrcArray.length; y++) {
|
||||
var imgName = htmlImagesSrcArray[y].substr(htmlImagesSrcArray[y].lastIndexOf("/"));
|
||||
if (loadedImg.src.lastIndexOf(imgName) !== -1) {
|
||||
htmlImagesArray[y] = loadedImg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (notloadedImgs.length === 0) {
|
||||
console.log("Images loaded");
|
||||
callback.apply(null, [htmlImagesArray]);
|
||||
}
|
||||
};
|
||||
|
||||
for ( i = 0; i < htmlImagesSrcArray.length; i++) {
|
||||
img = new Image();
|
||||
htmlImagesArray.addImage(img);
|
||||
addOnloadHandler(img, htmlImagesArray);
|
||||
img.src = htmlImagesSrcArray[i];
|
||||
}
|
||||
};
|
||||
|
||||
function addOnloadHandler(img, htmlImagesArray) {
|
||||
img.onload = function() {
|
||||
htmlImagesArray.loaded(this);
|
||||
};
|
||||
}
|
||||
|
||||
export default (ImageLoader);
|
||||
@@ -0,0 +1,317 @@
|
||||
import ImageLoader from './image_loader';
|
||||
|
||||
var InputStream = {};
|
||||
InputStream.createVideoStream = function(video) {
|
||||
var that = {},
|
||||
_config = null,
|
||||
_eventNames = ['canrecord', 'ended'],
|
||||
_eventHandlers = {},
|
||||
_calculatedWidth,
|
||||
_calculatedHeight,
|
||||
_topRight = {x: 0, y: 0},
|
||||
_canvasSize = {x: 0, y: 0};
|
||||
|
||||
function initSize() {
|
||||
var width = video.videoWidth,
|
||||
height = video.videoHeight;
|
||||
|
||||
_calculatedWidth =
|
||||
_config.size ? width / height > 1 ? _config.size : Math.floor((width / height) * _config.size) : width;
|
||||
_calculatedHeight =
|
||||
_config.size ? width / height > 1 ? Math.floor((height / width) * _config.size) : _config.size : height;
|
||||
|
||||
_canvasSize.x = _calculatedWidth;
|
||||
_canvasSize.y = _calculatedHeight;
|
||||
}
|
||||
|
||||
that.getRealWidth = function() {
|
||||
return video.videoWidth;
|
||||
};
|
||||
|
||||
that.getRealHeight = function() {
|
||||
return video.videoHeight;
|
||||
};
|
||||
|
||||
that.getWidth = function() {
|
||||
return _calculatedWidth;
|
||||
};
|
||||
|
||||
that.getHeight = function() {
|
||||
return _calculatedHeight;
|
||||
};
|
||||
|
||||
that.setWidth = function(width) {
|
||||
_calculatedWidth = width;
|
||||
};
|
||||
|
||||
that.setHeight = function(height) {
|
||||
_calculatedHeight = height;
|
||||
};
|
||||
|
||||
that.setInputStream = function(config) {
|
||||
_config = config;
|
||||
video.src = (typeof config.src !== 'undefined') ? config.src : '';
|
||||
};
|
||||
|
||||
that.ended = function() {
|
||||
return video.ended;
|
||||
};
|
||||
|
||||
that.getConfig = function() {
|
||||
return _config;
|
||||
};
|
||||
|
||||
that.setAttribute = function(name, value) {
|
||||
video.setAttribute(name, value);
|
||||
};
|
||||
|
||||
that.pause = function() {
|
||||
video.pause();
|
||||
};
|
||||
|
||||
that.play = function() {
|
||||
video.play();
|
||||
};
|
||||
|
||||
that.setCurrentTime = function(time) {
|
||||
if (_config.type !== "LiveStream") {
|
||||
video.currentTime = time;
|
||||
}
|
||||
};
|
||||
|
||||
that.addEventListener = function(event, f, bool) {
|
||||
if (_eventNames.indexOf(event) !== -1) {
|
||||
if (!_eventHandlers[event]) {
|
||||
_eventHandlers[event] = [];
|
||||
}
|
||||
_eventHandlers[event].push(f);
|
||||
} else {
|
||||
video.addEventListener(event, f, bool);
|
||||
}
|
||||
};
|
||||
|
||||
that.clearEventHandlers = function() {
|
||||
_eventNames.forEach(function(eventName) {
|
||||
var handlers = _eventHandlers[eventName];
|
||||
if (handlers && handlers.length > 0) {
|
||||
handlers.forEach(function(handler) {
|
||||
video.removeEventListener(eventName, handler);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
that.trigger = function(eventName, args) {
|
||||
var j,
|
||||
handlers = _eventHandlers[eventName];
|
||||
|
||||
if (eventName === 'canrecord') {
|
||||
initSize();
|
||||
}
|
||||
if (handlers && handlers.length > 0) {
|
||||
for ( j = 0; j < handlers.length; j++) {
|
||||
handlers[j].apply(that, args);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
that.setTopRight = function(topRight) {
|
||||
_topRight.x = topRight.x;
|
||||
_topRight.y = topRight.y;
|
||||
};
|
||||
|
||||
that.getTopRight = function() {
|
||||
return _topRight;
|
||||
};
|
||||
|
||||
that.setCanvasSize = function(size) {
|
||||
_canvasSize.x = size.x;
|
||||
_canvasSize.y = size.y;
|
||||
};
|
||||
|
||||
that.getCanvasSize = function() {
|
||||
return _canvasSize;
|
||||
};
|
||||
|
||||
that.getFrame = function() {
|
||||
return video;
|
||||
};
|
||||
|
||||
return that;
|
||||
};
|
||||
|
||||
InputStream.createLiveStream = function(video) {
|
||||
video.setAttribute("autoplay", true);
|
||||
var that = InputStream.createVideoStream(video);
|
||||
|
||||
that.ended = function() {
|
||||
return false;
|
||||
};
|
||||
|
||||
return that;
|
||||
};
|
||||
|
||||
InputStream.createImageStream = function() {
|
||||
var that = {};
|
||||
var _config = null;
|
||||
|
||||
var width = 0,
|
||||
height = 0,
|
||||
frameIdx = 0,
|
||||
paused = true,
|
||||
loaded = false,
|
||||
imgArray = null,
|
||||
size = 0,
|
||||
offset = 1,
|
||||
baseUrl = null,
|
||||
ended = false,
|
||||
calculatedWidth,
|
||||
calculatedHeight,
|
||||
_eventNames = ['canrecord', 'ended'],
|
||||
_eventHandlers = {},
|
||||
_topRight = {x: 0, y: 0},
|
||||
_canvasSize = {x: 0, y: 0};
|
||||
|
||||
function loadImages() {
|
||||
loaded = false;
|
||||
ImageLoader.load(baseUrl, function(imgs) {
|
||||
imgArray = imgs;
|
||||
width = imgs[0].width;
|
||||
height = imgs[0].height;
|
||||
calculatedWidth =
|
||||
_config.size ? width / height > 1 ? _config.size : Math.floor((width / height) * _config.size) : width;
|
||||
calculatedHeight =
|
||||
_config.size ? width / height > 1 ? Math.floor((height / width) * _config.size) : _config.size : height;
|
||||
_canvasSize.x = calculatedWidth;
|
||||
_canvasSize.y = calculatedHeight;
|
||||
loaded = true;
|
||||
frameIdx = 0;
|
||||
setTimeout(function() {
|
||||
publishEvent("canrecord", []);
|
||||
}, 0);
|
||||
}, offset, size, _config.sequence);
|
||||
}
|
||||
|
||||
function publishEvent(eventName, args) {
|
||||
var j,
|
||||
handlers = _eventHandlers[eventName];
|
||||
|
||||
if (handlers && handlers.length > 0) {
|
||||
for ( j = 0; j < handlers.length; j++) {
|
||||
handlers[j].apply(that, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
that.trigger = publishEvent;
|
||||
|
||||
that.getWidth = function() {
|
||||
return calculatedWidth;
|
||||
};
|
||||
|
||||
that.getHeight = function() {
|
||||
return calculatedHeight;
|
||||
};
|
||||
|
||||
that.setWidth = function(newWidth) {
|
||||
calculatedWidth = newWidth;
|
||||
};
|
||||
|
||||
that.setHeight = function(newHeight) {
|
||||
calculatedHeight = newHeight;
|
||||
};
|
||||
|
||||
that.getRealWidth = function() {
|
||||
return width;
|
||||
};
|
||||
|
||||
that.getRealHeight = function() {
|
||||
return height;
|
||||
};
|
||||
|
||||
that.setInputStream = function(stream) {
|
||||
_config = stream;
|
||||
if (stream.sequence === false) {
|
||||
baseUrl = stream.src;
|
||||
size = 1;
|
||||
} else {
|
||||
baseUrl = stream.src;
|
||||
size = stream.length;
|
||||
}
|
||||
loadImages();
|
||||
};
|
||||
|
||||
that.ended = function() {
|
||||
return ended;
|
||||
};
|
||||
|
||||
that.setAttribute = function() {};
|
||||
|
||||
that.getConfig = function() {
|
||||
return _config;
|
||||
};
|
||||
|
||||
that.pause = function() {
|
||||
paused = true;
|
||||
};
|
||||
|
||||
that.play = function() {
|
||||
paused = false;
|
||||
};
|
||||
|
||||
that.setCurrentTime = function(time) {
|
||||
frameIdx = time;
|
||||
};
|
||||
|
||||
that.addEventListener = function(event, f) {
|
||||
if (_eventNames.indexOf(event) !== -1) {
|
||||
if (!_eventHandlers[event]) {
|
||||
_eventHandlers[event] = [];
|
||||
}
|
||||
_eventHandlers[event].push(f);
|
||||
}
|
||||
};
|
||||
|
||||
that.setTopRight = function(topRight) {
|
||||
_topRight.x = topRight.x;
|
||||
_topRight.y = topRight.y;
|
||||
};
|
||||
|
||||
that.getTopRight = function() {
|
||||
return _topRight;
|
||||
};
|
||||
|
||||
that.setCanvasSize = function(canvasSize) {
|
||||
_canvasSize.x = canvasSize.x;
|
||||
_canvasSize.y = canvasSize.y;
|
||||
};
|
||||
|
||||
that.getCanvasSize = function() {
|
||||
return _canvasSize;
|
||||
};
|
||||
|
||||
that.getFrame = function() {
|
||||
var frame;
|
||||
|
||||
if (!loaded){
|
||||
return null;
|
||||
}
|
||||
if (!paused) {
|
||||
frame = imgArray[frameIdx];
|
||||
if (frameIdx < (size - 1)) {
|
||||
frameIdx++;
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
ended = true;
|
||||
publishEvent("ended", []);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
return frame;
|
||||
};
|
||||
|
||||
return that;
|
||||
};
|
||||
|
||||
export default InputStream;
|
||||
Reference in New Issue
Block a user