jfjoch_viewer: Add calibration viewer

This commit is contained in:
2025-11-06 16:01:37 +01:00
parent 4be250a489
commit 003e2f0a8e
11 changed files with 629 additions and 1 deletions
+5
View File
@@ -64,6 +64,11 @@ ADD_EXECUTABLE(jfjoch_viewer jfjoch_viewer.cpp JFJochViewerWindow.cpp JFJochView
JFJochViewerToolbarImage.h
JFJochViewerToolbarDisplay.cpp
JFJochViewerToolbarDisplay.h
SimpleImage.h
widgets/JFJochSimpleImageViewer.cpp
widgets/JFJochSimpleImageViewer.h
windows/JFJochCalibrationWindow.cpp
windows/JFJochCalibrationWindow.h
)
TARGET_LINK_LIBRARIES(jfjoch_viewer Qt6::Core Qt6::Gui Qt6::Widgets Qt6::Charts Qt6::DBus
+13 -1
View File
@@ -388,5 +388,17 @@ void JFJochImageReadingWorker::UploadUserMask() {
http_reader.UploadUserMask(user_mask);
}
void JFJochImageReadingWorker::LoadCalibration(QString dataset) {
if (!http_mode) {
auto tmp = std::make_shared<SimpleImage>();
try {
tmp->image = file_reader.ReadCalibration(tmp->buffer, dataset.toStdString());
std::shared_ptr<const SimpleImage> ctmp = tmp;
emit simpleImageLoaded(ctmp);
} catch (const std::exception &e) {
logger.Info("Error loading calibration: {}", e.what());
}
}
logger.Info("HTTP mode doesn't allow to read calibration (at the moment");
}
+5
View File
@@ -16,6 +16,7 @@
#include "../common/Logger.h"
#include "../reader/JFJochHttpReader.h"
#include "../image_analysis/MXAnalysisWithoutFPGA.h"
#include "SimpleImage.h"
Q_DECLARE_METATYPE(std::shared_ptr<const JFJochReaderDataset>)
Q_DECLARE_METATYPE(std::shared_ptr<const JFJochReaderImage>)
@@ -23,6 +24,7 @@ Q_DECLARE_METATYPE(DiffractionExperiment)
Q_DECLARE_METATYPE(SpotFindingSettings)
Q_DECLARE_METATYPE(IndexingSettings)
Q_DECLARE_METATYPE(UnitCell)
Q_DECLARE_METATYPE(std::shared_ptr<const SimpleImage>)
class JFJochImageReadingWorker : public QObject {
Q_OBJECT
@@ -67,6 +69,7 @@ signals:
void imageNumberChanged(int64_t total_images, int64_t current_image);
void setToolbarMode(JFJochViewerToolbarImage::ToolbarMode input);
void setRings(const QVector<float> &v);
void simpleImageLoaded(std::shared_ptr<const SimpleImage> &image);
public:
JFJochImageReadingWorker(const SpotFindingSettings &settings, const DiffractionExperiment& experiment, QObject *parent = nullptr);
~JFJochImageReadingWorker() override = default;
@@ -91,6 +94,8 @@ public slots:
void SaveUserMaskTIFF(QString filename);
void UploadUserMask();
void ClearUserMask();
void LoadCalibration(QString dataset);
};
+17
View File
@@ -76,6 +76,12 @@ JFJochViewerMenu::JFJochViewerMenu(QWidget *parent) : QMenuBar(parent) {
connect(toggleProcessingWindowAction, &QAction::toggled,
this, &JFJochViewerMenu::processingWindowToggled);
toggleCalibrationWindowAction = windowMenu->addAction("Calibration");
toggleCalibrationWindowAction->setCheckable(true);
toggleCalibrationWindowAction->setChecked(false);
connect(toggleCalibrationWindowAction, &QAction::toggled,
this, &JFJochViewerMenu::calibrationWindowToggled);
QMenu *helpMenu = addMenu("Help");
// Add "About" action
const QAction *aboutAction = helpMenu->addAction("About");
@@ -153,6 +159,17 @@ void JFJochViewerMenu::metadataWindowClosing() {
toggleMetadataWindowAction->setChecked(false);
}
void JFJochViewerMenu::calibrationWindowClosing() {
toggleCalibrationWindowAction->setChecked(false);
}
void JFJochViewerMenu::calibrationWindowToggled(bool checked) {
if (checked)
emit openCalibrationWindow();
else
emit closeCalibrationWindow();
}
void JFJochViewerMenu::spotListWindowToggled(bool checked) {
if (checked)
emit openSpotListWindow();
+9
View File
@@ -13,6 +13,8 @@ class JFJochViewerMenu : public QMenuBar {
QAction *toggleSpotWindowAction = nullptr;
QAction *toggleReflectionWindowAction = nullptr;
QAction *toggleProcessingWindowAction = nullptr;
QAction *toggleCalibrationWindowAction = nullptr;
public:
explicit JFJochViewerMenu(QWidget *parent = nullptr);
~JFJochViewerMenu() override = default;
@@ -31,6 +33,10 @@ signals:
void openProcessingWindow();
void closeProcessingWindow();
void openCalibrationWindow();
void closeCalibrationWindow();
void saveUserMaskTiffSelected(const QString &filename);
void uploadUserMaskSelected();
void clearUserMaskSelected();
@@ -41,6 +47,8 @@ public slots:
void spotListWindowClosing();
void reflectionListWindowClosing();
void processingWindowClosing();
void calibrationWindowClosing();
private slots:
void aboutSelected();
void quitSelected();
@@ -52,6 +60,7 @@ private slots:
void spotListWindowToggled(bool checked);
void reflectionListWindowToggled(bool checked);
void processingWindowToggled(bool checked);
void calibrationWindowToggled(bool checked);
void saveUserMaskAsTiffSelected();
void uploadUserMaskAction();
+14
View File
@@ -17,6 +17,7 @@
#include "windows/JFJochViewerProcessingWindow.h"
#include "windows/JFJochViewerSpotListWindow.h"
#include "windows/JFJochViewerReflectionListWindow.h"
#include "windows/JFJochCalibrationWindow.h"
JFJochViewerWindow::JFJochViewerWindow(QWidget *parent, bool dbus, const QString &file) : QMainWindow(parent) {
menuBar = new JFJochViewerMenu(this);
@@ -90,6 +91,7 @@ JFJochViewerWindow::JFJochViewerWindow(QWidget *parent, bool dbus, const QString
auto spotWindow = new JFJochViewerSpotListWindow(this);
auto reflectionWindow = new JFJochViewerReflectionListWindow(this);
auto processingWindow = new JFJochViewerProcessingWindow(spot_finding_settings, indexing_settings, this);
auto calibrationWindow = new JFJochCalibrationWindow(this);
new JFJochViewerAdaptor(this);
@@ -309,6 +311,18 @@ JFJochViewerWindow::JFJochViewerWindow(QWidget *parent, bool dbus, const QString
connect(side_panel, &JFJochViewerSidePanel::highlightIceRings,
viewer, &JFJochViewerImage::highlightIceRings);
connect(menuBar, &JFJochViewerMenu::openCalibrationWindow,
calibrationWindow, &JFJochCalibrationWindow::open);
connect(menuBar, &JFJochViewerMenu::closeCalibrationWindow,
calibrationWindow, &JFJochCalibrationWindow::close);
connect(calibrationWindow, &JFJochCalibrationWindow::closing,
menuBar, &JFJochViewerMenu::calibrationWindowClosing);
connect(reading_worker, &JFJochImageReadingWorker::datasetLoaded,
calibrationWindow, &JFJochCalibrationWindow::datasetLoaded);
connect(reading_worker, &JFJochImageReadingWorker::simpleImageLoaded,
calibrationWindow, &JFJochCalibrationWindow::calibrationLoaded);
if (!file.isEmpty())
LoadFile(file, 0, 1);
}
+10
View File
@@ -0,0 +1,10 @@
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include "../common/CompressedImage.h"
struct SimpleImage {
CompressedImage image;
std::vector<uint8_t> buffer;
};
+331
View File
@@ -0,0 +1,331 @@
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include "JFJochSimpleImageViewer.h"
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
#include <QWheelEvent>
#include <QScrollBar>
#include <QtMath>
#include <cstring>
#include <algorithm>
#include "../../common/JFJochException.h"
static inline double normalize_to_unit(double raw, double bg, double fg) {
const double denom = std::max(1e-12, double(fg) - double(bg));
double v = (raw - bg) / denom;
if (v < 0.0) v = 0.0;
if (v > 1.0) v = 1.0;
return v;
}
JFJochSimpleImageViewer::JFJochSimpleImageViewer(QWidget *parent)
: QGraphicsView(parent) {
setDragMode(QGraphicsView::NoDrag);
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
setRenderHint(QPainter::Antialiasing);
setRenderHint(QPainter::SmoothPixmapTransform);
setFocusPolicy(Qt::ClickFocus);
auto *scn = new QGraphicsScene(this);
setScene(scn);
// Optional: a sensible default colormap
color_scale_.Select(ColorScaleEnum::Indigo);
// Keep overlays in pixel units independent of zoom (for labels font sizing)
setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
}
void JFJochSimpleImageViewer::clear() {
has_image_ = false;
image_.reset();
if (scene())
scene()->clear();
}
void JFJochSimpleImageViewer::setImage(const std::shared_ptr<const SimpleImage> &img) {
image_ = img;
has_image_ = true;
renderImage();
updateScene();
}
void JFJochSimpleImageViewer::setBackground(float v) {
background_ = v;
emit backgroundChanged(background_);
if (has_image_) {
renderImage();
// Preserve current transform while updating
updateScene();
}
}
void JFJochSimpleImageViewer::setForeground(float v) {
foreground_ = std::max(1e-6f, v);
emit foregroundChanged(foreground_);
if (has_image_) {
renderImage();
updateScene();
}
}
void JFJochSimpleImageViewer::setColorMap(int colorMapEnumValue) {
try {
color_scale_.Select(static_cast<ColorScaleEnum>(colorMapEnumValue));
if (has_image_) {
renderImage();
updateScene();
}
} catch (...) {
// ignore invalid value
}
}
void JFJochSimpleImageViewer::wheelEvent(QWheelEvent *event) {
if (!scene() || !has_image_) return;
const double zoomFactor = 1.15;
const QPointF targetScenePos = mapToScene(event->position().toPoint());
if (event->modifiers() == Qt::ShiftModifier) {
// Shift + wheel adjusts foreground (like your main viewer)
float new_fg = foreground_ + event->angleDelta().y() / 120.0f;
if (new_fg < 1.0f) new_fg = 1.0f;
setForeground(new_fg);
} else {
if (event->angleDelta().y() > 0) {
if (scale_factor_ * zoomFactor < 500.0) {
scale_factor_ *= zoomFactor;
scale(zoomFactor, zoomFactor);
}
} else {
if (scale_factor_ > 0.2) {
scale_factor_ *= 1.0 / zoomFactor;
scale(1.0 / zoomFactor, 1.0 / zoomFactor);
}
}
// Keep focus under mouse
const QPointF updatedCenter = mapToScene(viewport()->rect().center());
const QPointF delta = targetScenePos - updatedCenter;
translate(delta.x(), delta.y());
// Only labels depend on redraw; pixmap stays. Rebuild scene to re-place labels
updateScene();
}
}
void JFJochSimpleImageViewer::mousePressEvent(QMouseEvent *event) {
if (!scene() || !has_image_) return;
if (event->button() == Qt::LeftButton) {
panning_ = true;
setCursor(Qt::ClosedHandCursor);
last_mouse_pos_ = event->pos();
}
QGraphicsView::mousePressEvent(event);
}
void JFJochSimpleImageViewer::mouseMoveEvent(QMouseEvent *event) {
if (!scene() || !has_image_) return;
if (panning_) {
const QPointF delta = mapToScene(event->pos()) - mapToScene(last_mouse_pos_);
last_mouse_pos_ = event->pos();
translate(delta.x(), delta.y());
// labels positions are in scene coords, scene items re-used; no special handling
} else {
auto coord = mapToScene(event->pos());
if ((coord.x() >= 0)
&& (coord.x() < image_->image.GetWidth())
&& (coord.y() >= 0)
&& (coord.y() < image_->image.GetHeight())) {
emit writeStatusBar(QString("x=%1 y=%2 %3 ")
.arg(coord.x(), 0, 'f', 1)
.arg(coord.y(), 0, 'f', 1)
.arg(image_values_[int(coord.x()) + int(coord.y()) * image_->image.GetWidth()]
), 6000);
} else
emit writeStatusBar("", 6000);
}
QGraphicsView::mouseMoveEvent(event);
}
void JFJochSimpleImageViewer::mouseReleaseEvent(QMouseEvent *event) {
if (!scene() || !has_image_) return;
if (event->button() == Qt::LeftButton && panning_) {
panning_ = false;
setCursor(Qt::ArrowCursor);
}
QGraphicsView::mouseReleaseEvent(event);
}
void JFJochSimpleImageViewer::resizeEvent(QResizeEvent *event) {
QGraphicsView::resizeEvent(event);
// Nothing special; keep current transform and scene
}
void JFJochSimpleImageViewer::renderImage() {
const size_t W = image_->image.GetWidth();
const size_t H = image_->image.GetHeight();
if (W == 0 || H == 0) return;
// Prepare destination QImage (RGB888)
QImage qimg(int(W), int(H), QImage::Format_RGB888);
image_rgb_.resize(W * H);
image_values_.resize(W * H);
std::vector<uint8_t> image_buffer;
// Access uncompressed data
const uint8_t *src = image_->image.GetUncompressedPtr(image_buffer);
const auto mode = image_->image.GetMode();
auto write_rgb_row = [&](int y) -> uchar * {
return qimg.scanLine(y);
};
auto write_pixel = [&](size_t idx, uchar *dstRow, const rgb &c) {
dstRow[idx * 3 + 0] = c.r;
dstRow[idx * 3 + 1] = c.g;
dstRow[idx * 3 + 2] = c.b;
image_rgb_[idx] = c;
};
// Fast path: packed RGB (assumed 3 bytes per pixel)
if (mode == CompressedImageMode::RGB) {
for (int y = 0; y < int(H); ++y) {
const rgb *row = reinterpret_cast<const rgb *>(src + y * W * sizeof(rgb));
uchar *dst = write_rgb_row(y);
for (size_t x = 0; x < W; ++x) {
const rgb c = row[x];
write_pixel(x, dst, c);
}
}
} else {
switch (mode) {
case CompressedImageMode::Uint8:
renderImage<uint8_t>(qimg, src);
break;
case CompressedImageMode::Int8:
renderImage<int8_t>(qimg, src);
break;
case CompressedImageMode::Uint16:
renderImage<uint16_t>(qimg, src);
break;
case CompressedImageMode::Int16:
renderImage<int16_t>(qimg, src);
break;
case CompressedImageMode::Uint32:
renderImage<uint32_t>(qimg, src);
break;
case CompressedImageMode::Int32:
renderImage<int32_t>(qimg, src);
break;
case CompressedImageMode::Float32:
renderImage<float>(qimg, src);
break;
case CompressedImageMode::Float64:
renderImage<double>(qimg, src);
break;
case CompressedImageMode::Float16:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Float16 not supported");
break;
}
}
// Build pixmap
pixmap_ = QPixmap::fromImage(qimg);
}
void JFJochSimpleImageViewer::updateScene() {
if (!scene()) return;
scene()->clear();
if (!has_image_) return;
// Add base image
scene()->addItem(new QGraphicsPixmapItem(pixmap_));
QFont font("Arial", 1); // Font for pixel value text
font.setPixelSize(1); // This will render very small text (1-pixel high).
// Get the visible area in the scene coordinates
QRectF visibleRect = mapToScene(viewport()->geometry()).boundingRect();
// Calculate the range of pixels to process
const int W = int(image_->image.GetWidth());
const int H = int(image_->image.GetHeight());
const int startX = std::max(0, static_cast<int>(std::floor(visibleRect.left())));
const int endX = std::min(W, static_cast<int>(std::ceil(visibleRect.right())));
const int startY = std::max(0, static_cast<int>(std::floor(visibleRect.top())));
const int endY = std::min(H, static_cast<int>(std::ceil(visibleRect.bottom())));
// Only when zoomed in and region small (performance)
if (scale_factor_ > 20.0 && (endX - startX + 1) * (endY - startY + 1) < 500) {
const qreal f = std::clamp(scale_factor_, 0.5, 50.0);
QFont font("Arial", 1);
font.setPixelSize(1); // 1 px font; we use scaling below as needed
for (int y = startY; y < endY; ++y) {
const size_t base = size_t(y) * size_t(W);
for (int x = startX; x < endX; ++x) {
const size_t idx = base + size_t(x);
const double raw = image_values_[idx];
const rgb c = image_rgb_[idx];
// If no scalar was stored (e.g., RGB source), you can skip or compute some alt text
if (std::isnan(raw)) continue;
// Text content from original value
const QString pixelText = QString::number(raw);
// Contrast against colored pixel
QGraphicsTextItem *textItem = scene()->addText(pixelText, font);
if (luminance(c) > 128.0)
textItem->setDefaultTextColor(Qt::black);
else
textItem->setDefaultTextColor(Qt::white);
textItem->setPos(x - 0.7, y - 0.8);
textItem->setScale(0.2);
textItem->setZValue(10.0);
}
}
}
}
template<class T>
void JFJochSimpleImageViewer::renderImage(QImage &qimg, const uint8_t *input) {
const size_t W = image_->image.GetWidth();
const size_t H = image_->image.GetHeight();
auto ptr = reinterpret_cast<const T *>(input);
int64_t val;
for (int i = 0; i < W * H; i++) {
if (std::is_floating_point_v<T>)
val = std::lround(ptr[i]);
else
val = static_cast<int64_t>(ptr[i]);
image_values_[i] = val;
}
if (auto_fgbg) {
auto vec1(image_values_);
std::sort(vec1.begin(), vec1.end());
background_ = vec1[0];
foreground_ = vec1[vec1.size() - 1];
emit backgroundChanged(background_);
emit foregroundChanged(foreground_);
}
for (int y = 0; y < H; ++y) {
uchar *scanLine = qimg.scanLine(y); // Get writable pointer to the row
for (int x = 0; x < W; ++x) {
image_rgb_[y * W + x] = color_scale_.Apply(image_values_[y * W + x], background_, foreground_);
scanLine[x * 3 + 0] = image_rgb_[y * W + x].r; // Red
scanLine[x * 3 + 1] = image_rgb_[y * W + x].g; // Green
scanLine[x * 3 + 2] = image_rgb_[y * W + x].b; // Blue
}
}
}
+71
View File
@@ -0,0 +1,71 @@
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include <QGraphicsView>
#include <QVector>
#include <QColor>
#include <QPointF>
#include <QGraphicsTextItem>
#include <vector>
#include "../SimpleImage.h"
#include "../../common/ColorScale.h"
class JFJochSimpleImageViewer : public QGraphicsView {
Q_OBJECT
public:
explicit JFJochSimpleImageViewer(QWidget* parent = nullptr);
void setImage(const std::shared_ptr<const SimpleImage> &img);
void clear();
public slots:
void setBackground(float v);
void setForeground(float v);
void setColorMap(int colorMapEnumValue);
signals:
void foregroundChanged(float v);
void backgroundChanged(float v);
void writeStatusBar(QString string, int timeout);
protected:
void wheelEvent(QWheelEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
void resizeEvent(QResizeEvent* event) override;
private:
struct Label {
QPointF pos;
QString text;
QColor color;
};
void renderImage(); // builds pixmap_ from current image_ + settings
void updateScene(); // clears scene, adds pixmap + labels
// Image and rendering state
std::shared_ptr<const SimpleImage> image_;
bool has_image_ = false;
QPixmap pixmap_;
std::vector<rgb> image_rgb_; // intermediate RGB buffer to feed QImage
std::vector<int64_t> image_values_; // original scalar per pixel (for label text)
// View/interaction
double scale_factor_ = 1.0;
QPoint last_mouse_pos_;
bool panning_ = false;
// Settings
float background_ = 0.0f;
float foreground_ = 10.0f;
ColorScale color_scale_;
bool auto_fgbg = true;
template <class T>
void renderImage(QImage &qimg, const uint8_t *input);
};
+108
View File
@@ -0,0 +1,108 @@
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include "JFJochCalibrationWindow.h"
#include <QCloseEvent>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QLabel>
JFJochCalibrationWindow::JFJochCalibrationWindow(QWidget *parent) : QMainWindow(parent) {
QWidget *centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
auto grid_layout = new QGridLayout();
viewer = new JFJochSimpleImageViewer(this);
calibration_option = new QComboBox(this);
color_map_select = new QComboBox(this);
color_map_select->addItem("Viridis", static_cast<int>(ColorScaleEnum::Viridis));
color_map_select->addItem("Heat", static_cast<int>(ColorScaleEnum::Heat));
color_map_select->addItem("Indigo", static_cast<int>(ColorScaleEnum::Indigo));
color_map_select->addItem("B/W", static_cast<int>(ColorScaleEnum::BW));
color_map_select->setCurrentIndex(static_cast<int>(ColorScaleEnum::Indigo));
background_slider = new SliderPlusBox(1, 32768, 1.0, 0, this, SliderPlusBox::ScaleType::Linear);
foreground_slider = new SliderPlusBox(1, 32768, 1.0, 0, this, SliderPlusBox::ScaleType::Linear);
auto background_row = new QHBoxLayout();
auto foreground_row = new QHBoxLayout();
background_row->addWidget(new QLabel("Background:"));
background_row->addWidget(background_slider);
foreground_row->addWidget(new QLabel("Foreground:"));
foreground_row->addWidget(foreground_slider);
grid_layout->addWidget(calibration_option, 0, 0);
grid_layout->addWidget(color_map_select, 0, 1);
grid_layout->addLayout(background_row, 1, 0, 1, 2);
grid_layout->addLayout(foreground_row, 2, 0, 1, 2);
grid_layout->addWidget(viewer, 3, 0, 1, 2);
connect(viewer, &JFJochSimpleImageViewer::backgroundChanged,
[this] (float val) {background_slider->setValue(val);});
connect(viewer, &JFJochSimpleImageViewer::foregroundChanged,
[this] (float val) {foreground_slider->setValue(val);});
connect(color_map_select, &QComboBox::currentIndexChanged, this, [this](int index) {
viewer->setColorMap(index);
});
connect(calibration_option, &QComboBox::currentIndexChanged, this, &JFJochCalibrationWindow::CalibrationSelected);
centralWidget->setLayout(grid_layout);
statusBar = new QStatusBar(this);
setStatusBar(statusBar);
connect(viewer, &JFJochSimpleImageViewer::writeStatusBar,
statusBar, &QStatusBar::showMessage);
}
void JFJochCalibrationWindow::closeEvent(QCloseEvent *event) {
event->accept();
emit closing();
}
void JFJochCalibrationWindow::open() {
show();
raise();
activateWindow();
}
void JFJochCalibrationWindow::datasetLoaded(std::shared_ptr<const JFJochReaderDataset> in_dataset) {
dataset = std::move(in_dataset);
QSignalBlocker b(calibration_option);
calibration_option->clear();
if (dataset) {
calibration_option->addItem("Pixel mask");
for (auto &calibration : dataset->calibration_data)
calibration_option->addItem(calibration.c_str());
}
LoadMask();
}
void JFJochCalibrationWindow::calibrationLoaded(std::shared_ptr<const SimpleImage> &image) {
viewer->setImage(image);
}
void JFJochCalibrationWindow::LoadMask() {
if (dataset) {
auto mask = std::make_shared<SimpleImage>();
auto tmp = dataset->pixel_mask.GetMask();
mask->buffer.resize(tmp.size() * sizeof(uint32_t));
memcpy(mask->buffer.data(), tmp.data(), tmp.size() * sizeof(uint32_t));
mask->image = CompressedImage(mask->buffer.data(), mask->buffer.size(),
dataset->experiment.GetXPixelsNum(), dataset->experiment.GetYPixelsNum(), CompressedImageMode::Uint32);
viewer->setImage(mask);
}
}
void JFJochCalibrationWindow::CalibrationSelected(int val) {
if (val == 0)
LoadMask();
else
emit loadCalibration(calibration_option->itemText(val));
}
+46
View File
@@ -0,0 +1,46 @@
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include <QMainWindow>
#include <QComboBox>
#include <QString>
#include <QStatusBar>
#include "../widgets/JFJochSimpleImageViewer.h"
#include "../../reader/JFJochReaderDataset.h"
#include "../SimpleImage.h"
#include "../widgets/SliderPlusBox.h"
class JFJochCalibrationWindow : public QMainWindow {
Q_OBJECT
QComboBox *calibration_option;
QComboBox *color_map_select;
SliderPlusBox *foreground_slider;
SliderPlusBox *background_slider;
QStatusBar *statusBar;
std::shared_ptr<const JFJochReaderDataset> dataset;
JFJochSimpleImageViewer *viewer = nullptr;
void closeEvent(QCloseEvent *event) override;
public:
JFJochCalibrationWindow(QWidget *parent = nullptr);
signals:
void closing();
void loadCalibration(QString name);
private slots:
void LoadMask();
void CalibrationSelected(int val);
public slots:
void open();
void datasetLoaded(std::shared_ptr<const JFJochReaderDataset> in_dataset);
void calibrationLoaded(std::shared_ptr<const SimpleImage> &image);
};