v1.0.0-rc.123 (#30)
All checks were successful
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 10m22s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 11m30s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 11m41s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 12m32s
Build Packages / Generate python client (push) Successful in 18s
Build Packages / Build documentation (push) Successful in 54s
Build Packages / Create release (push) Has been skipped
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 9m44s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 8m53s
Build Packages / build:rpm (rocky8) (push) Successful in 9m40s
Build Packages / build:rpm (rocky9) (push) Successful in 10m37s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 9m54s
Build Packages / Unit tests (push) Successful in 1h6m33s
All checks were successful
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 10m22s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 11m30s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 11m41s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 12m32s
Build Packages / Generate python client (push) Successful in 18s
Build Packages / Build documentation (push) Successful in 54s
Build Packages / Create release (push) Has been skipped
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 9m44s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 8m53s
Build Packages / build:rpm (rocky8) (push) Successful in 9m40s
Build Packages / build:rpm (rocky9) (push) Successful in 10m37s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 9m54s
Build Packages / Unit tests (push) Successful in 1h6m33s
This is an UNSTABLE release. * jfjoch_broker: Use newer version of Google Ceres for (potential) CUDA 13 compatibility * jfjoch_broker: Improve performance of generating preview images, especially for large detectors (9M-16M) * jfjoch_viewer: Improve performance of displaying images, especially for large detectors (9M-16M) * jfjoch_viewer: Add more color schemes for better image readability * HDF5: Common mutex for reading and writing HDF5 if both operations were to happen in the same executable * HDF5: suppress warning if path (upstream group) doesn't exists when checking if leaf exists Reviewed-on: #30 Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch> Co-committed-by: Filip Leonarski <filip.leonarski@psi.ch>
This commit was merged in pull request #30.
This commit is contained in:
@@ -5,12 +5,88 @@
|
||||
#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<uint8_t>(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<uint8_t>(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;
|
||||
}
|
||||
|
||||
ColorScale::ColorScale() : lut_(kLutSize) {
|
||||
CalcLUT();
|
||||
}
|
||||
|
||||
void ColorScale::Select(ColorScaleEnum val) {
|
||||
current = val;
|
||||
CalcLUT();
|
||||
}
|
||||
|
||||
const std::vector<rgb> &ColorScale::LUTData() const {
|
||||
return lut_;
|
||||
}
|
||||
|
||||
void ColorScale::CalcLUT() const {
|
||||
const std::vector<rgb>* 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::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;
|
||||
case ColorScaleEnum::Magma:
|
||||
map = &magma_colormap; break;
|
||||
case ColorScaleEnum::Inferno:
|
||||
map = &inferno_colormap; break;
|
||||
default:
|
||||
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
|
||||
"Color scale unknown");
|
||||
}
|
||||
|
||||
if (current == ColorScaleEnum::Green1) {
|
||||
for (size_t i = 0; i < kLutSize; ++i) {
|
||||
const float f = static_cast<float>(i) / static_cast<float>(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<float>(i) / static_cast<float>(kLutSize - 1);
|
||||
lut_[i] = GreenAsinh(f, 8.0f);
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < kLutSize; ++i) {
|
||||
const float f = static_cast<float>(i) / static_cast<float>(kLutSize - 1);
|
||||
lut_[i] = Apply(f, *map);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
rgb ColorScale::Apply(float input, const std::vector<rgb> &map) {
|
||||
@@ -45,8 +121,6 @@ rgb ColorScale::Apply(ColorScaleSpecial input) const {
|
||||
}
|
||||
|
||||
rgb ColorScale::Apply(float input, float min, float max) const {
|
||||
// Assume min and max is finite
|
||||
|
||||
if (!std::isfinite(input))
|
||||
return gap;
|
||||
|
||||
@@ -58,19 +132,14 @@ rgb ColorScale::Apply(float input, float min, float max) const {
|
||||
else
|
||||
f = (input - min) / (max - min);
|
||||
|
||||
switch (current) {
|
||||
case ColorScaleEnum::Viridis:
|
||||
return Apply(f, viridis_colormap);
|
||||
case ColorScaleEnum::Heat:
|
||||
return Apply(f, heat_colormap);
|
||||
case ColorScaleEnum::Indigo:
|
||||
return Apply(f, white_to_indigo_colormap);
|
||||
case ColorScaleEnum::BW:
|
||||
return Apply(f, white_to_black_colormap);
|
||||
default:
|
||||
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
|
||||
"Color scale unknown");
|
||||
}
|
||||
const size_t idx = static_cast<size_t>(f * static_cast<float>(kLutSize - 1));
|
||||
return lut_[idx];
|
||||
}
|
||||
|
||||
rgb ColorScale::ApplyLUTIndex(size_t idx) const {
|
||||
if (idx >= kLutSize)
|
||||
return lut_[kLutSize-1];
|
||||
return lut_[idx];
|
||||
}
|
||||
|
||||
ColorScale &ColorScale::Gap(rgb input) {
|
||||
@@ -82,28 +151,3 @@ ColorScale &ColorScale::BadPixel(rgb input) {
|
||||
bad = input;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rgb rainbowColor(float t) {
|
||||
// Ensure t is in [0,1]
|
||||
t = std::max(0.0f, std::min(1.0f, t));
|
||||
|
||||
// Convert to hue (0 to 6)
|
||||
float hue = t * 6.0f;
|
||||
|
||||
int phase = static_cast<int>(hue);
|
||||
float fract = hue - phase;
|
||||
|
||||
uint8_t p = static_cast<uint8_t>(255 * (1.0f - fract));
|
||||
uint8_t q = static_cast<uint8_t>(255 * fract);
|
||||
uint8_t full = 255;
|
||||
|
||||
switch (phase) {
|
||||
case 0: return {full, q, 0}; // Red to Yellow
|
||||
case 1: return {p, full, 0}; // Yellow to Green
|
||||
case 2: return {0, full, q}; // Green to Cyan
|
||||
case 3: return {0, p, full}; // Cyan to Blue
|
||||
case 4: return {q, 0, full}; // Blue to Magenta
|
||||
case 5: return {full, 0, p}; // Magenta to Red
|
||||
default: return {full, 0, 0}; // Fallback (red)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user