diff --git a/common/ColorScale.cpp b/common/ColorScale.cpp index 9747afac..dd30897a 100644 --- a/common/ColorScale.cpp +++ b/common/ColorScale.cpp @@ -5,6 +5,26 @@ #include "ColorScale.h" #include "JFJochException.h" +static inline float Clamp01(float x) { + return (x < 0.0f) ? 0.0f : (x > 1.0f ? 1.0f : x); +} + +// Gamma-mapped green (recommended gamma = 0.7) +static inline rgb GreenGamma(float f, float gamma = 0.7f) { + f = Clamp01(f); + const float g = std::pow(f, gamma); + const uint8_t G = static_cast(std::lround(255.0f * g)); + return {.r = 0, .g = G, .b = 0}; +} + +// Asinh-mapped green (recommended k = 8.0) +static inline rgb GreenAsinh(float f, float k = 8.0f) { + f = Clamp01(f); + const float g = std::asinh(k * f) / std::asinh(k); + const uint8_t G = static_cast(std::lround(255.0f * g)); + return {.r = 0, .g = G, .b = 0}; +} + float luminance(rgb input) { return 0.2126f * input.r + 0.7152f * input.g + 0.0722f * input.b; } @@ -26,18 +46,43 @@ void ColorScale::CalcLUT() const { const std::vector* map = nullptr; switch (current) { case ColorScaleEnum::Viridis: map = &viridis_colormap; break; - case ColorScaleEnum::Heat: map = &heat_colormap; break; - case ColorScaleEnum::Indigo: map = &white_to_indigo_colormap; break; - case ColorScaleEnum::BW: map = &white_to_black_colormap; break; + case ColorScaleEnum::Heat: map = &heat_colormap; + break; + case ColorScaleEnum::Indigo: map = &white_to_indigo_colormap; + break; + case ColorScaleEnum::BW: map = &white_to_black_colormap; + break; + case ColorScaleEnum::WB: map = &black_to_white_colormap; + break; + case ColorScaleEnum::Green1: + case ColorScaleEnum::Green2: + map = nullptr; + break; // handled below + case ColorScaleEnum::Green3: + map = &green_colormap; + break; default: throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Color scale unknown"); } - for (size_t i = 0; i < kLutSize; ++i) { - const float f = static_cast(i) / static_cast(kLutSize - 1); - lut_[i] = Apply(f, *map); + if (current == ColorScaleEnum::Green1) { + for (size_t i = 0; i < kLutSize; ++i) { + const float f = static_cast(i) / static_cast(kLutSize - 1); + lut_[i] = GreenGamma(f, 0.7f); + } + } else if (current == ColorScaleEnum::Green2) { + for (size_t i = 0; i < kLutSize; ++i) { + const float f = static_cast(i) / static_cast(kLutSize - 1); + lut_[i] = GreenAsinh(f, 8.0f); + } + } else { + for (size_t i = 0; i < kLutSize; ++i) { + const float f = static_cast(i) / static_cast(kLutSize - 1); + lut_[i] = Apply(f, *map); + } } + } rgb ColorScale::Apply(float input, const std::vector &map) { diff --git a/common/ColorScale.h b/common/ColorScale.h index dcd7995b..af862232 100644 --- a/common/ColorScale.h +++ b/common/ColorScale.h @@ -21,7 +21,11 @@ enum class ColorScaleEnum : int { Viridis = 0, Heat = 1, Indigo = 2, - BW = 3 + BW = 3, + WB = 4, + Green1 = 5, + Green2 = 6, + Green3 = 7 }; enum class ColorScaleSpecial { @@ -47,6 +51,14 @@ class ColorScale { {255, 255, 255}, {0, 0, 0} }; + const std::vector black_to_white_colormap = { + {0, 0, 0}, {255, 255, 255} + }; + + const std::vector green_colormap = { + {0, 0, 0}, {0, 255, 0} + }; + ColorScaleEnum current = ColorScaleEnum::Indigo; rgb gap = {.r = 190, .g = 190, .b = 190}; // Gray diff --git a/viewer/toolbar/JFJochViewerToolbarDisplay.cpp b/viewer/toolbar/JFJochViewerToolbarDisplay.cpp index fd8dd1b7..a907c335 100644 --- a/viewer/toolbar/JFJochViewerToolbarDisplay.cpp +++ b/viewer/toolbar/JFJochViewerToolbarDisplay.cpp @@ -25,7 +25,12 @@ JFJochViewerToolbarDisplay::JFJochViewerToolbarDisplay(QWidget *parent) color_map_select->addItem("Viridis", static_cast(ColorScaleEnum::Viridis)); color_map_select->addItem("Heat", static_cast(ColorScaleEnum::Heat)); color_map_select->addItem("Indigo", static_cast(ColorScaleEnum::Indigo)); - color_map_select->addItem("B/W", static_cast(ColorScaleEnum::BW)); + color_map_select->addItem("Black on white", static_cast(ColorScaleEnum::BW)); + color_map_select->addItem("White on black", static_cast(ColorScaleEnum::WB)); + color_map_select->addItem("Green (gamma)", static_cast(ColorScaleEnum::Green1)); + color_map_select->addItem("Green (asinh)", static_cast(ColorScaleEnum::Green2)); + color_map_select->addItem("Green (linear)", static_cast(ColorScaleEnum::Green3)); + color_map_select->setCurrentIndex(static_cast(ColorScaleEnum::Indigo)); addWidget(color_map_select);