2
votes

I have a 4 channel png image with 8x8 Pixels that is loaded by a QImage. The QImage is then scaled by a factor of 200, so the image will have a new resolution of 1600x1600, each original pixel having a size of 200x200. But when this image is added to a QLabel through the means of a QPixmap and shown on screen, the drawn pixels will have slightly different sizes.

I've taken screenshots with Gimp and looked at the painted image more closely. It seems that every other pixel is slightly bigger than it should be, 201 instead of 200 pixels wide for example. The very last pixel in a row will then be smaller to compensate, so that the entire image has the correct size in the end.

This does not happen for all scaling factors, 100 is fine for example and so are factors that are a power of 2, such as 256.

My original approach was using a QGraphicsView and a QGraphicsPixmapItem in which case I scaled the GraphicsItem instead of the image. The effect was the same.

What effect am I seeing here? And what, if anything, can be done about it?

The code to reproduce this issue is very straightforward

int scale = 200;
image = QImage("some image file");
QPixmap pixmap = QPixmap::fromImage(image.scaled(image.size() * scale));
some_label->setPixmap(pixmap);
1
I am not sure that this solves your problem, but you could do the scaling yourself when drawing the (unscaled) pixmap, as seen here: github.com/gerbilvis/gerbil/blob/master/gui/widgets/… The scaling happens through a QTransform set up here: github.com/gerbilvis/gerbil/blob/master/gui/widgets/… (your QTransform is much simpler to set up, with fixed scale and translation) Btw. this is a very efficient method with GL rendering backend.ypnos
Thank you. I would have never guessed this problem might come from the scaling algorithm. I thought it was a mere painting/presentation issue. But I just saved the scaled image to disk and sure enough, it's wrong as well. Thanks for the tip :)ifschleife

1 Answers

1
votes

Turns out the easiest solution to my problem is to use QOpenGLWidget in the QGraphicsView:

setViewport(new QOpenGLWidget);

This single line in the constructor will result in much higher precision when scaling an image with the caveat of adding OpenGL as a dependency. Another gotcha with this approach is that calling setViewport invalidates many of the settings done on a QGraphicsView. So if the view is set up in a UI file, as in my case, make sure to call other setters after calling setViewport.

I could not find a better solution that would work without OpenGL, short of writing my own rasterizer of course.