Skip to content

Fix "Smooth scaling" artifact#104

Draft
abaeyens wants to merge 2 commits into
ros-visualization:rolling-develfrom
abaeyens:abaeyens/rolling/fix-smooth-scaling-artifact
Draft

Fix "Smooth scaling" artifact#104
abaeyens wants to merge 2 commits into
ros-visualization:rolling-develfrom
abaeyens:abaeyens/rolling/fix-smooth-scaling-artifact

Conversation

@abaeyens
Copy link
Copy Markdown
Contributor

@abaeyens abaeyens commented May 14, 2026

Fix #103.

Used generative AI: Claude Opus 4.7

The following PR must be merged first:

abaeyens added 2 commits May 14, 2026 17:26
Solves ros-visualization#85

What this fixes: the scaling artefacts are now gone because a true 1-to-1 pixel mapping occurs from image message to the display, without scaling twice in between.

What this _probably_ does not fix: the frame size still isn't handled correctly, it just got hidden because  got set to zero. I'm afraid it will arise again when people including this code set  to a non-zero value.

Signed-off-by: Arne Baeyens <mail@arnebaeyens.com>
The smooth-scaling branch called QImage::scaled() with KeepAspectRatio,
which rounds the result down to the largest aspect-preserving integer
size that fits inside contentsRect(). resizeToFitAspectRatio(), however,
rounds the widget dimensions to the nearest integer (+0.5). When the
two rounding directions disagreed (about half the time, depending on
the layout dimensions), drawImage(contentsRect(), image) stretched the
scaled image by 1 px on one axis, breaking the aspect ratio the
KeepAspectRatio mode was supposed to preserve.

Use IgnoreAspectRatio so the scaled image's size matches contentsRect()
exactly and no second stretch happens at draw time. This also makes
the smooth branch consistent with the non-smooth branch, which already
scales non-uniformly via drawImage(contentsRect(), qimage_).

Refs: ros-visualization#103
Signed-off-by: Arne Baeyens <mail@arnebaeyens.com>
@abaeyens
Copy link
Copy Markdown
Contributor Author

While reviewing, you may want to apply the following diff:

diff --git a/src/rqt_image_view/ratio_layouted_frame.cpp b/src/rqt_image_view/ratio_layouted_frame.cpp
index 442b4b7..7941b46 100644
--- a/src/rqt_image_view/ratio_layouted_frame.cpp
+++ b/src/rqt_image_view/ratio_layouted_frame.cpp
@@ -33,6 +33,7 @@
 
 #include <assert.h>
 #include <QMouseEvent>
+#include <iostream>
 
 #include <rqt_image_view/ratio_layouted_frame.hpp>
 
@@ -85,6 +86,7 @@ void RatioLayoutedFrame::resizeToFitAspectRatio()
   double width;
   double height;
 
+  std::cout << "contentsRect() shape: " << contentsRect().width() << ", " << contentsRect().height() << std::endl;
   if (outer_layout_) {
     width = outer_layout_->contentsRect().width();
     height = outer_layout_->contentsRect().height();
@@ -162,6 +164,7 @@ void RatioLayoutedFrame::paintEvent(QPaintEvent * event)
     // TODO(anyone): check if full draw is really necessary
     // QPaintEvent* paint_event = dynamic_cast<QPaintEvent*>(event);
     // painter.drawImage(paint_event->rect(), qimage_);
+    std::cout << "original image shape:   " << qimage_.width() << ", " << qimage_.height() << "px" << std::endl;
     if (!smoothImage_) {
       painter.drawImage(contentsRect(), qimage_);
     } else {
@@ -170,9 +173,12 @@ void RatioLayoutedFrame::paintEvent(QPaintEvent * event)
       } else {
         QImage image = qimage_.scaled(contentsRect().width(), contentsRect().height(),
                                       Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+        std::cout << "scaled image shape:   " << image.width() << ", " << image.height() << "px" << std::endl;
         painter.drawImage(contentsRect(), image);
       }
     }
+    std::cout << "contentsRect() shape: " << contentsRect().width() << ", " << contentsRect().height() << " px" << std::endl;
+    std::cout << std::endl;
   } else {
     // default image with gradient
     QLinearGradient gradient(0, 0, frameRect().width(), frameRect().height());

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Scaling artifacts when enabling "Smooth scaling"

1 participant