Krita Source Code Documentation
Loading...
Searching...
No Matches
KoColorProfile.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2007 Cyrille Berger <cberger@cberger.net>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-or-later
5*/
6
7#include <algorithm>
8#include <array>
9#include <cmath>
10
11#include "KoColorProfile.h"
12#include "DebugPigment.h"
13#include "kis_assert.h"
14
15struct Q_DECL_HIDDEN KoColorProfile::Private {
16 QString name;
17 QString info;
18 QString fileName;
19 QString manufacturer;
20 QString copyright;
21 int primaries {-1};
23};
24
25KoColorProfile::KoColorProfile(const QString &fileName) : d(new Private)
26{
27// dbgPigment <<" Profile filename =" << fileName;
28 d->fileName = fileName;
29}
30
32 : d(new Private(*profile.d))
33{
34}
35
40
42{
43 return false;
44}
45
46bool KoColorProfile::save(const QString & filename)
47{
48 Q_UNUSED(filename);
49 return false;
50}
51
52
53QString KoColorProfile::name() const
54{
55 return d->name;
56}
57
58QString KoColorProfile::info() const
59{
60 return d->info;
62QString KoColorProfile::manufacturer() const
63{
64 return d->manufacturer;
65}
66QString KoColorProfile::copyright() const
67{
68 return d->copyright;
69}
70QString KoColorProfile::fileName() const
71{
72 return d->fileName;
73}
74
75void KoColorProfile::setFileName(const QString &f)
76{
77 d->fileName = f;
78}
79
81{
82 if (d->primaries == -1) {
85
86 bool match = false;
87 if (hasColorants()) {
89 if (col.size()<8) {
91 //too few colorants.
92 d->primaries = int(primaries);
93 return (primaries);
94 }
95 QVector<double> colorants = {wp[0], wp[1], col[0], col[1], col[3], col[4], col[6], col[7]};
96 QVector<double> compare;
97
102
103 for (ColorPrimaries check: primariesList) {
104 colorantsForType(check, compare);
105 if (compare.size() <8) {
106 KIS_SAFE_ASSERT_RECOVER(compare.size() < 8) { continue; }
107 //too few colorants, skip.
108 }
109 match = true;
110 for (int i=0; i<colorants.size(); i++) {
111 match = std::fabs(colorants[i] - compare[i]) < 0.00001;
112 if (!match) {
113 break;
114 }
115 }
116 if (match) {
117 primaries = check;
118 }
119 }
120 }
121
122 d->primaries = int(primaries);
123 }
124 return ColorPrimaries(d->primaries);
125}
126
128{
129 switch (primaries) {
131 return QStringLiteral("Rec. 709");
133 return QStringLiteral("BT. 470 System M");
135 return QStringLiteral("BT. 470 System B, G");
137 return QStringLiteral("Generic Film");
139 return QStringLiteral("SMPTE 240 M");
141 return QStringLiteral("Rec. 2020");
143 return QStringLiteral("Rec. 601");
145 return QStringLiteral("Display P3");
147 return QStringLiteral("DCI P3");
149 return QStringLiteral("XYZ primaries");
151 return QStringLiteral("EBU Tech 3213 E");
153 return QStringLiteral("ProPhoto");
155 return QStringLiteral("A98");
157 break;
158 }
159 return QStringLiteral("Unspecified");
160}
161
163{
164 switch (ColorPrimaries(primaries)) {
166 break;
168 // Unquantized.
169 colorants = {0.310, 0.316};
170 colorants.append({0.67, 0.33});
171 colorants.append({0.21, 0.71});
172 colorants.append({0.14, 0.08});
173 //Illuminant C
174 break;
176 // Unquantized.
177 colorants = {0.3127, 0.3290};
178 colorants.append({0.64, 0.33});
179 colorants.append({0.29, 0.60});
180 colorants.append({0.1500, 0.06});
181 break;
183 colorants = {0.3127, 0.3290};
184 colorants.append({0.630, 0.340});
185 colorants.append({0.310, 0.595});
186 colorants.append({0.155, 0.070});
187 break;
189 colorants = {0.3127, 0.3290};
190 colorants.append({0.630, 0.340});
191 colorants.append({0.310, 0.595});
192 colorants.append({0.155, 0.070});
193 break;
195 colorants = {0.310, 0.316};
196 colorants.append({0.681, 0.319});
197 colorants.append({0.243, 0.692});
198 colorants.append({0.145, 0.049});
199 //Illuminant C
200 break;
202 //prequantization courtesy of Elle Stone.
203 colorants = {0.3127, 0.3290};
204 colorants.append({0.708012540607, 0.291993664388});
205 colorants.append({0.169991652439, 0.797007778423});
206 colorants.append({0.130997824007, 0.045996550894});
207 break;
209 colorants = {1.0/3, 1.0/3};
210 colorants.append({1.0, 0});
211 colorants.append({0, 1.0});
212 colorants.append({0, 0});
213 break;
215 colorants = {0.314, 0.351};
216 colorants.append({0.6800, 0.3200});
217 colorants.append({0.2650, 0.6900});
218 colorants.append({0.1500, 0.0600});
219 break;
221 colorants = {0.3127, 0.3290};
222 colorants.append({0.6800, 0.3200});
223 colorants.append({0.2650, 0.6900});
224 colorants.append({0.1500, 0.0600});
225 break;
227 colorants = {0.3127, 0.3290};
228 colorants.append({0.63, 0.34});
229 colorants.append({0.295, 0.605});
230 colorants.append({0.155, 0.077});
231 break;
233 //prequantization courtesy of Elle Stone.
234 colorants = {0.3457, 0.3585};
235 colorants.append({0.7347, 0.2653});
236 colorants.append({0.1596, 0.8404});
237 colorants.append({0.0366, 0.0001});
238 break;
240 //prequantization courtesy of Elle Stone.
241 colorants = {0.3127, 0.3290};
242 colorants.append({0.639996511, 0.329996864});
243 colorants.append({0.210005295, 0.710004866});
244 colorants.append({0.149997606, 0.060003644});
245 break;
247 default:
248 // Prequantized colorants, courtesy of Elle Stone
249 colorants = {0.3127, 0.3290};
250 colorants.append({0.639998686, 0.330010138});
251 colorants.append({0.300003784, 0.600003357});
252 colorants.append({0.150002046, 0.059997204});
253 break;
254
255 }
256}
257
259{
260 // Parse from an estimated gamma
261 const QVector<double> estimatedTRC = getEstimatedTRC();
262 const double error = 0.0001;
263 // Make sure the TRC is uniform across all channels
264 const bool isUniformTRC = (estimatedTRC[0] == estimatedTRC[1] && estimatedTRC[0] == estimatedTRC[2]);
265 if (d->characteristics == TRC_UNSPECIFIED && isUniformTRC && hasTRC()) {
266 if (isLinear()) {
267 d->characteristics = TRC_LINEAR;
268 } else if (std::fabs(estimatedTRC[0] - (461.0 / 256.0)) < error) {
269 // ICC v2 u8Fixed8Number calculation
270 // Or can be prequantized as 1.80078125, courtesy of Elle Stone
271 d->characteristics = TRC_GAMMA_1_8;
272 } else if (std::fabs(estimatedTRC[0] - (563.0 / 256.0)) < error) {
273 // Or can be prequantized as 2.19921875, courtesy of Elle Stone
274 d->characteristics = TRC_A98;
275 } else if (std::fabs(estimatedTRC[0] - 1.8) < error) {
276 d->characteristics = TRC_GAMMA_1_8;
277 } else if (std::fabs(estimatedTRC[0] - 2.2) < error) {
278 d->characteristics = TRC_ITU_R_BT_470_6_SYSTEM_M;
279 } else if (std::fabs(estimatedTRC[0] - 2.4) < error) {
280 d->characteristics = TRC_GAMMA_2_4;
281 } else if (std::fabs(estimatedTRC[0] - 2.8) < error) {
282 d->characteristics = TRC_ITU_R_BT_470_6_SYSTEM_B_G;
283 } else {
284 // Escort to curve matching if no gamma is matched
285 static constexpr std::array<TransferCharacteristics, 12> trcList = {{TRC_ITU_R_BT_709_5,
295 TRC_A98,
296 TRC_LAB_L}};
297 const auto characteristic =
298 std::find_if(trcList.begin(), trcList.end(), [&](const TransferCharacteristics &check) -> bool {
299 return compareTRC(check, static_cast<float>(error));
300 });
301 if (characteristic != trcList.end()) {
302 d->characteristics = *characteristic;
303 }
304 }
305 }
306 return d->characteristics;
307}
308
310{
311 d->primaries = int(primaries);
312 d->characteristics = curve;
313}
314
316{
317 switch (curve) {
321 return QString("rec 709 trc");
323 return QString("rec 2020 12bit trc");
325 return QString("Gamma 2.2");
327 return QString("Gamma 2.8");
328 case TRC_SMPTE_240M:
329 return QString("SMPTE 240 trc");
330 case TRC_LINEAR:
331 return QString("Linear");
333 return QString("Logarithmic 100");
335 return QString("Logarithmic 100 sqrt10");
337 return QString("IEC 61966 2.4");
340 return QString("sRGB trc");
342 return QString("SMPTE ST 428");
344 return QString("Perceptual Quantizer");
346 return QString("Hybrid Log Gamma");
347 case TRC_GAMMA_1_8:
348 return QString("Gamma 1.8");
349 case TRC_GAMMA_2_4:
350 return QString("Gamma 2.4");
351 case TRC_A98:
352 return QString("Gamma A98");
353 case TRC_PROPHOTO:
354 return QString("ProPhoto trc");
355 case TRC_LAB_L:
356 return QString("Lab L* trc");
357 case TRC_UNSPECIFIED:
358 break;
359 }
360
361 return QString("Unspecified");
362}
363
364void KoColorProfile::setName(const QString &name)
365{
366 d->name = name;
367}
368void KoColorProfile::setInfo(const QString &info)
369{
370 d->info = info;
371}
372void KoColorProfile::setManufacturer(const QString &manufacturer)
373{
374 d->manufacturer = manufacturer;
375}
376void KoColorProfile::setCopyright(const QString &copyright)
377{
378 d->copyright = copyright;
379}
ColorPrimaries
The colorPrimaries enum Enum of colorants, follows ITU H.273 for values 0 to 255, and has extra known...
@ PRIMARIES_ITU_R_BT_2020_2_AND_2100_0
@ PRIMARIES_ITU_R_BT_470_6_SYSTEM_M
@ PRIMARIES_EBU_Tech_3213_E
@ PRIMARIES_UNSPECIFIED
@ PRIMARIES_ITU_R_BT_470_6_SYSTEM_B_G
@ PRIMARIES_SMPTE_240M
@ PRIMARIES_ITU_R_BT_601_6
@ PRIMARIES_SMPTE_RP_431_2
@ PRIMARIES_PROPHOTO
@ PRIMARIES_ADOBE_RGB_1998
@ PRIMARIES_GENERIC_FILM
@ PRIMARIES_SMPTE_EG_432_1
@ PRIMARIES_ITU_R_BT_709_5
@ PRIMARIES_SMPTE_ST_428_1
TransferCharacteristics
The transferCharacteristics enum Enum of transfer characteristics, follows ITU H.273 for values 0 to ...
@ TRC_IEC_61966_2_4
@ TRC_ITU_R_BT_2020_2_10bit
@ TRC_LOGARITHMIC_100
@ TRC_ITU_R_BT_470_6_SYSTEM_M
@ TRC_ITU_R_BT_470_6_SYSTEM_B_G
@ TRC_ITU_R_BT_1361
@ TRC_ITU_R_BT_2100_0_HLG
@ TRC_ITU_R_BT_2100_0_PQ
@ TRC_ITU_R_BT_601_6
@ TRC_IEC_61966_2_1
@ TRC_ITU_R_BT_709_5
@ TRC_SMPTE_ST_428_1
@ TRC_LOGARITHMIC_100_sqrt10
@ TRC_ITU_R_BT_2020_2_12bit
#define KIS_SAFE_ASSERT_RECOVER(cond)
Definition kis_assert.h:126
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129
static void colorantsForType(ColorPrimaries primaries, QVector< double > &colorants)
colorantsForPrimaries fills a QVector<float> with the xy values of the whitepoint and red,...
virtual QVector< qreal > getColorantsxyY() const =0
void setFileName(const QString &filename)
void setCopyright(const QString &copyright)
Private *const d
static QString getTransferCharacteristicName(TransferCharacteristics curve)
getTransferCharacteristicName
static QString getColorPrimariesName(ColorPrimaries primaries)
getColorPrimariesName
virtual bool save(const QString &fileName)
virtual ColorPrimaries getColorPrimaries() const
getColorPrimaries
void setName(const QString &name)
virtual QVector< qreal > getEstimatedTRC() const =0
virtual bool hasColorants() const =0
virtual bool load()
virtual bool isLinear() const =0
void setManufacturer(const QString &manufacturer)
KoColorProfile(const QString &fileName=QString())
virtual QVector< qreal > getWhitePointxyY() const =0
virtual bool hasTRC() const =0
virtual TransferCharacteristics getTransferCharacteristics() const
getTransferCharacteristics This function should be subclassed at some point so we can get the value f...
void setCharacteristics(ColorPrimaries primaries, TransferCharacteristics curve)
setCharacteristics ideally, we'd read this from the icc profile curve, but that can be tricky,...
virtual ~KoColorProfile()
void setInfo(const QString &info)