jfjoch_viewer: Simplify JFJochSimpleImage
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user