Files
Jungfraujoch/viewer/image_viewer/JFJochDiffractionImage.h
T
leonarski_fandClaude Fable 5 ec05a6c4d6 Viewer: coral secondary-lattice spots, ring arcs, legend, ROI swatches, save JPEG
- Colour indexed spots from a secondary (or further) lattice in coral (#FA7268),
  the viewer's finishing accent, in the diffraction-image overlay.
- Draw resolution rings by sweeping ResPhiToPxl into a QPainterPath (like the
  azimuthal ROI arcs), replacing the 4-point bounding-box ellipse and the
  poni_rot_3=0 hack, so rings follow the geometry on tilted detectors.
- Add a spot/prediction colour legend to the Image-features side panel; the two
  user-adjustable swatches track the colour picker.
- Show a colour swatch matching the on-image annotation on each ROI-list item,
  via a shared ROIAnnotationColor palette used by both the overlay and the list.
- Add "Save image as JPEG..." / "...with overlay as JPEG..." to the image
  right-click menu, reusing a factored renderToImage() helper.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 12:04:12 +02:00

122 lines
4.2 KiB
C++

// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include "JFJochImage.h"
#include "../../reader/JFJochReaderImage.h"
#include "../../common/ROIDefinition.h"
class ROIAzimuthal;
class DiffractionGeometry;
class JFJochDiffractionImage : public JFJochImage {
Q_OBJECT
QColor spot_color = Qt::green;
QColor prediction_color = Qt::darkRed;
QColor ice_ring_color = Qt::cyan;
QColor second_lattice_color = QColor(0xFA, 0x72, 0x68); // coral, the viewer "finishing" accent
float hover_resolution = NAN;
QGraphicsTextItem* hover_resolution_item = nullptr; // big text in top-left
public:
enum class RingMode {Auto, Estimation, Manual, None, IceRings};
Q_ENUM(RingMode)
JFJochDiffractionImage(QWidget *parent = nullptr);
private:
void addCustomOverlay() override;
void LoadImageInternal();
void DrawResolutionRings();
void DrawROIs();
void DrawAzimuthalROI(const ROIAzimuthal &az, const QColor &color, const DiffractionGeometry &geom);
void AddROILabel(const std::string &name, const QColor &color, float px, float py);
// Interactive editing of the selected (named) ROI: move box/circle for now.
bool roiEditPress(const QPointF &scenePos) override;
void roiEditMove(const QPointF &scenePos) override;
void roiEditRelease() override;
void roiScratchDrawn() override;
void keyPressEvent(QKeyEvent *event) override; // Delete removes the selected ROI
[[nodiscard]] ROIDefinition BuildEditedROIDefinition() const; // current ROIs with the edit applied
[[nodiscard]] ResizeHandle hitTestBoxHandle(const QRectF &r, const QPointF &p, qreal tol) const;
// Grab points for an azimuthal ROI: inner/outer arc (resize Q/d) and the two phi
// edges (rotate). The phi handles are only meaningful for a sector (HasPhi()).
void azimuthalHandles(const ROIAzimuthal &az, const DiffractionGeometry &geom,
QPointF &inner, QPointF &outer, QPointF &phimin, QPointF &phimax) const;
QString selected_roi_;
enum class RoiEdit { None, MoveBox, ResizeBox, MoveCircle, ResizeCircle,
AzimInner, AzimOuter, RotatePhiMin, RotatePhiMax };
RoiEdit roi_edit_ = RoiEdit::None;
ResizeHandle box_handle_ = ResizeHandle::None;
QString edit_name_;
QRectF edit_box_;
QPointF edit_center_;
double edit_radius_ = 0;
float edit_d_min_ = 0, edit_d_max_ = 0, edit_phi_min_ = 0, edit_phi_max_ = 0; // azimuthal edit state
bool edit_has_phi_ = false;
QPointF move_last_;
bool live_pending_ = false; // a live edit is being recomputed; throttles emissions
void DrawSpots();
void DrawPredictions();
void DrawBeamCenter();
void DrawTopPixels();
void DrawSaturation();
void DrawResolutionText();
void DrawCross(float x, float y, float size, float width, float z = 1);
void UpdateForeground();
void beforeOverlayCleared() override;
void leaveEvent(QEvent *event) override;
std::shared_ptr<const JFJochReaderImage> image;
int32_t show_highest_pixels = 0;
QVector<float> res_ring = {};
RingMode ring_mode = RingMode::Estimation;
bool show_spots = false;
bool show_predictions = false;
bool show_roi_labels = false;
bool show_roi_fill = false;
bool highlight_ice_rings = true;
float ice_ring_width_Q_recipA = 0.01;
void mouseHover(QMouseEvent* event) override;
signals:
void roiGeometryEdited(ROIDefinition rois);
void roiSelected(QString name); // user picked an ROI by clicking it on the image
public slots:
void setSelectedROI(QString name);
void loadImage(std::shared_ptr<const JFJochReaderImage> image);
void setAutoForeground(bool input);
void setResolutionRing(QVector<float> v);
void setResolutionRingMode(RingMode mode);
void showSpots(bool input);
void showPredictions(bool input);
void showROILabels(bool input);
void showROIFill(bool input);
void setSpotColor(QColor input);
void setPredictionColor(QColor input);
void showHighestPixels(int32_t v);
void showSaturation(bool input);
void highlightIceRings(bool input);
void setHDRMode(bool input);
};