Files
image-sequencer/src/ImageSequencer.js
2018-12-17 10:56:17 +05:30

469 lines
14 KiB
JavaScript

if (typeof window !== 'undefined') { isBrowser = true }
else { var isBrowser = false }
require('./util/getStep.js');
ImageSequencer = function ImageSequencer(options) {
var sequencer = (this.name == "ImageSequencer") ? this : this.sequencer;
options = options || {};
options.inBrowser = options.inBrowser || isBrowser;
options.sequencerCounter = 0;
function objTypeOf(object) {
return Object.prototype.toString.call(object).split(" ")[1].slice(0, -1)
}
function log(color, msg) {
if (options.ui != "none") {
if (arguments.length == 1) console.log(arguments[0]);
else if (arguments.length == 2) console.log(color, msg);
}
}
function copy(a) {
if (!typeof (a) == "object") return a;
if (objTypeOf(a) == "Array") return a.slice();
if (objTypeOf(a) == "Object") {
var b = {};
for (var v in a) {
b[v] = copy(a[v]);
}
return b;
}
return a;
}
function makeArray(input) {
return (objTypeOf(input) == "Array") ? input : [input];
}
var image,
steps = [],
modules = require('./Modules'),
sequences = require('./SavedSequences.json'),
formatInput = require('./FormatInput'),
images = {},
inputlog = [],
events = require('./ui/UserInterface')(),
fs = require('fs');
if (options.inBrowser) {
for (o in sequencer) {
modules[o] = sequencer[o];
}
sequences = JSON.parse(window.localStorage.getItem('sequences'));
if (!sequences) {
sequences = {};
window.localStorage.setItem('sequences', JSON.stringify(sequences));
}
}
// if in browser, prompt for an image
// if (options.imageSelect || options.inBrowser) addStep('image-select');
// else if (options.imageUrl) loadImage(imageUrl);
function addSteps() {
var this_ = (this.name == "ImageSequencer") ? this : this.sequencer;
var args = (this.name == "ImageSequencer") ? [] : [this.images];
var json_q = {};
for (var arg in arguments) { args.push(copy(arguments[arg])); }
json_q = formatInput.call(this_, args, "+");
inputlog.push({ method: "addSteps", json_q: copy(json_q) });
for (var i in json_q)
for (var j in json_q[i])
require("./AddStep")(this_, i, json_q[i][j].name, json_q[i][j].o);
return this;
}
function removeStep(image, index) {
//remove the step from images[image].steps and redraw remaining images
if (index > 0) {
thisStep = images[image].steps[index];
thisStep.UI.onRemove(thisStep.options.step);
images[image].steps.splice(index, 1);
}
//tell the UI a step has been removed
}
function removeSteps(image, index) {
var run = {}, indices;
var this_ = (this.name == "ImageSequencer") ? this : this.sequencer;
var args = (this.name == "ImageSequencer") ? [] : [this.images];
for (var arg in arguments) args.push(copy(arguments[arg]));
var json_q = formatInput.call(this_, args, "-");
inputlog.push({ method: "removeSteps", json_q: copy(json_q) });
for (var img in json_q) {
indices = json_q[img].sort(function(a, b) { return b - a });
run[img] = indices[indices.length - 1];
for (var i in indices)
removeStep(img, indices[i]);
}
// this.run(run); // This is creating problems
return this;
}
function insertSteps(image, index, name, o) {
var run = {};
var this_ = (this.name == "ImageSequencer") ? this : this.sequencer;
var args = (this.name == "ImageSequencer") ? [] : [this.images];
for (var arg in arguments) args.push(arguments[arg]);
var json_q = formatInput.call(this_, args, "^");
inputlog.push({ method: "insertSteps", json_q: copy(json_q) });
for (var img in json_q) {
var details = json_q[img];
details = details.sort(function(a, b) { return b.index - a.index });
for (var i in details)
require("./InsertStep")(this_, img, details[i].index, details[i].name, details[i].o);
run[img] = details[details.length - 1].index;
}
// this.run(run); // This is Creating issues
return this;
}
// Config is an object which contains the runtime configuration like progress bar
// information and index from which the sequencer should run
function run(config, t_image, t_from) {
let progressObj, index = 0;
config = config || { mode: 'no-arg' };
if (config.index) index = config.index;
if (config.mode != 'test') {
if (config.mode != "no-arg" && typeof config != 'function') {
if (config.progressObj) progressObj = config.progressObj;
delete arguments['0'];
}
}
else {
arguments['0'] = config.mode;
}
var this_ = (this.name == "ImageSequencer") ? this : this.sequencer;
var args = (this.name == "ImageSequencer") ? [] : [this.images];
for (var arg in arguments) args.push(copy(arguments[arg]));
var callback = function() { };
for (var arg in args)
if (objTypeOf(args[arg]) == "Function")
callback = args.splice(arg, 1)[0];
var json_q = formatInput.call(this_, args, "r");
require('./Run')(this_, json_q, callback, index, progressObj);
return true;
}
function loadImages() {
var args = [];
var sequencer = this;
for (var arg in arguments) args.push(copy(arguments[arg]));
var json_q = formatInput.call(this, args, "l");
inputlog.push({ method: "loadImages", json_q: copy(json_q) });
var loadedimages = this.copy(json_q.loadedimages);
var ret = {
name: "ImageSequencer Wrapper",
sequencer: this,
addSteps: this.addSteps,
removeSteps: this.removeSteps,
insertSteps: this.insertSteps,
run: this.run,
UI: this.UI,
setUI: this.setUI,
images: loadedimages
};
function load(i) {
if (i == loadedimages.length) {
json_q.callback.call(ret);
return;
}
var img = loadedimages[i];
require('./ui/LoadImage')(sequencer, img, json_q.images[img], function() {
load(++i);
});
}
load(0);
}
function replaceImage(selector, steps, options) {
options = options || {};
options.callback = options.callback || function() { };
return require('./ReplaceImage')(this, selector, steps, options);
}
function setUI(UI) {
this.events = require('./ui/UserInterface')(UI);
}
var exportBin = function(dir, basic, filename) {
return require('./ExportBin')(dir, this, basic, filename);
}
function modulesInfo(name) {
var modulesdata = {}
if (name == "load-image") return {};
if (arguments.length == 0) {
for (var modulename in this.modules) {
modulesdata[modulename] = modules[modulename][1];
}
for (var sequencename in this.sequences) {
modulesdata[sequencename] = { name: sequencename, steps: this.sequences[sequencename] };
}
}
else {
if (modules[name])
modulesdata = modules[name][1];
else
modulesdata = { 'inputs': sequences[name]['options'] };
}
return modulesdata;
}
// Genates a CLI string for the current sequence
function toCliString() {
var cliStringSteps = `"`, cliOptions = {};
for (var step in this.steps) {
if (this.steps[step].options.name !== "load-image")
cliStringSteps += `${this.steps[step].options.name} `;
for (var inp in modulesInfo(this.steps[step].options.name).inputs) {
cliOptions[inp] = this.steps[step].options[inp];
}
}
cliStringSteps = cliStringSteps.substr(0, cliStringSteps.length - 1) + `"`;
return `sequencer -i [PATH] -s ${cliStringSteps} -d '${JSON.stringify(cliOptions)}'`
}
// Strigifies the current sequence
function toString(step) {
if (step) {
return stepToString(step);
} else {
return copy(this.images.image1.steps).map(stepToString).slice(1).join(',');
}
}
// Stringifies one step of the sequence
function stepToString(step) {
let inputs = modulesInfo(step.options.name).inputs || {}, op = {};
for (let input in inputs) {
if (!!step.options[input] && step.options[input] != inputs[input].default) {
op[input] = step.options[input];
op[input] = encodeURIComponent(op[input]);
}
}
var configurations = Object.keys(op).map(key => key + ':' + op[key]).join('|');
return `${step.options.name}{${configurations}}`;
}
// exports the current sequence as an array of JSON steps
function toJSON() {
return this.stringToJSON(this.toString());
}
// Coverts stringified sequence into an array of JSON steps
function stringToJSON(str) {
let steps;
if (str.includes(','))
steps = str.split(',');
else
steps = [str];
return steps.map(stringToJSONstep);
}
// Converts one stringified step into JSON
function stringToJSONstep(str) {
var bracesStrings;
if (str.includes('{'))
if (str.includes('(') && str.indexOf('(') < str.indexOf('{'))
bracesStrings = ['(', ')'];
else
bracesStrings = ['{', '}'];
else
bracesStrings = ['(', ')'];
if (str.indexOf(bracesStrings[0]) === -1) { // if there are no settings specified
var moduleName = str.substr(0);
stepSettings = "";
} else {
var moduleName = str.substr(0, str.indexOf(bracesStrings[0]));
stepSettings = str.slice(str.indexOf(bracesStrings[0]) + 1, -1);
}
stepSettings = stepSettings.split('|').reduce(function formatSettings(accumulator, current, i) {
var settingName = current.substr(0, current.indexOf(':')),
settingValue = current.substr(current.indexOf(':') + 1);
settingValue = settingValue.replace(/^\(/, '').replace(/\)$/, ''); // strip () at start/end
settingValue = settingValue.replace(/^\{/, '').replace(/\}$/, ''); // strip {} at start/end
settingValue = decodeURIComponent(settingValue);
current = [
settingName,
settingValue
];
if (!!settingName) accumulator[settingName] = settingValue;
return accumulator;
}, {});
return {
name: moduleName,
options: stepSettings
}
}
// imports a string into the sequencer steps
function importString(str) {
let sequencer = this;
if (this.name != "ImageSequencer")
sequencer = this.sequencer;
var stepsFromString = stringToJSON(str);
stepsFromString.forEach(function eachStep(stepObj) {
sequencer.addSteps(stepObj.name, stepObj.options);
});
}
// imports a array of JSON steps into the sequencer steps
function importJSON(obj) {
let sequencer = this;
if (this.name != "ImageSequencer")
sequencer = this.sequencer;
obj.forEach(function eachStep(stepObj) {
sequencer.addSteps(stepObj.name, stepObj.options);
});
}
function loadNewModule(name, options) {
if (!options) {
return this;
} else if (Array.isArray(options)) {
// contains the array of module and info
this.modules[name] = options;
} else if (options.func && options.info) {
// passed in options object
this.modules[name] = [
options.func, options.info
];
} else if (options.path && !this.inBrowser) {
// load from path(only in node)
const module = [
require(`${options.path}/Module.js`),
require(`${options.path}/info.json`)
];
this.modules[name] = module;
}
return this;
}
function saveNewModule(name, path) {
if (options.inBrowser) {
// Not for browser context
return;
}
var mods = fs.readFileSync('./src/Modules.js').toString();
mods = mods.substr(0, mods.length - 1) + " '" + name + "': require('" + path + "'),\n}";
fs.writeFileSync('./src/Modules.js', mods);
}
function createMetaModule(stepsCollection, info) {
var stepsArr = stepsCollection;
if (typeof stepsCollection === 'string')
stepsArr = stringToJSON(stepsCollection);
var metaMod = function() {
this.expandSteps(stepsArr);
return {
isMeta: true
}
}
return [metaMod, info];
}
function saveSequence(name, sequenceString) {
const sequence = stringToJSON(sequenceString);
// Save the given sequence string as a module
if (options.inBrowser) {
// Inside the browser we save the meta-modules using the Web Storage API
var sequences = JSON.parse(window.localStorage.getItem('sequences'));
sequences[name] = sequence;
window.localStorage.setItem('sequences', JSON.stringify(sequences));
}
else {
// In node we save the sequences in the json file SavedSequences.json
var sequences = require('./SavedSequences.json');
sequences[name] = sequence;
fs.writeFileSync('./src/SavedSequences.json', JSON.stringify(sequences));
}
}
function loadModules() {
// This function loads the modules and saved sequences
this.modules = require('./Modules');
if (options.inBrowser)
this.sequences = JSON.parse(window.localStorage.getItem('sequences'));
else
this.sequences = require('./SavedSequences.json');
}
return {
//literals and objects
name: "ImageSequencer",
options: options,
inputlog: inputlog,
modules: modules,
sequences: sequences,
images: images,
events: events,
//user functions
loadImages: loadImages,
loadImage: loadImages,
addSteps: addSteps,
removeSteps: removeSteps,
insertSteps: insertSteps,
replaceImage: replaceImage,
run: run,
setUI: setUI,
exportBin: exportBin,
modulesInfo: modulesInfo,
toCliString: toCliString,
toString: toString,
stepToString: stepToString,
toJSON: toJSON,
stringToJSON: stringToJSON,
stringToJSONstep: stringToJSONstep,
importString: importString,
importJSON: importJSON,
loadNewModule: loadNewModule,
saveNewModule: saveNewModule,
createMetaModule: createMetaModule,
saveSequence: saveSequence,
loadModules: loadModules,
//other functions
log: log,
objTypeOf: objTypeOf,
copy: copy,
setInputStep: require('./ui/SetInputStep')(sequencer)
}
}
module.exports = ImageSequencer;