You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
5.9 KiB
JavaScript
179 lines
5.9 KiB
JavaScript
/*
|
|
* Copyright (C) 2019 Intel Corporation
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
/* global
|
|
require:false
|
|
global:false
|
|
*/
|
|
|
|
(() => {
|
|
const PluginRegistry = require('./plugins');
|
|
const serverProxy = require('./server-proxy');
|
|
const { ArgumentError } = require('./exceptions');
|
|
const { isBrowser, isNode } = require('browser-or-node');
|
|
|
|
// This is the frames storage
|
|
const frameDataCache = {};
|
|
const frameCache = {};
|
|
|
|
/**
|
|
* Class provides meta information about specific frame and frame itself
|
|
* @memberof module:API.cvat.classes
|
|
* @hideconstructor
|
|
*/
|
|
class FrameData {
|
|
constructor(width, height, tid, number) {
|
|
Object.defineProperties(this, Object.freeze({
|
|
/**
|
|
* @name width
|
|
* @type {integer}
|
|
* @memberof module:API.cvat.classes.FrameData
|
|
* @readonly
|
|
* @instance
|
|
*/
|
|
width: {
|
|
value: width,
|
|
writable: false,
|
|
},
|
|
/**
|
|
* @name height
|
|
* @type {integer}
|
|
* @memberof module:API.cvat.classes.FrameData
|
|
* @readonly
|
|
* @instance
|
|
*/
|
|
height: {
|
|
value: height,
|
|
writable: false,
|
|
},
|
|
tid: {
|
|
value: tid,
|
|
writable: false,
|
|
},
|
|
/**
|
|
* @name number
|
|
* @type {integer}
|
|
* @memberof module:API.cvat.classes.FrameData
|
|
* @readonly
|
|
* @instance
|
|
*/
|
|
number: {
|
|
value: number,
|
|
writable: false,
|
|
},
|
|
}));
|
|
}
|
|
|
|
/**
|
|
* Method returns URL encoded image which can be placed in the img tag
|
|
* @method data
|
|
* @returns {string}
|
|
* @memberof module:API.cvat.classes.FrameData
|
|
* @instance
|
|
* @async
|
|
* @param {function} [onServerRequest = () => {}]
|
|
* callback which will be called if data absences local
|
|
* @throws {module:API.cvat.exception.ServerError}
|
|
* @throws {module:API.cvat.exception.PluginError}
|
|
*/
|
|
async data(onServerRequest = () => {}) {
|
|
const result = await PluginRegistry
|
|
.apiWrapper.call(this, FrameData.prototype.data, onServerRequest);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
FrameData.prototype.data.implementation = async function (onServerRequest) {
|
|
return new Promise(async (resolve, reject) => {
|
|
try {
|
|
if (this.number in frameCache[this.tid]) {
|
|
resolve(frameCache[this.tid][this.number]);
|
|
} else {
|
|
onServerRequest();
|
|
const frame = await serverProxy.frames.getData(this.tid, this.number);
|
|
|
|
if (isNode) {
|
|
frameCache[this.tid][this.number] = global.Buffer.from(frame, 'binary').toString('base64');
|
|
resolve(frameCache[this.tid][this.number]);
|
|
} else if (isBrowser) {
|
|
const reader = new FileReader();
|
|
reader.onload = () => {
|
|
const image = new Image(frame.width, frame.height);
|
|
image.onload = () => {
|
|
frameCache[this.tid][this.number] = image;
|
|
resolve(frameCache[this.tid][this.number]);
|
|
};
|
|
image.src = reader.result;
|
|
};
|
|
|
|
reader.readAsDataURL(frame);
|
|
}
|
|
}
|
|
} catch (exception) {
|
|
reject(exception);
|
|
}
|
|
});
|
|
};
|
|
|
|
async function getPreview(taskID) {
|
|
return new Promise(async (resolve, reject) => {
|
|
try {
|
|
// Just go to server and get preview (no any cache)
|
|
const result = await serverProxy.frames.getPreview(taskID);
|
|
if (isNode) {
|
|
resolve(global.Buffer.from(result, 'binary').toString('base64'));
|
|
} else if (isBrowser) {
|
|
const reader = new FileReader();
|
|
reader.onload = () => {
|
|
resolve(reader.result);
|
|
};
|
|
reader.readAsDataURL(result);
|
|
}
|
|
} catch (error) {
|
|
reject(error);
|
|
}
|
|
});
|
|
}
|
|
|
|
async function getFrame(taskID, mode, frame) {
|
|
if (!(taskID in frameDataCache)) {
|
|
frameDataCache[taskID] = {
|
|
meta: await serverProxy.frames.getMeta(taskID),
|
|
};
|
|
|
|
frameCache[taskID] = {};
|
|
}
|
|
|
|
if (!(frame in frameDataCache[taskID])) {
|
|
let size = null;
|
|
if (mode === 'interpolation') {
|
|
[size] = frameDataCache[taskID].meta;
|
|
} else if (mode === 'annotation') {
|
|
if (frame >= frameDataCache[taskID].meta.length) {
|
|
throw new ArgumentError(
|
|
`Meta information about frame ${frame} can't be received from the server`,
|
|
);
|
|
} else {
|
|
size = frameDataCache[taskID].meta[frame];
|
|
}
|
|
} else {
|
|
throw new ArgumentError(
|
|
`Invalid mode is specified ${mode}`,
|
|
);
|
|
}
|
|
|
|
frameDataCache[taskID][frame] = new FrameData(size.width, size.height, taskID, frame);
|
|
}
|
|
|
|
return frameDataCache[taskID][frame];
|
|
}
|
|
|
|
module.exports = {
|
|
FrameData,
|
|
getFrame,
|
|
getPreview,
|
|
};
|
|
})();
|