diff --git a/dist/image-sequencer.js b/dist/image-sequencer.js index f63b2ee6..a3224152 100644 --- a/dist/image-sequencer.js +++ b/dist/image-sequencer.js @@ -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.setup) module.setup(); + if (module.name !== "image-select") { - 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('
'); - 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('
'); + 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('

' + module.title + '

'); + } 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) { - // PixelManipulation returns an image - require('./PixelManipulation.js')(_image, { - onComplete: options.onComplete, + function draw(image) { + function changePixel(r, g, b, a) { + return [0, g, 0, a]; + } + 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() {} // optional - function setup() { - options.ui = options.createUserInterface({ - selector: 'mod-ndvi-red' - }); - } - - function draw(_image) { - require('./PixelManipulation.js')(_image, { - onComplete: options.onComplete, + 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 }); } - function changePixel(r, g, b, a) { - var ndvi = 255 * (b - r) / (1.00 * b + r); - return [ndvi, ndvi, ndvi, a]; - } - 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 } } diff --git a/index.html b/index.html index 40d6a320..baabd142 100644 --- a/index.html +++ b/index.html @@ -65,7 +65,7 @@ sequencer = ImageSequencer(); -// sequencer.loadImage('examples/grid.png'); + sequencer.loadImage('examples/grid.png'); sequencer.addStep('ndvi-red'); sequencer.addStep('image-threshold'); diff --git a/src/ImageSequencer.AddStep.js b/src/ImageSequencer.AddStep.js new file mode 100644 index 00000000..e69de29b diff --git a/src/ImageSequencer.js b/src/ImageSequencer.js index c5116fac..63e9c81c 100644 --- a/src/ImageSequencer.js +++ b/src/ImageSequencer.js @@ -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.setup) module.setup(); + if (module.name !== "image-select") { - 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 { diff --git a/src/UserInterface.js b/src/UserInterface.js index 27e79e84..6c72af23 100644 --- a/src/UserInterface.js +++ b/src/UserInterface.js @@ -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('
'); - 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('
'); + 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('

' + module.title + '

'); + } return { - create: create, + el: options.el, + uniqueSelector: options.uniqueSelector, + selector: options.selector, + display: display, remove: remove } diff --git a/src/modules/GreenChannel.js b/src/modules/GreenChannel.js index 37d86bdd..cac57206 100644 --- a/src/modules/GreenChannel.js +++ b/src/modules/GreenChannel.js @@ -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) { - // PixelManipulation returns an image - require('./PixelManipulation.js')(_image, { - onComplete: options.onComplete, + function draw(image) { + function changePixel(r, g, b, a) { + return [0, g, 0, a]; + } + 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 } } diff --git a/src/modules/ImageSelect.js b/src/modules/ImageSelect.js index 878ceee4..40f22ecf 100644 --- a/src/modules/ImageSelect.js +++ b/src/modules/ImageSelect.js @@ -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() { diff --git a/src/modules/ImageThreshold.js b/src/modules/ImageThreshold.js index 7e821743..c9311ba1 100644 --- a/src/modules/ImageThreshold.js +++ b/src/modules/ImageThreshold.js @@ -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 } diff --git a/src/modules/NdviRed.js b/src/modules/NdviRed.js index f2de120a..36afc931 100644 --- a/src/modules/NdviRed.js +++ b/src/modules/NdviRed.js @@ -5,30 +5,23 @@ module.exports = function NdviRed(options) { options = options || {}; - var image; + //function setup() {} // optional - function setup() { - options.ui = options.createUserInterface({ - selector: 'mod-ndvi-red' - }); - } - - function draw(_image) { - require('./PixelManipulation.js')(_image, { - onComplete: options.onComplete, + 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 }); } - function changePixel(r, g, b, a) { - var ndvi = 255 * (b - r) / (1.00 * b + r); - return [ndvi, ndvi, ndvi, a]; - } - return { title: "NDVI for red-filtered cameras (blue is infrared)", options: options, - draw: draw, - setup: setup + //setup: setup, // optional + draw: draw } } diff --git a/src/modules/PixelManipulation.js b/src/modules/PixelManipulation.js index 5017277c..de7b2a70 100644 --- a/src/modules/PixelManipulation.js +++ b/src/modules/PixelManipulation.js @@ -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); diff --git a/src/modules/Plot.js b/src/modules/Plot.js index 8f541bd6..10cb2c52 100644 --- a/src/modules/Plot.js +++ b/src/modules/Plot.js @@ -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 } }