[graphics/krita] /: Make default PQ profile the 203 nits one, and implement search for reference white.
Wolthera van Hövell <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 086abdb2be85f0e09bf161d46393b2be69b0fb75 by Wolthera van Hövell, on behalf of Wolthera van Hövell tot Westerflier.
Committed on 16/07/2026 at 16:26.
Pushed by woltherav into branch 'master'.
Make default PQ profile the 203 nits one, and implement search for reference white.
M +6 -1 libs/pigment/KoColorProfileStorage.cpp
M +12 -5 libs/pigment/KoColorSpaceRegistry.cpp
M +4 -0 libs/surfacecolormanagementapi/surfacecolormanagement/KisSurfaceColorimetryIccUtils.cpp
M +1 -2 libs/widgets/KisVisualColorModel.cpp
M +33 -10 plugins/color/lcms2engine/tests/TestIccFromColorimetryConversion.cpp
M +22 -2 plugins/color/lcms2engine/tests/TestProfileGeneration.cpp
M +3 -0 plugins/color/lcms2engine/tests/TestProfileGeneration.h
M +2 -3 plugins/dockers/smallcolorselector/kis_small_color_widget.cc
https://invent.kde.org/graphics/krita/-/commit/086abdb2be85f0e09bf161d46393b2be69b0fb75
diff --git a/libs/pigment/KoColorProfileStorage.cpp b/libs/pigment/KoColorProfileStorage.cpp
index b9bafc12fe9..d4dabfa4575 100644
--- a/libs/pigment/KoColorProfileStorage.cpp
+++ b/libs/pigment/KoColorProfileStorage.cpp
@@ -186,6 +186,7 @@ QList<const KoColorProfile *> KoColorProfileStorage::profilesFor(const KoColorPr
bool colorantMatch = (!query.rgbColorants.isEmpty() || query.primaries != PRIMARIES_UNSPECIFIED);
bool colorantTypeMatch = (query.primaries == PRIMARIES_UNSPECIFIED);
bool transferMatch = (query.transfer == TRC_UNSPECIFIED);
+ bool luminanceMatch = true;
if (query.primaries != PRIMARIES_UNSPECIFIED) {
if (int(profile->getColorPrimaries()) == query.primaries) {
colorantTypeMatch = true;
@@ -224,7 +225,11 @@ QList<const KoColorProfile *> KoColorProfileStorage::profilesFor(const KoColorPr
}
}
- if (transferMatch && colorantMatch && colorantTypeMatch) {
+ if (query.hdrReferenceWhite && query.transfer == TRC_ITU_R_BT_2100_0_PQ) {
+ luminanceMatch = (profile->hdrReferenceWhite() && qFuzzyCompare(*profile->hdrReferenceWhite(), *query.hdrReferenceWhite));
+ }
+
+ if (transferMatch && colorantMatch && colorantTypeMatch && luminanceMatch) {
profiles.push_back(profile);
}
}
diff --git a/libs/pigment/KoColorSpaceRegistry.cpp b/libs/pigment/KoColorSpaceRegistry.cpp
index 9ad6af7bb40..5f58930f1be 100644
--- a/libs/pigment/KoColorSpaceRegistry.cpp
+++ b/libs/pigment/KoColorSpaceRegistry.cpp
@@ -687,7 +687,7 @@ const KoColorProfile *KoColorSpaceRegistry::p2020G10Profile() const
const KoColorProfile *KoColorSpaceRegistry::p2020PQProfile() const
{
- return profileByName("Krita Rec. 2100 Perceptual Quantizer (80cd/m²)");
+ return profileByName("Krita Rec. 2100 Perceptual Quantizer (203cd/m²)");
}
const KoColorProfile *KoColorSpaceRegistry::p709G10Profile() const
@@ -711,20 +711,23 @@ const KoColorProfile *KoColorSpaceRegistry::profileFor(const KoColorProfileQuery
}
if (query.primaries == PRIMARIES_ITU_R_BT_2020_2_AND_2100_0) {
- if (query.transfer == TRC_ITU_R_BT_2100_0_PQ) {
+ if (query.transfer == TRC_ITU_R_BT_2100_0_PQ
+ && query.hdrReferenceWhite
+ && qFuzzyCompare(*query.hdrReferenceWhite, 203.0)) {
return p2020PQProfile();
} else if (query.transfer == TRC_LINEAR) {
return p2020G10Profile();
}
}
- QList<const KoColorProfile*> list = d->profileStorage.profilesFor(query.primaries, query.transfer);
+ QList<const KoColorProfile*> list = d->profileStorage.profilesFor(query);
if (!list.empty()) {
return list.first();
}
KoColorSpaceEngine *engine = KoColorSpaceEngineRegistry::instance()->get("icc");
- if (engine && generate) {
+ // We're disabling custom generation of PQ profiles for now.
+ if (engine && generate && !(query.hdrReferenceWhite && query.transfer == TRC_ITU_R_BT_2100_0_PQ)) {
return engine->getProfile(query);
}
@@ -829,9 +832,13 @@ QColorSpace KoColorSpaceRegistry::QColorSpaceForProfile(const KoColorProfile *pr
return QColorSpace(QColorSpace::SRgb);
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
- if (profile == p2020PQProfile()) {
+ if (profile == p2020PQProfile()
+ || (profile->getColorPrimaries() == PRIMARIES_ITU_R_BT_2020_2_AND_2100_0
+ && profile->getTransferCharacteristics() == TRC_ITU_R_BT_2100_0_PQ)) {
return QColorSpace(QColorSpace::Bt2100Pq);
}
+ // TODO: we'll need to fine tune the conversion between non "rec 2100" pq profiles and qcolorspace.
+ // Though, arguably, these probably don't show up in a QColorSpace way, and should roundtrip in the icc cicp values.
#endif
return QColorSpace::fromIccProfile(profile->rawData());
}
diff --git a/libs/surfacecolormanagementapi/surfacecolormanagement/KisSurfaceColorimetryIccUtils.cpp b/libs/surfacecolormanagementapi/surfacecolormanagement/KisSurfaceColorimetryIccUtils.cpp
index 0c7996b1738..f8974868b8c 100644
--- a/libs/surfacecolormanagementapi/surfacecolormanagement/KisSurfaceColorimetryIccUtils.cpp
+++ b/libs/surfacecolormanagementapi/surfacecolormanagement/KisSurfaceColorimetryIccUtils.cpp
@@ -92,6 +92,10 @@ KoColorProfileQuery colorSpaceToRequest(ColorSpace cs)
request.rgbColorants.clear();
}
+ if (request.transfer == TRC_ITU_R_BT_2100_0_PQ) {
+ request.hdrReferenceWhite = std::make_optional(double(cs.luminance->referenceLuminance));
+ }
+
return request;
}
diff --git a/libs/widgets/KisVisualColorModel.cpp b/libs/widgets/KisVisualColorModel.cpp
index 6098aafaf1f..3404d8df888 100644
--- a/libs/widgets/KisVisualColorModel.cpp
+++ b/libs/widgets/KisVisualColorModel.cpp
@@ -83,8 +83,7 @@ void KisVisualColorModel::slotSetColorSpace(const KoColorSpace *cs)
// PQ color space is not very suitable for color picking, substitute with linear one
if (cs->colorModelId() == RGBAColorModelID
- && KoColorSpaceRegistry::instance()->p2020PQProfile()
- && cs->profile()->uniqueId() == KoColorSpaceRegistry::instance()->p2020PQProfile()->uniqueId()) {
+ && cs->profile()->getTransferCharacteristics() == TRC_ITU_R_BT_2100_0_PQ) {
csNew = KoColorSpaceRegistry::instance()->
colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id(),
diff --git a/plugins/color/lcms2engine/tests/TestIccFromColorimetryConversion.cpp b/plugins/color/lcms2engine/tests/TestIccFromColorimetryConversion.cpp
index a7fd50d9774..36791528f02 100644
--- a/plugins/color/lcms2engine/tests/TestIccFromColorimetryConversion.cpp
+++ b/plugins/color/lcms2engine/tests/TestIccFromColorimetryConversion.cpp
@@ -26,6 +26,7 @@ void TestIccFromColorimetryConversion::testRequestConstruction_data()
QTest::addColumn<bool>("isValid");
QTest::addColumn<ColorPrimaries>("expectedPrimaries");
QTest::addColumn<TransferCharacteristics>("expectedTransferFunction");
+ QTest::addColumn<double>("expectedReferenceWhite");
using KisSurfaceColorimetry::ColorSpace;
using KisSurfaceColorimetry::NamedPrimaries;
@@ -35,6 +36,7 @@ void TestIccFromColorimetryConversion::testRequestConstruction_data()
ColorSpace cs;
cs.primaries = p;
cs.transferFunction = tf;
+ cs.luminance->referenceLuminance = 80;
return cs;
};
@@ -42,49 +44,57 @@ void TestIccFromColorimetryConversion::testRequestConstruction_data()
<< makeCS(NamedPrimaries::primaries_srgb, NamedTransferFunction::transfer_function_srgb)
<< true
<< PRIMARIES_ITU_R_BT_709_5
- << TRC_IEC_61966_2_1;
+ << TRC_IEC_61966_2_1
+ << 0.0;
QTest::newRow("srgb-linear")
<< makeCS(NamedPrimaries::primaries_srgb, NamedTransferFunction::transfer_function_ext_linear)
<< true
<< PRIMARIES_ITU_R_BT_709_5
- << TRC_LINEAR;
+ << TRC_LINEAR
+ << 0.0;
QTest::newRow("srgb-2.2")
<< makeCS(NamedPrimaries::primaries_srgb, NamedTransferFunction::transfer_function_gamma22)
<< true
<< PRIMARIES_ITU_R_BT_709_5
- << TRC_ITU_R_BT_470_6_SYSTEM_M;
+ << TRC_ITU_R_BT_470_6_SYSTEM_M
+ << 0.0;
QTest::newRow("srgb-2.8")
<< makeCS(NamedPrimaries::primaries_srgb, NamedTransferFunction::transfer_function_gamma28)
<< true
<< PRIMARIES_ITU_R_BT_709_5
- << TRC_ITU_R_BT_470_6_SYSTEM_B_G;
+ << TRC_ITU_R_BT_470_6_SYSTEM_B_G
+ << 0.0;
QTest::newRow("bt2020-linear")
<< makeCS(NamedPrimaries::primaries_bt2020, NamedTransferFunction::transfer_function_ext_linear)
<< true
<< PRIMARIES_ITU_R_BT_2020_2_AND_2100_0
- << TRC_LINEAR;
+ << TRC_LINEAR
+ << 0.0;
QTest::newRow("bt2020-pq")
<< makeCS(NamedPrimaries::primaries_bt2020, NamedTransferFunction::transfer_function_st2084_pq)
<< true
<< PRIMARIES_ITU_R_BT_2020_2_AND_2100_0
- << TRC_ITU_R_BT_2100_0_PQ;
+ << TRC_ITU_R_BT_2100_0_PQ
+ << 80.0;
QTest::newRow("unknown-srgb")
<< makeCS(NamedPrimaries::primaries_unknown, NamedTransferFunction::transfer_function_srgb)
<< false
<< PRIMARIES_UNSPECIFIED
- << TRC_IEC_61966_2_1;
+ << TRC_IEC_61966_2_1
+ << 0.0;
QTest::newRow("srgb-unknown")
<< makeCS(NamedPrimaries::primaries_srgb, NamedTransferFunction::transfer_function_unknown)
<< false
<< PRIMARIES_ITU_R_BT_709_5
- << TRC_UNSPECIFIED;
+ << TRC_UNSPECIFIED
+ << 0.0;
// any pq-space that is not bt2020pq is considered unsupported
@@ -92,13 +102,15 @@ void TestIccFromColorimetryConversion::testRequestConstruction_data()
<< makeCS(NamedPrimaries::primaries_srgb, NamedTransferFunction::transfer_function_st2084_pq)
<< false
<< PRIMARIES_ITU_R_BT_709_5
- << TRC_UNSPECIFIED;
+ << TRC_UNSPECIFIED
+ << 0.0;
QTest::newRow("adobergb-pq")
<< makeCS(NamedPrimaries::primaries_adobe_rgb, NamedTransferFunction::transfer_function_st2084_pq)
<< false
<< PRIMARIES_ADOBE_RGB_1998
- << TRC_UNSPECIFIED;
+ << TRC_UNSPECIFIED
+ << 0.0;
}
void TestIccFromColorimetryConversion::testRequestConstruction()
@@ -107,12 +119,17 @@ void TestIccFromColorimetryConversion::testRequestConstruction()
QFETCH(bool, isValid);
QFETCH(ColorPrimaries, expectedPrimaries);
QFETCH(TransferCharacteristics, expectedTransferFunction);
+ QFETCH(double, expectedReferenceWhite);
auto request = KisSurfaceColorimetry::colorSpaceToRequest(colorSpace);
QCOMPARE(request.isRgb(), isValid);
QCOMPARE(request.primaries, expectedPrimaries);
QCOMPARE(request.transfer, expectedTransferFunction);
+ if (expectedReferenceWhite > 0.0) {
+ QVERIFY(request.hdrReferenceWhite);
+ QVERIFY(qFuzzyCompare(*request.hdrReferenceWhite, expectedReferenceWhite));
+ }
QVERIFY(request.rgbColorants.isEmpty());
}
@@ -213,6 +230,7 @@ void TestIccFromColorimetryConversion::testProfileConstruction()
QFETCH(bool, isValid);
QFETCH(ColorPrimaries, expectedPrimaries);
QFETCH(TransferCharacteristics, expectedTransferFunction);
+ QFETCH(double, expectedReferenceWhite);
// skip inherited invalid requests
if (!isValid) return;
@@ -227,6 +245,11 @@ void TestIccFromColorimetryConversion::testProfileConstruction()
QCOMPARE(profile->getColorPrimaries(), expectedPrimaries);
QCOMPARE(profile->getTransferCharacteristics(), expectedTransferFunction);
+ if (expectedReferenceWhite > 0.0) {
+ QVERIFY(profile->hdrReferenceWhite());
+ QVERIFY(qFuzzyCompare(*profile->hdrReferenceWhite(), expectedReferenceWhite));
+ }
+
qDebug() << ppVar(profile->name()) << ppVar(profile->fileName());
}
diff --git a/plugins/color/lcms2engine/tests/TestProfileGeneration.cpp b/plugins/color/lcms2engine/tests/TestProfileGeneration.cpp
index 062cd783e7c..007945f039f 100644
--- a/plugins/color/lcms2engine/tests/TestProfileGeneration.cpp
+++ b/plugins/color/lcms2engine/tests/TestProfileGeneration.cpp
@@ -393,12 +393,13 @@ void TestProfileGeneration::testCICPwriting()
QFETCH(ColorPrimaries, primaries);
QFETCH(TransferCharacteristics, transfer);
KoColorProfileQuery query(primaries, transfer);
+ if (transfer == TRC_ITU_R_BT_2100_0_PQ) {
+ query.hdrReferenceWhite = std::make_optional(203.0);
+ }
const KoColorProfile *profile = KoColorSpaceRegistry::instance()->profileFor(query);
QVERIFY(profile);
- // TODO: write and reload the profile.
-
QVERIFY(profile->getColorPrimaries() == primaries);
QVERIFY(profile->getTransferCharacteristics() == transfer);
@@ -412,4 +413,23 @@ void TestProfileGeneration::testCICPwriting()
QVERIFY(lcms->cicpTransfer() == transfer);
}
+void TestProfileGeneration::testRetrieveNits_data()
+{
+ QTest::addColumn<double>("expectedReferenceWhite");
+ QTest::addRow("rec2100PQ 80nits") << 80.0;
+ QTest::addRow("rec2100PQ 203nits") << 203.0;
+}
+
+void TestProfileGeneration::testRetrieveNits()
+{
+ QFETCH(double, expectedReferenceWhite);
+ KoColorProfileQuery query(PRIMARIES_ITU_R_BT_2020_2_AND_2100_0, TRC_ITU_R_BT_2100_0_PQ);
+ query.hdrReferenceWhite = std::make_optional(expectedReferenceWhite);
+ const KoColorProfile *profile = KoColorSpaceRegistry::instance()->profileFor(query);
+
+ QVERIFY(profile);
+ QVERIFY(profile->hdrReferenceWhite());
+ QVERIFY(qFuzzyCompare(*profile->hdrReferenceWhite(), expectedReferenceWhite));
+}
+
KISTEST_MAIN(TestProfileGeneration)
diff --git a/plugins/color/lcms2engine/tests/TestProfileGeneration.h b/plugins/color/lcms2engine/tests/TestProfileGeneration.h
index fca9d8e942f..bfb4d1ea01f 100644
--- a/plugins/color/lcms2engine/tests/TestProfileGeneration.h
+++ b/plugins/color/lcms2engine/tests/TestProfileGeneration.h
@@ -17,6 +17,9 @@ private Q_SLOTS:
void testCICPwriting_data();
void testCICPwriting();
+ void testRetrieveNits_data();
+ void testRetrieveNits();
+
};
#endif // TESTPROFILEGENERATION_H
diff --git a/plugins/dockers/smallcolorselector/kis_small_color_widget.cc b/plugins/dockers/smallcolorselector/kis_small_color_widget.cc
index cee7e70c8dc..05235630f53 100644
--- a/plugins/dockers/smallcolorselector/kis_small_color_widget.cc
+++ b/plugins/dockers/smallcolorselector/kis_small_color_widget.cc
@@ -107,8 +107,7 @@ struct KisSmallColorWidget::Private {
if (result
&& result->colorModelId() == RGBAColorModelID
&& result->profile()
- && KoColorSpaceRegistry::instance()->p2020PQProfile()
- && result->profile()->uniqueId() == KoColorSpaceRegistry::instance()->p2020PQProfile()->uniqueId()) {
+ && result->profile()->getTransferCharacteristics() == TRC_ITU_R_BT_2100_0_PQ) {
result = KoColorSpaceRegistry::instance()->
colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id(),
@@ -490,7 +489,7 @@ void KisSmallColorWidget::slotDisplayConfigurationChanged()
(cs->colorDepthId() == Float16BitsColorDepthID ||
cs->colorDepthId() == Float32BitsColorDepthID ||
cs->colorDepthId() == Float64BitsColorDepthID ||
- cs->profile()->uniqueId() == KoColorSpaceRegistry::instance()->p2020PQProfile()->uniqueId());
+ cs->profile()->getTransferCharacteristics() == TRC_ITU_R_BT_2100_0_PQ);
}
if (d->dynamicRange) {