diff options
Diffstat (limited to 'tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp')
-rw-r--r-- | tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp | 460 |
1 files changed, 421 insertions, 39 deletions
diff --git a/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp b/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp index 08f45a2552..e23b3d21a1 100644 --- a/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp +++ b/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2018 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> @@ -7,6 +7,7 @@ #include <qcolorspace.h> #include <qimage.h> #include <qimagereader.h> +#include <qrgbafloat.h> #include <private/qcolorspace_p.h> @@ -42,7 +43,12 @@ private slots: void imageConversionOverLargerGamut(); void imageConversionOverLargerGamut2_data(); void imageConversionOverLargerGamut2(); - + void imageConversionOverAnyGamutFP_data(); + void imageConversionOverAnyGamutFP(); + void imageConversionOverAnyGamutFP2_data(); + void imageConversionOverAnyGamutFP2(); + void imageConversionOverNonThreeComponentMatrix_data(); + void imageConversionOverNonThreeComponentMatrix(); void loadImage(); void primaries(); @@ -61,6 +67,14 @@ private slots: void transferFunctionTable(); void description(); + void whitePoint_data(); + void whitePoint(); + void setWhitePoint(); + void grayColorSpace(); + void grayColorSpaceEffectivelySRgb(); + + void scaleAlphaValue(); + void hdrColorSpaces(); }; tst_QColorSpace::tst_QColorSpace() @@ -111,6 +125,15 @@ void tst_QColorSpace::namedColorSpaces_data() QTest::newRow("ProPhoto RGB") << QColorSpace::ProPhotoRgb << true << QColorSpace::Primaries::ProPhotoRgb << QColorSpace::TransferFunction::ProPhotoRgb; + QTest::newRow("BT.2020") << QColorSpace::Bt2020 << true + << QColorSpace::Primaries::Bt2020 + << QColorSpace::TransferFunction::Bt2020; + QTest::newRow("BT.2100 PQ") << QColorSpace::Bt2100Pq << true + << QColorSpace::Primaries::Bt2020 + << QColorSpace::TransferFunction::St2084; + QTest::newRow("BT.2100 HLG") << QColorSpace::Bt2100Hlg << true + << QColorSpace::Primaries::Bt2020 + << QColorSpace::TransferFunction::Hlg; QTest::newRow("0") << QColorSpace::NamedColorSpace(0) << false << QColorSpace::Primaries::Custom @@ -178,15 +201,46 @@ void tst_QColorSpace::fromIccProfile_data() QTest::addColumn<QString>("testProfile"); QTest::addColumn<QColorSpace::NamedColorSpace>("namedColorSpace"); QTest::addColumn<QColorSpace::TransferFunction>("transferFunction"); + QTest::addColumn<QColorSpace::TransformModel>("transformModel"); + QTest::addColumn<QColorSpace::ColorModel>("colorModel"); QTest::addColumn<QString>("description"); QString prefix = QFINDTESTDATA("resources/"); // Read the official sRGB ICCv2 profile: QTest::newRow("sRGB2014 (ICCv2)") << prefix + "sRGB2014.icc" << QColorSpace::SRgb - << QColorSpace::TransferFunction::SRgb << QString("sRGB2014"); + << QColorSpace::TransferFunction::SRgb + << QColorSpace::TransformModel::ThreeComponentMatrix + << QColorSpace::ColorModel::Rgb << QString("sRGB2014"); // My monitor's profile: QTest::newRow("HP ZR30w (ICCv4)") << prefix + "HP_ZR30w.icc" << QColorSpace::NamedColorSpace(0) - << QColorSpace::TransferFunction::Gamma << QString("HP Z30i"); + << QColorSpace::TransferFunction::Gamma + << QColorSpace::TransformModel::ThreeComponentMatrix + << QColorSpace::ColorModel::Rgb << QString("HP Z30i"); + // A profile to HD TV + QTest::newRow("VideoHD") << prefix + "VideoHD.icc" << QColorSpace::NamedColorSpace(0) + << QColorSpace::TransferFunction::Custom + << QColorSpace::TransformModel::ElementListProcessing + << QColorSpace::ColorModel::Rgb << QString("HDTV (Rec. 709)"); + // sRGB on PCSLab format + QTest::newRow("sRGB ICCv4 Appearance") << prefix + "sRGB_ICC_v4_Appearance.icc" << QColorSpace::NamedColorSpace(0) + << QColorSpace::TransferFunction::Custom + << QColorSpace::TransformModel::ElementListProcessing + << QColorSpace::ColorModel::Rgb << QString("sRGB_ICC_v4_Appearance.icc"); + // Grayscale profile + QTest::newRow("sGrey-v4") << prefix + "sGrey-v4.icc" << QColorSpace::NamedColorSpace(0) + << QColorSpace::TransferFunction::SRgb + << QColorSpace::TransformModel::ThreeComponentMatrix + << QColorSpace::ColorModel::Gray << QString("sGry"); + // CMYK profile + QTest::newRow("CGATS compat") << prefix + "CGATS001Compat-v2-micro.icc" << QColorSpace::NamedColorSpace(0) + << QColorSpace::TransferFunction::Custom + << QColorSpace::TransformModel::ElementListProcessing + << QColorSpace::ColorModel::Cmyk << QString("uCMY"); + // BT.2100 PQ profile + QTest::newRow("BT.2100 PQ") << prefix + "Rec. ITU-R BT.2100 PQ.icc" << QColorSpace::Bt2100Pq + << QColorSpace::TransferFunction::St2084 + << QColorSpace::TransformModel::ThreeComponentMatrix + << QColorSpace::ColorModel::Rgb << QString("Rec. ITU-R BT.2100 PQ"); } void tst_QColorSpace::fromIccProfile() @@ -194,10 +248,12 @@ void tst_QColorSpace::fromIccProfile() QFETCH(QString, testProfile); QFETCH(QColorSpace::NamedColorSpace, namedColorSpace); QFETCH(QColorSpace::TransferFunction, transferFunction); + QFETCH(QColorSpace::TransformModel, transformModel); + QFETCH(QColorSpace::ColorModel, colorModel); QFETCH(QString, description); QFile file(testProfile); - file.open(QIODevice::ReadOnly); + QVERIFY(file.open(QIODevice::ReadOnly)); QByteArray iccProfile = file.readAll(); QColorSpace fileColorSpace = QColorSpace::fromIccProfile(iccProfile); QVERIFY(fileColorSpace.isValid()); @@ -206,7 +262,23 @@ void tst_QColorSpace::fromIccProfile() QCOMPARE(fileColorSpace, namedColorSpace); QCOMPARE(fileColorSpace.transferFunction(), transferFunction); + QCOMPARE(fileColorSpace.transformModel(), transformModel); + QCOMPARE(fileColorSpace.colorModel(), colorModel); QCOMPARE(fileColorSpace.description(), description); + + QByteArray iccProfile2 = fileColorSpace.iccProfile(); + QCOMPARE(iccProfile, iccProfile2); + QColorSpace fileColorSpace2 = QColorSpace::fromIccProfile(iccProfile2); + QCOMPARE(fileColorSpace2, fileColorSpace); + + // Change description to force generation of new icc profile data. + fileColorSpace2.setDescription("Hello my QTest description"); + iccProfile2 = fileColorSpace2.iccProfile(); + QCOMPARE_NE(iccProfile, iccProfile2); + fileColorSpace2 = QColorSpace::fromIccProfile(iccProfile2); + QVERIFY(fileColorSpace2.isValid()); + // Note, we do not currently compare description in color space equality + QCOMPARE(fileColorSpace2, fileColorSpace); } void tst_QColorSpace::imageConversion_data() @@ -217,9 +289,10 @@ void tst_QColorSpace::imageConversion_data() QTest::newRow("sRGB -> Display-P3") << QColorSpace::SRgb << QColorSpace::DisplayP3 << 0; QTest::newRow("sRGB -> Adobe RGB") << QColorSpace::SRgb << QColorSpace::AdobeRgb << 2; - QTest::newRow("Display-P3 -> sRGB") << QColorSpace::DisplayP3 << QColorSpace::SRgb << 0; QTest::newRow("Adobe RGB -> sRGB") << QColorSpace::AdobeRgb << QColorSpace::SRgb << 2; + QTest::newRow("Adobe RGB -> Display-P3") << QColorSpace::AdobeRgb << QColorSpace::DisplayP3 << 4; QTest::newRow("Display-P3 -> Adobe RGB") << QColorSpace::DisplayP3 << QColorSpace::AdobeRgb << 2; + QTest::newRow("Display-P3 -> sRGB") << QColorSpace::DisplayP3 << QColorSpace::SRgb << 0; QTest::newRow("sRGB -> sRGB Linear") << QColorSpace::SRgb << QColorSpace::SRgbLinear << 0; QTest::newRow("sRGB Linear -> sRGB") << QColorSpace::SRgbLinear << QColorSpace::SRgb << 0; } @@ -246,9 +319,9 @@ void tst_QColorSpace::imageConversion() int lastBlue = 0; for (int i = 0; i < 256; ++i) { QRgb p = testImage.pixel(i, 0); - QVERIFY(qRed(p) >= lastRed); - QVERIFY(qGreen(p) >= lastGreen); - QVERIFY(qBlue(p) >= lastBlue); + QCOMPARE_GE(qRed(p), lastRed); + QCOMPARE_GE(qGreen(p), lastGreen); + QCOMPARE_GE(qBlue(p), lastBlue); lastRed = qRed(p); lastGreen = qGreen(p); lastBlue = qBlue(p); @@ -261,11 +334,12 @@ void tst_QColorSpace::imageConversion() QCOMPARE(testImage.colorSpace(), QColorSpace(fromColorSpace)); for (int i = 0; i < 256; ++i) { QRgb p = testImage.pixel(i, 0); - QVERIFY(qAbs(qRed(p) - qGreen(p)) <= tolerance); - QVERIFY(qAbs(qRed(p) - qBlue(p)) <= tolerance); - QVERIFY((lastRed - qRed(p)) <= (tolerance / 2)); - QVERIFY((lastGreen - qGreen(p)) <= (tolerance / 2)); - QVERIFY((lastBlue - qBlue(p)) <= (tolerance / 2)); + QCOMPARE_LE(qAbs(qRed(p) - qBlue(p)), tolerance); + QCOMPARE_LE(qAbs(qRed(p) - qGreen(p)), tolerance); + QCOMPARE_LE(qAbs(qGreen(p) - qBlue(p)), tolerance); + QCOMPARE_LE(lastRed - qRed(p), tolerance / 2); + QCOMPARE_LE(lastBlue - qBlue(p), tolerance / 2); + QCOMPARE_LE(lastGreen - qGreen(p), tolerance / 2); lastRed = qRed(p); lastGreen = qGreen(p); lastBlue = qBlue(p); @@ -306,9 +380,9 @@ void tst_QColorSpace::imageConversion64() int lastBlue = 0; for (int i = 0; i < 256; ++i) { QRgb p = testImage.pixel(i, 0); - QVERIFY(qRed(p) >= lastRed); - QVERIFY(qGreen(p) >= lastGreen); - QVERIFY(qBlue(p) >= lastBlue); + QCOMPARE_GE(qRed(p), lastRed); + QCOMPARE_GE(qGreen(p), lastGreen); + QCOMPARE_GE(qBlue(p), lastBlue); lastRed = qRed(p); lastGreen = qGreen(p); lastBlue = qBlue(p); @@ -323,9 +397,9 @@ void tst_QColorSpace::imageConversion64() QRgb p = testImage.pixel(i, 0); QCOMPARE(qRed(p), qGreen(p)); QCOMPARE(qRed(p), qBlue(p)); - QVERIFY((lastRed - qRed(p)) <= 0); - QVERIFY((lastGreen - qGreen(p)) <= 0); - QVERIFY((lastBlue - qBlue(p)) <= 0); + QCOMPARE_GE(qRed(p), lastRed); + QCOMPARE_GE(qGreen(p), lastGreen); + QCOMPARE_GE(qBlue(p), lastBlue); lastRed = qRed(p); lastGreen = qGreen(p); lastBlue = qBlue(p); @@ -349,8 +423,10 @@ void tst_QColorSpace::imageConversion64PM() for (int j = 0; j < 16; ++j) { int a = j * 15; - for (int i = 0; i < 256; ++i) - testImage.setPixel(i, j, qPremultiply(qRgba(i, i, i, a))); + for (int i = 0; i < 256; ++i) { + QRgba64 color = QRgba64::fromRgba(i, i, i, a); + testImage.setPixelColor(i, j, QColor::fromRgba64(color)); + } } testImage.setColorSpace(fromColorSpace); @@ -366,17 +442,17 @@ void tst_QColorSpace::imageConversion64PM() const int expectedAlpha = j * 15; for (int i = 0; i < 256; ++i) { QRgb p = testImage.pixel(i, j); - QVERIFY(qRed(p) >= lastRed); - QVERIFY(qGreen(p) >= lastGreen); - QVERIFY(qBlue(p) >= lastBlue); + QCOMPARE_GE(qRed(p), lastRed); + QCOMPARE_GE(qGreen(p), lastGreen); + QCOMPARE_GE(qBlue(p), lastBlue); QCOMPARE(qAlpha(p), expectedAlpha); lastRed = qRed(p); lastGreen = qGreen(p); lastBlue = qBlue(p); } - QVERIFY(lastRed <= expectedAlpha); - QVERIFY(lastGreen <= expectedAlpha); - QVERIFY(lastBlue <= expectedAlpha); + QCOMPARE_LE(lastRed, expectedAlpha); + QCOMPARE_LE(lastGreen, expectedAlpha); + QCOMPARE_LE(lastBlue, expectedAlpha); lastRed = 0; lastGreen = 0; lastBlue = 0; @@ -389,15 +465,15 @@ void tst_QColorSpace::imageConversion64PM() for (int i = 0; i < 256; ++i) { QRgb expected = qPremultiply(qRgba(i, i, i, expectedAlpha)); QRgb p = testImage.pixel(i, j); - QCOMPARE(qRed(p), qGreen(p)); - QCOMPARE(qRed(p), qBlue(p)); + QCOMPARE_LE(qAbs(qRed(p) - qGreen(p)), 1); + QCOMPARE_LE(qAbs(qRed(p) - qBlue(p)), 1); QCOMPARE(qAlpha(p), expectedAlpha); - QVERIFY((lastRed - qRed(p)) <= 0); - QVERIFY((lastGreen - qGreen(p)) <= 0); - QVERIFY((lastBlue - qBlue(p)) <= 0); - QVERIFY(qAbs(qRed(p) - qRed(expected)) <= 1); - QVERIFY(qAbs(qGreen(p) - qGreen(expected)) <= 1); - QVERIFY(qAbs(qBlue(p) - qBlue(expected)) <= 1); + QCOMPARE_GE(qRed(p), lastRed); + QCOMPARE_GE(qGreen(p), lastGreen); + QCOMPARE_GE(qBlue(p), lastBlue); + QCOMPARE_LE(qAbs(qRed(p) - qRed(expected)), 1); + QCOMPARE_LE(qAbs(qGreen(p) - qGreen(expected)), 1); + QCOMPARE_LE(qAbs(qBlue(p) - qBlue(expected)), 1); lastRed = qRed(p); lastGreen = qGreen(p); lastBlue = qBlue(p); @@ -437,14 +513,14 @@ void tst_QColorSpace::imageConversionOverLargerGamut() testImage.setColorSpace(csfrom); for (int y = 0; y < 256; ++y) for (int x = 0; x < 256; ++x) - testImage.setPixel(x, y, qRgb(x, y, 0)); + testImage.setPixel(x, y, qRgb(x, y, qAbs(x - y))); QImage resultImage = testImage.convertedToColorSpace(csto); for (int y = 0; y < 256; ++y) { int lastRed = 0; for (int x = 0; x < 256; ++x) { QRgb p = resultImage.pixel(x, y); - QVERIFY(qRed(p) >= lastRed); + QCOMPARE_GE(qRed(p), lastRed); lastRed = qRed(p); } } @@ -452,7 +528,7 @@ void tst_QColorSpace::imageConversionOverLargerGamut() int lastGreen = 0; for (int y = 0; y < 256; ++y) { QRgb p = resultImage.pixel(x, y); - QVERIFY(qGreen(p) >= lastGreen); + QCOMPARE_GE(qGreen(p), lastGreen); lastGreen = qGreen(p); } } @@ -515,6 +591,138 @@ void tst_QColorSpace::imageConversionOverLargerGamut2() QVERIFY(resultImage.pixelColor(0, 255).greenF() > 1.0f); } +void tst_QColorSpace::imageConversionOverAnyGamutFP_data() +{ + QTest::addColumn<QColorSpace::NamedColorSpace>("fromColorSpace"); + QTest::addColumn<QColorSpace::NamedColorSpace>("toColorSpace"); + + QTest::newRow("sRGB -> Display-P3") << QColorSpace::SRgb << QColorSpace::DisplayP3; + QTest::newRow("sRGB -> Adobe RGB") << QColorSpace::SRgb << QColorSpace::AdobeRgb; + QTest::newRow("sRGB -> ProPhoto RGB") << QColorSpace::SRgb << QColorSpace::ProPhotoRgb; + QTest::newRow("Adobe RGB -> sRGB") << QColorSpace::AdobeRgb << QColorSpace::SRgb; + QTest::newRow("Adobe RGB -> Display-P3") << QColorSpace::AdobeRgb << QColorSpace::DisplayP3; + QTest::newRow("Adobe RGB -> ProPhoto RGB") << QColorSpace::AdobeRgb << QColorSpace::ProPhotoRgb; + QTest::newRow("Display-P3 -> sRGB") << QColorSpace::DisplayP3 << QColorSpace::SRgb; + QTest::newRow("Display-P3 -> Adobe RGB") << QColorSpace::DisplayP3 << QColorSpace::AdobeRgb; + QTest::newRow("Display-P3 -> ProPhoto RGB") << QColorSpace::DisplayP3 << QColorSpace::ProPhotoRgb; +} + +void tst_QColorSpace::imageConversionOverAnyGamutFP() +{ + QFETCH(QColorSpace::NamedColorSpace, fromColorSpace); + QFETCH(QColorSpace::NamedColorSpace, toColorSpace); + + QColorSpace csfrom(fromColorSpace); + QColorSpace csto(toColorSpace); + csfrom.setTransferFunction(QColorSpace::TransferFunction::Linear); + csto.setTransferFunction(QColorSpace::TransferFunction::Linear); + + QImage testImage(256, 256, QImage::Format_RGBX32FPx4); + testImage.setColorSpace(csfrom); + for (int y = 0; y < 256; ++y) + for (int x = 0; x < 256; ++x) + testImage.setPixel(x, y, qRgb(x, y, 0)); + + QImage resultImage = testImage.convertedToColorSpace(csto); + resultImage.convertToColorSpace(csfrom); + + for (int y = 0; y < 256; ++y) { + for (int x = 0; x < 256; ++x) { + QCOMPARE(resultImage.pixel(x, y), testImage.pixel(x, y)); + } + } +} + +void tst_QColorSpace::imageConversionOverAnyGamutFP2_data() +{ + imageConversionOverAnyGamutFP_data(); +} + +void tst_QColorSpace::imageConversionOverAnyGamutFP2() +{ + QFETCH(QColorSpace::NamedColorSpace, fromColorSpace); + QFETCH(QColorSpace::NamedColorSpace, toColorSpace); + + // Same as imageConversionOverAnyGamutFP but using format switching transform + QColorSpace csfrom(fromColorSpace); + QColorSpace csto(toColorSpace); + csfrom.setTransferFunction(QColorSpace::TransferFunction::Linear); + csto.setTransferFunction(QColorSpace::TransferFunction::Linear); + + QImage testImage(256, 256, QImage::Format_RGB32); + testImage.setColorSpace(csfrom); + for (int y = 0; y < 256; ++y) + for (int x = 0; x < 256; ++x) + testImage.setPixel(x, y, qRgb(x, y, 0)); + + QImage resultImage = testImage.convertedToColorSpace(csto, QImage::Format_RGBX32FPx4); + resultImage.convertToColorSpace(csfrom, QImage::Format_RGB32); + + for (int y = 0; y < 256; ++y) { + for (int x = 0; x < 256; ++x) { + QCOMPARE(resultImage.pixel(x, y), testImage.pixel(x, y)); + } + } +} + +void tst_QColorSpace::imageConversionOverNonThreeComponentMatrix_data() +{ + QTest::addColumn<QColorSpace>("fromColorSpace"); + QTest::addColumn<QColorSpace>("toColorSpace"); + + QString prefix = QFINDTESTDATA("resources/"); + QFile file1(prefix + "VideoHD.icc"); + QFile file2(prefix + "sRGB_ICC_v4_Appearance.icc"); + QVERIFY(file1.open(QFile::ReadOnly)); + QVERIFY(file2.open(QFile::ReadOnly)); + QByteArray iccProfile1 = file1.readAll(); + QByteArray iccProfile2 = file2.readAll(); + QColorSpace hdtvColorSpace = QColorSpace::fromIccProfile(iccProfile1); + QColorSpace srgbPcsColorSpace = QColorSpace::fromIccProfile(iccProfile2); + + QTest::newRow("sRGB PCSLab -> sRGB") << srgbPcsColorSpace << QColorSpace(QColorSpace::SRgb); + QTest::newRow("sRGB -> sRGB PCSLab") << QColorSpace(QColorSpace::SRgb) << srgbPcsColorSpace; + QTest::newRow("HDTV -> sRGB") << hdtvColorSpace << QColorSpace(QColorSpace::SRgb); + QTest::newRow("sRGB -> HDTV") << QColorSpace(QColorSpace::SRgb) << hdtvColorSpace; + QTest::newRow("sRGB PCSLab -> HDTV") << srgbPcsColorSpace << hdtvColorSpace; + QTest::newRow("HDTV -> sRGB PCSLab") << hdtvColorSpace << srgbPcsColorSpace; +} + +void tst_QColorSpace::imageConversionOverNonThreeComponentMatrix() +{ + QFETCH(QColorSpace, fromColorSpace); + QFETCH(QColorSpace, toColorSpace); + QVERIFY(fromColorSpace.isValid()); + QVERIFY(toColorSpace.isValidTarget()); + + QVERIFY(!fromColorSpace.transformationToColorSpace(toColorSpace).isIdentity()); + + QImage testImage(256, 256, QImage::Format_RGBX64); + testImage.setColorSpace(fromColorSpace); + for (int y = 0; y < 256; ++y) + for (int x = 0; x < 256; ++x) + testImage.setPixel(x, y, qRgb(x, y, 0)); + + QImage resultImage = testImage.convertedToColorSpace(toColorSpace); + QCOMPARE(resultImage.size(), testImage.size()); + for (int y = 0; y < 256; ++y) { + int lastRed = 0; + for (int x = 0; x < 256; ++x) { + QRgb p = resultImage.pixel(x, y); + QVERIFY(qRed(p) >= lastRed); + lastRed = qRed(p); + } + } + for (int x = 0; x < 256; ++x) { + int lastGreen = 0; + for (int y = 0; y < 256; ++y) { + QRgb p = resultImage.pixel(x, y); + QVERIFY(qGreen(p) >= lastGreen); + lastGreen = qGreen(p); + } + } +} + void tst_QColorSpace::loadImage() { QString prefix = QFINDTESTDATA("resources/"); @@ -692,10 +900,28 @@ void tst_QColorSpace::changePrimaries() cs.setPrimaries(QColorSpace::Primaries::DciP3D65); QVERIFY(cs.isValid()); QCOMPARE(cs, QColorSpace(QColorSpace::DisplayP3)); + QCOMPARE(cs.transformModel(), QColorSpace::TransformModel::ThreeComponentMatrix); cs.setTransferFunction(QColorSpace::TransferFunction::Linear); cs.setPrimaries(QPointF(0.3127, 0.3290), QPointF(0.640, 0.330), QPointF(0.3000, 0.6000), QPointF(0.150, 0.060)); QCOMPARE(cs, QColorSpace(QColorSpace::SRgbLinear)); + + + QFile iccFile(QFINDTESTDATA("resources/") + "VideoHD.icc"); + QVERIFY(iccFile.open(QFile::ReadOnly)); + QByteArray iccData = iccFile.readAll(); + QColorSpace hdtvColorSpace = QColorSpace::fromIccProfile(iccData); + QVERIFY(hdtvColorSpace.isValid()); + QCOMPARE(hdtvColorSpace.transformModel(), QColorSpace::TransformModel::ElementListProcessing); + QCOMPARE(hdtvColorSpace.primaries(), QColorSpace::Primaries::Custom); + QCOMPARE(hdtvColorSpace.transferFunction(), QColorSpace::TransferFunction::Custom); + // Unsets both primaries and transferfunction because they were inseparable in element list processing + hdtvColorSpace.setPrimaries(QColorSpace::Primaries::SRgb); + QVERIFY(!hdtvColorSpace.isValid()); + hdtvColorSpace.setTransferFunction(QColorSpace::TransferFunction::SRgb); + QVERIFY(hdtvColorSpace.isValid()); + QCOMPARE(hdtvColorSpace.transformModel(), QColorSpace::TransformModel::ThreeComponentMatrix); + QCOMPARE(hdtvColorSpace, QColorSpace(QColorSpace::SRgb)); } void tst_QColorSpace::transferFunctionTable() @@ -744,5 +970,161 @@ void tst_QColorSpace::description() QCOMPARE(srgb.description(), QLatin1String("Linear sRGB")); // Set to empty returns default behavior } +void tst_QColorSpace::whitePoint_data() +{ + QTest::addColumn<QColorSpace::NamedColorSpace>("namedColorSpace"); + QTest::addColumn<QPointF>("whitePoint"); + + QTest::newRow("sRGB") << QColorSpace::SRgb << QColorVector::D65Chromaticity(); + QTest::newRow("Adobe RGB") << QColorSpace::AdobeRgb << QColorVector::D65Chromaticity(); + QTest::newRow("Display-P3") << QColorSpace::DisplayP3 << QColorVector::D65Chromaticity(); + QTest::newRow("ProPhoto RGB") << QColorSpace::ProPhotoRgb << QColorVector::D50Chromaticity(); +} + +void tst_QColorSpace::whitePoint() +{ + QFETCH(QColorSpace::NamedColorSpace, namedColorSpace); + QFETCH(QPointF, whitePoint); + + QColorSpace colorSpace(namedColorSpace); + QPointF wpt = colorSpace.whitePoint(); + QCOMPARE_LE(qAbs(wpt.x() - whitePoint.x()), 0.0000001); + QCOMPARE_LE(qAbs(wpt.y() - whitePoint.y()), 0.0000001); +} + +void tst_QColorSpace::setWhitePoint() +{ + QColorSpace colorSpace(QColorSpace::SRgb); + colorSpace.setWhitePoint(QPointF(0.33, 0.33)); + QCOMPARE_NE(colorSpace, QColorSpace(QColorSpace::SRgb)); + colorSpace.setWhitePoint(QColorVector::D65Chromaticity()); + // Check our matrix manipulations returned us to where we came from + QCOMPARE(colorSpace, QColorSpace(QColorSpace::SRgb)); +} + +void tst_QColorSpace::grayColorSpace() +{ + QColorSpace spc; + QCOMPARE(spc.colorModel(), QColorSpace::ColorModel::Undefined); + QVERIFY(!spc.isValid()); + spc.setWhitePoint(QColorVector::D65Chromaticity()); + spc.setTransferFunction(QColorSpace::TransferFunction::SRgb); + QVERIFY(spc.isValid()); + QCOMPARE(spc.colorModel(), QColorSpace::ColorModel::Gray); + + QColorSpace spc2(QColorVector::D65Chromaticity(), QColorSpace::TransferFunction::SRgb); + QVERIFY(spc2.isValid()); + QCOMPARE(spc2.colorModel(), QColorSpace::ColorModel::Gray); + QCOMPARE(spc, spc2); + + QImage rgbImage(1, 8, QImage::Format_RGB32); + QImage grayImage(1, 255, QImage::Format_Grayscale8); + // RGB images can not have gray color space + rgbImage.setColorSpace(spc2); + grayImage.setColorSpace(spc2); + QCOMPARE_NE(rgbImage.colorSpace(), spc2); + QCOMPARE(grayImage.colorSpace(), spc2); + // But gray images can have RGB color space + rgbImage.setColorSpace(QColorSpace::SRgb); + grayImage.setColorSpace(QColorSpace::SRgb); + QCOMPARE(rgbImage.colorSpace(), QColorSpace(QColorSpace::SRgb)); + QCOMPARE(grayImage.colorSpace(), QColorSpace(QColorSpace::SRgb)); + + // While we can not set a grayscale color space on rgb image, we can convert to one + QImage grayImage2 = rgbImage.convertedToColorSpace(spc2); + QCOMPARE(grayImage2.colorSpace(), spc2); + QCOMPARE(grayImage2.format(), QImage::Format_Grayscale8); +} + +void tst_QColorSpace::grayColorSpaceEffectivelySRgb() +{ + // Test grayscale colorspace conversion by making a gray color space that should act like sRGB on gray values. + QColorSpace sRgb(QColorSpace::SRgb); + QColorSpace sRgbGray(QColorVector::D65Chromaticity(), QColorSpace::TransferFunction::SRgb); + + QImage grayImage1(256, 1, QImage::Format_Grayscale8); + QImage grayImage2(256, 1, QImage::Format_Grayscale8); + for (int i = 0; i < 256; ++i) { + grayImage1.bits()[i] = i; + grayImage2.bits()[i] = i; + } + grayImage1.setColorSpace(sRgb); + grayImage2.setColorSpace(sRgbGray); + + QImage rgbImage1 = grayImage1.convertedTo(QImage::Format_RGB32); + QImage rgbImage2 = grayImage2.convertedToColorSpace(sRgb, QImage::Format_RGB32); + + QCOMPARE(rgbImage1, rgbImage2); +} + +void tst_QColorSpace::scaleAlphaValue() +{ + QImage image(1, 1, QImage::Format_ARGB32); + image.setPixel(0, 0, qRgba(255, 255, 255, 125)); + image.setColorSpace(QColorSpace::SRgb); + image.convertToColorSpace(QColorSpace::SRgbLinear, QImage::Format_RGBA64); + QCOMPARE(reinterpret_cast<const QRgba64 *>(image.constBits())->alpha(), 257 * 125); +} + +void tst_QColorSpace::hdrColorSpaces() +{ + QColorSpace bt2020linear(QColorSpace::Primaries::Bt2020, QColorSpace::TransferFunction::Linear); + QColorTransform pqToLinear = QColorSpace(QColorSpace::Bt2100Pq).transformationToColorSpace(bt2020linear); + QColorTransform hlgToLinear = QColorSpace(QColorSpace::Bt2100Hlg).transformationToColorSpace(bt2020linear); + + QColor maxWhite = QColor::fromRgbF(1.0f, 1.0f, 1.0f); + QColor hlgWhite = QColor::fromRgbF(0.5f, 0.5f, 0.5f); + QCOMPARE(hlgToLinear.map(maxWhite).redF(), 12.f); + QCOMPARE(hlgToLinear.map(maxWhite).greenF(), 12.f); + QCOMPARE(hlgToLinear.map(maxWhite).blueF(), 12.f); + QCOMPARE(hlgToLinear.map(hlgWhite).redF(), 1.f); + QCOMPARE(hlgToLinear.map(hlgWhite).greenF(), 1.f); + QCOMPARE(hlgToLinear.map(hlgWhite).blueF(), 1.f); + QCOMPARE(pqToLinear.map(maxWhite).redF(), 64.f); + QCOMPARE(pqToLinear.map(maxWhite).greenF(), 64.f); + QCOMPARE(pqToLinear.map(maxWhite).blueF(), 64.f); + + { + QImage image(1, 1, QImage::Format_RGBA32FPx4); + image.setPixel(0, 0, qRgba(255, 255, 255, 255)); + image.setColorSpace(QColorSpace::Bt2100Pq); + QImage image2 = image.convertedToColorSpace(bt2020linear); + QCOMPARE(image2.pixelColor(0, 0).redF(), 64.f); + image.setColorSpace(QColorSpace::Bt2100Hlg); + image2 = image.convertedToColorSpace(bt2020linear); + QCOMPARE(image2.pixelColor(0, 0).redF(), 12.f); + } + { + QImage image(1, 1, QImage::Format_RGBA32FPx4_Premultiplied); + image.setPixel(0, 0, qRgba(255, 255, 255, 255)); + image.setColorSpace(QColorSpace::Bt2100Pq); + QImage image2 = image.convertedToColorSpace(bt2020linear); + QCOMPARE(image2.pixelColor(0, 0).redF(), 64.f); + image.setColorSpace(QColorSpace::Bt2100Hlg); + image2 = image.convertedToColorSpace(bt2020linear); + QCOMPARE(image2.pixelColor(0, 0).redF(), 12.f); + } + { + QImage image(1, 1, QImage::Format_ARGB32); + image.setPixel(0, 0, qRgba(255, 255, 255, 255)); + image.setColorSpace(QColorSpace::Bt2100Pq); + QImage image2 = image.convertedToColorSpace(bt2020linear, QImage::Format_RGBA32FPx4); + QCOMPARE(image2.pixelColor(0, 0).redF(), 64.f); + image.setColorSpace(QColorSpace::Bt2100Hlg); + image2 = image.convertedToColorSpace(bt2020linear, QImage::Format_RGBA32FPx4); + QCOMPARE(image2.pixelColor(0, 0).redF(), 12.f); + } + { + QImage image(1, 1, QImage::Format_ARGB32_Premultiplied); + image.setPixel(0, 0, qRgba(255, 255, 255, 255)); + image.setColorSpace(QColorSpace::Bt2100Pq); + QImage image2 = image.convertedToColorSpace(bt2020linear, QImage::Format_RGBA32FPx4); + QCOMPARE(image2.pixelColor(0, 0).redF(), 64.f); + image.setColorSpace(QColorSpace::Bt2100Hlg); + image2 = image.convertedToColorSpace(bt2020linear, QImage::Format_RGBA32FPx4); + QCOMPARE(image2.pixelColor(0, 0).redF(), 12.f); + } +} + QTEST_MAIN(tst_QColorSpace) #include "tst_qcolorspace.moc" |