diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt index a4dea6825b..e0dbb45660 100644 --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -242,3 +242,14 @@ target_link_libraries(testOutputTransform ) add_test(NAME kwin-testOutputTransform COMMAND testOutputTransform) ecm_mark_as_test(testOutputTransform) + +######################################################## +# Test Colorspace +######################################################## +add_executable(testColorspaces test_colorspaces.cpp) +target_link_libraries(testColorspaces + Qt::Test + kwin +) +add_test(NAME kwin-testColorspaces COMMAND testColorspaces) +ecm_mark_as_test(testColorspaces) diff --git a/autotests/test_colorspaces.cpp b/autotests/test_colorspaces.cpp new file mode 100644 index 0000000000..d2fcbe1665 --- /dev/null +++ b/autotests/test_colorspaces.cpp @@ -0,0 +1,76 @@ +/* + SPDX-FileCopyrightText: 2023 Xaver Hugl + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ + +#include + +#include "core/colorspace.h" + +using namespace KWin; + +class TestColorspaces : public QObject +{ + Q_OBJECT + +public: + TestColorspaces() = default; + +private Q_SLOTS: + void roundtripConversion_data(); + void roundtripConversion(); +}; + +static bool compareVectors(const QVector3D &one, const QVector3D &two, float maxDifference) +{ + const bool ret = std::abs(one.x() - two.x()) <= maxDifference + && std::abs(one.y() - two.y()) <= maxDifference + && std::abs(one.z() - two.z()) <= maxDifference; + if (!ret) { + qWarning() << one << "!=" << two << "within" << maxDifference; + } + return ret; +} + +void TestColorspaces::roundtripConversion_data() +{ + QTest::addColumn("srcColorimetry"); + QTest::addColumn("srcTransferFunction"); + QTest::addColumn("dstColorimetry"); + QTest::addColumn("dstTransferFunction"); + QTest::addColumn("requiredAccuracy"); + + const double resolution10bit = std::pow(1.0 / 2.0, 10); + QTest::addRow("BT709 (sRGB) <-> BT2020 (linear)") << NamedColorimetry::BT709 << NamedTransferFunction::sRGB << NamedColorimetry::BT2020 << NamedTransferFunction::linear << resolution10bit; + QTest::addRow("BT709 (gamma 2.2) <-> BT2020 (linear)") << NamedColorimetry::BT709 << NamedTransferFunction::gamma22 << NamedColorimetry::BT2020 << NamedTransferFunction::linear << resolution10bit; + QTest::addRow("BT709 (scRGB) <-> BT2020 (linear)") << NamedColorimetry::BT709 << NamedTransferFunction::scRGB << NamedColorimetry::BT2020 << NamedTransferFunction::linear << resolution10bit; + QTest::addRow("BT709 (linear) <-> BT2020 (linear)") << NamedColorimetry::BT709 << NamedTransferFunction::linear << NamedColorimetry::BT2020 << NamedTransferFunction::linear << resolution10bit; + QTest::addRow("BT709 (PQ) <-> BT2020 (linear)") << NamedColorimetry::BT709 << NamedTransferFunction::PerceptualQuantizer << NamedColorimetry::BT2020 << NamedTransferFunction::linear << 3 * resolution10bit; +} + +void TestColorspaces::roundtripConversion() +{ + QFETCH(NamedColorimetry, srcColorimetry); + QFETCH(NamedTransferFunction, srcTransferFunction); + QFETCH(NamedColorimetry, dstColorimetry); + QFETCH(NamedTransferFunction, dstTransferFunction); + QFETCH(double, requiredAccuracy); + + const auto src = ColorDescription(srcColorimetry, srcTransferFunction, 100, 0, 100, 100, 0); + const auto dst = ColorDescription(dstColorimetry, dstTransferFunction, 100, 0, 100, 100, 0); + + const QVector3D red(1, 0, 0); + const QVector3D green(0, 1, 0); + const QVector3D blue(0, 0, 1); + const QVector3D white(1, 1, 1); + + QVERIFY(compareVectors(dst.mapTo(src.mapTo(red, dst), src), red, requiredAccuracy)); + QVERIFY(compareVectors(dst.mapTo(src.mapTo(green, dst), src), green, requiredAccuracy)); + QVERIFY(compareVectors(dst.mapTo(src.mapTo(blue, dst), src), blue, requiredAccuracy)); + QVERIFY(compareVectors(dst.mapTo(src.mapTo(white, dst), src), white, requiredAccuracy)); +} + +QTEST_MAIN(TestColorspaces) + +#include "test_colorspaces.moc"