Image gets de-pixalated or distorted (unclear) when we change the desktop display scale to 125%
-
Hi all, hope you are doing good.
I am using QT for one of my desktop application. I am trying to show a pdf inside a QT widget QPainter.
The pdf looks just fine when I launch the application. But, when I am changing the display scale to 125% resolution.
Then the drawing in the pdf gets distorted, or unclear. Changing back the scale to 100% makes it clear again.
But, it should not happen in the first place.To demonstrate that, I have developed a sample application and used an image to show inside the qpainter.
Same issue occurs.
Clear image at 100% scale
unclear/distorted image at 125% scale.
Currently I am using QT 6.8.1. the issue doesn't reproduce on QT 5.14.2 version and below.
This is a blocker for me. Can someone please help me with it.
Below is the code part.
main.cpp ```
#include "QtPainterDemo681.h"
#include <QtWidgets/QApplication>int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QtPainterDemo681 w;
w.resize(1400, 700);
w.show();
return a.exec();
}QtPainterDemo681.h
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_QtPainterDemo681.h"
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QImage>
#include <QMouseEvent>
#include <QDebug>class QtPainterDemo681 : public QMainWindow
{
Q_OBJECTpublic:
QtPainterDemo681(QWidget *parent = nullptr);
~QtPainterDemo681();virtual void paintEvent(QPaintEvent* eventP);
private:
Ui::QtPainterDemo681Class ui;
};QtPainterDemo681.cpp
#include "QtPainterDemo681.h"
QtPainterDemo681::QtPainterDemo681(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
}QtPainterDemo681::~QtPainterDemo681()
{}void QtPainterDemo681::paintEvent(QPaintEvent* eventP)
{
QPainter painter(this);QImage image("../../clearImag.jpg"); if (image.isNull()) { qDebug() << "Failed to load image."; return; } painter.drawImage(0, 0, image);
}
-
Hi all, hope you are doing good.
I am using QT for one of my desktop application. I am trying to show a pdf inside a QT widget QPainter.
The pdf looks just fine when I launch the application. But, when I am changing the display scale to 125% resolution.
Then the drawing in the pdf gets distorted, or unclear. Changing back the scale to 100% makes it clear again.
But, it should not happen in the first place.To demonstrate that, I have developed a sample application and used an image to show inside the qpainter.
Same issue occurs.
Clear image at 100% scale
unclear/distorted image at 125% scale.
Currently I am using QT 6.8.1. the issue doesn't reproduce on QT 5.14.2 version and below.
This is a blocker for me. Can someone please help me with it.
Below is the code part.
main.cpp ```
#include "QtPainterDemo681.h"
#include <QtWidgets/QApplication>int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QtPainterDemo681 w;
w.resize(1400, 700);
w.show();
return a.exec();
}QtPainterDemo681.h
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_QtPainterDemo681.h"
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QImage>
#include <QMouseEvent>
#include <QDebug>class QtPainterDemo681 : public QMainWindow
{
Q_OBJECTpublic:
QtPainterDemo681(QWidget *parent = nullptr);
~QtPainterDemo681();virtual void paintEvent(QPaintEvent* eventP);
private:
Ui::QtPainterDemo681Class ui;
};QtPainterDemo681.cpp
#include "QtPainterDemo681.h"
QtPainterDemo681::QtPainterDemo681(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
}QtPainterDemo681::~QtPainterDemo681()
{}void QtPainterDemo681::paintEvent(QPaintEvent* eventP)
{
QPainter painter(this);QImage image("../../clearImag.jpg"); if (image.isNull()) { qDebug() << "Failed to load image."; return; } painter.drawImage(0, 0, image);
}
@wasimIM said in Image gets de-pixalated or distorted (unclear) when we change the desktop display scale to 125%:
The pdf looks just fine when I launch the application
You say PDF, but the code loads a JPEG?!
And this exact code does not distort the image on old Qt versions but it does on recent ones?!
-
When you display an image with 1000x1000 on a screen with a dpr=1,25 and a size of 1000x1000 then the image needs 1250pixels so it's scaled up. This is what you're seeing. So you should either create a pixmap with 1250x1250 pixels or use 1000/1.25=800x800 as size.
-
@Christian-Ehrlicher But why does the same code work for QT 5.14.2 version? This is regressed after QT 5.14.2.
-
I don't know but would guess it's because of the lack of proper high-dpi handling in Qt5.
-
When you display an image with 1000x1000 on a screen with a dpr=1,25 and a size of 1000x1000 then the image needs 1250pixels so it's scaled up. This is what you're seeing. So you should either create a pixmap with 1250x1250 pixels or use 1000/1.25=800x800 as size.
@Christian-Ehrlicher I didn't get this completely, I tried creating pixmap with 1250 x 1250. with code as below , but same issue. And 800x800 size of what?
QPixmap pixmap(1250, 1250); if (!pixmap.load("D:/temp/clearImag.jpg")) { // Load the image into QPixmap qWarning("Failed to load image"); }
-
Since the png or jpeg has a size, this is used when you create a QPixmap from it... I don't understand what you try to achieve here.
When you display an image with 1000x1000 on a screen with a dpr of 1.25 the resulting size of the image on the screen is 800x800 pixels because 800*1.25=1000 -
@Christian-Ehrlicher I just want to display a clear image. It should not be unclear with changing of the scaling.
-
Since a pixel based image can not be scaled without artificacts I don't see any solution.
-
I would try calling
QPixmap/QImage::setDevicePixelRatio
with the same device pixel ratio as the underlying QScreen. -
Exactly what @GrecKo said. In Qt 6, there was an overhaul of how HiDPI displays are handled - now Qt consistently works in Device Independent Pixels (DIPs), which are mapped to physical pixels by the paint engine. This means that anything painted with
QPainter
calls or otherwise through vector operations always correctly scales without the program needing to do anything, this is not the case for things painted from a pixmap. As experienced by OP, the automatic scaling of bitmaps hurts quality - but it is needed as otherwise the image would be too small.The way to get around it is to tell Qt explicitly what is the scaling ratio that the image is intended to be viewed at using the
setDevicePixelRatio
. If it is identical to the target drawing surfaces' scaling ratio, Qt will not do any automatic scaling of the image.Do note that indeed if the image is 1000X1000 physical pixels, and the scaling ratio is 1.25 for both the image and the widget - it will take 800x800 DIPs. This means that as the scaling ratio grows, the image will be drawn smaller and smaller. At some point you'll need to switch to an extra high quality version of the original image that has more pixel density, and Qt does have support for that. See https://doc.qt.io/qt-6/qpainter.html#drawing-high-resolution-versions-of-pixmaps-and-images
-
I would try calling
QPixmap/QImage::setDevicePixelRatio
with the same device pixel ratio as the underlying QScreen.@GrecKo said in Image gets de-pixalated or distorted (unclear) when we change the desktop display scale to 125%:
I would try calling QPixmap/QImage::setDevicePixelRatio with the same device pixel ratio as the underlying QScreen.
How should this help? When he wants to draw an image with 1000x1000px on a screen with 1000x1000 (and this is what he's doing), there are effectively 1250x1250 pixels needed to draw the image so a scaling will occour. The only way to avoid scaling is, as I already wrote, to paint it with 800x800px.
-
@GrecKo said in Image gets de-pixalated or distorted (unclear) when we change the desktop display scale to 125%:
I would try calling QPixmap/QImage::setDevicePixelRatio with the same device pixel ratio as the underlying QScreen.
How should this help? When he wants to draw an image with 1000x1000px on a screen with 1000x1000 (and this is what he's doing), there are effectively 1250x1250 pixels needed to draw the image so a scaling will occour. The only way to avoid scaling is, as I already wrote, to paint it with 800x800px.
Same difference. It is just that:
void Whatever::paintEvent(QPaintEvent* e) { // ...snip... image.setDevicePixelRatio(devicePixelRatio()); painter.drawImage(0, 0, image); }
Is identical to but often easier to do than:
void Whatever::paintEvent(QPaintEvent* e) { // ...snip... painter.drawImage(QRectF(0, 0, image.width() / devicePixelRatio(), image.height() / devicePixelRatio()), image); }
Since it can be done once after loading the image, and is an easy way to make sure the image is not scaled. It is true that it makes the image smaller, but it doesn't seem like the OP wanted it to be same size, they just wanted it to not be blurry?
-
Same difference. It is just that:
void Whatever::paintEvent(QPaintEvent* e) { // ...snip... image.setDevicePixelRatio(devicePixelRatio()); painter.drawImage(0, 0, image); }
Is identical to but often easier to do than:
void Whatever::paintEvent(QPaintEvent* e) { // ...snip... painter.drawImage(QRectF(0, 0, image.width() / devicePixelRatio(), image.height() / devicePixelRatio()), image); }
Since it can be done once after loading the image, and is an easy way to make sure the image is not scaled. It is true that it makes the image smaller, but it doesn't seem like the OP wanted it to be same size, they just wanted it to not be blurry?
@IgKh said in Image gets de-pixalated or distorted (unclear) when we change the desktop display scale to 125%:
ut it doesn't seem like the OP wanted it to be same size, they just wanted it to not be blurry?
I don't know, we just get a 'sample application' so ...
I am trying to show a pdf inside a QT widget QPainter. The pdf looks just fine when I launch the application.
... we don't know how the pdf is converted to a QImage/QPixmap/whatsoever.
I already told them to simply render the pdf image (as I would guess it's done this way e.g. with poppler) in size * dpr instead size but he doesn't care. -
@GrecKo said in Image gets de-pixalated or distorted (unclear) when we change the desktop display scale to 125%:
I would try calling QPixmap/QImage::setDevicePixelRatio with the same device pixel ratio as the underlying QScreen.
How should this help? When he wants to draw an image with 1000x1000px on a screen with 1000x1000 (and this is what he's doing), there are effectively 1250x1250 pixels needed to draw the image so a scaling will occour. The only way to avoid scaling is, as I already wrote, to paint it with 800x800px.
@Christian-Ehrlicher said in Image gets de-pixalated or distorted (unclear) when we change the desktop display scale to 125%:
The only way to avoid scaling is, as I already wrote, to paint it with 800x800px.
That's what
setDevicePixelRatio
does. -
@Christian-Ehrlicher said in Image gets de-pixalated or distorted (unclear) when we change the desktop display scale to 125%:
The only way to avoid scaling is, as I already wrote, to paint it with 800x800px.
That's what
setDevicePixelRatio
does.@GrecKo said in Image gets de-pixalated or distorted (unclear) when we change the desktop display scale to 125%:
That's what setDevicePixelRatio does.
Did I said something else?
I was (and still am) under the impression that he wants to draw with 1000x1000 ...