Skip to content

Commit 682bee3

Browse files
committed
background adjustment
1 parent 51da1b3 commit 682bee3

5 files changed

Lines changed: 121 additions & 4 deletions

File tree

res/shaders/ImageFragment.glsl

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,26 @@ float fmodf(float x, float y)
2828
return x - y * floor(x / y);
2929
}
3030

31+
vec3 RGBtoHCV(vec3 rgb)
32+
{
33+
// RGB [0..1] to Hue-Chroma-Value [0..1]
34+
// Based on work by Sam Hocevar and Emil Persson
35+
vec4 p = (rgb.g < rgb.b) ? vec4(rgb.bg, -1., 2. / 3.) : vec4(rgb.gb, 0., -1. / 3.);
36+
vec4 q = (rgb.r < p.x) ? vec4(p.xyw, rgb.r) : vec4(rgb.r, p.yzx);
37+
float c = q.x - min(q.w, q.y);
38+
float h = abs((q.w - q.y) / (6. * c + 1e-10) + q.z);
39+
return vec3(h, c, q.x);
40+
}
41+
42+
vec3 rgbToHsl(vec3 rgb)
43+
{
44+
// RGB [0..1] to Hue-Saturation-Lightness [0..1]
45+
vec3 hcv = RGBtoHCV(rgb);
46+
float z = hcv.z - hcv.y * 0.5;
47+
float s = hcv.y / (1. - abs(z * 2. - 1.) + 1e-10);
48+
return vec3(hcv.x, s, z);
49+
}
50+
3151
// Convert from HSL to RGB color space
3252
vec3 hslToRgb(float hue, float saturation, float lightness)
3353
{
@@ -128,8 +148,20 @@ void main(void)
128148
// Grab channel(s)
129149
float channel = toneMapChannel(displayRanges[0].x, displayRanges[0].y, texture(channelTextures, vec3(uv, 0)).r);
130150

151+
float intensity = toneMapChannel(displayRanges[1].x, displayRanges[1].y, texture(channelTextures, vec3(uv, 1)).r);
152+
131153
fragmentColor = texture(colorMapTexture, vec2(channel, 0));
132154

155+
float minBackground = displayRanges[1].x;
156+
float maxBackground = displayRanges[1].y;
157+
vec3 hsl = rgbToHsl(fragmentColor.rgb);
158+
float lightnessScaling = 0.0;
159+
if (maxBackground - minBackground > 0.001)
160+
lightnessScaling = (intensity - 0.5) * 0.5;
161+
162+
vec3 adjustedRgb = hslToRgb(360.0f * hsl.r, hsl.g, clamp(hsl.b + lightnessScaling, 0.0, 1.0));
163+
fragmentColor.rgb = adjustedRgb;
164+
133165
break;
134166
}
135167

src/ImageSettingsAction.cpp

Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,15 @@ ImageSettingsAction::ImageSettingsAction(QObject* parent, const QString& title)
2525
_interpolationTypeAction(this, "Interpolate", interpolationTypes.values(), "Bilinear"),
2626
_useConstantColorAction(this, "Use constant color", false),
2727
_fixChannelRangesToColorSpaceAction(this, "Set channel ranges to color space", false),
28-
_constantColorAction(this, "Constant color", QColor(Qt::white))
28+
_constantColorAction(this, "Constant color", QColor(Qt::white)),
29+
_useBackgroundAction(this, "Background"),
30+
_backgroundDimAction(this, "Background Dimension")
2931
{
3032
addAction(&_opacityAction);
3133
addAction(&_subsampleFactorAction);
3234
addAction(&_colorSpaceAction);
35+
addAction(&_useBackgroundAction);
36+
addAction(&_backgroundDimAction);
3337
addAction(&_scalarChannel1Action);
3438
addAction(&_scalarChannel2Action);
3539
addAction(&_scalarChannel3Action);
@@ -42,6 +46,9 @@ ImageSettingsAction::ImageSettingsAction(QObject* parent, const QString& title)
4246

4347
_subsampleFactorAction.setVisible(false);
4448

49+
_useBackgroundAction.setVisible(false);
50+
_backgroundDimAction.setVisible(false);
51+
4552
_opacityAction.setToolTip("Image layer opacity");
4653
_subsampleFactorAction.setToolTip("Subsampling factor");
4754
_scalarChannel1Action.setToolTip("Scalar channel 1");
@@ -188,6 +195,26 @@ void ImageSettingsAction::initialize(Layer* layer)
188195
_scalarChannel1Action.getWindowLevelAction().setEnabled(false);
189196
_scalarChannel2Action.getWindowLevelAction().setEnabled(false);
190197
_scalarChannel3Action.getWindowLevelAction().setEnabled(false);
198+
199+
_useBackgroundAction.setVisible(true);
200+
_useBackgroundAction.setChecked(false);
201+
_backgroundDimAction.setVisible(true);
202+
_backgroundDimAction.setEnabled(false);
203+
connect(&_useBackgroundAction, &ToggleAction::toggled, this, [this]() { _backgroundDimAction.setEnabled(_useBackgroundAction.isChecked()); });
204+
// get parent point dataset's dimensions
205+
auto parent = Dataset<Clusters>(_layer->getSourceDataset());
206+
while (parent->getDataType() != PointType) {
207+
parent = parent->getParent();
208+
}
209+
Dataset<Points> points = parent;
210+
if (points.isValid()) {
211+
QStringList parentDimNames;
212+
for (auto name: points->getDimensionNames()) parentDimNames << name;
213+
214+
_backgroundDimAction.setOptions(parentDimNames);
215+
_backgroundDimAction.setCurrentIndex(0);
216+
}
217+
191218
}
192219
else {
193220
if (_layer->getNumberOfImages() >= 2) {
@@ -199,6 +226,9 @@ void ImageSettingsAction::initialize(Layer* layer)
199226
}
200227
}
201228

229+
connect(&_backgroundDimAction, &OptionAction::currentIndexChanged, this, &ImageSettingsAction::updateColorMapImage);
230+
connect(&_useBackgroundAction, &ToggleAction::toggled, this, &ImageSettingsAction::updateColorMapImage);
231+
202232
connect(&_colorMap1DAction, &ColorMapAction::imageChanged, this, &ImageSettingsAction::updateColorMapImage);
203233
connect(&_colorMap2DAction, &ColorMapAction::imageChanged, this, &ImageSettingsAction::updateColorMapImage);
204234
//connect(&_colorMapAction.getDiscretizeAction(), &ToggleAction::toggled, this, &ImageSettingsAction::updateColorMapImage);
@@ -274,11 +304,47 @@ const std::uint32_t ImageSettingsAction::getNumberOfActiveScalarChannels() const
274304
return 0;
275305
}
276306

277-
QImage ImageSettingsAction::getColorMapImage() const
307+
QImage ImageSettingsAction::getColorMapImage()
278308
{
279309
if (_layer->getSourceDataset()->getDataType() == ClusterType) {
280310
const auto& clusters = Dataset<Clusters>(_layer->getSourceDataset())->getClusters();
281311

312+
// get parent point dataset's dimensions
313+
auto parent = Dataset<Clusters>(_layer->getSourceDataset());
314+
while (parent->getDataType() != PointType) {
315+
parent = parent->getParent();
316+
}
317+
Dataset<Points> points = parent;
318+
_backgroundMin = 0.0;
319+
_backgroundMax = 0.0;
320+
if (points.isValid() && _useBackgroundAction.isChecked()) {
321+
float min = std::numeric_limits<float>::max();
322+
float max = std::numeric_limits<float>::min();
323+
int dim = _backgroundDimAction.getCurrentIndex();
324+
for (const auto& cluster: clusters) {
325+
if (dim < 0) break;
326+
int numIndices = cluster.getNumberOfIndices();
327+
std::vector<float> data(numIndices);
328+
points->populateDataForDimensions(data, std::vector<int>{dim}, cluster.getIndices());
329+
min = std::min(*std::min_element(data.begin(), data.end()), min);
330+
max = std::max(*std::max_element(data.begin(), data.end()), max);
331+
}
332+
_backgroundMin = min;
333+
_backgroundMax = max;
334+
335+
if (dim >= 0) {
336+
int numPixels = _layer->getImagesDataset()->getNumberOfPixels();
337+
std::vector<float> fullImage(numPixels);
338+
points->extractDataForDimension(fullImage, dim);
339+
340+
_scalarData.clear();
341+
_scalarData.reserve(numPixels);
342+
std::copy(fullImage.begin(), fullImage.end(), std::back_inserter(_scalarData));
343+
}
344+
}
345+
_scalarDataRange.first = _backgroundMin;
346+
_scalarDataRange.second = _backgroundMax;
347+
282348
QImage discreteColorMapImage(static_cast<std::int32_t>(clusters.size()), 1, QImage::Format::Format_RGB32);
283349

284350
auto clusterIndex = 0;
@@ -323,8 +389,12 @@ void ImageSettingsAction::updateColorMapImage()
323389
}
324390

325391

326-
if (_colorSpaceAction.getCurrentIndex() <= 1)
392+
if (_colorSpaceAction.getCurrentIndex() <= 1) {
327393
_layer->setColorMapImage(getColorMapImage(), interpolationType);
394+
if (_layer->getSourceDataset()->getDataType() == ClusterType && _scalarData.size() > 0) {
395+
_layer->setChannelScalarData(ScalarChannelAction::Identifier::Channel2, _scalarData, _scalarDataRange);
396+
}
397+
}
328398
}
329399

330400
void ImageSettingsAction::colorSpaceChanged()

src/ImageSettingsAction.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class ImageSettingsAction : public GroupAction
4747
protected: // Color map
4848

4949
/** Get color map image */
50-
QImage getColorMapImage() const;
50+
QImage getColorMapImage();
5151

5252
/** Update the color map image and notify others */
5353
void updateColorMapImage();
@@ -129,6 +129,12 @@ class ImageSettingsAction : public GroupAction
129129
QTimer _updateSelectionTimer; /** Timer to update layer selection when appropriate */
130130
QTimer _updateScalarDataTimer; /** Timer to update layer scalar data when appropriate */
131131

132+
ToggleAction _useBackgroundAction;
133+
OptionAction _backgroundDimAction;
134+
float _backgroundMin{0.0}, _backgroundMax{0.0};
135+
QVector<float> _scalarData;
136+
QPair<float, float> _scalarDataRange{0.0, 0.0};
137+
132138
static const std::int32_t LAZY_UPDATE_INTERVAL = 0;
133139
};
134140

src/Layer.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,14 @@ void Layer::setColorMapImage(const QImage& colorMapImage, const InterpolationTyp
289289
invalidate();
290290
}
291291

292+
void Layer::setChannelScalarData(const std::uint32_t& channelIndex, const QVector<float>& scalarData, const QPair<float, float>& displayRange)
293+
{
294+
auto imageProp = this->getPropByName<ImageProp>("ImageProp");
295+
296+
imageProp->setChannelScalarData(channelIndex, scalarData, displayRange);
297+
invalidate();
298+
}
299+
292300
void Layer::updateWindowTitle()
293301
{
294302
try {

src/Layer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ class Layer : public mv::gui::GroupsAction, public Renderable
187187
* @param interpolationType Interpolation type
188188
*/
189189
void setColorMapImage(const QImage& colorMapImage, const InterpolationType& interpolationType);
190+
void setChannelScalarData(const std::uint32_t& channelIndex, const QVector<float>& scalarData, const QPair<float, float>& displayRange);
190191

191192
protected: // Miscellaneous
192193

0 commit comments

Comments
 (0)