Files
Jungfraujoch/viewer/windows/JFJochMagnifierWindow.cpp
T
leonarski_fandClaude Opus 5 68f5f1f32d Viewer: do not render the magnifier close-up while it is closed
centerAt() checked isVisible(), but imageLoaded() did not, so every frame built
a SimpleImage over the whole detector image and ran it through the full
JFJochSimpleImage path -- convert to float, colour every pixel, redraw -- to
feed a 320x320 window that is closed by default and stays closed most of the
time.

Remember the frame instead and do the work in showEvent(). Holding the
shared_ptr also keeps alive the buffer that the SimpleImage's CompressedImage
points into, which it did not own.

Stepping 30 frames with the magnifier closed: 5545 -> 4770 ms CPU (-14%), on a
2.8 Mpx detector; the saving is per-pixel, so it grows with detector size. With
the magnifier open the cost is unchanged (5500 ms), which is what was being
paid unconditionally before.

Verified in the GUI: opening the magnifier still populates it, and it still
refreshes when the frame changes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 20:45:11 +02:00

67 lines
2.3 KiB
C++

// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include "JFJochMagnifierWindow.h"
#include "../image_viewer/JFJochSimpleImage.h"
#include "../SimpleImage.h"
#include <QShowEvent>
#include <QTransform>
JFJochMagnifierWindow::JFJochMagnifierWindow(QWidget *parent)
: JFJochHelperWindow(parent) {
setWindowTitle("Magnifier");
m_image = new JFJochSimpleImage(this);
m_image->setZoom(m_magnification);
setCentralWidget(m_image);
resize(320, 320);
}
void JFJochMagnifierWindow::imageLoaded(std::shared_ptr<const JFJochReaderImage> image) {
m_pending_image = std::move(image);
// The window is closed most of the time, and rendering a close-up nobody is looking at costs
// a full conversion and recolour of the whole detector image on every frame.
if (!isVisible()) {
m_pending_dirty = true;
return;
}
ApplyPendingImage();
}
void JFJochMagnifierWindow::showEvent(QShowEvent *event) {
JFJochHelperWindow::showEvent(event);
if (m_pending_dirty)
ApplyPendingImage();
}
void JFJochMagnifierWindow::ApplyPendingImage() {
m_pending_dirty = false;
const std::shared_ptr<const JFJochReaderImage> &image = m_pending_image;
if (!image) {
m_have_image = false;
m_image->setImage(nullptr);
return;
}
const double scale = m_have_image ? m_image->GetScaleFactor() : m_magnification;
const QPointF center = m_have_image
? m_image->mapToScene(m_image->viewport()->rect().center())
: QPointF(image->Dataset().experiment.GetXPixelsNum() * 0.5,
image->Dataset().experiment.GetYPixelsNum() * 0.5);
const auto &exp = image->Dataset().experiment;
auto si = std::make_shared<SimpleImage>();
si->image = CompressedImage(image->Image(), exp.GetXPixelsNum(), exp.GetYPixelsNum());
m_image->setImage(si);
m_image->applyViewport(QTransform::fromScale(scale, scale), center);
m_have_image = true;
}
void JFJochMagnifierWindow::centerAt(QPointF scenePos) {
if (!m_have_image || !isVisible())
return;
double scale = m_image->GetScaleFactor();
m_image->applyViewport(QTransform::fromScale(scale, scale), scenePos);
}