From 6d1af4921f471571d0dc51da72ebaab317b8c1be Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Sun, 26 Jul 2026 20:45:11 +0200 Subject: [PATCH] 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) --- viewer/windows/JFJochMagnifierWindow.cpp | 21 +++++++++++++++++++++ viewer/windows/JFJochMagnifierWindow.h | 9 +++++++++ 2 files changed, 30 insertions(+) diff --git a/viewer/windows/JFJochMagnifierWindow.cpp b/viewer/windows/JFJochMagnifierWindow.cpp index 06f1f109..198072bf 100644 --- a/viewer/windows/JFJochMagnifierWindow.cpp +++ b/viewer/windows/JFJochMagnifierWindow.cpp @@ -5,6 +5,7 @@ #include "../image_viewer/JFJochSimpleImage.h" #include "../SimpleImage.h" +#include #include JFJochMagnifierWindow::JFJochMagnifierWindow(QWidget *parent) @@ -17,6 +18,26 @@ JFJochMagnifierWindow::JFJochMagnifierWindow(QWidget *parent) } void JFJochMagnifierWindow::imageLoaded(std::shared_ptr 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 &image = m_pending_image; + if (!image) { m_have_image = false; m_image->setImage(nullptr); diff --git a/viewer/windows/JFJochMagnifierWindow.h b/viewer/windows/JFJochMagnifierWindow.h index 91ec2621..5676155a 100644 --- a/viewer/windows/JFJochMagnifierWindow.h +++ b/viewer/windows/JFJochMagnifierWindow.h @@ -18,6 +18,15 @@ class JFJochMagnifierWindow : public JFJochHelperWindow { double m_magnification = 12.0; bool m_have_image = false; + // Building the close-up converts and colours the whole detector image, so it is only done + // while the window is actually up. The frame is remembered either way; holding the + // shared_ptr also keeps alive the buffer the SimpleImage points into. + std::shared_ptr m_pending_image; + bool m_pending_dirty = false; + void ApplyPendingImage(); + + void showEvent(QShowEvent *event) override; + public: explicit JFJochMagnifierWindow(QWidget *parent = nullptr);