mirror of
https://github.com/publiclab/image-sequencer.git
synced 2025-12-12 11:20:02 +01:00
major restructuring, ui code separation and sequential processing
This commit is contained in:
31
README.md
31
README.md
@@ -5,6 +5,10 @@ ImageFlow
|
|||||||
|
|
||||||
* [ ] steps don't run on last step; they run on initial image
|
* [ ] steps don't run on last step; they run on initial image
|
||||||
|
|
||||||
|
|
||||||
|
// add createUserInterface() which is set up by default to draw on ImageBoardUI, but could be swapped for nothing, or an equiv. lib
|
||||||
|
// it could create the interface and use event listeners like module.on('draw', fn()); to update the interface
|
||||||
|
|
||||||
* [ ] spinners before panels are complete
|
* [ ] spinners before panels are complete
|
||||||
* [ ] ability to start running at any point -- already works?
|
* [ ] ability to start running at any point -- already works?
|
||||||
* [ ] setNextStep()?
|
* [ ] setNextStep()?
|
||||||
@@ -16,6 +20,8 @@ ImageFlow
|
|||||||
* [ ] comparisons with diff
|
* [ ] comparisons with diff
|
||||||
* [ ] standardize panel addition with submodule that offers Panel.display(image)
|
* [ ] standardize panel addition with submodule that offers Panel.display(image)
|
||||||
|
|
||||||
|
https://www.npmjs.com/package/histogram
|
||||||
|
|
||||||
* [ ] make an Infragram module that accepts a math expression
|
* [ ] make an Infragram module that accepts a math expression
|
||||||
* [ ] click to expand for all images
|
* [ ] click to expand for all images
|
||||||
* [ ] "add a new step" menu
|
* [ ] "add a new step" menu
|
||||||
@@ -27,3 +33,28 @@ ImageFlow
|
|||||||
* we should make defaults a config of the first module
|
* we should make defaults a config of the first module
|
||||||
|
|
||||||
* [ ] output in animated Gif?
|
* [ ] output in animated Gif?
|
||||||
|
|
||||||
|
****
|
||||||
|
|
||||||
|
## Why
|
||||||
|
|
||||||
|
How can Scratch/others do what a scientific tool does?
|
||||||
|
|
||||||
|
* if it passes the same tests, it's empirically equivalent
|
||||||
|
|
||||||
|
Competitive with program X? Build bridges
|
||||||
|
|
||||||
|
Show your work: Collins
|
||||||
|
|
||||||
|
Activities: teachability -- each step
|
||||||
|
|
||||||
|
Evidentiary: Chain of custody
|
||||||
|
|
||||||
|
Store each previous step, log, in metadata -- like shapefiles
|
||||||
|
|
||||||
|
****
|
||||||
|
|
||||||
|
Ideas:
|
||||||
|
|
||||||
|
https://github.com/vicapow/jsqrcode
|
||||||
|
|
||||||
|
|||||||
5655
dist/imageboard.js
vendored
5655
dist/imageboard.js
vendored
File diff suppressed because one or more lines are too long
@@ -44,6 +44,7 @@
|
|||||||
<option value="ndvi-red">NDVI with red filter</option>
|
<option value="ndvi-red">NDVI with red filter</option>
|
||||||
<option value="green-channel">Green channel</option>
|
<option value="green-channel">Green channel</option>
|
||||||
<option value="plot">Plot with colorbar</option>
|
<option value="plot">Plot with colorbar</option>
|
||||||
|
<option value="image-threshold">Threshold image</option>
|
||||||
</select>
|
</select>
|
||||||
<p><button class="btn btn-default add-step">Add step</button></p>
|
<p><button class="btn btn-default add-step">Add step</button></p>
|
||||||
</form>
|
</form>
|
||||||
@@ -68,7 +69,8 @@
|
|||||||
// });
|
// });
|
||||||
|
|
||||||
imageboard.addStep('ndvi-red');
|
imageboard.addStep('ndvi-red');
|
||||||
imageboard.addStep('plot');
|
imageboard.addStep('image-threshold');
|
||||||
|
//imageboard.addStep('plot');
|
||||||
|
|
||||||
$('.add-step').click(function(e) {
|
$('.add-step').click(function(e) {
|
||||||
|
|
||||||
|
|||||||
@@ -29,8 +29,8 @@
|
|||||||
"buffer": "^5.0.2",
|
"buffer": "^5.0.2",
|
||||||
"plotly.js": "^1.21.2",
|
"plotly.js": "^1.21.2",
|
||||||
|
|
||||||
"image-filter-threshold": "^0.0.8",
|
"image-filter-threshold": "git+https://github.com/canastro/image-filter-threshold#prebundle",
|
||||||
"babelify": "^7.2.0",
|
"image-filter-core": "git+https://github.com/canastro/image-filter-core#prebundle",
|
||||||
|
|
||||||
"browserify": "13.0.0",
|
"browserify": "13.0.0",
|
||||||
"grunt": "^0.4.5",
|
"grunt": "^0.4.5",
|
||||||
|
|||||||
@@ -1,42 +1,52 @@
|
|||||||
ImageBoard = function ImageBoard(options) {
|
ImageBoard = function ImageBoard(options) {
|
||||||
|
|
||||||
options = options || {};
|
options = options || {};
|
||||||
options.container = options.container || '.panels';
|
options.defaultSteps = options.defaultSteps || function defaultSteps() {
|
||||||
|
addStep('image-select');
|
||||||
var image;
|
|
||||||
var modules = require('./Modules');
|
|
||||||
var steps = [];
|
|
||||||
|
|
||||||
function addStep(name, stepOptions) {
|
|
||||||
steps.push({
|
|
||||||
module: modules[name]({
|
|
||||||
container: options.container // this is a bit redundant
|
|
||||||
}),
|
|
||||||
options: stepOptions
|
|
||||||
});
|
|
||||||
steps[steps.length - 1].module.setup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// by default, always begin with an ImageSelect module
|
var image,
|
||||||
addStep('image-select');
|
steps = [],
|
||||||
|
modules = require('./Modules'),
|
||||||
|
ui = require('./UserInterface')();
|
||||||
|
|
||||||
function setup() {
|
options.defaultSteps();
|
||||||
|
|
||||||
steps.forEach(function forEachStep(step, index) {
|
function addStep(name, o) {
|
||||||
|
console.log('adding step "' + name + '"');
|
||||||
|
|
||||||
// different behavior for first step:
|
o = o || {};
|
||||||
var onComplete = (index !== 0) ? false : function (image) {
|
o.container = o.container || options.selector;
|
||||||
run(image); // begin run on image selection
|
o.createUserInterface = o.createUserInterface || ui.create;
|
||||||
|
|
||||||
|
var module = modules[name](o);
|
||||||
|
|
||||||
|
steps.push(module);
|
||||||
|
|
||||||
|
if (steps.length > 1) {
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (step.module.setup) step.module.setup(onComplete);
|
module.options.onComplete = function onComplete(_image) {
|
||||||
|
if (module.options.ui) module.options.ui.el.html(_image);
|
||||||
|
}
|
||||||
|
|
||||||
});
|
} else {
|
||||||
|
|
||||||
|
module.setup(); // just set up initial ImageSelect
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setup();
|
|
||||||
|
|
||||||
function log(msg) {
|
function log(msg) {
|
||||||
$('.log').append(msg + ' at ' + new Date());
|
$('.log').append(msg + ' at ' + new Date());
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
@@ -44,34 +54,21 @@ ImageBoard = function ImageBoard(options) {
|
|||||||
|
|
||||||
function run() {
|
function run() {
|
||||||
|
|
||||||
var lastImage;
|
steps[0].draw();
|
||||||
|
|
||||||
// THIS MUST BE EVENT BASED OR CALLBACKED -- ITS ASYNCHRONOUS
|
|
||||||
steps.forEach(function forEachStep(step) {
|
|
||||||
|
|
||||||
step.module.run(lastImage, function onComplete(image) {
|
|
||||||
lastImage = image;
|
|
||||||
log('completed step "' + step.module.title + '"');
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
return lastImage;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// load default starting image
|
// load default starting image
|
||||||
// i.e. from parameter
|
// i.e. from parameter
|
||||||
|
// this could send the image to ImageSelect, or something?
|
||||||
|
// not currently working
|
||||||
function loadImage(src, callback) {
|
function loadImage(src, callback) {
|
||||||
|
|
||||||
image = new Image();
|
image = new Image();
|
||||||
|
|
||||||
image.onload = function() {
|
image.onload = function() {
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
||||||
if (callback) callback(image);
|
if (callback) callback(image);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
image.src = src;
|
image.src = src;
|
||||||
@@ -83,7 +80,8 @@ ImageBoard = function ImageBoard(options) {
|
|||||||
addStep: addStep,
|
addStep: addStep,
|
||||||
run: run,
|
run: run,
|
||||||
modules: modules,
|
modules: modules,
|
||||||
steps: steps
|
steps: steps,
|
||||||
|
ui: ui
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,71 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* Core modules; externalized these wrapper modules with:
|
* Core modules
|
||||||
* 'image-select': require('./modules/ImageSelect.js'),
|
|
||||||
*/
|
*/
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
||||||
// How much of this wrapper is necessary?
|
'image-select': require('./modules/ImageSelect'),
|
||||||
// Could it be for UI, and the actual module is for functionality?
|
'green-channel': require('./modules/GreenChannel'),
|
||||||
// But 'image-select' is not set up that way; it's UI. But it's special.
|
'ndvi-red': require('./modules/NdviRed'),
|
||||||
'image-select': function ImageSelect() {
|
'plot': require('./modules/Plot'),
|
||||||
|
'image-threshold': require('./modules/ImageThreshold')
|
||||||
|
|
||||||
var imageselect;
|
|
||||||
|
|
||||||
function setup(onComplete) {
|
|
||||||
imageselect = require('./modules/ImageSelect.js')({
|
|
||||||
output: onComplete,
|
|
||||||
selector: '#drop'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function run(image, onComplete) {
|
|
||||||
if (onComplete) onComplete(get());
|
|
||||||
}
|
|
||||||
|
|
||||||
function get() {
|
|
||||||
return imageselect.getImage();
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
title: "Select image",
|
|
||||||
run: run,
|
|
||||||
setup: setup,
|
|
||||||
get: get
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
'green-channel': require('./modules/GreenChannel.js'),
|
|
||||||
'ndvi-red': require('./modules/NdviRed.js'),
|
|
||||||
'plot': require('./modules/Plot.js'),
|
|
||||||
|
|
||||||
/*
|
|
||||||
'image-threshold': {
|
|
||||||
name: "Threshold image",
|
|
||||||
run: function imageThreshold(image, onComplete, options) {
|
|
||||||
|
|
||||||
options = options || {};
|
|
||||||
options.threshold = options.threshold || 30;
|
|
||||||
|
|
||||||
var canvas = document.createElement('canvas');
|
|
||||||
var context = canvas.getContext('2d');
|
|
||||||
context.drawImage(image, 0, 0 );
|
|
||||||
var imageData = context.getImageData(0, 0, element.width, element.height);
|
|
||||||
|
|
||||||
var imageThreshold = require('../node_modules/image-filter-threshold/src/index.js');
|
|
||||||
|
|
||||||
var result = imageThreshold({
|
|
||||||
data: imageData,
|
|
||||||
threshold: options.threshold
|
|
||||||
}).then(function (result) {
|
|
||||||
var image = new Image();
|
|
||||||
image.onload = function onLoad() {
|
|
||||||
onComplete(image);
|
|
||||||
}
|
|
||||||
image.src = result;
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|||||||
26
src/UserInterface.js
Normal file
26
src/UserInterface.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Default UI for ImageBoard
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
create: create
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -5,26 +5,17 @@ module.exports = function GreenChannel(options) {
|
|||||||
|
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
var image,
|
var image;
|
||||||
selector = 'mod-green-channel',
|
|
||||||
random = options.random || parseInt(Math.random() * (new Date()).getTime() / 1000000),
|
|
||||||
uniqueSelector = selector + '-' + random,
|
|
||||||
el;
|
|
||||||
|
|
||||||
// should we just run setup on constructor?
|
|
||||||
function setup() {
|
function setup() {
|
||||||
|
options.ui = options.createUserInterface({
|
||||||
$(options.container).append('<div class="panel ' + selector + ' ' + uniqueSelector + '"></div>');
|
selector: 'mod-green-channel'
|
||||||
el = $('.' + uniqueSelector);
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function run(_image, onComplete, options) {
|
function draw(_image) {
|
||||||
require('./PixelManipulation.js')(_image, {
|
require('./PixelManipulation.js')(_image, {
|
||||||
onComplete: function displayImage(image) {
|
onComplete: options.onComplete,
|
||||||
el.html(image);
|
|
||||||
onComplete(image);
|
|
||||||
},
|
|
||||||
changePixel: changePixel
|
changePixel: changePixel
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -36,8 +27,8 @@ module.exports = function GreenChannel(options) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
title: "Green channel only",
|
title: "Green channel only",
|
||||||
run: run,
|
options: options,
|
||||||
setup: setup,
|
draw: draw,
|
||||||
image: image
|
setup: setup
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,68 +7,78 @@ module.exports = function ImageSelect(options) {
|
|||||||
options = options || {};
|
options = options || {};
|
||||||
options.selector = options.selector || "#drop";
|
options.selector = options.selector || "#drop";
|
||||||
options.inputSelector = options.inputSelector || "#file-select";
|
options.inputSelector = options.inputSelector || "#file-select";
|
||||||
options.output = options.output || function output(image) {
|
options.ui = options.ui || {};
|
||||||
return image;
|
options.ui.el = options.ui.el || $(options.selector);
|
||||||
}
|
|
||||||
|
|
||||||
var image;
|
var image,
|
||||||
|
el = options.ui.el;
|
||||||
|
|
||||||
// CSS UI
|
function setup() {
|
||||||
|
|
||||||
$(options.selector).on('dragenter', function(e) {
|
// CSS UI
|
||||||
$(options.selector).addClass('hover');
|
el.on('dragenter', function(e) {
|
||||||
});
|
el.addClass('hover');
|
||||||
|
});
|
||||||
|
|
||||||
$(options.selector).on('dragleave', function(e) {
|
el.on('dragleave', function(e) {
|
||||||
$(options.selector).removeClass('hover');
|
el.removeClass('hover');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Drag & Drop behavior
|
// Drag & Drop behavior
|
||||||
|
function onImage(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation(); // stops the browser from redirecting.
|
||||||
|
|
||||||
var onImage = function(e) {
|
var files;
|
||||||
e.preventDefault();
|
if (e.target && e.target.files) files = e.target.files;
|
||||||
e.stopPropagation(); // stops the browser from redirecting.
|
else files = e.dataTransfer.files;
|
||||||
|
|
||||||
var files;
|
for (var i = 0, f; f = files[i]; i++) {
|
||||||
if (e.target && e.target.files) files = e.target.files;
|
// Read the File objects in this FileList.
|
||||||
else files = e.dataTransfer.files;
|
|
||||||
|
|
||||||
for (var i = 0, f; f = files[i]; i++) {
|
reader = new FileReader();
|
||||||
// Read the File objects in this FileList.
|
reader.onload = function(e) {
|
||||||
|
// we should trigger "load" event here
|
||||||
|
|
||||||
reader = new FileReader();
|
image = new Image();
|
||||||
reader.onload = function(e) {
|
image.src = event.target.result;
|
||||||
// we should trigger "load" event here
|
|
||||||
|
|
||||||
image = new Image();
|
el.html(image); // may be redundant
|
||||||
image.src = event.target.result;
|
|
||||||
|
|
||||||
$(options.selector).html(image);
|
// this is done once per image:
|
||||||
|
options.onComplete(image);
|
||||||
|
}
|
||||||
|
reader.readAsDataURL(f);
|
||||||
|
|
||||||
// this is done once per image:
|
|
||||||
options.output(image);
|
|
||||||
}
|
}
|
||||||
reader.readAsDataURL(f);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onDragOver(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
e.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
|
||||||
|
}
|
||||||
|
|
||||||
|
el.on('dragover', onDragOver, false);
|
||||||
|
el[0].addEventListener('drop', onImage, false);
|
||||||
|
$(options.inputSelector).change(onImage);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDragOver(e) {
|
function draw(_image) {
|
||||||
e.stopPropagation();
|
if (options.onComplete) options.onComplete(image);
|
||||||
e.preventDefault();
|
|
||||||
e.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$(options.selector).on('dragover', onDragOver, false);
|
function get() {
|
||||||
$(options.selector)[0].addEventListener('drop', onImage, false);
|
|
||||||
$(options.inputSelector).change(onImage);
|
|
||||||
|
|
||||||
function getImage() {
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getImage: getImage
|
title: "Select image",
|
||||||
|
options: options,
|
||||||
|
draw: draw,
|
||||||
|
setup: setup,
|
||||||
|
get: get
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
51
src/modules/ImageThreshold.js
Normal file
51
src/modules/ImageThreshold.js
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Image thresholding with 'image-filter-threshold'
|
||||||
|
*/
|
||||||
|
module.exports = function ImageThreshold(options) {
|
||||||
|
|
||||||
|
options = options || {};
|
||||||
|
options.threshold = options.threshold || 30;
|
||||||
|
|
||||||
|
var image;
|
||||||
|
|
||||||
|
function setup() {
|
||||||
|
options.ui = options.createUserInterface({
|
||||||
|
selector: 'mod-image-threshold'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function draw(_image) {
|
||||||
|
var canvas = document.createElement('canvas');
|
||||||
|
canvas.width = _image.width;
|
||||||
|
canvas.height = _image.height;
|
||||||
|
var context = canvas.getContext('2d');
|
||||||
|
context.drawImage(_image, 0, 0 );
|
||||||
|
var imageData = context.getImageData(0, 0, _image.width, _image.height);
|
||||||
|
|
||||||
|
var imageThreshold = require('image-filter-threshold');
|
||||||
|
var imageFilterCore = require('image-filter-core');
|
||||||
|
|
||||||
|
var result = imageThreshold({
|
||||||
|
data: imageData,
|
||||||
|
threshold: options.threshold
|
||||||
|
}).then(function (imageData) {
|
||||||
|
image = new Image();
|
||||||
|
image.onload = function onLoad() {
|
||||||
|
if (options.onComplete) options.onComplete(image);
|
||||||
|
}
|
||||||
|
image.src = imageFilterCore.convertImageDataToCanvasURL(imageData);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function get() {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: "Threshold image",
|
||||||
|
options: options,
|
||||||
|
setup: setup,
|
||||||
|
draw: draw,
|
||||||
|
get: get
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,29 +5,19 @@ module.exports = function NdviRed(options) {
|
|||||||
|
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
var image,
|
var image;
|
||||||
selector = 'mod-ndvi-red',
|
|
||||||
random = options.random || parseInt(Math.random() * (new Date()).getTime() / 1000000),
|
|
||||||
uniqueSelector = selector + '-' + random,
|
|
||||||
el;
|
|
||||||
|
|
||||||
// should we just run setup on constructor?
|
|
||||||
function setup() {
|
function setup() {
|
||||||
|
options.ui = options.createUserInterface({
|
||||||
$(options.container).append('<div class="panel ' + selector + ' ' + uniqueSelector + '"></div>');
|
selector: 'mod-ndvi-red'
|
||||||
el = $('.' + uniqueSelector);
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function run(_image, onComplete, options) {
|
function draw(_image) {
|
||||||
require('./PixelManipulation.js')(_image, {
|
require('./PixelManipulation.js')(_image, {
|
||||||
onComplete: function displayImage(image) {
|
onComplete: options.onComplete,
|
||||||
el.html(image);
|
|
||||||
onComplete(image);
|
|
||||||
},
|
|
||||||
changePixel: changePixel
|
changePixel: changePixel
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function changePixel(r, g, b, a) {
|
function changePixel(r, g, b, a) {
|
||||||
@@ -37,8 +27,8 @@ module.exports = function NdviRed(options) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
title: "NDVI for red-filtered cameras (blue is infrared)",
|
title: "NDVI for red-filtered cameras (blue is infrared)",
|
||||||
run: run,
|
options: options,
|
||||||
setup: setup,
|
draw: draw,
|
||||||
image: image
|
setup: setup
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,11 +48,11 @@ module.exports = function PixelManipulation(image, options) {
|
|||||||
savePixels(pixels, options.format)
|
savePixels(pixels, options.format)
|
||||||
.on('end', function() {
|
.on('end', function() {
|
||||||
|
|
||||||
var image = new Image();
|
var img = new Image();
|
||||||
|
|
||||||
if (options.onComplete) options.onComplete(image);
|
img.src = 'data:image/' + options.format + ';base64,' + buffer.read().toString();
|
||||||
|
|
||||||
image.src = 'data:image/' + options.format + ';base64,' + buffer.read().toString();
|
if (options.onComplete) options.onComplete(img);
|
||||||
|
|
||||||
}).pipe(buffer);
|
}).pipe(buffer);
|
||||||
|
|
||||||
|
|||||||
@@ -4,26 +4,20 @@
|
|||||||
module.exports = function Plot(options) {
|
module.exports = function Plot(options) {
|
||||||
|
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
options.colorscale = options.colorscale || 'Jet',//'RdBu';
|
||||||
|
options.type = options.type || 'contour'; // or 'heatmap'
|
||||||
|
|
||||||
var image,
|
var image;
|
||||||
selector = 'mod-plot',
|
|
||||||
random = options.random || parseInt(Math.random() * (new Date()).getTime() / 1000000),
|
|
||||||
uniqueSelector = selector + '-' + random,
|
|
||||||
el;
|
|
||||||
|
|
||||||
// should we just run setup on constructor?
|
|
||||||
function setup() {
|
function setup() {
|
||||||
|
|
||||||
$(options.container).append('<div class="panel ' + selector + ' ' + uniqueSelector + '"></div>');
|
options.ui = options.createUserInterface({
|
||||||
el = $('.' + uniqueSelector);
|
selector: 'mod-plot'
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function run(_image, onComplete, options) {
|
function draw(_image) {
|
||||||
|
|
||||||
options = options || {};
|
|
||||||
options.colorscale = options.colorscale || 'Jet',//'RdBu';
|
|
||||||
options.type = options.type || 'contour'; // or 'heatmap'
|
|
||||||
|
|
||||||
/* https://plot.ly/javascript/heatmap-and-contour-colorscales/#custom-colorscale
|
/* https://plot.ly/javascript/heatmap-and-contour-colorscales/#custom-colorscale
|
||||||
type: 'contour',
|
type: 'contour',
|
||||||
@@ -41,7 +35,7 @@ module.exports = function Plot(options) {
|
|||||||
var data = [{
|
var data = [{
|
||||||
z: [],
|
z: [],
|
||||||
colorscale: options.colorscale,
|
colorscale: options.colorscale,
|
||||||
type: 'heatmap'
|
type: options.type
|
||||||
}];
|
}];
|
||||||
|
|
||||||
getPixels(_image.src, function(err, pixels) {
|
getPixels(_image.src, function(err, pixels) {
|
||||||
@@ -61,19 +55,28 @@ module.exports = function Plot(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var layout = { title: '' };
|
var layout = { title: '' };
|
||||||
el.append('<div id="plot-' + random + '"></div>');
|
random = parseInt(Math.random() * (new Date()).getTime() / 1000000);
|
||||||
Plotly.newPlot('plot-' + random, data, layout);
|
|
||||||
|
|
||||||
// return Plotly.toImage(gd,{format:'jpeg',height:400,width:400});
|
options.ui.el.append('<div id="plot-' + random + '"></div>');
|
||||||
|
Plotly.newPlot('plot-' + random, data, layout)
|
||||||
|
/* .then(function afterPlot(graphData) {
|
||||||
|
|
||||||
|
options.onComplete(Plotly.toImage(graphData, {
|
||||||
|
format: 'jpeg',
|
||||||
|
height: _image.height,
|
||||||
|
width: _image.width
|
||||||
|
}));
|
||||||
|
|
||||||
|
});
|
||||||
|
*/
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: "Plot with colorbar",
|
title: "Plot with colorbar",
|
||||||
run: run,
|
options: options,
|
||||||
setup: setup,
|
draw: draw,
|
||||||
image: image
|
setup: setup
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user