jfjoch_viewer: Simplify JFJochSimpleImage

This commit is contained in:
2025-11-07 18:07:54 +01:00
parent b694c03e85
commit 3f68ffd05a
2 changed files with 15 additions and 118 deletions

View File

@@ -20,14 +20,6 @@ JFJochSimpleImage::JFJochSimpleImage(QWidget *parent)
setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
}
void JFJochSimpleImage::clear() {
has_image_ = false;
image_.reset();
if (scene())
scene()->clear();
}
void JFJochSimpleImage::setImage(std::shared_ptr<const SimpleImage> img) {
if (img) {
image_ = std::move(img);
@@ -236,78 +228,3 @@ void JFJochSimpleImage::renderImage(QImage &qimg, const uint8_t *input) {
}
}
JFJochSimpleImage::ROIStats
JFJochSimpleImage::computeROIStats(const QRect& roi_px) const {
ROIStats s;
if (!has_image_) return s;
const int W = int(image_->image.GetWidth());
const int H = int(image_->image.GetHeight());
const int x0 = std::clamp(roi_px.left(), 0, std::max(0, W - 1));
const int x1 = std::clamp(roi_px.right(), 0, std::max(0, W - 1));
const int y0 = std::clamp(roi_px.top(), 0, std::max(0, H - 1));
const int y1 = std::clamp(roi_px.bottom(), 0, std::max(0, H - 1));
if (x1 < x0 || y1 < y0) return s;
// One pass: min, max, sum, sum of squares
double sum = 0.0;
double sumsq = 0.0;
s.min = std::numeric_limits<double>::infinity();
s.max = -std::numeric_limits<double>::infinity();
s.count = 0;
for (int y = y0; y <= y1; ++y) {
const size_t base = size_t(y) * size_t(W);
for (int x = x0; x <= x1; ++x) {
const size_t idx = base + size_t(x);
const double v = image_values_[idx];
if (std::isnan(v)) continue; // skip invalid
if (v < s.min) s.min = v;
if (v > s.max) s.max = v;
sum += v;
sumsq += v * v;
++s.count;
}
}
if (!s.valid()) return s;
s.avg = sum / double(s.count);
double variance = sumsq / double(s.count) - s.avg * s.avg;
if (variance < 0.0) variance = 0.0; // guard small negatives from FP error
s.stddev = std::sqrt(variance);
return s;
}
void JFJochSimpleImage::onRepaintTimer() {
// Apply any pending pan
if (!qFuzzyIsNull(pan_accum_.x()) || !qFuzzyIsNull(pan_accum_.y())) {
translate(pan_accum_.x(), pan_accum_.y());
pan_accum_ = QPointF(0.0, 0.0);
}
// Rebuild scene if requested
if (needs_scene_update_) {
updateOverlay();
needs_scene_update_ = false;
}
// Stop timer if nothing pending
if (qFuzzyIsNull(pan_accum_.x()) && qFuzzyIsNull(pan_accum_.y()) && !needs_scene_update_) {
repaint_timer_.stop();
}
}
void JFJochSimpleImage::schedulePanDelta(const QPointF& d) {
pan_accum_ += d;
if (!repaint_timer_.isActive())
repaint_timer_.start();
}
void JFJochSimpleImage::scheduleSceneUpdate() {
needs_scene_update_ = true;
if (!repaint_timer_.isActive())
repaint_timer_.start();
}

View File

@@ -17,44 +17,24 @@
class JFJochSimpleImage : public JFJochImage {
Q_OBJECT
void Redraw() override;
public:
explicit JFJochSimpleImage(QWidget* parent = nullptr);
void setImage(std::shared_ptr<const SimpleImage> img);
void clear();
private:
struct ROIStats {
double min = std::numeric_limits<double>::infinity();
double max = -std::numeric_limits<double>::infinity();
double avg = std::numeric_limits<double>::quiet_NaN();
double stddev = std::numeric_limits<double>::quiet_NaN();
size_t count = 0;
bool valid() const { return std::isfinite(min) && std::isfinite(max) && count > 0; }
};
void renderImage(); // builds pixmap_ from current image_ + settings
void updateOverlay() override; // clears scene, adds pixmap + labels + ROI (if any)
ROIStats computeROIStats(const QRect& roi_px) const;
// Image and rendering state
std::shared_ptr<const SimpleImage> image_;
bool has_image_ = false;
std::vector<double> image_values_; // original scalar values per pixel (for labels and min/max)
// Smooth movement/repaint
QTimer repaint_timer_;
QPointF pan_accum_{0.0, 0.0};
bool needs_scene_update_ = false;
void schedulePanDelta(const QPointF& d);
void scheduleSceneUpdate();
void onRepaintTimer();
template <class T>
void renderImage(QImage &qimg, const uint8_t *input);
bool auto_fgbg = true;
void mouseHover(QMouseEvent* event) override;
void Redraw() override;
public:
explicit JFJochSimpleImage(QWidget *parent = nullptr);
void setImage(std::shared_ptr<const SimpleImage> img);
private:
template<class T>
void renderImage(QImage &qimg, const uint8_t *input);
void renderImage(); // builds pixmap_ from current image_ + settings
void updateOverlay() override; // clears scene, adds pixmap + labels + ROI (if any)
void mouseHover(QMouseEvent *event) override;
};