2511-eiger-mask #2
@@ -71,6 +71,8 @@ ADD_EXECUTABLE(jfjoch_viewer jfjoch_viewer.cpp JFJochViewerWindow.cpp JFJochView
|
||||
windows/JFJochCalibrationWindow.h
|
||||
windows/JFJochHelperWindow.cpp
|
||||
windows/JFJochHelperWindow.h
|
||||
widgets/JFJochImage.cpp
|
||||
widgets/JFJochImage.h
|
||||
)
|
||||
|
||||
TARGET_LINK_LIBRARIES(jfjoch_viewer Qt6::Core Qt6::Gui Qt6::Widgets Qt6::Charts Qt6::DBus
|
||||
|
||||
86
viewer/widgets/JFJochImage.cpp
Normal file
86
viewer/widgets/JFJochImage.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
#include "JFJochImage.h"
|
||||
|
||||
#include <QScrollBar>
|
||||
#include <QWheelEvent>
|
||||
|
||||
JFJochImage::JFJochImage(QWidget *parent) : QGraphicsView(parent) {
|
||||
setDragMode(QGraphicsView::NoDrag); // Disable default drag mode
|
||||
setTransformationAnchor(QGraphicsView::AnchorUnderMouse); // Zoom anchors
|
||||
setRenderHint(QPainter::Antialiasing); // Enable smooth rendering
|
||||
setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
|
||||
setFocusPolicy(Qt::ClickFocus);
|
||||
// Connect the horizontal scrollbar's valueChanged signal
|
||||
connect(horizontalScrollBar(), &QScrollBar::valueChanged, this, &JFJochImage::onScroll);
|
||||
|
||||
// Connect the vertical scrollbar's valueChanged signal
|
||||
connect(verticalScrollBar(), &QScrollBar::valueChanged, this, &JFJochImage::onScroll);
|
||||
}
|
||||
|
||||
void JFJochImage::onScroll(int value) {
|
||||
updateOverlay();
|
||||
}
|
||||
|
||||
void JFJochImage::changeBackground(float val) {
|
||||
background = val;
|
||||
Redraw();
|
||||
}
|
||||
|
||||
void JFJochImage::changeForeground(float val) {
|
||||
foreground = val;
|
||||
Redraw();
|
||||
}
|
||||
|
||||
void JFJochImage::setColorMap(int color_map) {
|
||||
try {
|
||||
color_scale.Select(static_cast<ColorScaleEnum>(color_map));
|
||||
Redraw();
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
void JFJochImage::setFeatureColor(QColor input) {
|
||||
feature_color = input;
|
||||
Redraw();
|
||||
}
|
||||
|
||||
void JFJochImage::wheelEvent(QWheelEvent *event) {
|
||||
if (!scene()) return;
|
||||
|
||||
const double zoomFactor = 1.15; // Zoom factor
|
||||
|
||||
// Get the position of the mouse in scene coordinates
|
||||
QPointF targetScenePos = mapToScene(event->position().toPoint());
|
||||
|
||||
if (event->modifiers() == Qt::ShiftModifier) {
|
||||
float new_foreground = foreground + event->angleDelta().y() / 120.0f;
|
||||
if (new_foreground < 1)
|
||||
new_foreground = 1.0;
|
||||
foreground = new_foreground;
|
||||
emit foregroundChanged(foreground);
|
||||
Redraw();
|
||||
} else {
|
||||
// Perform zooming
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust the view's center to keep the zoom focused on the mouse position
|
||||
QPointF updatedViewportCenter = mapToScene(viewport()->rect().center());
|
||||
QPointF delta = targetScenePos - updatedViewportCenter;
|
||||
translate(delta.x(), delta.y()); // Shift the view
|
||||
|
||||
updateOverlay();
|
||||
}
|
||||
}
|
||||
43
viewer/widgets/JFJochImage.h
Normal file
43
viewer/widgets/JFJochImage.h
Normal file
@@ -0,0 +1,43 @@
|
||||
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
#ifndef JFJOCH_JFJOCHIMAGE_H
|
||||
#define JFJOCH_JFJOCHIMAGE_H
|
||||
|
||||
#include <QGraphicsView>
|
||||
#include "../../common/ColorScale.h"
|
||||
|
||||
class JFJochImage : public QGraphicsView {
|
||||
Q_OBJECT
|
||||
|
||||
virtual void updateOverlay() = 0;
|
||||
virtual void Redraw() = 0;
|
||||
|
||||
void wheelEvent(QWheelEvent* event) override;
|
||||
|
||||
protected:
|
||||
QColor feature_color = Qt::magenta;
|
||||
float foreground = 10.0;
|
||||
float background = 0.0;
|
||||
double scale_factor = 1.0;
|
||||
ColorScale color_scale;
|
||||
std::vector<rgb> image_rgb;
|
||||
QPixmap pixmap;
|
||||
|
||||
signals:
|
||||
void foregroundChanged(float v);
|
||||
void backgroundChanged(float v);
|
||||
void writeStatusBar(QString string, int timeout_ms = 0);
|
||||
|
||||
private slots:
|
||||
void onScroll(int value);
|
||||
public slots:
|
||||
void setFeatureColor(QColor input);
|
||||
void setColorMap(int color_map);
|
||||
void changeForeground(float val);
|
||||
void changeBackground(float val);
|
||||
public:
|
||||
explicit JFJochImage(QWidget *parent = nullptr);
|
||||
};
|
||||
|
||||
#endif //JFJOCH_JFJOCHIMAGE_H
|
||||
@@ -21,26 +21,15 @@ static inline double normalize_to_unit(double raw, double bg, double fg) {
|
||||
}
|
||||
|
||||
JFJochSimpleImageViewer::JFJochSimpleImageViewer(QWidget *parent)
|
||||
: QGraphicsView(parent) {
|
||||
setDragMode(QGraphicsView::NoDrag);
|
||||
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
|
||||
setRenderHint(QPainter::Antialiasing);
|
||||
setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
setFocusPolicy(Qt::ClickFocus);
|
||||
|
||||
: JFJochImage(parent) {
|
||||
auto *scn = new QGraphicsScene(this);
|
||||
setScene(scn);
|
||||
|
||||
// Optional: a sensible default colormap
|
||||
color_scale_.Select(ColorScaleEnum::Indigo);
|
||||
color_scale.Select(ColorScaleEnum::Indigo);
|
||||
|
||||
// Keep overlays in pixel units independent of zoom (for labels font sizing)
|
||||
setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
|
||||
|
||||
// QTimer for smoother movement/updates
|
||||
repaint_timer_.setInterval(16); // ~60 FPS
|
||||
repaint_timer_.setSingleShot(false);
|
||||
connect(&repaint_timer_, &QTimer::timeout, this, &JFJochSimpleImageViewer::onRepaintTimer);
|
||||
}
|
||||
|
||||
void JFJochSimpleImageViewer::clear() {
|
||||
@@ -55,69 +44,14 @@ void JFJochSimpleImageViewer::setImage(std::shared_ptr<const SimpleImage> img) {
|
||||
image_ = std::move(img);
|
||||
has_image_ = true;
|
||||
renderImage();
|
||||
updateScene();
|
||||
updateOverlay();
|
||||
}
|
||||
|
||||
void JFJochSimpleImageViewer::setBackground(float v) {
|
||||
background_ = v;
|
||||
emit backgroundChanged(background_);
|
||||
void JFJochSimpleImageViewer::Redraw() {
|
||||
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();
|
||||
updateOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +64,7 @@ void JFJochSimpleImageViewer::mousePressEvent(QMouseEvent* event) {
|
||||
// With Shift -> ROI interactions (draw/resize/move); without -> pan
|
||||
if (event->modifiers() & Qt::Modifier::SHIFT) {
|
||||
// Determine if we are over an existing ROI handle
|
||||
active_handle_ = hitTestROIHandle(scenePos, 4.0 / std::sqrt(std::max(1e-4, scale_factor_)));
|
||||
active_handle_ = hitTestROIHandle(scenePos, 4.0 / std::sqrt(std::max(1e-4, scale_factor)));
|
||||
if (active_handle_ != ResizeHandle::None && active_handle_ != ResizeHandle::Inside) {
|
||||
mouse_event_type_ = MouseEventType::ResizingROI;
|
||||
roi_start_pos_ = roi_box_.topLeft();
|
||||
@@ -167,7 +101,7 @@ void JFJochSimpleImageViewer::mouseMoveEvent(QMouseEvent* event) {
|
||||
const QPointF delta = mapToScene(event->pos()) - mapToScene(last_mouse_pos_);
|
||||
last_mouse_pos_ = event->pos();
|
||||
translate(delta.x(), delta.y());
|
||||
updateScene();
|
||||
updateOverlay();
|
||||
break;
|
||||
}
|
||||
case MouseEventType::DrawingROI: {
|
||||
@@ -254,7 +188,7 @@ void JFJochSimpleImageViewer::renderImage() {
|
||||
|
||||
// Prepare destination QImage (RGB888)
|
||||
QImage qimg(int(W), int(H), QImage::Format_RGB888);
|
||||
image_rgb_.resize(W * H);
|
||||
image_rgb.resize(W * H);
|
||||
image_values_.resize(W * H);
|
||||
|
||||
std::vector<uint8_t> image_buffer;
|
||||
@@ -271,7 +205,7 @@ void JFJochSimpleImageViewer::renderImage() {
|
||||
dstRow[idx * 3 + 0] = c.r;
|
||||
dstRow[idx * 3 + 1] = c.g;
|
||||
dstRow[idx * 3 + 2] = c.b;
|
||||
image_rgb_[idx] = c;
|
||||
image_rgb[idx] = c;
|
||||
};
|
||||
|
||||
// Fast path: packed RGB (assumed 3 bytes per pixel)
|
||||
@@ -317,16 +251,16 @@ void JFJochSimpleImageViewer::renderImage() {
|
||||
}
|
||||
|
||||
// Build pixmap
|
||||
pixmap_ = QPixmap::fromImage(qimg);
|
||||
pixmap = QPixmap::fromImage(qimg);
|
||||
}
|
||||
|
||||
void JFJochSimpleImageViewer::updateScene() {
|
||||
void JFJochSimpleImageViewer::updateOverlay() {
|
||||
if (!scene()) return;
|
||||
scene()->clear();
|
||||
if (!has_image_) return;
|
||||
|
||||
// Add base image
|
||||
scene()->addItem(new QGraphicsPixmapItem(pixmap_));
|
||||
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).
|
||||
@@ -344,8 +278,8 @@ void JFJochSimpleImageViewer::updateScene() {
|
||||
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);
|
||||
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
|
||||
|
||||
@@ -355,7 +289,7 @@ void JFJochSimpleImageViewer::updateScene() {
|
||||
const size_t idx = base + size_t(x);
|
||||
|
||||
const double raw = image_values_[idx];
|
||||
const rgb c = image_rgb_[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;
|
||||
@@ -398,19 +332,19 @@ void JFJochSimpleImageViewer::renderImage(QImage &qimg, const uint8_t *input) {
|
||||
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_);
|
||||
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
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -480,7 +414,7 @@ void JFJochSimpleImageViewer::drawROI(QGraphicsScene* scn) {
|
||||
scn->addRect(roi_box_, pen);
|
||||
|
||||
// Small corner handles
|
||||
const qreal handleSize = 3.0 / std::sqrt(std::max(1e-4, scale_factor_));
|
||||
const qreal handleSize = 3.0 / std::sqrt(std::max(1e-4, scale_factor));
|
||||
auto addHandle = [&](const QPointF& p) {
|
||||
scn->addRect(QRectF(p.x() - handleSize, p.y() - handleSize, 2 * handleSize, 2 * handleSize),
|
||||
QPen(feature_color, 1), QBrush(feature_color));
|
||||
@@ -508,11 +442,11 @@ void JFJochSimpleImageViewer::drawROI(QGraphicsScene* scn) {
|
||||
const int H = int(image_->image.GetHeight());
|
||||
int px = std::clamp(roi_px.left(), 0, std::max(0, W - 1));
|
||||
int py = std::clamp(roi_px.top(), 0, std::max(0, H - 1));
|
||||
const rgb bgc = image_rgb_[size_t(py) * size_t(W) + size_t(px)];
|
||||
const rgb bgc = image_rgb[size_t(py) * size_t(W) + size_t(px)];
|
||||
const bool darkText = luminance(bgc) > 128.0;
|
||||
|
||||
QFont font("Arial");
|
||||
const qreal f = std::clamp(scale_factor_, 0.5, 50.0);
|
||||
const qreal f = std::clamp(scale_factor, 0.5, 50.0);
|
||||
font.setPointSizeF(14.0 / std::sqrt(f));
|
||||
|
||||
auto* t = scn->addText(text, font);
|
||||
@@ -579,7 +513,7 @@ void JFJochSimpleImageViewer::onRepaintTimer() {
|
||||
|
||||
// Rebuild scene if requested
|
||||
if (needs_scene_update_) {
|
||||
updateScene();
|
||||
updateOverlay();
|
||||
needs_scene_update_ = false;
|
||||
}
|
||||
|
||||
@@ -600,8 +534,3 @@ void JFJochSimpleImageViewer::scheduleSceneUpdate() {
|
||||
if (!repaint_timer_.isActive())
|
||||
repaint_timer_.start();
|
||||
}
|
||||
|
||||
void JFJochSimpleImageViewer::setFeatureColor(QColor input) {
|
||||
feature_color = input;
|
||||
scheduleSceneUpdate();
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QGraphicsView>
|
||||
#include "JFJochImage.h"
|
||||
#include <QVector>
|
||||
#include <QColor>
|
||||
#include <QPointF>
|
||||
@@ -14,27 +14,16 @@
|
||||
#include "../SimpleImage.h"
|
||||
#include "../../common/ColorScale.h"
|
||||
|
||||
class JFJochSimpleImageViewer : public QGraphicsView {
|
||||
class JFJochSimpleImageViewer : public JFJochImage {
|
||||
Q_OBJECT
|
||||
QColor feature_color = Qt::magenta;
|
||||
|
||||
void Redraw() override;
|
||||
public:
|
||||
explicit JFJochSimpleImageViewer(QWidget* parent = nullptr);
|
||||
void setImage(std::shared_ptr<const SimpleImage> img);
|
||||
void clear();
|
||||
|
||||
public slots:
|
||||
void setBackground(float v);
|
||||
void setForeground(float v);
|
||||
void setColorMap(int colorMapEnumValue);
|
||||
void setFeatureColor(QColor input);
|
||||
signals:
|
||||
void foregroundChanged(float v);
|
||||
void backgroundChanged(float v);
|
||||
void writeStatusBar(QString string, int timeout_ms = 0);
|
||||
|
||||
protected:
|
||||
void wheelEvent(QWheelEvent* event) override;
|
||||
void mousePressEvent(QMouseEvent* event) override;
|
||||
void mouseMoveEvent(QMouseEvent* event) override;
|
||||
void mouseReleaseEvent(QMouseEvent* event) override;
|
||||
@@ -57,19 +46,17 @@ private:
|
||||
};
|
||||
|
||||
void renderImage(); // builds pixmap_ from current image_ + settings
|
||||
void updateScene(); // clears scene, adds pixmap + labels + ROI (if any)
|
||||
void updateOverlay() override; // clears scene, adds pixmap + labels + ROI (if any)
|
||||
void drawROI(QGraphicsScene* scn); // draw box and stats
|
||||
ROIStats computeROIStats(const QRect& roi_px) const;
|
||||
|
||||
// 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<double> image_values_; // original scalar values per pixel (for labels and min/max)
|
||||
|
||||
// View/interaction
|
||||
double scale_factor_ = 1.0;
|
||||
QPoint last_mouse_pos_;
|
||||
bool panning_ = false;
|
||||
|
||||
@@ -81,13 +68,6 @@ private:
|
||||
void scheduleSceneUpdate();
|
||||
void onRepaintTimer();
|
||||
|
||||
// Settings
|
||||
float background_ = 0.0f;
|
||||
float foreground_ = 10.0f;
|
||||
ColorScale color_scale_;
|
||||
bool show_labels_ = false;
|
||||
std::vector<Label> labels_;
|
||||
|
||||
template <class T>
|
||||
void renderImage(QImage &qimg, const uint8_t *input);
|
||||
|
||||
|
||||
@@ -12,58 +12,7 @@
|
||||
#include <cmath>
|
||||
|
||||
// Constructor
|
||||
JFJochViewerImage::JFJochViewerImage(QWidget *parent) : QGraphicsView(parent) {
|
||||
setDragMode(QGraphicsView::NoDrag); // Disable default drag mode
|
||||
setTransformationAnchor(QGraphicsView::AnchorUnderMouse); // Zoom anchors
|
||||
setRenderHint(QPainter::Antialiasing); // Enable smooth rendering
|
||||
setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
|
||||
setFocusPolicy(Qt::ClickFocus);
|
||||
// Connect the horizontal scrollbar's valueChanged signal
|
||||
connect(horizontalScrollBar(), &QScrollBar::valueChanged, this, &JFJochViewerImage::onScroll);
|
||||
|
||||
// Connect the vertical scrollbar's valueChanged signal
|
||||
connect(verticalScrollBar(), &QScrollBar::valueChanged, this, &JFJochViewerImage::onScroll);
|
||||
}
|
||||
|
||||
// Handle zooming with mouse wheel
|
||||
void JFJochViewerImage::wheelEvent(QWheelEvent *event) {
|
||||
if (!scene() || !image) return;
|
||||
|
||||
const double zoomFactor = 1.15; // Zoom factor
|
||||
|
||||
// Get the position of the mouse in scene coordinates
|
||||
QPointF targetScenePos = mapToScene(event->position().toPoint());
|
||||
|
||||
if (event->modifiers() == Qt::ShiftModifier) {
|
||||
float new_foreground = foreground + event->angleDelta().y() / 120.0f;
|
||||
if (new_foreground < 1)
|
||||
new_foreground = 1.0;
|
||||
foreground = new_foreground;
|
||||
emit foregroundChanged(foreground);
|
||||
Redraw();
|
||||
} else {
|
||||
// Perform zooming
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust the view's center to keep the zoom focused on the mouse position
|
||||
QPointF updatedViewportCenter = mapToScene(viewport()->rect().center());
|
||||
QPointF delta = targetScenePos - updatedViewportCenter;
|
||||
translate(delta.x(), delta.y()); // Shift the view
|
||||
|
||||
updateOverlay();
|
||||
}
|
||||
}
|
||||
JFJochViewerImage::JFJochViewerImage(QWidget *parent) : JFJochImage(parent) {}
|
||||
|
||||
QPointF RoundPoint(const QPointF &input) {
|
||||
return QPointF(qRound(input.x()), qRound(input.y()));
|
||||
@@ -540,10 +489,6 @@ void JFJochViewerImage::resizeEvent(QResizeEvent *event) {
|
||||
updateOverlay();
|
||||
}
|
||||
|
||||
void JFJochViewerImage::onScroll(int value) {
|
||||
updateOverlay();
|
||||
}
|
||||
|
||||
void JFJochViewerImage::Redraw() {
|
||||
if (!image) return;
|
||||
|
||||
@@ -573,15 +518,6 @@ void JFJochViewerImage::loadImage(std::shared_ptr<const JFJochReaderImage> in_im
|
||||
}
|
||||
}
|
||||
|
||||
void JFJochViewerImage::changeBackground(float val) {
|
||||
background = val;
|
||||
Redraw();
|
||||
}
|
||||
|
||||
void JFJochViewerImage::changeForeground(float val) {
|
||||
foreground = val;
|
||||
Redraw();
|
||||
}
|
||||
|
||||
void JFJochViewerImage::setAutoForeground(bool input) {
|
||||
auto_foreground = input;
|
||||
@@ -593,13 +529,7 @@ void JFJochViewerImage::setAutoForeground(bool input) {
|
||||
}
|
||||
}
|
||||
|
||||
void JFJochViewerImage::setColorMap(int color_map) {
|
||||
try {
|
||||
color_scale.Select(static_cast<ColorScaleEnum>(color_map));
|
||||
Redraw();
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void JFJochViewerImage::setResolutionRing(QVector<float> v) {
|
||||
res_ring = v;
|
||||
@@ -622,10 +552,7 @@ void JFJochViewerImage::showPredictions(bool input) {
|
||||
Redraw();
|
||||
}
|
||||
|
||||
void JFJochViewerImage::setFeatureColor(QColor input) {
|
||||
feature_color = input;
|
||||
Redraw();
|
||||
}
|
||||
|
||||
|
||||
void JFJochViewerImage::setSpotColor(QColor input) {
|
||||
spot_color = input;
|
||||
|
||||
@@ -4,43 +4,39 @@
|
||||
#ifndef JFJOCHVIEWERIMAGE_H
|
||||
#define JFJOCHVIEWERIMAGE_H
|
||||
|
||||
#include <QGraphicsView>
|
||||
#include "JFJochImage.h"
|
||||
#include <QVector>
|
||||
#include "../../reader/JFJochHDF5Reader.h"
|
||||
#include "../../common/ColorScale.h"
|
||||
|
||||
class JFJochViewerImage : public QGraphicsView {
|
||||
class JFJochViewerImage : public JFJochImage {
|
||||
Q_OBJECT
|
||||
|
||||
bool auto_foreground = false;
|
||||
|
||||
QColor feature_color = Qt::magenta;
|
||||
QColor spot_color = Qt::green;
|
||||
QColor prediction_color = Qt::darkRed;
|
||||
QColor ice_ring_color = Qt::cyan;
|
||||
|
||||
QPixmap pixmap;
|
||||
|
||||
QRectF roi_box;
|
||||
|
||||
public:
|
||||
JFJochViewerImage(QWidget *parent = nullptr);
|
||||
signals:
|
||||
void foregroundChanged(float val);
|
||||
void roiBoxUpdated(QRect box);
|
||||
void roiCircleUpdated(double x, double y, double radius);
|
||||
void writeStatusBar(QString string);
|
||||
private:
|
||||
void wheelEvent(QWheelEvent *event) override; // Zooming
|
||||
void mousePressEvent(QMouseEvent *event) override; // Panning start
|
||||
void mouseMoveEvent(QMouseEvent *event) override; // Panning interaction
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
void updateOverlay();
|
||||
|
||||
void updateOverlay() override;
|
||||
void Redraw() override;
|
||||
|
||||
void updateROI();
|
||||
|
||||
void LoadImageInternal();
|
||||
void Redraw();
|
||||
void DrawResolutionRings();
|
||||
void DrawSpots();
|
||||
void DrawPredictions();
|
||||
@@ -49,13 +45,8 @@ private:
|
||||
void DrawSaturation();
|
||||
void DrawCross(float x, float y, float size, float width, float z = 1);
|
||||
|
||||
double scale_factor = 1.0;
|
||||
ColorScale color_scale;
|
||||
std::shared_ptr<const JFJochReaderImage> image;
|
||||
std::vector<rgb> image_rgb;
|
||||
|
||||
float foreground = 10;
|
||||
float background = 0;
|
||||
int32_t show_highest_pixels = 0;
|
||||
|
||||
QVector<float> res_ring = {};
|
||||
@@ -76,21 +67,15 @@ private:
|
||||
MouseEventType mouse_event_type = MouseEventType::None;
|
||||
RoiType roi_type = RoiType::RoiBox;
|
||||
|
||||
protected slots:
|
||||
void onScroll(int value);
|
||||
public slots:
|
||||
void loadImage(std::shared_ptr<const JFJochReaderImage> image);
|
||||
void setAutoForeground(bool input);
|
||||
void changeForeground(float val);
|
||||
void changeBackground(float val);
|
||||
|
||||
void setResolutionRing(QVector<float> v);
|
||||
void setResolutionRingAuto();
|
||||
void showSpots(bool input);
|
||||
void showPredictions(bool input);
|
||||
|
||||
void setColorMap(int color_map);
|
||||
void setFeatureColor(QColor input);
|
||||
void setSpotColor(QColor input);
|
||||
void setPredictionColor(QColor input);
|
||||
|
||||
|
||||
@@ -47,6 +47,9 @@ JFJochCalibrationWindow::JFJochCalibrationWindow(QWidget *parent) : JFJochHelper
|
||||
connect(viewer, &JFJochSimpleImageViewer::foregroundChanged,
|
||||
[this] (float val) {foreground_slider->setValue(val);});
|
||||
|
||||
connect(background_slider, &SliderPlusBox::valueChanged, viewer, &JFJochSimpleImageViewer::changeBackground);
|
||||
connect(foreground_slider, &SliderPlusBox::valueChanged, viewer, &JFJochSimpleImageViewer::changeForeground);
|
||||
|
||||
connect(color_map_select, &QComboBox::currentIndexChanged, this, [this](int index) {
|
||||
viewer->setColorMap(index);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user