v1.0.0-rc.110 (#16)
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 7m46s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 8m45s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 6m56s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 5m58s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 6m59s
Build Packages / build:rpm (rocky8) (push) Successful in 7m33s
Build Packages / Generate python client (push) Successful in 19s
Build Packages / Build documentation (push) Successful in 41s
Build Packages / Create release (push) Has been skipped
Build Packages / build:rpm (rocky9) (push) Successful in 8m45s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 7m51s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 7m12s
Build Packages / Unit tests (push) Successful in 1h8m51s

This is an UNSTABLE release.

* jfjoch_broker: Add auto-contrast option for preview images
* Frontend: Add logo image
* jfjoch_viewer: Add logo image
* jfjoch_viewer: For image chart allow to set min value to zero
* jfjoch_viewer: For resolution estimation plots, visualization uses 1/d^2 as measure
* jfjoch_viewer: Add 3D unit cell visualization (experimental/WIP/not really there)
* Documentation: Add logo image

Reviewed-on: #16
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 #16.
This commit is contained in:
2025-11-28 12:47:35 +01:00
committed by leonarski_f
parent 05410d7cb3
commit 224cc8b89c
178 changed files with 855 additions and 268 deletions
+54 -26
View File
@@ -48,14 +48,46 @@ void PreviewImage::roi(std::vector<rgb> &ret, int64_t in_xpixel, int64_t in_ypix
}
template<class T>
std::vector<rgb> PreviewImage::GenerateRGB(const uint8_t* value_8,
std::vector<rgb> PreviewImage::GenerateRGB(const uint8_t *value_8,
int64_t special_value_64,
int64_t sat_value_64,
const ColorScale &scale,
const PreviewImageSettings& settings) const {
const PreviewImageSettings &settings) const {
auto value = reinterpret_cast<const T *>(value_8);
auto special_value = static_cast<T>(special_value_64);
std::vector<rgb> ret(xpixel*ypixel);
float background = settings.background_value.value_or(0.0);
float foreground;
if (settings.saturation_value.has_value())
foreground = settings.saturation_value.value();
else {
// Auto-contrast procedure
std::vector<int64_t> valid;
valid.reserve(xpixel * ypixel);
for (int i = 0; i < xpixel * ypixel; i++) {
if ((value[i] != special_value)
&& (value[i] != sat_value_64)
&& (mask[i] != MaskDet)
&& (mask[i] != MaskGap)
&& (!settings.show_user_mask || (mask[i] != MaskUsr)))
valid.push_back(static_cast<int64_t>(value[i]));
}
if (!valid.empty()) {
const size_t m = valid.size();
size_t ignore = std::max<size_t>(1, static_cast<size_t>(std::floor(m * auto_foreground_range)));
if (ignore >= m) ignore = m - 1; // ensure at least one value remains
const size_t rank = m - ignore - 1; // 0-based index for the desired value
std::nth_element(valid.begin(), valid.begin() + rank, valid.end());
foreground = static_cast<float>(valid[rank]);
} else {
// Fallback to something above background if no valid pixels remain
foreground = background + 1.0f;
}
}
std::vector<rgb> ret(xpixel * ypixel);
for (int i = 0; i < xpixel*ypixel; i++) {
if (mask[i] == MaskGap)
ret[i] = scale.Apply(ColorScaleSpecial::Gap);
@@ -64,7 +96,7 @@ std::vector<rgb> PreviewImage::GenerateRGB(const uint8_t* value_8,
|| (settings.show_user_mask && (mask[i] == MaskUsr))) {
ret[i] = scale.Apply(ColorScaleSpecial::BadPixel);
} else
ret[i] = scale.Apply(value[i], 0.0, settings.saturation_value);;
ret[i] = scale.Apply(value[i], background, foreground);
}
return ret;
}
@@ -197,15 +229,13 @@ void PreviewImage::Configure() {
ypixel = 0;
}
std::vector<rgb> PreviewImage::GenerateRGB(const PreviewImageSettings &settings,
const CompressedImage &xray_image,
const std::vector<SpotToSave> &in_spots) const {
std::vector<rgb> v(xray_image.GetWidth() * xray_image.GetHeight());
if (xray_image.GetUncompressedSize() == 0)
std::vector<rgb> PreviewImage::GenerateRGB(const PreviewImageSettings &settings, const DataMessage &msg) const {
std::vector<rgb> v(msg.image.GetWidth() * msg.image.GetHeight());
if (msg.image.GetUncompressedSize() == 0)
return {};
std::vector<uint8_t> tmp;
const uint8_t* image_ptr = xray_image.GetUncompressedPtr(tmp);
const uint8_t* image_ptr = msg.image.GetUncompressedPtr(tmp);
{
// JPEG compression is outside the critical loop protected by m
@@ -214,37 +244,39 @@ std::vector<rgb> PreviewImage::GenerateRGB(const PreviewImageSettings &settings,
ColorScale scale;
scale.Select(settings.scale);
switch (xray_image.GetMode()) {
switch (msg.image.GetMode()) {
case CompressedImageMode::Int8:
v = GenerateRGB<int8_t>(image_ptr, INT8_MIN, scale, settings);
v = GenerateRGB<int8_t>(image_ptr, INT8_MIN, INT8_MAX, scale, settings);
break;
case CompressedImageMode::Int16:
v = GenerateRGB<int16_t>(image_ptr, INT16_MIN, scale, settings);
v = GenerateRGB<int16_t>(image_ptr, INT16_MIN, INT16_MAX, scale, settings);
break;
case CompressedImageMode::Int32:
v = GenerateRGB<int32_t>(image_ptr, INT32_MIN, scale, settings);
v = GenerateRGB<int32_t>(image_ptr, INT32_MIN, INT32_MAX, scale, settings);
break;
case CompressedImageMode::Uint8:
v = GenerateRGB<uint8_t>(image_ptr,UINT8_MAX, scale, settings);
v = GenerateRGB<uint8_t>(image_ptr,UINT8_MAX, UINT8_MAX, scale, settings);
break;
case CompressedImageMode::Uint16:
v = GenerateRGB<uint16_t>(image_ptr,UINT16_MAX, scale, settings);
v = GenerateRGB<uint16_t>(image_ptr,UINT16_MAX, UINT16_MAX, scale, settings);
break;
case CompressedImageMode::Uint32:
v = GenerateRGB<uint32_t>(image_ptr,UINT16_MAX, scale, settings);
v = GenerateRGB<uint32_t>(image_ptr,UINT32_MAX, UINT32_MAX, scale, settings);
break;
default:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Mode not supported");
}
if (settings.show_spots)
AddSpots(v, in_spots);
AddSpots(v, msg.spots);
if (settings.show_roi)
AddROI(v);
if (settings.resolution_ring)
AddResolutionRing(v, settings.resolution_ring.value());
else if (settings.show_res_est && msg.resolution_estimate)
AddResolutionRing(v, msg.resolution_estimate.value());
if (settings.show_beam_center)
AddBeamCenter(v);
@@ -252,11 +284,9 @@ std::vector<rgb> PreviewImage::GenerateRGB(const PreviewImageSettings &settings,
return v;
}
std::string PreviewImage::GenerateImage(const PreviewImageSettings& settings,
const CompressedImage& image,
const std::vector<SpotToSave>& in_spots) const {
auto v = GenerateRGB(settings, image, in_spots);
CompressedImage rgb_image(v, image.GetWidth(), image.GetHeight());
std::string PreviewImage::GenerateImage(const PreviewImageSettings& settings, const DataMessage &msg) const {
auto v = GenerateRGB(settings, msg);
CompressedImage rgb_image(v, msg.image.GetWidth(), msg.image.GetHeight());
switch (settings.format) {
case PreviewImageFormat::JPEG:
return WriteJPEGToMem(rgb_image, settings.jpeg_quality);
@@ -273,9 +303,7 @@ std::string PreviewImage::GenerateImage(const PreviewImageSettings &settings, co
if (!cbor || !cbor->data_message)
return {};
return GenerateImage(settings,
cbor->data_message->image,
cbor->data_message->spots);
return GenerateImage(settings, *cbor->data_message);
}
std::string PreviewImage::GenerateTIFF(const std::vector<uint8_t>& cbor_format) {