summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladimir Belyavsky <[email protected]>2024-03-14 20:06:36 +0300
committerVladimir Belyavsky <[email protected]>2024-03-19 17:22:16 +0000
commit4c21f728374605ff529aa53c63c3d59517098435 (patch)
treec8598e47a28a343a71744c36ee072870d9a84a86
parent224b7c6b6a2a425487df19643709d105e8f3cdd5 (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.cpp32
-rw-r--r--tests/auto/gui/image/qimagereader/tst_qimagereader.cpp57
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();