thorough rework of API

This commit is contained in:
jywarren
2017-03-03 10:51:58 -05:00
parent f56e833540
commit fc63c88d5a
11 changed files with 202 additions and 228 deletions

View File

@@ -184095,44 +184095,53 @@ if (typeof window !== 'undefined') window.$ = window.jQuery = require('jquery');
ImageSequencer = function ImageSequencer(options) {
options = options || {};
options.defaultSteps = options.defaultSteps || function defaultSteps() {
addStep('image-select');
}
options.inBrowser = options.inBrowser || typeof window !== 'undefined';
options.ui = options.ui || require('./UserInterface');
var image,
steps = [],
modules = require('./Modules');
options.ui = options.ui || require('./UserInterface')();
options.defaultSteps();
// if in browser, prompt for an image
if (options.imageSelect || options.inBrowser) addStep('image-select', { selector: "#drop" });
else if (options.imageUrl) loadImage(imageUrl);
// soon, detect local or URL?
function addStep(name, o) {
console.log('adding step "' + name + '"');
o = o || {};
o.name = o.name || name;
o.selector = o.selector || 'ismod-' + name;
o.container = o.container || options.selector;
o.createUserInterface = o.createUserInterface || options.ui.create;
var module = modules[name](o);
steps.push(module);
if (steps.length > 1) {
if (module.name !== "image-select") {
if (module.setup) module.setup();
var lastStep = steps[steps.length - 2];
// connect last step to input of this step
lastStep.options.onComplete = function onComplete(_image) {
log('running module "' + name + '"');
if (lastStep.options.ui) lastStep.options.ui.el.html(_image);
module.draw(_image);
// add a default UI, unless the module has one specified
if (module.hasOwnProperty('setup')) module.setup();
else {
setup.apply(module); // run default setup() in scope of module (is this right?)
function setup() {
module.options.ui = options.ui({
selector: o.selector
});
}
}
module.options.onComplete = function onComplete(_image) {
if (module.options.ui) module.options.ui.el.html(_image);
var previousStep = steps[steps.length - 2];
if (previousStep) {
// connect output of last step to input of this step
previousStep.options.output = function output(image) {
log('running module "' + name + '"');
// display the image in any available ui
if (previousStep.options.ui && previousStep.options.ui.display) previousStep.options.ui.display(image);
module.draw(image);
}
}
} else {
@@ -184140,6 +184149,20 @@ ImageSequencer = function ImageSequencer(options) {
module.setup(); // just set up initial ImageSelect
}
// Pre-set the initial output behavior of the final step,
// which will be changed if an additional step is added.
module.options.output = function output(image) {
if (module.options.ui && module.options.ui.display) module.options.ui.display(image);
}
}
// passed image is optional but you can pass a
// non-stored image through the whole steps chain
function run(image) {
if (image) steps[1].draw(image);
else steps[0].draw();
}
function log(msg) {
@@ -184147,27 +184170,17 @@ ImageSequencer = function ImageSequencer(options) {
console.log(msg);
}
function run() {
steps[0].draw();
}
// load default starting image
// i.e. from parameter
// this could send the image to ImageSelect, or something?
// not currently working
function loadImage(src, callback) {
image = new Image();
image.onload = function() {
run();
run(image);
if (callback) callback(image);
}
image.src = src;
}
return {
@@ -184199,38 +184212,40 @@ module.exports = {
},{"./modules/GreenChannel":1610,"./modules/ImageSelect":1611,"./modules/ImageThreshold":1612,"./modules/NdviRed":1613,"./modules/Plot":1615}],1609:[function(require,module,exports){
/*
* Default UI for ImageBoard
* Default UI for each image-sequencer module
*/
module.exports = function UserInterface(options) {
options = options || {};
options.container = options.container || ".panels";
// method to create a UI for a given module
function create(o) {
o.random = o.random || parseInt(Math.random() * (new Date()).getTime() / 1000000);
o.uniqueSelector = o.uniqueSelector || o.selector + '-' + o.random;
$(options.container).append('<div class="panel ' + o.selector + ' ' + o.uniqueSelector + '"></div>');
o.el = o.el || $('.' + o.uniqueSelector);
return {
el: o.el,
uniqueSelector: o.uniqueSelector,
selector: o.selector
}
options.random = options.random || parseInt(Math.random() * (new Date()).getTime() / 1000000);
options.uniqueSelector = options.uniqueSelector || options.selector + '-' + options.random;
$(options.container).append('<div class="panel ' + options.selector + ' ' + options.uniqueSelector + '"></div>');
options.el = options.el || $('.' + options.uniqueSelector);
createLabel(options.el);
// method to remove the UI for a given method, and remove the step
function display(image) {
options.el.html(image);
}
// method to remove the UI for a given method, and remove the step
function remove() {
}
function remove() {}
// method to reorder steps, and update the UI
//function move() {
//function move() {}
//}
function createLabel(el) {
console.log("createLabel", module.title)
el.append('<h3 class="title">' + module.title + '</h3>');
}
return {
create: create,
el: options.el,
uniqueSelector: options.uniqueSelector,
selector: options.selector,
display: display,
remove: remove
}
@@ -184244,31 +184259,24 @@ module.exports = function GreenChannel(options) {
options = options || {};
var image;
//function setup() {} // optional
function setup() {
options.ui = options.createUserInterface({
selector: 'mod-green-channel'
});
function draw(image) {
function changePixel(r, g, b, a) {
return [0, g, 0, a];
}
function draw(_image) {
// PixelManipulation returns an image
require('./PixelManipulation.js')(_image, {
onComplete: options.onComplete,
return require('./PixelManipulation.js')(image, {
output: options.output,
changePixel: changePixel
});
}
function changePixel(r, g, b, a) {
return [0, g, 0, a];
}
return {
title: "Green channel only",
description: "Displays only the green channel of an image",
options: options,
draw: draw,
setup: setup
//setup: setup, // optional
draw: draw
}
}
@@ -184279,7 +184287,7 @@ module.exports = function GreenChannel(options) {
*/
module.exports = function ImageSelect(options) {
//window.$ = window.jQuery = require('jquery');
if (!window.hasOwnProperty('$')) window.$ = window.jQuery = require('jquery');
options = options || {};
options.selector = options.selector || "#drop";
@@ -184287,11 +184295,11 @@ module.exports = function ImageSelect(options) {
options.ui = options.ui || {};
options.ui.el = options.ui.el || $(options.selector);
if (options.ui.el.length === 0) console.log('No UI element found with given selector: ', options.selector);
var image,
el = options.ui.el;
console.log(el,$('body'));
function setup() {
// CSS UI
@@ -184325,7 +184333,7 @@ console.log(el,$('body'));
el.html(image); // may be redundant
// this is done once per image:
options.onComplete(image);
options.output(image);
}
reader.readAsDataURL(f);
@@ -184344,8 +184352,10 @@ console.log(el,$('body'));
}
function draw(_image) {
if (options.onComplete) options.onComplete(image);
// this module is unique because it creates the image
function draw(image) {
options.ui.display(image);
if (options.output) options.output(image);
}
function get() {
@@ -184362,7 +184372,7 @@ console.log(el,$('body'));
}
},{}],1612:[function(require,module,exports){
},{"jquery":89}],1612:[function(require,module,exports){
/*
* Image thresholding with 'image-filter-threshold'
*/
@@ -184373,19 +184383,13 @@ module.exports = function ImageThreshold(options) {
var image;
function setup() {
options.ui = options.createUserInterface({
selector: 'mod-image-threshold'
});
}
function draw(_image) {
function draw(inputImage) {
var canvas = document.createElement('canvas');
canvas.width = _image.naturalWidth;
canvas.height = _image.naturalHeight;
canvas.width = inputImage.naturalWidth;
canvas.height = inputImage.naturalHeight;
var context = canvas.getContext('2d');
context.drawImage(_image, 0, 0 );
var imageData = context.getImageData(0, 0, _image.naturalWidth, _image.naturalHeight);
context.drawImage(inputImage, 0, 0 );
var imageData = context.getImageData(0, 0, inputImage.naturalWidth, inputImage.naturalHeight);
var imageThreshold = require('image-filter-threshold');
var imageFilterCore = require('image-filter-core');
@@ -184396,7 +184400,7 @@ module.exports = function ImageThreshold(options) {
}).then(function (imageData) {
image = new Image();
image.onload = function onLoad() {
if (options.onComplete) options.onComplete(image);
if (options.output) options.output(image);
}
image.src = imageFilterCore.convertImageDataToCanvasURL(imageData);
});
@@ -184409,7 +184413,6 @@ module.exports = function ImageThreshold(options) {
return {
title: "Threshold image",
options: options,
setup: setup,
draw: draw,
get: get
}
@@ -184423,31 +184426,24 @@ module.exports = function NdviRed(options) {
options = options || {};
var image;
function setup() {
options.ui = options.createUserInterface({
selector: 'mod-ndvi-red'
});
}
function draw(_image) {
require('./PixelManipulation.js')(_image, {
onComplete: options.onComplete,
changePixel: changePixel
});
}
//function setup() {} // optional
function draw(image) {
function changePixel(r, g, b, a) {
var ndvi = 255 * (b - r) / (1.00 * b + r);
return [ndvi, ndvi, ndvi, a];
}
return require('./PixelManipulation.js')(image, {
output: options.output,
changePixel: changePixel
});
}
return {
title: "NDVI for red-filtered cameras (blue is infrared)",
options: options,
draw: draw,
setup: setup
//setup: setup, // optional
draw: draw
}
}
@@ -184506,7 +184502,7 @@ module.exports = function PixelManipulation(image, options) {
img.src = 'data:image/' + options.format + ';base64,' + buffer.read().toString();
if (options.onComplete) options.onComplete(img);
if (options.output) options.output(img);
}).pipe(buffer);
@@ -184526,14 +184522,6 @@ module.exports = function Plot(options) {
var image;
function setup() {
options.ui = options.createUserInterface({
selector: 'mod-plot'
});
}
function draw(_image) {
/* https://plot.ly/javascript/heatmap-and-contour-colorscales/#custom-colorscale
@@ -184578,7 +184566,7 @@ module.exports = function Plot(options) {
Plotly.newPlot('plot-' + random, data, layout)
/* .then(function afterPlot(graphData) {
options.onComplete(Plotly.toImage(graphData, {
options.output(Plotly.toImage(graphData, {
format: 'jpeg',
height: _image.height,
width: _image.width
@@ -184593,8 +184581,7 @@ module.exports = function Plot(options) {
return {
title: "Plot with colorbar",
options: options,
draw: draw,
setup: setup
draw: draw
}
}

View File

@@ -65,7 +65,7 @@
sequencer = ImageSequencer();
// sequencer.loadImage('examples/grid.png');
sequencer.loadImage('examples/grid.png');
sequencer.addStep('ndvi-red');
sequencer.addStep('image-threshold');

View File

View File

@@ -3,44 +3,53 @@ if (typeof window !== 'undefined') window.$ = window.jQuery = require('jquery');
ImageSequencer = function ImageSequencer(options) {
options = options || {};
options.defaultSteps = options.defaultSteps || function defaultSteps() {
addStep('image-select');
}
options.inBrowser = options.inBrowser || typeof window !== 'undefined';
options.ui = options.ui || require('./UserInterface');
var image,
steps = [],
modules = require('./Modules');
options.ui = options.ui || require('./UserInterface')();
options.defaultSteps();
// if in browser, prompt for an image
if (options.imageSelect || options.inBrowser) addStep('image-select', { selector: "#drop" });
else if (options.imageUrl) loadImage(imageUrl);
// soon, detect local or URL?
function addStep(name, o) {
console.log('adding step "' + name + '"');
o = o || {};
o.name = o.name || name;
o.selector = o.selector || 'ismod-' + name;
o.container = o.container || options.selector;
o.createUserInterface = o.createUserInterface || options.ui.create;
var module = modules[name](o);
steps.push(module);
if (steps.length > 1) {
if (module.name !== "image-select") {
if (module.setup) module.setup();
var lastStep = steps[steps.length - 2];
// connect last step to input of this step
lastStep.options.onComplete = function onComplete(_image) {
log('running module "' + name + '"');
if (lastStep.options.ui) lastStep.options.ui.el.html(_image);
module.draw(_image);
// add a default UI, unless the module has one specified
if (module.hasOwnProperty('setup')) module.setup();
else {
setup.apply(module); // run default setup() in scope of module (is this right?)
function setup() {
module.options.ui = options.ui({
selector: o.selector
});
}
}
module.options.onComplete = function onComplete(_image) {
if (module.options.ui) module.options.ui.el.html(_image);
var previousStep = steps[steps.length - 2];
if (previousStep) {
// connect output of last step to input of this step
previousStep.options.output = function output(image) {
log('running module "' + name + '"');
// display the image in any available ui
if (previousStep.options.ui && previousStep.options.ui.display) previousStep.options.ui.display(image);
module.draw(image);
}
}
} else {
@@ -48,6 +57,20 @@ ImageSequencer = function ImageSequencer(options) {
module.setup(); // just set up initial ImageSelect
}
// Pre-set the initial output behavior of the final step,
// which will be changed if an additional step is added.
module.options.output = function output(image) {
if (module.options.ui && module.options.ui.display) module.options.ui.display(image);
}
}
// passed image is optional but you can pass a
// non-stored image through the whole steps chain
function run(image) {
if (image) steps[1].draw(image);
else steps[0].draw();
}
function log(msg) {
@@ -55,27 +78,17 @@ ImageSequencer = function ImageSequencer(options) {
console.log(msg);
}
function run() {
steps[0].draw();
}
// load default starting image
// i.e. from parameter
// this could send the image to ImageSelect, or something?
// not currently working
function loadImage(src, callback) {
image = new Image();
image.onload = function() {
run();
run(image);
if (callback) callback(image);
}
image.src = src;
}
return {

View File

@@ -1,36 +1,38 @@
/*
* Default UI for ImageBoard
* Default UI for each image-sequencer module
*/
module.exports = function UserInterface(options) {
options = options || {};
options.container = options.container || ".panels";
// method to create a UI for a given module
function create(o) {
o.random = o.random || parseInt(Math.random() * (new Date()).getTime() / 1000000);
o.uniqueSelector = o.uniqueSelector || o.selector + '-' + o.random;
$(options.container).append('<div class="panel ' + o.selector + ' ' + o.uniqueSelector + '"></div>');
o.el = o.el || $('.' + o.uniqueSelector);
return {
el: o.el,
uniqueSelector: o.uniqueSelector,
selector: o.selector
}
options.random = options.random || parseInt(Math.random() * (new Date()).getTime() / 1000000);
options.uniqueSelector = options.uniqueSelector || options.selector + '-' + options.random;
$(options.container).append('<div class="panel ' + options.selector + ' ' + options.uniqueSelector + '"></div>');
options.el = options.el || $('.' + options.uniqueSelector);
createLabel(options.el);
// method to remove the UI for a given method, and remove the step
function display(image) {
options.el.html(image);
}
// method to remove the UI for a given method, and remove the step
function remove() {
}
function remove() {}
// method to reorder steps, and update the UI
//function move() {
//function move() {}
//}
function createLabel(el) {
console.log("createLabel", module.title)
el.append('<h3 class="title">' + module.title + '</h3>');
}
return {
create: create,
el: options.el,
uniqueSelector: options.uniqueSelector,
selector: options.selector,
display: display,
remove: remove
}

View File

@@ -5,30 +5,23 @@ module.exports = function GreenChannel(options) {
options = options || {};
var image;
//function setup() {} // optional
function setup() {
options.ui = options.createUserInterface({
selector: 'mod-green-channel'
});
function draw(image) {
function changePixel(r, g, b, a) {
return [0, g, 0, a];
}
function draw(_image) {
// PixelManipulation returns an image
require('./PixelManipulation.js')(_image, {
onComplete: options.onComplete,
return require('./PixelManipulation.js')(image, {
output: options.output,
changePixel: changePixel
});
}
function changePixel(r, g, b, a) {
return [0, g, 0, a];
}
return {
title: "Green channel only",
description: "Displays only the green channel of an image",
options: options,
draw: draw,
setup: setup
//setup: setup, // optional
draw: draw
}
}

View File

@@ -4,7 +4,7 @@
*/
module.exports = function ImageSelect(options) {
//window.$ = window.jQuery = require('jquery');
if (!window.hasOwnProperty('$')) window.$ = window.jQuery = require('jquery');
options = options || {};
options.selector = options.selector || "#drop";
@@ -12,11 +12,11 @@ module.exports = function ImageSelect(options) {
options.ui = options.ui || {};
options.ui.el = options.ui.el || $(options.selector);
if (options.ui.el.length === 0) console.log('No UI element found with given selector: ', options.selector);
var image,
el = options.ui.el;
console.log(el,$('body'));
function setup() {
// CSS UI
@@ -50,7 +50,7 @@ console.log(el,$('body'));
el.html(image); // may be redundant
// this is done once per image:
options.onComplete(image);
options.output(image);
}
reader.readAsDataURL(f);
@@ -69,8 +69,10 @@ console.log(el,$('body'));
}
function draw(_image) {
if (options.onComplete) options.onComplete(image);
// this module is unique because it creates the image
function draw(image) {
options.ui.display(image);
if (options.output) options.output(image);
}
function get() {

View File

@@ -8,19 +8,13 @@ module.exports = function ImageThreshold(options) {
var image;
function setup() {
options.ui = options.createUserInterface({
selector: 'mod-image-threshold'
});
}
function draw(_image) {
function draw(inputImage) {
var canvas = document.createElement('canvas');
canvas.width = _image.naturalWidth;
canvas.height = _image.naturalHeight;
canvas.width = inputImage.naturalWidth;
canvas.height = inputImage.naturalHeight;
var context = canvas.getContext('2d');
context.drawImage(_image, 0, 0 );
var imageData = context.getImageData(0, 0, _image.naturalWidth, _image.naturalHeight);
context.drawImage(inputImage, 0, 0 );
var imageData = context.getImageData(0, 0, inputImage.naturalWidth, inputImage.naturalHeight);
var imageThreshold = require('image-filter-threshold');
var imageFilterCore = require('image-filter-core');
@@ -31,7 +25,7 @@ module.exports = function ImageThreshold(options) {
}).then(function (imageData) {
image = new Image();
image.onload = function onLoad() {
if (options.onComplete) options.onComplete(image);
if (options.output) options.output(image);
}
image.src = imageFilterCore.convertImageDataToCanvasURL(imageData);
});
@@ -44,7 +38,6 @@ module.exports = function ImageThreshold(options) {
return {
title: "Threshold image",
options: options,
setup: setup,
draw: draw,
get: get
}

View File

@@ -5,30 +5,23 @@ module.exports = function NdviRed(options) {
options = options || {};
var image;
function setup() {
options.ui = options.createUserInterface({
selector: 'mod-ndvi-red'
});
}
function draw(_image) {
require('./PixelManipulation.js')(_image, {
onComplete: options.onComplete,
changePixel: changePixel
});
}
//function setup() {} // optional
function draw(image) {
function changePixel(r, g, b, a) {
var ndvi = 255 * (b - r) / (1.00 * b + r);
return [ndvi, ndvi, ndvi, a];
}
return require('./PixelManipulation.js')(image, {
output: options.output,
changePixel: changePixel
});
}
return {
title: "NDVI for red-filtered cameras (blue is infrared)",
options: options,
draw: draw,
setup: setup
//setup: setup, // optional
draw: draw
}
}

View File

@@ -52,7 +52,7 @@ module.exports = function PixelManipulation(image, options) {
img.src = 'data:image/' + options.format + ';base64,' + buffer.read().toString();
if (options.onComplete) options.onComplete(img);
if (options.output) options.output(img);
}).pipe(buffer);

View File

@@ -9,14 +9,6 @@ module.exports = function Plot(options) {
var image;
function setup() {
options.ui = options.createUserInterface({
selector: 'mod-plot'
});
}
function draw(_image) {
/* https://plot.ly/javascript/heatmap-and-contour-colorscales/#custom-colorscale
@@ -61,7 +53,7 @@ module.exports = function Plot(options) {
Plotly.newPlot('plot-' + random, data, layout)
/* .then(function afterPlot(graphData) {
options.onComplete(Plotly.toImage(graphData, {
options.output(Plotly.toImage(graphData, {
format: 'jpeg',
height: _image.height,
width: _image.width
@@ -76,7 +68,6 @@ module.exports = function Plot(options) {
return {
title: "Plot with colorbar",
options: options,
draw: draw,
setup: setup
draw: draw
}
}