Viewer: lay out pixel labels only for the area being repainted

drawPixelLabels took its range from the whole viewport rather than from the
exposed rect it was given, so a 200x40 px hover repaint still walked up to 5000
cells doing mapFromScene + QImage::pixel + drawText for each, only to have the
result clipped away. With hover feedback now rate-limited to 15 Hz that ran ~75
times a second at high zoom, against once per overlay rebuild before the
rendering rework. Intersect with the exposed rect; same in the magnifier.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-30 11:22:27 +02:00
co-authored by Claude Opus 5
parent dc5721ad8a
commit 379feac2e9
3 changed files with 9 additions and 5 deletions
+2 -1
View File
@@ -91,7 +91,8 @@ void JFJochFollowerImage::drawForeground(QPainter *painter, const QRectF &rect)
if (static_cast<int64_t>(pixels.size()) < static_cast<int64_t>(W) * H)
return; // values belong to a different frame
const QRectF visible = mapToScene(viewport()->rect()).boundingRect();
// Clipped to the exposed area, for the same reason as JFJochImage::drawPixelLabels.
const QRectF visible = mapToScene(viewport()->rect()).boundingRect() & rect;
const int x0 = std::max(0, static_cast<int>(std::floor(visible.left())));
const int x1 = std::min(W, static_cast<int>(std::ceil(visible.right())));
const int y0 = std::max(0, static_cast<int>(std::floor(visible.top())));
+6 -3
View File
@@ -852,10 +852,13 @@ QString JFJochImage::PixelLabel(int x, int y) const {
return QString::number(val, 'e', 1);
}
void JFJochImage::drawPixelLabels(QPainter *painter) {
void JFJochImage::drawPixelLabels(QPainter *painter, const QRectF &rect) {
constexpr int kMaxLabels = 5000;
const QRectF visibleRect = mapToScene(viewport()->rect()).boundingRect();
// Only the exposed area, not the whole viewport: a hover repaint dirties a couple of hundred
// pixels, and laying out every visible cell for it would do thousands of mapFromScene / pixel /
// drawText calls whose output is then clipped away - at up to 15 repaints a second.
const QRectF visibleRect = mapToScene(viewport()->rect()).boundingRect() & rect;
const int startX = std::max(0, static_cast<int>(std::floor(visibleRect.left())));
const int endX = std::min(static_cast<int>(W), static_cast<int>(std::ceil(visibleRect.right())));
const int startY = std::max(0, static_cast<int>(std::floor(visibleRect.top())));
@@ -895,7 +898,7 @@ void JFJochImage::drawForeground(QPainter *painter, const QRectF &rect) {
QGraphicsView::drawForeground(painter, rect);
if (scale_factor > 30.0 && W * H > 0 && frame_ && !frame_->isNull())
drawPixelLabels(painter);
drawPixelLabels(painter, rect);
}
void JFJochImage::resetScenePointers() {
+1 -1
View File
@@ -82,7 +82,7 @@ class JFJochImage : public QGraphicsView {
void DrawROI();
virtual void addCustomOverlay();
void updateROI();
void drawPixelLabels(QPainter *painter);
void drawPixelLabels(QPainter *painter, const QRectF &rect);
void wheelEvent(QWheelEvent* event) override;
void resizeEvent(QResizeEvent *event) override;
void contextMenuEvent(QContextMenuEvent *event) override;