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;
61}
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()<3) {
91 //too few colorants.
92 d->primaries = int(primaries);
93 return (primaries);
94 }
96 colorants.append(wp);
99
104
105 for (ColorPrimaries check: primariesList) {
106 colorantsForType(check, wp2, compare);
107 if (compare.size() <3) {
108 KIS_SAFE_ASSERT_RECOVER(compare.size() < 3) { continue; }
109 //too few colorants, skip.
110 }
111 compare.append(wp2);
112 match = true;
113 for (int i=0; i<colorants.size(); i++) {
114 match = std::fabs(colorants[i].x - compare[i].x) < 0.0001
115 && std::fabs(colorants[i].y - compare[i].y) < 0.0001;
116 if (!match) {
117 break;
118 }
119 }
120 if (match) {
121 primaries = check;
122 }
123 }
124 }
125
126 d->primaries = int(primaries);
127 }
128 return ColorPrimaries(d->primaries);
129}
130
132{
133 switch (primaries) {
135 return QStringLiteral("Rec. 709");
137 return QStringLiteral("BT. 470 System M");
139 return QStringLiteral("BT. 470 System B, G");
141 return QStringLiteral("Generic Film");
143 return QStringLiteral("SMPTE 240 M");
145 return QStringLiteral("Rec. 2020");
147 return QStringLiteral("Rec. 601");
149 return QStringLiteral("Display P3");
151 return QStringLiteral("DCI P3");
153 return QStringLiteral("XYZ primaries");
155 return QStringLiteral("EBU Tech 3213 E");
157 return QStringLiteral("ProPhoto");
159 return QStringLiteral("A98");
161 break;
162 }
163 return QStringLiteral("Unspecified");
164}
165
167 KoColorimetryUtils::xy &whitePoint,
169 const bool prequantized)
170{
172 switch (ColorPrimaries(primaries)) {
174 break;
176 // Unquantized.
178 whitePoint = c.white().toxy();
179 colorants = {c.red().toxy(), c.green().toxy(), c.blue().toxy()};
180 //Illuminant C
181 break;
183 // Unquantized.
185 whitePoint = c.white().toxy();
186 colorants = {c.red().toxy(), c.green().toxy(), c.blue().toxy()};
187 break;
190 whitePoint = c.white().toxy();
191 colorants = {c.red().toxy(), c.green().toxy(), c.blue().toxy()};
192 break;
194 whitePoint = {0.3127, 0.3290};
195 colorants = {{0.630, 0.340}};
196 colorants.append({0.310, 0.595});
197 colorants.append({0.155, 0.070});
198 break;
201 whitePoint = c.white().toxy();
202 colorants = {c.red().toxy(), c.green().toxy(), c.blue().toxy()};
203 //Illuminant C
204 break;
206 //prequantization courtesy of Elle Stone.
207
208 if (prequantized) {
209 whitePoint = {0.3127, 0.3290};
210 colorants = {{0.708012540607, 0.291993664388}};
211 colorants.append({0.169991652439, 0.797007778423});
212 colorants.append({0.130997824007, 0.045996550894});
213 } else {
215 whitePoint = c.white().toxy();
216 colorants = {c.red().toxy(), c.green().toxy(), c.blue().toxy()};
217 }
218 break;
221 whitePoint = c.white().toxy();
222 colorants = {c.red().toxy(), c.green().toxy(), c.blue().toxy()};
223 break;
226 whitePoint = c.white().toxy();
227 colorants = {c.red().toxy(), c.green().toxy(), c.blue().toxy()};
228 break;
231 whitePoint = c.white().toxy();
232 colorants = {c.red().toxy(), c.green().toxy(), c.blue().toxy()};
233 break;
235 whitePoint = {0.3127, 0.3290};
236 colorants = {{0.63, 0.34}};
237 colorants.append({0.295, 0.605});
238 colorants.append({0.155, 0.077});
239 break;
241
242 if (prequantized) {
243 //prequantization courtesy of Elle Stone.
244 whitePoint = {0.3457, 0.3585};
245 colorants = {{0.7347, 0.2653}};
246 colorants.append({0.1596, 0.8404});
247 colorants.append({0.0366, 0.0001});
248 } else {
249 whitePoint = {0.3457, 0.3585};
250 colorants = {{0.734699, 0.265301}};
251 colorants.append({0.159597, 0.840403});
252 colorants.append({0.036598, 0.000105});
253 }
254
255 break;
257 if (prequantized) {
258 //prequantization courtesy of Elle Stone.
259 whitePoint = {0.3127, 0.3290};
260 colorants = {{0.639996511, 0.329996864}};
261 colorants.append({0.210005295, 0.710004866});
262 colorants.append({0.149997606, 0.060003644});
263 } else {
265 whitePoint = c.white().toxy();
266 colorants = {c.red().toxy(), c.green().toxy(), c.blue().toxy()};
267 }
268 break;
270 default:
271 if (prequantized) {
272 // Prequantized colorants, courtesy of Elle Stone
273 whitePoint = {0.3127, 0.3290};
274 colorants = {{0.639998686, 0.330010138}};
275 colorants.append({0.300003784, 0.600003357});
276 colorants.append({0.150002046, 0.059997204});
277 } else {
279 whitePoint = c.white().toxy();
280 colorants = {c.red().toxy(), c.green().toxy(), c.blue().toxy()};
281 }
282 break;
283
284 }
285}
286
288{
289 // Parse from an estimated gamma
290 const QVector<double> estimatedTRC = getEstimatedTRC();
291 const double error = 0.0001;
292 // Make sure the TRC is uniform across all channels
293 const bool isUniformTRC = (estimatedTRC[0] == estimatedTRC[1] && estimatedTRC[0] == estimatedTRC[2]);
294 if (d->characteristics == TRC_UNSPECIFIED && isUniformTRC && hasTRC()) {
295 if (isLinear()) {
296 d->characteristics = TRC_LINEAR;
297 } else if (std::fabs(estimatedTRC[0] - (461.0 / 256.0)) < error) {
298 // ICC v2 u8Fixed8Number calculation
299 // Or can be prequantized as 1.80078125, courtesy of Elle Stone
300 d->characteristics = TRC_GAMMA_1_8;
301 } else if (std::fabs(estimatedTRC[0] - (563.0 / 256.0)) < error) {
302 // Or can be prequantized as 2.19921875, courtesy of Elle Stone
303 d->characteristics = TRC_A98;
304 } else if (std::fabs(estimatedTRC[0] - 1.8) < error) {
305 d->characteristics = TRC_GAMMA_1_8;
306 } else if (std::fabs(estimatedTRC[0] - 2.2) < error) {
307 d->characteristics = TRC_ITU_R_BT_470_6_SYSTEM_M;
308 } else if (std::fabs(estimatedTRC[0] - 2.4) < error) {
309 d->characteristics = TRC_GAMMA_2_4;
310 } else if (std::fabs(estimatedTRC[0] - 2.8) < error) {
311 d->characteristics = TRC_ITU_R_BT_470_6_SYSTEM_B_G;
312 } else {
313 // Escort to curve matching if no gamma is matched
314 static constexpr std::array<TransferCharacteristics, 12> trcList = {{TRC_ITU_R_BT_709_5,
324 TRC_A98,
325 TRC_LAB_L}};
326 const auto characteristic =
327 std::find_if(trcList.begin(), trcList.end(), [&](const TransferCharacteristics &check) -> bool {
328 return compareTRC(check, static_cast<float>(error));
329 });
330 if (characteristic != trcList.end()) {
331 d->characteristics = *characteristic;
332 }
333 }
334 }
335 return d->characteristics;
336}
337
339{
340 d->primaries = int(primaries);
341 d->characteristics = curve;
342}
343
345{
346 switch (curve) {
350 return QString("rec 709 trc");
352 return QString("rec 2020 12bit trc");
354 return QString("Gamma 2.2");
356 return QString("Gamma 2.8");
357 case TRC_SMPTE_240M:
358 return QString("SMPTE 240 trc");
359 case TRC_LINEAR:
360 return QString("Linear");
362 return QString("Logarithmic 100");
364 return QString("Logarithmic 100 sqrt10");
366 return QString("IEC 61966 2.4");
369 return QString("sRGB trc");
371 return QString("SMPTE ST 428");
373 return QString("Perceptual Quantizer");
375 return QString("Hybrid Log Gamma");
376 case TRC_GAMMA_1_8:
377 return QString("Gamma 1.8");
378 case TRC_GAMMA_2_4:
379 return QString("Gamma 2.4");
380 case TRC_A98:
381 return QString("Gamma A98");
382 case TRC_PROPHOTO:
383 return QString("ProPhoto trc");
384 case TRC_LAB_L:
385 return QString("Lab L* trc");
386 case TRC_UNSPECIFIED:
387 break;
388 }
389
390 return QString("Unspecified");
391}
392
393void KoColorProfile::setName(const QString &name)
394{
395 d->name = name;
396}
397void KoColorProfile::setInfo(const QString &info)
398{
399 d->info = info;
400}
401void KoColorProfile::setManufacturer(const QString &manufacturer)
402{
403 d->manufacturer = manufacturer;
404}
405void KoColorProfile::setCopyright(const QString &copyright)
406{
407 d->copyright = copyright;
408}
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
static const Colorimetry DCIP3
static const Colorimetry BT2020
static const Colorimetry PAL_M
static const Colorimetry CIEXYZ
static const Colorimetry BT709
static const Colorimetry DisplayP3
static const Colorimetry AdobeRGB
static const Colorimetry NTSC
static const Colorimetry GenericFilm
#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
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 KoColorimetryUtils::xyY getWhitePointxyY() const =0
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
static void colorantsForType(ColorPrimaries primaries, KoColorimetryUtils::xy &whitePoint, QList< KoColorimetryUtils::xy > &colorants, const bool prequantized=false)
colorantsForPrimaries fills a QVector<float> with the xy values of the whitepoint and red,...
virtual bool load()
virtual bool isLinear() const =0
void setManufacturer(const QString &manufacturer)
KoColorProfile(const QString &fileName=QString())
virtual QVector< KoColorimetryUtils::xyY > getColorantsxyY() 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)