diff options
author | Vladimir Belyavsky <[email protected]> | 2024-03-14 20:06:36 +0300 |
---|---|---|
committer | Vladimir Belyavsky <[email protected]> | 2024-03-19 17:22:16 +0000 |
commit | 4c21f728374605ff529aa53c63c3d59517098435 (patch) | |
tree | c8598e47a28a343a71744c36ee072870d9a84a86 | |
parent | 224b7c6b6a2a425487df19643709d105e8f3cdd5 (diff) |
QImageReader: allow only one dimension to be used for scaledSize
If only one dimension (width or height) of the scaled size is set
by an user, let's try to calculate the second one, based on the
image original size and maintaining the aspect ratio.
[ChangeLog][QtGui][QImageReader] Allow only one dimension (width
or height) to be set for the scaled size. In this case, the other
will be calculated automatically based on the original image size
and maintaining the aspect ratio.
Task-number: QTBUG-115039
Change-Id: If1b13b1ead3cf788915c08bdb3ba8becd8bf8042
Reviewed-by: Eirik Aavitsland <[email protected]>
-rw-r--r-- | src/gui/image/qimagereader.cpp | 32 | ||||
-rw-r--r-- | tests/auto/gui/image/qimagereader/tst_qimagereader.cpp | 57 |
2 files changed, 83 insertions, 6 deletions
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index c97fa63e5c0..4a5bd6136b5 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -940,6 +940,10 @@ QRect QImageReader::clipRect() const support scaling), QImageReader will use QImage::scale() with Qt::SmoothScaling. + If only one dimension is set in \a size, the other one will be + computed from the image's \l {size()} {natural size} so as to + maintain the aspect ratio. + \sa scaledSize(), setClipRect(), setScaledClipRect() */ void QImageReader::setScaledSize(const QSize &size) @@ -1178,7 +1182,23 @@ bool QImageReader::read(QImage *image) if (!d->initHandler()) return false; - const bool supportScaledSize = supportsOption(QImageIOHandler::ScaledSize) && d->scaledSize.isValid(); + QSize scaledSize = d->scaledSize; + if ((scaledSize.width() <= 0 && scaledSize.height() > 0) || + (scaledSize.height() <= 0 && scaledSize.width() > 0)) { + // if only one dimension is given, let's try to calculate the second one + // based on the original image size and maintaining the aspect ratio + if (const QSize originalSize = size(); !originalSize.isEmpty()) { + if (scaledSize.width() <= 0) { + const auto ratio = qreal(scaledSize.height()) / originalSize.height(); + scaledSize.setWidth(qRound(originalSize.width() * ratio)); + } else { + const auto ratio = qreal(scaledSize.width()) / originalSize.width(); + scaledSize.setHeight(qRound(originalSize.height() * ratio)); + } + } + } + + const bool supportScaledSize = supportsOption(QImageIOHandler::ScaledSize) && scaledSize.isValid(); const bool supportClipRect = supportsOption(QImageIOHandler::ClipRect) && !d->clipRect.isNull(); const bool supportScaledClipRect = supportsOption(QImageIOHandler::ScaledClipRect) && !d->scaledClipRect.isNull(); @@ -1187,7 +1207,7 @@ bool QImageReader::read(QImage *image) if (supportClipRect || d->clipRect.isNull()) { // Only enable the ScaledSize option if there is no clip rect, or // if the handler also supports ClipRect. - d->handler->setOption(QImageIOHandler::ScaledSize, d->scaledSize); + d->handler->setOption(QImageIOHandler::ScaledSize, scaledSize); } } if (supportClipRect) @@ -1229,8 +1249,8 @@ bool QImageReader::read(QImage *image) // supports scaled clipping but not scaling, most // likely a broken handler. } else { - if (d->scaledSize.isValid()) { - *image = image->scaled(d->scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + if (scaledSize.isValid()) { + *image = image->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); } if (d->scaledClipRect.isValid()) { *image = image->copy(d->scaledClipRect); @@ -1256,8 +1276,8 @@ bool QImageReader::read(QImage *image) // provide all workarounds. if (d->clipRect.isValid()) *image = image->copy(d->clipRect); - if (d->scaledSize.isValid()) - *image = image->scaled(d->scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + if (scaledSize.isValid()) + *image = image->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); if (d->scaledClipRect.isValid()) *image = image->copy(d->scaledClipRect); } diff --git a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp index a7011a26369..6d875ec0ab6 100644 --- a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp @@ -62,6 +62,9 @@ private slots: void setScaledSize_data(); void setScaledSize(); + void setScaledSizeOneDimension_data(); + void setScaledSizeOneDimension(); + void setClipRect_data(); void setClipRect(); @@ -371,6 +374,60 @@ void tst_QImageReader::setScaledSize() QCOMPARE(image.size(), newSize); } +void tst_QImageReader::setScaledSizeOneDimension_data() +{ + QTest::addColumn<QString>("fileName"); + QTest::addColumn<QByteArray>("format"); + + QTest::newRow("PNG: kollada") << QString("kollada") << QByteArray("png"); + QTest::newRow("JPEG: beavis") << QString("beavis") << QByteArray("jpeg"); + QTest::newRow("GIF: earth") << QString("earth") << QByteArray("gif"); + QTest::newRow("SVG: rect") << QString("rect") << QByteArray("svg"); + QTest::newRow("BMP: colorful") << QString("colorful") << QByteArray("bmp"); + QTest::newRow("XPM: marble") << QString("marble") << QByteArray("xpm"); + QTest::newRow("PPM: teapot") << QString("teapot") << QByteArray("ppm"); + QTest::newRow("XBM: gnus") << QString("gnus") << QByteArray("xbm"); +} + +void tst_QImageReader::setScaledSizeOneDimension() +{ + QFETCH(QString, fileName); + QFETCH(QByteArray, format); + + SKIP_IF_UNSUPPORTED(format); + + const QSize originalSize = QImageReader(prefix + fileName).size(); + QVERIFY(!originalSize.isEmpty()); + + auto testScaledSize = [&] (const QSize &scaledSize) { + QSize expectedSize = scaledSize; + if (scaledSize.width() <= 0) + expectedSize.setWidth(qRound(originalSize.width() * + (qreal(scaledSize.height()) / originalSize.height()))); + else if (scaledSize.height() <= 0) + expectedSize.setHeight(qRound(originalSize.height() * + (qreal(scaledSize.width()) / originalSize.width()))); + + QImageReader reader(prefix + fileName); + reader.setScaledSize(scaledSize); + QImage image = reader.read(); + QVERIFY(!image.isNull()); + QCOMPARE(image.size(), expectedSize); + }; + + // downscale + testScaledSize(QSize(originalSize.width() / 2, 0)); + testScaledSize(QSize(originalSize.width() / 2, -1)); + testScaledSize(QSize(0, originalSize.height() / 2)); + testScaledSize(QSize(-1, originalSize.height() / 2)); + + // upscale + testScaledSize(QSize(originalSize.width() * 2, 0)); + testScaledSize(QSize(originalSize.width() * 2, -1)); + testScaledSize(QSize(0, originalSize.height() * 2)); + testScaledSize(QSize(-1, originalSize.height() * 2)); +} + void tst_QImageReader::task255627_setNullScaledSize_data() { setScaledSize_data(); |