PDA

View Full Version : Qt5 - C++ - QImage - NOT scaling right



Vildnex
26th July 2020, 13:22
I'm getting confused by the way of drawImage and scaledToHeight (or any kind of scaling) is working. Could any of you help me to understand what's going on here?

So I have the fallowing code:



auto cellX = this->parentWidget()->width() / 100;
auto cellY = this->parentWidget()->height() / 100;

QImage icon(dir.absoluteFilePath(m_viewModel.icon));
QImage scaled = icon.scaledToHeight(cellY * 40, Qt::SmoothTransformation);
painter.drawImage(cellX * 20, cellY * 20, scaled);

Now if I understand it correctly this should work as the following:



QImage QImage::scaledToHeight(int height, Qt::TransformationMode mode = Qt::FastTransformation) const

Returns a scaled copy of the image. The returned image is scaled to
the given height using the specified transformation mode.

This function automatically calculates the width of the image so that
the ratio of the image is preserved.

If the given height is 0 or negative, a null image is returned.


and also



void QPainter::drawImage(int x, int y, const QImage &image, int sx = 0, int sy = 0, int sw = -1, int sh = -1, Qt::ImageConversionFlags flags = Qt::AutoColor)

This is an overloaded function.

Draws an image at (x, y) by copying a part of image into the paint
device.

(x, y) specifies the top-left point in the paint device that is to be
drawn onto. (sx, sy) specifies the top-left point in image that is to
be drawn. The default is (0, 0).

(sw, sh) specifies the size of the image that is to be drawn. The
default, (0, 0) (and negative) means all the way to the bottom-right
of the image.


So in other words, scaledToHeight is going to return a new image scaled according to that specific height and drawImage is going to draw that specific image started from point X, Y which I'm going to mention down to the end of the image (because it's -1 and -1 default)

13511
13512
13513

QUESTION:

As you could see already my scaled image is strictly dependent on the position of drawImage, why is that? How can I scale and draw my image properly? Or in other words WHY if I will position my image at 0 0 or not will affect how my image looks like?

CODE:

I have my Widget Class which looks something like this:


class AC_SpeedLevelController : public QWidget {
Q_OBJECT

protected:
void paintEvent(QPaintEvent *event) override;

private:
AC_ButtonViewModel m_viewModel{};
public:
explicit AC_SpeedLevelController(QWidget *parent);

void setupStyle(const AC_ButtonViewModel &model) override;

};


My paintEvent is going to look like:


void AC_SpeedLevelController::paintEvent(QPaintEvent *event) {
QWidget::paintEvent(event);
QPainter painter(this);

QDir dir(qApp->applicationDirPath());
dir.cd("icons");
auto cellX = this->parentWidget()->width() / 100;
auto cellY = this->parentWidget()->height() / 100;

QImage icon(dir.absoluteFilePath(m_viewModel.icon));
QImage scaled = icon.scaledToHeight(cellY * 20, Qt::SmoothTransformation);
painter.drawImage(0, 0, scaled);
}

d_stranz
26th July 2020, 20:16
QDir dir(qApp->applicationDirPath());
dir.cd("icons");
auto cellX = this->parentWidget()->width() / 100;
auto cellY = this->parentWidget()->height() / 100;

QImage icon(dir.absoluteFilePath(m_viewModel.icon));
QImage scaled = icon.scaledToHeight(cellY * 20, Qt::SmoothTransformation);


You don't want to do this in a paint event. Do it in a resize event and store the scaled image as a member variable. It's a complete waste of time to re-scale the image every time you draw it when the window size hasn't changed. It just slows your GUI down. And why are you repeatedly reading the icon from the file. Read it once and save it in a member variable.

As for your code, I don't know what you are trying to do. You are scaling your image so the height is 40% of the parent window's height, then you are drawing it at a position 20% of both width and height. What are you expecting to see?

Why are you using the parent widget and not the current widget (this) itself? Is the parent widget what you think it is?