diff --git a/app/index.html b/app/index.html
index c994b45..0aaf368 100644
--- a/app/index.html
+++ b/app/index.html
@@ -87,6 +87,8 @@
var G_GUI_Controller = new function() {
this.pixelCountX = 8;
this.pixelCountY = 8;
+ this.brightness = 0;
+ this.contrast = 0;
this.digitalMag = "1.00x";
this.advancedMode = false;
this.updateViews = function(){
@@ -95,6 +97,14 @@
G_Update_GroundTruth();
G_Update_InfoDisplays();
};
+ this.updateFilters = function(){ G_UpdateFilters(); },
+ this.globalBC = true;
+ this.resetBC = function(){
+ let cGui = G_GUI_Controller.controls;
+ cGui.brightness.setValue(0);
+ cGui.contrast.setValue(0);
+ G_UpdateFilters();
+ },
this.groundTruthImg = 'grains2tl.png';
this.pause_vSEM = G_VSEM_PAUSED;
this.doImageMetric = G_IMG_METRIC_ENABLED;
@@ -114,6 +124,16 @@
var gui_ip = gui.addFolder('Imaging Parameters');
gui_ip.add(G_GUI_Controller, 'pixelCountX', 1, 64, 1).onChange(G_GUI_Controller.updateViews);
gui_ip.add(G_GUI_Controller, 'pixelCountY', 1, 64, 1).onChange(G_GUI_Controller.updateViews);
+ G_GUI_Controller.controls.brightness = gui_ip
+ .add(G_GUI_Controller, 'brightness', -1, 1, 0.01)
+ .onChange(G_GUI_Controller.updateFilters);
+ G_GUI_Controller.controls.contrast = gui_ip
+ .add(G_GUI_Controller, 'contrast', -100, 100, 0.1)
+ .onChange(G_GUI_Controller.updateFilters);
+ gui_ip.add(G_GUI_Controller, 'globalBC')
+ .name('Global B/C')
+ .onChange(G_GUI_Controller.updateFilters);
+ gui_ip.add(G_GUI_Controller, 'resetBC').name('Reset Brightness / Contrast');
gui_ip.add(G_GUI_Controller, 'digitalMag').listen();
G_GUI_Controller.controls.pixelSize_nm = gui_ip
.add(G_GUI_Controller, 'pixelSize_nm', 1, 1000, 1).onChange(function(){
@@ -157,10 +177,9 @@
aboutBtn.name("About " + G_APP_NAME + " / Credits");
gui_io.open();
- $("#options").append(gui.domElement).draggable({
- // containment: 'body',
- handle: '#options-handle',
- });
+ $("#options").append(gui.domElement)
+ .position({at:'right bottom', my:'right bottom', of: '#options-anchor'})
+ .draggable({handle: '#options-handle'});
// used to auto-name the export files with a counter
var G_Export_img_count = 0;
diff --git a/app/src/css/style.css b/app/src/css/style.css
index 5df346b..a96cda2 100644
--- a/app/src/css/style.css
+++ b/app/src/css/style.css
@@ -104,13 +104,14 @@ summary {
#options-anchor {
display: inline-block;
position: fixed;
- top: 35vh;
- right: 0.25em;
+ bottom: 0;
+ right: 0;
z-index: 69;
user-select: none;
cursor: move;
width: 0;
height: 0;
+ margin: 2em 1em;
}
#options-full-resample {
diff --git a/app/src/main.js b/app/src/main.js
index 858a00d..1911cfd 100644
--- a/app/src/main.js
+++ b/app/src/main.js
@@ -15,6 +15,7 @@
* G_Update_InfoDisplays
* G_update_ImgMetrics
* G_UpdateRuler
+ * G_UpdateFilters
* G_AUTO_PREVIEW_LIMIT
* G_VSEM_PAUSED
* G_IMG_METRIC_ENABLED
@@ -88,6 +89,8 @@ var G_Update_InfoDisplays = null;
var G_update_ImgMetrics = null;
/** global reference to update the ruler */
var G_UpdateRuler = null;
+/** global reference to update/apply image filters */
+var G_UpdateFilters = null;
/** a global reference to the main body container that holds the boxes/stages.
* @todo do we still need this? Maybe remove... */
@@ -376,6 +379,36 @@ function OnImageLoaded(eImg, stages){
doUpdate();
});
+ function updateFilters(){
+ var doBC = Utils.getGlobalBCInput();
+ if (doBC) {
+ // stages that we want to apply filters to...
+ var fStages = [
+ groundtruthMapStage, baseImageStage,
+ spotContentStage, probeLayoutStage,
+ layoutSampledStage
+ ];
+
+ // apply the filters
+ const brightness = Utils.getBrightnessInput();
+ const contrast = Utils.getContrastInput();
+ for (let i = 0; i < fStages.length; i++) {
+ const fStage = fStages[i];
+ let image = Utils.getFirstImageFromStage(fStage);
+ Utils.applyBrightnessContrast(image, brightness, contrast);
+ }
+
+ // for the resulting images, the sampling function, Utils.ComputeProbeValue_gs(),
+ // is made B/C aware and using Konva's built-in filters directly.
+ }
+
+ // call global visual update
+ doUpdate();
+ }
+ // update filters once immediately
+ updateFilters();
+ G_UpdateFilters = updateFilters;
+
doUpdate();
Utils.updateAdvancedMode();
diff --git a/app/src/utils.js b/app/src/utils.js
index 46de8a3..6b23fa3 100644
--- a/app/src/utils.js
+++ b/app/src/utils.js
@@ -143,6 +143,9 @@ const Utils = {
getRowsInput: function(){ return G_GUI_Controller.pixelCountY; },
getColsInput: function(){ return G_GUI_Controller.pixelCountX; },
+ getBrightnessInput: function(){ return G_GUI_Controller.brightness; },
+ getContrastInput: function(){ return G_GUI_Controller.contrast; },
+ getGlobalBCInput: function(){ return G_GUI_Controller.globalBC; },
getCellWInput: function(){ return this.getInputValueInt($('#iCellW')); },
getCellHInput: function(){ return this.getInputValueInt($('#iCellH')); },
getSpotXInput: function(){ return this.getInputValueInt($('#iSpotX')); },
@@ -1504,6 +1507,17 @@ const Utils = {
// grab the pixel data from the pixel selection area
var pxData = ctx.getImageData(0,0,cv.width,cv.height);
+ // hack to directly use Konva's built-in filters code
+ if (typeof Konva != 'undefined') {
+ var brightnessFunc = Konva.Filters.Brighten.bind({
+ brightness: () => this.getBrightnessInput()});
+ var contrastFunc = Konva.Filters.Contrast.bind({
+ contrast: () => this.getContrastInput()});
+ // apply it directly to out image data before we sample it.
+ brightnessFunc(pxData);
+ contrastFunc(pxData);
+ }
+
// compute the average pixel (excluding 0-0-0-0 rgba pixels)
var pxColor = this.get_avg_pixel_gs(pxData);
@@ -1515,6 +1529,43 @@ const Utils = {
return pxColor;
},
+ /**
+ * Applies Brightness/Contrast (B/C) values to a given Konva stage or drawable.
+ * @param {*} drawable The Konva stage or drawable / drawElement.
+ * @param {*} brightness The brightness value, from -1 to 1.
+ * @param {*} contrast The contrast value, mainly from -100 to 100.
+ */
+ applyBrightnessContrast: function(drawable, brightness=0, contrast=0) {
+ // cache step is need for filter effects to be visible.
+ // https://konvajs.org/docs/performance/Shape_Caching.html
+ drawable.cache();
+
+ // Filters: https://konvajs.org/api/Konva.Filters.html
+ // Brightness => https://konvajs.org/docs/filters/Brighten.html
+ // Contrast => https://konvajs.org/docs/filters/Contrast.html
+ var currentFilters = drawable.filters();
+ // null check, default to empty array if n/a.
+ currentFilters = currentFilters != null ? currentFilters : [];
+ // Add filter if not already included...
+ var currentFiltersByName = currentFilters.map(x => x.name);
+ var filtersToSet = currentFilters;
+ var added = 0;
+ ['Brighten', 'Contrast'].forEach(filterName => {
+ if (!currentFiltersByName.includes(filterName)) {
+ filtersToSet.push(Konva.Filters[filterName]);
+ added++;
+ }
+ });
+ drawable.filters(filtersToSet);
+ if (G_DEBUG) {
+ console.log("filters added:", added);
+ }
+
+ // apply B/C filter values
+ drawable.brightness(brightness);
+ drawable.contrast(contrast);
+ },
+
/**
* Find and gets the first "image" type from the first layer of the given Konva stage
* @param {*} stage the stage to search through