diff options
Diffstat (limited to 'tests/auto/gui/image/qimagereader')
-rw-r--r-- | tests/auto/gui/image/qimagereader/BLACKLIST | 8 | ||||
-rw-r--r-- | tests/auto/gui/image/qimagereader/CMakeLists.txt | 11 | ||||
-rw-r--r-- | tests/auto/gui/image/qimagereader/images/image.pbm | 10 | ||||
-rw-r--r-- | tests/auto/gui/image/qimagereader/tst_qimagereader.cpp | 293 |
4 files changed, 219 insertions, 103 deletions
diff --git a/tests/auto/gui/image/qimagereader/BLACKLIST b/tests/auto/gui/image/qimagereader/BLACKLIST new file mode 100644 index 0000000000..6422ff1dac --- /dev/null +++ b/tests/auto/gui/image/qimagereader/BLACKLIST @@ -0,0 +1,8 @@ +[setClipRect:SVG: rect] +wayland +[setClipRect:SVGZ: rect] +wayland +[setScaledClipRect:SVG: rect] +wayland +[setScaledClipRect:SVGZ: rect] +wayland diff --git a/tests/auto/gui/image/qimagereader/CMakeLists.txt b/tests/auto/gui/image/qimagereader/CMakeLists.txt index 3a2dceeebe..2a14ca3c9c 100644 --- a/tests/auto/gui/image/qimagereader/CMakeLists.txt +++ b/tests/auto/gui/image/qimagereader/CMakeLists.txt @@ -1,9 +1,16 @@ -# Generated from qimagereader.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qimagereader Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qimagereader LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + # Collect test data file(GLOB_RECURSE test_data_glob RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} @@ -17,7 +24,7 @@ list(APPEND test_data ${test_data_glob}) qt_internal_add_test(tst_qimagereader SOURCES tst_qimagereader.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate Qt::Gui Qt::GuiPrivate diff --git a/tests/auto/gui/image/qimagereader/images/image.pbm b/tests/auto/gui/image/qimagereader/images/image.pbm index 67e5efa3e9..e529536ca4 100644 --- a/tests/auto/gui/image/qimagereader/images/image.pbm +++ b/tests/auto/gui/image/qimagereader/images/image.pbm @@ -1,8 +1,8 @@ P1 16 6 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 +10 00 00 00 01 00 00 01 +1000 0000 0100 0001 +100000000 1000001 +1000000001000001 +10 000 0000 10000 01 diff --git a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp index b01eb83089..96af8b4e9b 100644 --- a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp @@ -1,6 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -11,7 +10,7 @@ #include <QImageReader> #include <QImageWriter> #include <QPixmap> -#include <QSet> +#include <QScopeGuard> #include <QTcpSocket> #include <QTcpServer> #include <QTimer> @@ -63,6 +62,9 @@ private slots: void setScaledSize_data(); void setScaledSize(); + void setScaledSizeOneDimension_data(); + void setScaledSizeOneDimension(); + void setClipRect_data(); void setClipRect(); @@ -301,25 +303,52 @@ void tst_QImageReader::jpegRgbCmyk() QImage image1(prefix + QLatin1String("YCbCr_cmyk.jpg")); QImage image2(prefix + QLatin1String("YCbCr_cmyk.png")); - if (image1 != image2) { - // first, do some obvious tests - QCOMPARE(image1.height(), image2.height()); - QCOMPARE(image1.width(), image2.width()); - QCOMPARE(image1.format(), image2.format()); - QCOMPARE(image1.format(), QImage::Format_RGB32); - - // compare all the pixels with a slack of 3. This ignores rounding errors - // in libjpeg/libpng, where some versions sacrifice accuracy for speed. - for (int h = 0; h < image1.height(); ++h) { - const uchar *s1 = image1.constScanLine(h); - const uchar *s2 = image2.constScanLine(h); - for (int w = 0; w < image1.width() * 4; ++w) { - if (*s1 != *s2) { - QVERIFY2(qAbs(*s1 - *s2) <= 3, qPrintable(QString("images differ in line %1, col %2 (image1: %3, image2: %4)").arg(h).arg(w).arg(*s1, 0, 16).arg(*s2, 0, 16))); - } - s1++; - s2++; - } + QVERIFY(!image1.isNull()); + QVERIFY(!image2.isNull()); + + QCOMPARE(image1.height(), image2.height()); + QCOMPARE(image1.width(), image2.width()); + + QCOMPARE(image1.format(), QImage::Format_CMYK8888); + QCOMPARE(image2.format(), QImage::Format_RGB32); + + // compare all the pixels with a slack of 3. This ignores rounding errors + // in libjpeg/libpng, where some versions sacrifice accuracy for speed. + const auto fuzzyCompareColors = [](const QColor &c1, const QColor &c2) { + int c1rgba[4]; + int c2rgba[4]; + + c1.getRgb(c1rgba + 0, + c1rgba + 1, + c1rgba + 2, + c1rgba + 3); + + c2.getRgb(c2rgba + 0, + c2rgba + 1, + c2rgba + 2, + c2rgba + 3); + + const auto fuzzyCompare = [](int a, int b) { + return qAbs(a - b) <= 3; + }; + + return fuzzyCompare(c1rgba[0], c2rgba[0]) && + fuzzyCompare(c1rgba[1], c2rgba[1]) && + fuzzyCompare(c1rgba[2], c2rgba[2]) && + fuzzyCompare(c1rgba[3], c2rgba[3]); + }; + + for (int h = 0; h < image1.height(); ++h) { + const uchar *sl1 = image1.constScanLine(h); + const uchar *sl2 = image2.constScanLine(h); + for (int w = 0; w < image1.width(); ++w) { + const uchar *s1 = sl1 + w * 4; + const uchar *s2 = sl2 + w * 4; + + QColor c1 = QColor::fromCmyk(s1[0], s1[1], s1[2], s1[3]); + QColor c2 = QColor::fromRgb(s2[2], s2[1], s2[0]); + QVERIFY2(fuzzyCompareColors(c1, c2), + qPrintable(QString("images differ in line %1, col %2").arg(h).arg(w))); } } } @@ -372,6 +401,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(); @@ -487,8 +570,11 @@ void tst_QImageReader::setScaledClipRect() QImageReader originalReader(prefix + fileName); originalReader.setScaledSize(QSize(300, 300)); QImage originalImage = originalReader.read(); - if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive) && format.contains("svg")) - QEXPECT_FAIL("", "This fails on Wayland, see QTBUG-100917.", Abort); + if (format.contains("svg")) { + // rendering of subrect may yield slight rounding differences, truncate them away + image.convertTo(QImage::Format_RGB444); + originalImage.convertTo(QImage::Format_RGB444); + } QCOMPARE(originalImage.copy(newRect), image); } @@ -530,7 +616,7 @@ void tst_QImageReader::imageFormat_data() QTest::newRow("ppm-4") << QString("test.ppm") << QByteArray("ppm") << QImage::Format_RGB32; QTest::newRow("jpeg-1") << QString("beavis.jpg") << QByteArray("jpeg") << QImage::Format_Grayscale8; - QTest::newRow("jpeg-2") << QString("YCbCr_cmyk.jpg") << QByteArray("jpeg") << QImage::Format_RGB32; + QTest::newRow("jpeg-2") << QString("YCbCr_cmyk.jpg") << QByteArray("jpeg") << QImage::Format_CMYK8888; QTest::newRow("jpeg-3") << QString("YCbCr_rgb.jpg") << QByteArray("jpeg") << QImage::Format_RGB32; QTest::newRow("gif-1") << QString("earth.gif") << QByteArray("gif") << QImage::Format_Invalid; @@ -591,41 +677,31 @@ void tst_QImageReader::multiWordNamedColorXPM() QCOMPARE(image.pixel(0, 2), qRgb(255, 250, 205)); // lemon chiffon } -void tst_QImageReader::supportedFormats() +namespace { +template <typename ForwardIterator> +bool is_sorted_unique(ForwardIterator first, ForwardIterator last) { - QList<QByteArray> formats = QImageReader::supportedImageFormats(); - QList<QByteArray> sortedFormats = formats; - std::sort(sortedFormats.begin(), sortedFormats.end()); - - // check that the list is sorted - QCOMPARE(formats, sortedFormats); - - QSet<QByteArray> formatSet; - foreach (QByteArray format, formats) - formatSet << format; + // a range is sorted with no dups iff each *i < *(i+1), so check that none are >=: + return std::adjacent_find(first, last, std::greater_equal<>{}) == last; +} +} - // check that the list does not contain duplicates - QCOMPARE(formatSet.size(), formats.size()); +void tst_QImageReader::supportedFormats() +{ + const QList<QByteArray> formats = QImageReader::supportedImageFormats(); + auto printOnFailure = qScopeGuard([&] { qDebug() << formats; }); + QVERIFY(is_sorted_unique(formats.begin(), formats.end())); + printOnFailure.dismiss(); } void tst_QImageReader::supportedMimeTypes() { - QList<QByteArray> mimeTypes = QImageReader::supportedMimeTypes(); - QList<QByteArray> sortedMimeTypes = mimeTypes; - std::sort(sortedMimeTypes.begin(), sortedMimeTypes.end()); - - // check that the list is sorted - QCOMPARE(mimeTypes, sortedMimeTypes); - - QSet<QByteArray> mimeTypeSet; - foreach (QByteArray mimeType, mimeTypes) - mimeTypeSet << mimeType; - + const QList<QByteArray> mimeTypes = QImageReader::supportedMimeTypes(); + auto printOnFailure = qScopeGuard([&] { qDebug() << mimeTypes; }); + QVERIFY(is_sorted_unique(mimeTypes.begin(), mimeTypes.end())); // check the list as a minimum contains image/bmp - QVERIFY(mimeTypeSet.contains("image/bmp")); - - // check that the list does not contain duplicates - QCOMPARE(mimeTypeSet.size(), mimeTypes.size()); + QVERIFY(mimeTypes.contains("image/bmp")); + printOnFailure.dismiss(); } void tst_QImageReader::setBackgroundColor_data() @@ -670,7 +746,7 @@ void tst_QImageReader::supportsAnimation_data() QTest::newRow("BMP: colorful") << QString("colorful.bmp") << false; QTest::newRow("BMP: font") << QString("font.bmp") << false; QTest::newRow("BMP: signed char") << QString("crash-signed-char.bmp") << false; - QTest::newRow("BMP: test32bfv4") << QString("test32bfv4.bmp") << false;; + QTest::newRow("BMP: test32bfv4") << QString("test32bfv4.bmp") << false; QTest::newRow("BMP: test32v5") << QString("test32v5.bmp") << false; QTest::newRow("XPM: marble") << QString("marble.xpm") << false; QTest::newRow("PNG: kollada") << QString("kollada.png") << false; @@ -1620,43 +1696,56 @@ void tst_QImageReader::supportsOption_data() QTest::addColumn<QIntList>("options"); QTest::newRow("png") << QString("black.png") - << (QIntList() << QImageIOHandler::Gamma - << QImageIOHandler::Description - << QImageIOHandler::Quality - << QImageIOHandler::CompressionRatio - << QImageIOHandler::Size - << QImageIOHandler::ScaledSize); + << QIntList{ + QImageIOHandler::Gamma, + QImageIOHandler::Description, + QImageIOHandler::Quality, + QImageIOHandler::CompressionRatio, + QImageIOHandler::Size, + QImageIOHandler::ScaledSize, + QImageIOHandler::ImageFormat, + }; } void tst_QImageReader::supportsOption() { QFETCH(QString, fileName); - QFETCH(QIntList, options); - - QSet<QImageIOHandler::ImageOption> allOptions; - allOptions << QImageIOHandler::Size - << QImageIOHandler::ClipRect - << QImageIOHandler::Description - << QImageIOHandler::ScaledClipRect - << QImageIOHandler::ScaledSize - << QImageIOHandler::CompressionRatio - << QImageIOHandler::Gamma - << QImageIOHandler::Quality - << QImageIOHandler::Name - << QImageIOHandler::SubType - << QImageIOHandler::IncrementalReading - << QImageIOHandler::Endianness - << QImageIOHandler::Animation - << QImageIOHandler::BackgroundColor; + QFETCH(const QIntList, options); QImageReader reader(prefix + fileName); - for (int i = 0; i < options.size(); ++i) { - QVERIFY(reader.supportsOption(QImageIOHandler::ImageOption(options.at(i)))); - allOptions.remove(QImageIOHandler::ImageOption(options.at(i))); - } - foreach (QImageIOHandler::ImageOption option, allOptions) - QVERIFY(!reader.supportsOption(option)); + for (int i = 0; ; ++i) { + // this switch ensures the compiler warns when we miss an enumerator [-Wswitch] + // do _not_ add a default case! + switch (const auto o = QImageIOHandler::ImageOption(i)) { + case QImageIOHandler::Size: + case QImageIOHandler::ClipRect: + case QImageIOHandler::Description: + case QImageIOHandler::ScaledClipRect: + case QImageIOHandler::ScaledSize: + case QImageIOHandler::CompressionRatio: + case QImageIOHandler::Gamma: + case QImageIOHandler::Quality: + case QImageIOHandler::Name: + case QImageIOHandler::SubType: + case QImageIOHandler::IncrementalReading: + case QImageIOHandler::Endianness: + case QImageIOHandler::Animation: + case QImageIOHandler::BackgroundColor: + case QImageIOHandler::ImageFormat: + case QImageIOHandler::SupportedSubTypes: + case QImageIOHandler::OptimizedWrite: + case QImageIOHandler::ProgressiveScanWrite: + case QImageIOHandler::ImageTransformation: + { + auto printOnFailure = qScopeGuard([&] { qDebug("failed at %d", i); }); + QCOMPARE(reader.supportsOption(o), options.contains(i)); + printOnFailure.dismiss(); + continue; // ... as long as `i` represents a valid ImageOption value + } + } + break; // ... once `i` no longer represents a valid ImageOption value + } } void tst_QImageReader::autoDetectImageFormat() @@ -1825,13 +1914,13 @@ void tst_QImageReader::testIgnoresFormatAndExtension() SKIP_IF_UNSUPPORTED(expected.toLatin1()); - QList<QByteArray> formats = QImageReader::supportedImageFormats(); + const QList<QByteArray> formats = QImageReader::supportedImageFormats(); QString fileNameBase = prefix + name + QLatin1Char('.'); QString tempPath = m_temporaryDir.path(); if (!tempPath.endsWith(QLatin1Char('/'))) tempPath += QLatin1Char('/'); - foreach (const QByteArray &f, formats) { + for (const QByteArray &f : formats) { if (f == extension.toLocal8Bit()) continue; @@ -1981,19 +2070,31 @@ void tst_QImageReader::preserveTexts_data() for (int c = 0xa0; c <= 0xff; c++) latin1set.append(QLatin1Char(c)); - QStringList fileNames; - fileNames << QLatin1String(":/images/kollada.png") - << QLatin1String(":/images/txts.jpg"); - foreach (const QString &fileName, fileNames) { - QTest::newRow("Simple") << fileName << "simpletext"; - QTest::newRow("Whitespace") << fileName << " A text with whitespace "; - QTest::newRow("Newline") << fileName << "A text\nwith newlines\n"; - QTest::newRow("Double newlines") << fileName << "A text\n\nwith double newlines\n\n"; - QTest::newRow("Long") << fileName << QString("A rather long text, at least after many repetitions. ").repeated(100); - QTest::newRow("All Latin1 chars") << fileName << latin1set; + const QList<QLatin1StringView> fileNames{ + QLatin1StringView(":/images/kollada.png"), + QLatin1StringView(":/images/txts.jpg") + // Common prefix of length 9 before file names: ":/images/", skipped below by + 9. + }; + for (const auto &fileName : fileNames) { + QTest::addRow("Simple %s", fileName.data() + 9) + << QString(fileName) << "simpletext"; + QTest::addRow("Whitespace %s", fileName.data() + 9) + << QString(fileName) << " A text with whitespace "; + QTest::addRow("Newline %s", fileName.data() + 9) + << QString(fileName) << "A text\nwith newlines\n"; + QTest::addRow("Double newlines %s", fileName.data() + 9) + << QString(fileName) << "A text\n\nwith double newlines\n\n"; + QTest::addRow("Long %s", fileName.data() + 9) + << QString(fileName) + << QString("A rather long text, at least after many repetitions. ").repeated(100); + QTest::addRow("All Latin1 chars %s", fileName.data() + 9) + << QString(fileName) << latin1set; #if 0 // Depends on iTXt support in libpng - QTest::newRow("Multibyte string") << fileName << QString::fromUtf8("\341\233\222\341\233\226\341\232\251\341\232\271\341\232\242\341\233\232\341\232\240"); + QTest::addRow("Multibyte string %s", fileName.data() + 9) + << QString(fileName) + << QString::fromUtf8("\341\233\222\341\233\226\341\232\251\341\232" + "\271\341\232\242\341\233\232\341\232\240"); #endif } } |