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>
67 lines
2.3 KiB
C++
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);
|
|
}
|