Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_advanced_color_space_selector.cc
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2007 Cyrille Berger <cberger@cberger.net>
3 * SPDX-FileCopyrightText: 2011 Boudewijn Rempt <boud@valdyas.org>
4 * SPDX-FileCopyrightText: 2011 Srikanth Tiyyagura <srikanth.tulasiram@gmail.com>
5 * SPDX-FileCopyrightText: 2015 Wolthera van Hövell tot Westerflier <griffinvalley@gmail.com>
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
11
12#include <KoFileDialog.h>
13#include <KoColorProfile.h>
14#include <KoColorSpace.h>
16#include <KoColorSpaceEngine.h>
18#include <KoID.h>
19
20#include <KoConfig.h>
21#include <kis_icon.h>
22
23#include <QStandardPaths>
24#include <QTextBrowser>
25#include <QScrollBar>
26
27#include <KoResourcePaths.h>
28
29#include <QUrl>
30
31#include "ui_wdgcolorspaceselectoradvanced.h"
32
33#include <kis_debug.h>
34
35#include <kstandardguiitem.h>
36
38 Ui_WdgColorSpaceSelectorAdvanced* colorSpaceSelector;
39 QString knsrcFile;
40};
41
43 : QDialog(parent)
44 , d(new Private)
45{
46 setWindowTitle(caption);
47
48 d->colorSpaceSelector = new Ui_WdgColorSpaceSelectorAdvanced;
49 d->colorSpaceSelector->setupUi(this);
50
51 {
52 QSizePolicy policy = d->colorSpaceSelector->TongueWidget->sizePolicy();
53 policy.setHeightForWidth(true);
54 d->colorSpaceSelector->TongueWidget->setSizePolicy(policy);
55 }
56
57 {
58 QSizePolicy policy = d->colorSpaceSelector->TRCwidget->sizePolicy();
59 policy.setHeightForWidth(true);
60 d->colorSpaceSelector->TRCwidget->setSizePolicy(policy);
61 }
62
64 fillCmbDepths(d->colorSpaceSelector->cmbColorModels->currentItem());
65
66 d->colorSpaceSelector->bnInstallProfile->setIcon(koIcon("document-import-16"));
67 d->colorSpaceSelector->bnInstallProfile->setText(i18n("Import profile"));
68
69 connect(d->colorSpaceSelector->cmbColorModels, SIGNAL(activated(KoID)),
70 this, SLOT(fillCmbDepths(KoID)));
71 connect(d->colorSpaceSelector->cmbColorDepth, SIGNAL(activated(KoID)),
72 this, SLOT(fillLstProfiles()));
73 connect(d->colorSpaceSelector->cmbColorModels, SIGNAL(activated(KoID)),
74 this, SLOT(fillLstProfiles()));
75 connect(d->colorSpaceSelector->lstProfile, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
76 this, SLOT(colorSpaceChanged()));
77 connect(this, SIGNAL(selectionChanged(bool)),
78 this, SLOT(fillDescription()));
79 connect(this, SIGNAL(selectionChanged(bool)), d->colorSpaceSelector->TongueWidget, SLOT(repaint()));
80 connect(this, SIGNAL(selectionChanged(bool)), d->colorSpaceSelector->TRCwidget, SLOT(repaint()));
81
82 connect(d->colorSpaceSelector->bnInstallProfile, SIGNAL(clicked()), this, SLOT(installProfile()));
83
84 KGuiItem::assign(d->colorSpaceSelector->bnOK->button(QDialogButtonBox::Ok), KStandardGuiItem::ok());
85 KGuiItem::assign(d->colorSpaceSelector->bnOK->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel());
86 connect(d->colorSpaceSelector->bnOK, SIGNAL(accepted()), this, SLOT(accept()));
87 connect(d->colorSpaceSelector->bnOK, SIGNAL(rejected()), this, SLOT(reject()));
88
90}
91
97
99{
100 d->colorSpaceSelector->lstProfile->blockSignals(true);
101 const QString colorSpaceId = KoColorSpaceRegistry::instance()->colorSpaceId(d->colorSpaceSelector->cmbColorModels->currentItem(), d->colorSpaceSelector->cmbColorDepth->currentItem());
102 const QString defaultProfileName = KoColorSpaceRegistry::instance()->defaultProfileForColorSpace(colorSpaceId);
103 d->colorSpaceSelector->lstProfile->clear();
104
106 QStringList profileNames;
107 Q_FOREACH (const KoColorProfile *profile, profileList) {
108 profileNames.append(profile->name());
109 }
110 std::sort(profileNames.begin(), profileNames.end());
111 QListWidgetItem *defaultProfile = new QListWidgetItem;
112 defaultProfile->setText(defaultProfileName + " " + i18nc("This is appended to the color profile which is the default for the given colorspace and bit-depth","(Default)"));
113 Q_FOREACH (QString stringName, profileNames) {
114 if (stringName == defaultProfileName) {
115 d->colorSpaceSelector->lstProfile->addItem(defaultProfile);
116 } else {
117 d->colorSpaceSelector->lstProfile->addItem(stringName);
118 }
119 }
120 d->colorSpaceSelector->lstProfile->setCurrentItem(defaultProfile);
121 d->colorSpaceSelector->lstProfile->blockSignals(false);
123}
124
126{
127 KoID activeDepth = d->colorSpaceSelector->cmbColorDepth->currentItem();
128 d->colorSpaceSelector->cmbColorDepth->clear();
130 QList<KoID> sortedDepths;
131 if (depths.contains(Integer8BitsColorDepthID)) {
132 sortedDepths << Integer8BitsColorDepthID;
133 }
134 if (depths.contains(Integer16BitsColorDepthID)) {
135 sortedDepths << Integer16BitsColorDepthID;
136 }
137 if (depths.contains(Float16BitsColorDepthID)) {
138 sortedDepths << Float16BitsColorDepthID;
139 }
140 if (depths.contains(Float32BitsColorDepthID)) {
141 sortedDepths << Float32BitsColorDepthID;
142 }
143 if (depths.contains(Float64BitsColorDepthID)) {
144 sortedDepths << Float64BitsColorDepthID;
145 }
146
147 d->colorSpaceSelector->cmbColorDepth->setIDList(sortedDepths);
148 if (sortedDepths.contains(activeDepth)) {
149 d->colorSpaceSelector->cmbColorDepth->setCurrent(activeDepth);
150 }
151}
152
154{
155 QString notApplicable = i18nc("Not Applicable, used where there's no colorants or gamma curve found","N/A");
156 QString notApplicableTooltip = i18nc("@info:tooltip","This profile has no colorants.");
157 QString profileName = i18nc("Shows up instead of the name when there's no profile","No Profile Found");
158 QString whatIsColorant = i18n("Colorant in d50-adapted xyY.");
159 //set colorants
160 const QString colorSpaceId = KoColorSpaceRegistry::instance()->colorSpaceId(d->colorSpaceSelector->cmbColorModels->currentItem(), d->colorSpaceSelector->cmbColorDepth->currentItem());
162
163 if (!profileList.isEmpty()) {
164 profileName = currentColorSpace()->profile()->name();
165 if (currentColorSpace()->profile()->hasColorants()){
166 QVector <KoColorimetryUtils::xyY> colorants = currentColorSpace()->profile()->getColorantsxyY();
168 //QString text = currentColorSpace()->profile()->info() + " =" +
169 d->colorSpaceSelector->lblXYZ_W->setText(nameWhitePoint(whitepoint));
170 d->colorSpaceSelector->lblXYZ_W->setToolTip(QString::number(whitepoint.x, 'f', 4) + ", " + QString::number(whitepoint.y, 'f', 4) + ", " + QString::number(whitepoint.Y, 'f', 4));
171 d->colorSpaceSelector->TongueWidget->setToolTip("<html><head/><body><table><tr><th colspan='4'>"+i18nc("@info:tooltip","This profile has the following xyY colorants:")+"</th></tr><tr><td>"+
172 i18n("Red:") +"</td><td>"+QString::number(colorants[0].x, 'f', 4) + "</td><td>" + QString::number(colorants[0].y, 'f', 4) + "</td><td>" + QString::number(colorants[0].Y, 'f', 4)+"</td></tr><tr><td>"+
173 i18n("Green:")+"</td><td>"+QString::number(colorants[1].x, 'f', 4) + "</td><td>" + QString::number(colorants[1].y, 'f', 4) + "</td><td>" + QString::number(colorants[1].Y, 'f', 4)+"</th></tr><tr><td>"+
174 i18n("Blue:") +"</td><td>"+QString::number(colorants[2].x, 'f', 4) + "</td><td>" + QString::number(colorants[2].y, 'f', 4) + "</td><td>" + QString::number(colorants[2].Y, 'f', 4)+"</th></tr></table></body></html>");
175 } else {
177 d->colorSpaceSelector->lblXYZ_W->setText(nameWhitePoint(whitepoint2));
178 d->colorSpaceSelector->lblXYZ_W->setToolTip(QString::number(whitepoint2.x, 'f', 4) + ", " + QString::number(whitepoint2.y, 'f', 4) + ", " + QString::number(whitepoint2.Y, 'f', 4));
179 d->colorSpaceSelector->TongueWidget->setToolTip(notApplicableTooltip);
180 }
181 } else {
182 d->colorSpaceSelector->lblXYZ_W->setText(notApplicable);
183 d->colorSpaceSelector->lblXYZ_W->setToolTip(notApplicableTooltip);
184 d->colorSpaceSelector->TongueWidget->setToolTip(notApplicableTooltip);
185 }
186
187 //set TRC
188 QVector <double> estimatedTRC(3);
189 QString estimatedGamma = i18nc("Estimated Gamma indicates how the TRC (Tone Response Curve or Tone Reproduction Curve) is bent. A Gamma of 1.0 means linear.", "<b>Estimated Gamma</b>: ");
190 QString estimatedsRGB = i18nc("This is for special Gamma types that LCMS cannot differentiate between", "<b>Estimated Gamma</b>: sRGB, L* or rec709 TRC");
191 QString whatissRGB = i18nc("@info:tooltip","The Tone Response Curve of this color space is either sRGB, L* or rec709 TRC.");
192 QString currentModelStr = d->colorSpaceSelector->cmbColorModels->currentItem().id();
193
194 if (profileList.isEmpty()) {
195 d->colorSpaceSelector->TongueWidget->setProfileDataAvailable(false);
196 d->colorSpaceSelector->TRCwidget->setProfileDataAvailable(false);
197 }
198 else if (currentModelStr == "RGBA") {
199 QVector <KoColorimetryUtils::xyY> colorants = currentColorSpace()->profile()->getColorantsxyY();
201 d->colorSpaceSelector->TongueWidget->setRGBData(whitepoint, colorants);
202 d->colorSpaceSelector->TongueWidget->setGamut(currentColorSpace()->gamutXYY());
204 QString detCharacteristicsStr =
206 estimatedTRC = currentColorSpace()->profile()->getEstimatedTRC();
207 QString estimatedCurve = " Estimated curve: ";
208 QPolygonF redcurve;
209 QPolygonF greencurve;
210 QPolygonF bluecurve;
211 if (currentColorSpace()->profile()->hasTRC()){
212 for (int i=0; i<=10; i++) {
213 QVector <qreal> linear(3);
214 linear.fill(i*0.1);
216 estimatedCurve = estimatedCurve + ", " + QString::number(linear[0]);
217 QPointF tonepoint(linear[0],i*0.1);
218 redcurve<<tonepoint;
219 tonepoint.setX(linear[1]);
220 greencurve<<tonepoint;
221 tonepoint.setX(linear[2]);
222 bluecurve<<tonepoint;
223 }
224 d->colorSpaceSelector->TRCwidget->setRGBCurve(redcurve, greencurve, bluecurve);
225 } else {
226 QPolygonF curve = currentColorSpace()->estimatedTRCXYY();
227 int numPoints = curve.size() / 3;
228 for (int i = 0; i < numPoints; i++) {
229 redcurve << curve.at(i);
230 greencurve << curve.at(i + numPoints);
231 bluecurve << curve.at(i + 2*numPoints);
232 }
233 d->colorSpaceSelector->TRCwidget->setRGBCurve(redcurve, greencurve, bluecurve);
234 }
235
236 if (estimatedTRC[0] != -1 && currentColorSpace()->profile()->hasTRC()) {
237 d->colorSpaceSelector->TRCwidget->setToolTip(
238 "<html><head/><body>" + estimatedGamma + detCharacteristicsStr + "<br/>"
239 + QString::number(estimatedTRC[0]) + "," + QString::number(estimatedTRC[1]) + ","
240 + QString::number(estimatedTRC[2]) + "<br/>" + estimatedCurve + "</body></html>");
241 } else {
242 d->colorSpaceSelector->TRCwidget->setToolTip("<html><head/><body>" + estimatedGamma + detCharacteristicsStr
243 + "<br/>" + estimatedCurve + "</body></html>");
244 }
245 }
246 else if (currentModelStr == "GRAYA") {
248 d->colorSpaceSelector->TongueWidget->setGrayData(whitepoint);
249 d->colorSpaceSelector->TongueWidget->setGamut(currentColorSpace()->gamutXYY());
251 QString detCharacteristicsStr =
253 estimatedTRC = currentColorSpace()->profile()->getEstimatedTRC();
254 QString estimatedCurve = " Estimated curve: ";
255 QPolygonF tonecurve;
256 if (currentColorSpace()->profile()->hasTRC()){
257 for (int i=0; i<=10; i++) {
258 QVector <qreal> linear(3);
259 linear.fill(i*0.1);
261 estimatedCurve = estimatedCurve + ", " + QString::number(linear[0]);
262 QPointF tonepoint(linear[0],i*0.1);
263 tonecurve<<tonepoint;
264 }
265 } else {
266 d->colorSpaceSelector->TRCwidget->setProfileDataAvailable(false);
267 }
268 d->colorSpaceSelector->TRCwidget->setGreyscaleCurve(tonecurve);
269 if (estimatedTRC[0] != -1 && currentColorSpace()->profile()->hasTRC()) {
270 d->colorSpaceSelector->TRCwidget->setToolTip("<html><head/><body>" + estimatedGamma + detCharacteristicsStr
271 + "<br/>" + QString::number(estimatedTRC[0]) + "<br/>"
272 + estimatedCurve + "</body></html>");
273 } else {
274 d->colorSpaceSelector->TRCwidget->setToolTip("<html><head/><body>" + estimatedGamma + detCharacteristicsStr
275 + "<br/>" + estimatedCurve + "</body></html>");
276 }
277 }
278 else if (currentModelStr == "CMYKA") {
280 d->colorSpaceSelector->TongueWidget->setCMYKData(whitepoint);
281 d->colorSpaceSelector->TongueWidget->setGamut(currentColorSpace()->gamutXYY());
282 QString estimatedCurve = " Estimated curve: ";
283 QPolygonF tonecurve;
284 QPolygonF cyancurve;
285 QPolygonF magentacurve;
286 QPolygonF yellowcurve;
287 if (currentColorSpace()->profile()->hasTRC()){
288 for (int i=0; i<=10; i++) {
289 QVector <qreal> linear(3);
290 linear.fill(i*0.1);
292 estimatedCurve = estimatedCurve + ", " + QString::number(linear[0]);
293 QPointF tonepoint(linear[0],i*0.1);
294 tonecurve<<tonepoint;
295 }
296 d->colorSpaceSelector->TRCwidget->setGreyscaleCurve(tonecurve);
297 } else {
298 QPolygonF curve = currentColorSpace()->estimatedTRCXYY();
299 int numPoints = curve.size() / 4;
300 for (int i = 0; i < numPoints; i++) {
301 cyancurve << curve.at(i);
302 magentacurve << curve.at(i + numPoints);
303 yellowcurve << curve.at(i + 2*numPoints);
304 tonecurve << curve.at(i + 3*numPoints);
305 }
306 d->colorSpaceSelector->TRCwidget->setCMYKCurve(cyancurve, magentacurve, yellowcurve, tonecurve);
307 }
308 d->colorSpaceSelector->TRCwidget->setToolTip(i18nc("@info:tooltip","Estimated Gamma cannot be retrieved for CMYK."));
309 }
310 else if (currentModelStr == "XYZA") {
311 QString estimatedCurve = " Estimated curve: ";
312 estimatedTRC = currentColorSpace()->profile()->getEstimatedTRC();
313 QPolygonF tonecurve;
314 if (currentColorSpace()->profile()->hasTRC()){
315 for (int i=0; i<=10; i++) {
316 QVector <qreal> linear(3);
317 linear.fill(i*0.1);
319 estimatedCurve = estimatedCurve + ", " + QString::number(linear[0]);
320 QPointF tonepoint(linear[0],i*0.1);
321 tonecurve<<tonepoint;
322 }
323 d->colorSpaceSelector->TRCwidget->setGreyscaleCurve(tonecurve);
324 } else {
325 d->colorSpaceSelector->TRCwidget->setProfileDataAvailable(false);
326 }
328 d->colorSpaceSelector->TongueWidget->setXYZData(whitepoint);
329 d->colorSpaceSelector->TongueWidget->setGamut(currentColorSpace()->gamutXYY());
330 d->colorSpaceSelector->TRCwidget->setToolTip("<html><head/><body>"+estimatedGamma + QString::number(estimatedTRC[0])+"< br />"+estimatedCurve+"</body></html>");
331 }
332 else if (currentModelStr == "LABA") {
333 estimatedTRC = currentColorSpace()->profile()->getEstimatedTRC();
334 QString estimatedCurve = " Estimated curve: ";
335 QPolygonF tonecurve;
336 if (currentColorSpace()->profile()->hasTRC()){
337 for (int i=0; i<=10; i++) {
338 QVector <qreal> linear(3);
339 linear.fill(i*0.1);
341 estimatedCurve = estimatedCurve + ", " + QString::number(linear[0]);
342 QPointF tonepoint(linear[0],i*0.1);
343 tonecurve<<tonepoint;
344 }
345 d->colorSpaceSelector->TRCwidget->setGreyscaleCurve(tonecurve);
346 } else {
347 d->colorSpaceSelector->TRCwidget->setProfileDataAvailable(false);
348 }
350 d->colorSpaceSelector->TongueWidget->setLABData(whitepoint);
351 d->colorSpaceSelector->TongueWidget->setGamut(currentColorSpace()->gamutXYY());
352 d->colorSpaceSelector->TRCwidget->setToolTip("<html><head/><body>"+i18nc("@info:tooltip","This is assumed to be the L * TRC. ")+"<br />"+estimatedCurve+"</body></html>");
353 }
354 else if (currentModelStr == "YCbCrA") {
356 d->colorSpaceSelector->TongueWidget->setYCbCrData(whitepoint);
357 QString estimatedCurve = " Estimated curve: ";
358 QPolygonF tonecurve;
359 if (currentColorSpace()->profile()->hasTRC()){
360 for (int i=0; i<=10; i++) {
361 QVector <qreal> linear(3);
362 linear.fill(i*0.1);
364 estimatedCurve = estimatedCurve + ", " + QString::number(linear[0]);
365 QPointF tonepoint(linear[0],i*0.1);
366 tonecurve<<tonepoint;
367 }
368 d->colorSpaceSelector->TRCwidget->setGreyscaleCurve(tonecurve);
369 } else {
370 d->colorSpaceSelector->TRCwidget->setProfileDataAvailable(false);
371 }
372 d->colorSpaceSelector->TongueWidget->setGamut(currentColorSpace()->gamutXYY());
373 d->colorSpaceSelector->TRCwidget->setToolTip(i18nc("@info:tooltip","Estimated Gamma cannot be retrieved for YCbCr."));
374 }
375
376 d->colorSpaceSelector->textProfileDescription->clear();
377 if (!profileList.isEmpty()) {
378 d->colorSpaceSelector->textProfileDescription->append(
379 QString("<h3>%1</h3>").arg(i18nc("About <Profilename>", "About %1/%2", currentColorSpace()->name().toHtmlEscaped(), profileName.toHtmlEscaped())));
380 d->colorSpaceSelector->textProfileDescription->append(
381 QString("<p>%1</p>").arg(i18nc("ICC profile version", "ICC Version: %1", QString::number(currentColorSpace()->profile()->version()))));
382 if (currentColorSpace()->profile()->manufacturer() != profileName)
383 d->colorSpaceSelector->textProfileDescription->append(
384 QString("<p>%1</p>").arg(i18nc("Who made the profile?", "Manufacturer: %1", currentColorSpace()->profile()->manufacturer())));
385 d->colorSpaceSelector->textProfileDescription->append(
386 QString("<p>%1</p>")
387 .arg(i18nc("What is the copyright? These are from embedded strings from the icc profile, so they "
388 "default to english.",
389 "Copyright: %1",
390 currentColorSpace()->profile()->copyright().toHtmlEscaped())));
391 } else {
392 d->colorSpaceSelector->textProfileDescription->append(QString("<h3>%1</h3>").arg(profileName.toHtmlEscaped()));
393 }
394
395 if (currentModelStr == "RGBA") {
396 d->colorSpaceSelector->textProfileDescription->append("<p>"+i18nc("If the selected model is RGB",
397 "<b><a href=\"https://en.wikipedia.org/wiki/RGB_color_space\">RGB (Red, Green, Blue)</a></b>, is the color model used by screens and other light-based media.<br/>"
398 "RGB is an additive color model: adding colors together makes them brighter. This color "
399 "model is the most extensive of all color models, and is recommended as a model for painting,"
400 "that you can later convert to other spaces. RGB is also the recommended colorspace for HDR editing.")+"</p>");
401 } else if (currentModelStr == "CMYKA") {
402 d->colorSpaceSelector->textProfileDescription->append("<p>"+i18nc("If the selected model is CMYK",
403 "<b><a href=\"https://en.wikipedia.org/wiki/CMYK_color_model\">CMYK (Cyan, Magenta, Yellow, Key)</a></b>, "
404 "is the model used by printers and other ink-based media.<br/>"
405 "CMYK is a subtractive model, meaning that adding colors together will turn them darker. Because of CMYK "
406 "profiles being very specific per printer, it is recommended to work in RGB space, and then later convert "
407 "to a CMYK profile, preferably one delivered by your printer. <br/>"
408 "CMYK is <b>not</b> recommended for painting."
409 "Unfortunately, Krita cannot retrieve colorants or the TRC for this space.")+"</p>");
410 } else if (currentModelStr == "XYZA") {
411 d->colorSpaceSelector->textProfileDescription->append("<p>"+i18nc("If the selected model is XYZ",
412 "<b><a href=\"https://en.wikipedia.org/wiki/CIE_1931_color_space\">CIE XYZ</a></b>"
413 "is the space determined by the CIE as the space that encompasses all other colors, and used to "
414 "convert colors between profiles. XYZ is an additive color model, meaning that adding colors together "
415 "makes them brighter. XYZ is <b>not</b> recommended for painting, but can be useful to encode in. The Tone Response "
416 "Curve is assumed to be linear.")+"</p>");
417 } else if (currentModelStr == "GRAYA") {
418 d->colorSpaceSelector->textProfileDescription->append("<p>"+i18nc("If the selected model is Grayscale",
419 "<b><a href=\"https://en.wikipedia.org/wiki/Grayscale\">Grayscale</a></b> only allows for "
420 "gray values and transparent values. Grayscale images use half "
421 "the memory and disk space compared to an RGB image of the same bit-depth.<br/>"
422 "Grayscale is useful for inking and grayscale images. In "
423 "Krita, you can mix Grayscale and RGB layers in the same image.")+"</p>");
424 } else if (currentModelStr == "LABA") {
425 d->colorSpaceSelector->textProfileDescription->append("<p>"+i18nc("If the selected model is LAB",
426 "<b><a href=\"https://en.wikipedia.org/wiki/Lab_color_space\">L*a*b</a></b>. <b>L</b> stands for Lightness, "
427 "the <b>a</b> and <b>b</b> components represent color channels.<br/>"
428 "L*a*b is a special model for color correction. It is based on human perception, meaning that it "
429 "tries to encode the difference in lightness, red-green balance and yellow-blue balance. "
430 "This makes it useful for color correction, but the vast majority of color maths in the blending "
431 "modes do <b>not</b> work as expected here.<br/>"
432 "Similarly, Krita does not support HDR in LAB, meaning that HDR images converted to LAB lose color "
433 "information. This colorspace is <b>not</b> recommended for painting, nor for export, "
434 "but best as a space to do post-processing in. The TRC is assumed to be the L* TRC.")+"</p>");
435 } else if (currentModelStr == "YCbCrA") {
436 d->colorSpaceSelector->textProfileDescription->append("<p>"+i18nc("If the selected model is YCbCr",
437 "<b><a href=\"https://en.wikipedia.org/wiki/YCbCr\">YCbCr (Luma, Blue Chroma, Red Chroma)</a></b>, is a "
438 "model designed for video encoding. It is based on human perception, meaning that it tries to "
439 "encode the difference in lightness, red-green balance and yellow-blue balance. Chroma in "
440 "this case is then a word indicating a special type of saturation, in these cases the saturation "
441 "of Red and Blue, of which the desaturated equivalents are Green and Yellow respectively.")+"</p>");
442 }
443
444 QString currentDepthStr = d->colorSpaceSelector->cmbColorDepth->currentItem().id();
445
446 if (currentDepthStr == "U8") {
447 d->colorSpaceSelector->textProfileDescription->append("<p>"+i18nc("When the selected Bitdepth is 8",
448 "<b>8 bit integer</b>: The default number of colors per channel. Each channel will have 256 values available, "
449 "leading to a total amount of colors of 256 to the power of the number of channels. Recommended to use for images intended for the web, "
450 "or otherwise simple images.")+"</p>");
451 }
452 else if (currentDepthStr == "U16") {
453 d->colorSpaceSelector->textProfileDescription->append("<p>"+i18nc("When the selected Bitdepth is 16",
454 "<b>16 bit integer</b>: Also known as 'deep color'. 16 bit is ideal for editing images with a linear TRC, large "
455 "color space, or just when you need more precise color blending. This does take twice as much space on "
456 "the RAM and hard-drive than any given 8 bit image of the same properties, and for some devices it "
457 "takes much more processing power. We recommend watching the RAM usage of the file carefully, or "
458 "otherwise use 8 bit if your computer slows down. Take care to disable conversion optimization "
459 "when converting from 16 bit/channel to 8 bit/channel.")+"</p>");
460 }
461 else if (currentDepthStr == "F16") {
462 d->colorSpaceSelector->textProfileDescription->append("<p>"+i18nc("When the selected Bitdepth is 16 bit float",
463 "<b>16 bit floating point</b>: Also known as 'Half Floating Point', and the standard in VFX industry images. "
464 "16 bit float is ideal for editing images with a linear Tone Response Curve, large color space, or just when you need "
465 "more precise color blending. It being floating point is an absolute requirement for Scene Referred "
466 "(HDR) images. This does take twice as much space on the RAM and hard-drive than any given 8 bit image "
467 "of the same properties, and for some devices it takes much more processing power. We recommend watching "
468 "the RAM usage of the file carefully, or otherwise use 8 bit if your computer slows down.")+"</p>");
469 }
470 else if (currentDepthStr == "F32") {
471 d->colorSpaceSelector->textProfileDescription->append("<p>"+i18nc("When the selected Bitdepth is 32bit float",
472 "<b>32 bit float point</b>: Also known as 'Full Floating Point'. 32 bit float is ideal for editing images "
473 "with a linear TRC, large color space, or just when you need more precise color blending. It being "
474 "floating point is an absolute requirement for Scene Referred (HDR) images. This does take four times "
475 "as much space on the RAM and hard-drive than any given 8 bit image of the same properties, and for "
476 "some devices it takes much more processing power. We recommend watching the RAM usage of the file "
477 "carefully, or otherwise use 8 bit if your computer slows down.")+"</p>");
478 }
479 else if (currentDepthStr == "F64") {
480 d->colorSpaceSelector->textProfileDescription->append("<p>"+i18nc("When the selected Bitdepth is 64bit float, but this isn't actually available in Krita at the moment.",\
481 "<b>64 bit float point</b>: 64 bit float is as precise as it gets in current technology, and this depth is used "
482 "most of the time for images that are generated or used as an input for software. It being floating point "
483 "is an absolute requirement for Scene Referred (HDR) images. This does take eight times as much space on "
484 "the RAM and hard-drive than any given 8 bit image of the same properties, and for some devices it takes "
485 "much more processing power. We recommend watching the RAM usage of the file carefully, or otherwise use "
486 "8 bit if your computer slows down.")+"</p>");
487 }
488 if (profileList.isEmpty()==false) {
489 QString possibleConversionIntents = "<p>"+i18n("The following conversion intents are possible: ")+"<ul>";
490 if (currentColorSpace()->profile()->supportsPerceptual()){
491 possibleConversionIntents += "<li>"+i18n("Perceptual")+"</li>";
492 }
493 if (currentColorSpace()->profile()->supportsRelative()){
494 possibleConversionIntents += "<li>"+i18n("Relative Colorimetric")+"</li>";
495 }
496 if (currentColorSpace()->profile()->supportsAbsolute()){
497 possibleConversionIntents += "<li>"+i18n("Absolute Colorimetric")+"</li>";
498 }
499 if (currentColorSpace()->profile()->supportsSaturation()){
500 possibleConversionIntents += "<li>"+i18nc("ICC profile rendering intent", "Saturation")+"</li>";
501 }
502 possibleConversionIntents += "</ul></ul></p>";
503 d->colorSpaceSelector->textProfileDescription->append(possibleConversionIntents);
504 }
505 if (profileName.contains("-elle-")) {
506
507 d->colorSpaceSelector->textProfileDescription->append("<p>"+i18nc("These are Elle Stone's notes on her profiles that we ship.",
508 "<p><b>Extra notes on profiles by Elle Stone:</b></p>"
509 "<p><i>Krita comes with a number of high quality profiles created by "
510 "<a href=\"https://ninedegreesbelow.com\">Elle Stone</a>. This is a summary. Please check "
511 "<a href=\"https://ninedegreesbelow.com/photography/lcms-make-icc-profiles.html\">the full documentation</a> as well.</i></p>"));
512
513 if (profileName.contains("ACES-")) {
514
515 d->colorSpaceSelector->textProfileDescription->append(i18nc("From Elle's notes.",
516 "<p>Quoting Wikipedia, 'Academy Color Encoding System (ACES) is a color image "
517 "encoding system proposed by the Academy of Motion Picture Arts and Sciences that will allow for "
518 "a fully encompassing color accurate workflow, with 'seamless interchange of high quality motion "
519 "picture images regardless of source'.</p>"));
520 }
521 if (profileName.contains("ACEScg-")) {
522
523 d->colorSpaceSelector->textProfileDescription->append(i18nc("From Elle's notes.",
524 "<p>The ACEScg color space is smaller than the ACES color space, but large enough to contain the 'Rec-2020 gamut "
525 "and the DCI-P3 gamut', unlike the ACES color space it has no negative values and contains only few colors "
526 "that fall just barely outside the area of real colors humans can see</p>"));
527 }
528 if (profileName.contains("ClayRGB-")) {
529
530 d->colorSpaceSelector->textProfileDescription->append(i18nc("From Elle's notes.",
531 "<p>To avoid possible copyright infringement issues, I used 'ClayRGB' (following ArgyllCMS) as the base name "
532 "for these profiles. As used below, 'Compatible with Adobe RGB 1998' is terminology suggested in the preamble "
533 "to the AdobeRGB 1998 color space specifications.</p><p>"
534 "The Adobe RGB 1998 color gamut covers a higher "
535 "percentage of real-world cyans, greens, and yellow-greens than sRGB, but still doesn't include all printable "
536 "cyans, greens, yellow-greens, especially when printing using today's high-end, wider gamut, ink jet printers. "
537 "BetaRGB (not included in the profile pack) and Rec.2020 are better matches for the color gamuts of today's "
538 "wide gamut printers.</p><p>"
539 "The Adobe RGB 1998 color gamut is a reasonable approximation to some of today's "
540 "high-end wide gamut monitors.</p>"));
541 }
542 if (profileName.contains("AllColorsRGB-")) {
543
544 d->colorSpaceSelector->textProfileDescription->append(i18nc("From Elle's notes.",
545 "<p>This profile's color gamut is roughly the same size and shape as the ACES color space gamut, "
546 "and like the ACES color space, AllColorsRGB holds all possible real colors. But AllColorsRGB "
547 "actually has a slightly larger color gamut (to capture some fringe colors that barely qualify "
548 "as real when viewed by the standard observer) and uses the D50 white point.</p><p>"
549 "Just like the ACES color space, AllColorsRGB holds a high percentage of imaginary colors. See the Completely "
550 "<a href=\"https://ninedegreesbelow.com/photography/xyz-rgb.html\">"
551 "Painless Programmer's Guide to XYZ, RGB, ICC, xyY, and TRCs</a> for more information about imaginary "
552 "colors.</p><p>"
553 "There is no particular reason why anyone would want to use this profile "
554 "for editing, unless one needs to make sure your color space really does hold all "
555 "possible real colors.</p>"));
556 }
557 if (profileName.contains("CIERGB-")) {
558
559 d->colorSpaceSelector->textProfileDescription->append(i18nc("From Elle's notes.",
560 "<p>This profile is included mostly for its historical significance. "
561 "It's the color space that was used in the original color matching experiments "
562 "that led to the creation of the XYZ reference color space.</p><p>"
563 "The ASTM E white point "
564 "is probably the right E white point to use when making the CIERGB color space profile. "
565 "It's not clear to me what the correct CIERGB primaries really are. "
566 "Lindbloom gives one set. The LCMS version 1 tutorial gives a different set. "
567 "Experts in the field contend that the real primaries "
568 "should be calculated from the spectral wavelengths, so I did.</p>"));
569 }
570 if (profileName.contains("IdentityRGB-")) {
571
572 d->colorSpaceSelector->textProfileDescription->append(i18nc("From Elle's notes.",
573 "<p>The IdentityRGB working space is included in the profile pack because it's a mathematically "
574 "obvious way to include all possible visible colors, though it has a higher percentage of "
575 "imaginary colors than the ACES and AllColorsRGB color spaces. I cannot think of any reason "
576 "why you'd ever want to actually edit images in the IdentityRGB working space.</p>"));
577 }
578 if (profileName.contains("LargeRGB-")) {
579
580 d->colorSpaceSelector->textProfileDescription->append(i18nc("From Elle's notes.",
581 "<p>To avoid possible copyright infringement issues, I used 'LargeRGB' (following RawTherapee) "
582 "as the base name for these profiles.<p>"
583 "Kodak designed the RIMM/ROMM (ProPhotoRGB) color "
584 "gamut to include all printable and most real world colors. It includes some imaginary colors "
585 "and excludes some of the real world blues and violet blues that can be captured by digital "
586 "cameras. It also excludes some very saturated 'camera-captured' yellows as interpreted by "
587 "some (and probably many) camera matrix input profiles.</p><p>"
588 "The ProPhotoRGB primaries are "
589 "hard-coded into Adobe products such as Lightroom and the Dng-DCP camera 'profiles'. However, "
590 "other than being large enough to hold a lot of colors, ProPhotoRGB has no particular merit "
591 "as an RGB working space. Personally I recommend the Rec.2020 or ACEScg profiles over "
592 "ProPhotoRGB. But if you have an already well-established workflow using ProPhotoRGB, you "
593 "might find a shift to another RGB working space a little odd, at least at first, and so you "
594 "have to weight the pros and cons of changing your workflow.</p>"));
595 }
596 if (profileName.contains("Rec2020-")) {
597
598 d->colorSpaceSelector->textProfileDescription->append(i18nc("From Elle's notes.",
599 "<p>Rec.2020 is the up-and-coming replacement for the thoroughly outdated sRGB color space. As of "
600 "June 2015, very few (if any) display devices (and certainly no affordable display devices) can "
601 "display all of Rec.2020. However, display technology is closing in on Rec.2020, movies are "
602 "already being made for Rec.2020, and various cameras offer support for Rec.2020. And in the "
603 "digital darkroom Rec.2020 is much more suitable as a general RGB working space than the "
604 "exceedingly small sRGB color space.</p>"));
605 }
606 if (profileName.contains("sRGB-")) {
607 d->colorSpaceSelector->textProfileDescription->append(i18nc("From Elle's notes.",
608 "<p>Hewlett-Packard and Microsoft designed sRGB to match the color gamut of consumer-grade CRTs "
609 "from the 1990s. sRGB is the standard color space for the world wide web and is still the best "
610 "choice for exporting images to the internet.</p><p>"
611 "The sRGB color gamut was a good match to "
612 "calibrated decent quality CRTs. But sRGB is not a good match to many consumer-grade LCD monitors, "
613 "which often cannot display the more saturated sRGB blues and magentas (the good news: as technology "
614 "progresses, wider gamuts are trickling down to consumer grade monitors).</p><p>"
615 "Printer color gamuts can easily exceed the sRGB color gamut in cyans, greens, and yellow-greens. Colors from interpolated "
616 "camera raw files also often exceed the sRGB color gamut.</p><p>"
617 "As a very relevant aside, using perceptual "
618 "intent when converting to sRGB does not magically makes otherwise out of gamut colors fit inside the "
619 "sRGB color gamut! The standard sRGB color space (along with all the other the RGB profiles provided "
620 "in my profile pack) is a matrix profile, and matrix profiles don't have perceptual intent tables.</p>"));
621 }
622 if (profileName.contains("WideRGB-")) {
623 d->colorSpaceSelector->textProfileDescription->append(i18nc("From Elle's notes.",
624 "<p>To avoid possible copyright infringement issues, I used 'WideRGB' as the base name for these profiles.</p><p>"
625 "WideGamutRGB was designed by Adobe to be a wide gamut color space that uses spectral colors "
626 "as its primaries. Pascale's primary values produce a profile that matches old V2 Widegamut profiles "
627 "from Adobe and Canon. It is an interesting color space, but shortly after its introduction, Adobe "
628 "switched their emphasis to the ProPhotoRGB color space.</p>"));
629 }
630 if (profileName.contains("Gray-")) {
631 d->colorSpaceSelector->textProfileDescription->append(i18nc("From Elle's notes.",
632 "<p>These profiles are for use with RGB images that have been converted to monotone gray (black and white). "
633 "The main reason to convert from RGB to Gray is to save the file space needed to encode the image. "
634 "Google places a premium on fast-loading web pages, and images are one of the slower-loading elements "
635 "of a web page. So converting black and white images to Grayscale images does save some kilobytes. "
636 " For grayscale images uploaded to the internet, convert the image to the V2 Gray profile with the sRGB TRC.</p>"));
637 }
638 if (profileName.contains("-g10")) {
639 d->colorSpaceSelector->textProfileDescription->append(i18nc("From Elle's notes.",
640 "<p>The profiles that end in '-g10.icc' are linear gamma (gamma=1.0, 'linear light', etc) profiles and "
641 "should only be used when editing at high bit depths (16-bit floating point, 16-bit integer, 32-bit "
642 "floating point, 32-bit integer). Many editing operations produce better results in linear gamma color "
643 "spaces.</p>"));
644 }
645 if (profileName.contains("-labl")) {
646 d->colorSpaceSelector->textProfileDescription->append(i18nc("From Elle's notes.",
647 "<p>The profiles that end in '-labl.icc' have perceptually uniform TRCs. A few editing operations really "
648 "should be done on perceptually uniform RGB. Make sure you use the V4 versions for editing high bit depth "
649 "images.</p>"));
650 }
651 if (profileName.contains("-srgbtrc") || profileName.contains("-g22") || profileName.contains("-g18") || profileName.contains("-rec709")) {
652 d->colorSpaceSelector->textProfileDescription->append(i18nc("From Elle's notes.",
653 "<p>The profiles that end in '-srgbtrc.icc', '-g22.icc', and '-rec709.icc' have approximately but not exactly "
654 "perceptually uniform TRCs. ProPhotoRGB's gamma=1.8 TRC is not quite as close to being perceptually uniform.</p>"));
655 }
656 if (d->colorSpaceSelector->cmbColorDepth->currentItem().id()=="U8") {
657 d->colorSpaceSelector->textProfileDescription->append(i18nc("From Elle's notes.",
658 "<p>When editing 8-bit images, you should use a profile with a small color gamut and an approximately or "
659 "exactly perceptually uniform TRC. Of the profiles supplied in my profile pack, only the sRGB and AdobeRGB1998 "
660 "(ClayRGB) color spaces are small enough for 8-bit editing. Even with the AdobeRGB1998 color space you need to "
661 "be careful to not cause posterization. And of course you cannot use the linear gamma versions of these profiles "
662 "for 8-bit editing.</p>"));
663 }
664 if (profileName.contains("-V4-")) {
665 d->colorSpaceSelector->textProfileDescription->append(i18nc("From Elle's notes.",
666 "<p>Use V4 profiles for editing images using high bit depth image editors that use LCMS as the Color Management Module. "
667 "This includes Krita, digiKam/showFoto, and GIMP 2.9.</p>"));
668 }
669 if (profileName.contains("-V2-")) {
670 d->colorSpaceSelector->textProfileDescription->append(i18nc("From Elle's notes.",
671 "<p>Use V2 profiles for exporting finished images to be uploaded to the web or for use with imaging software that "
672 "cannot read V4 profiles.</p>"));
673 }
674 }
675
676
677 d->colorSpaceSelector->textProfileDescription->moveCursor(QTextCursor::Start);
678
679}
680
682 QString name=(QString::number(whitePoint.x) + ", " + QString::number(whitePoint.y, 'f', 4));
683 //A (0.451170, 0.40594) (2856K)(tungsten)
684 if ((whitePoint.x>0.451170-0.005 && whitePoint.x<0.451170 + 0.005) &&
685 (whitePoint.y>0.40594-0.005 && whitePoint.y<0.40594 + 0.005)){
686 name="A";
687 return name;
688 }
689 //B (0.34980, 0.35270) (4874K) (Direct Sunlight at noon)(obsolete)
690 //C (0.31039, 0.31905) (6774K) (average/north sky daylight)(obsolete)
691 //D50 (0.34773, 0.35952) (5003K) (Horizon Light, default color of white paper, ICC profile standard illuminant)
692 if ((whitePoint.x>0.34773-0.005 && whitePoint.x<0.34773 + 0.005) &&
693 (whitePoint.y>0.35952-0.005 && whitePoint.y<0.35952 + 0.005)){
694 name="D50";
695 return name;
696 }
697 //D55 (0.33411, 0.34877) (5503K) (Mid-morning / Mid-afternoon Daylight)
698 if ((whitePoint.x>0.33411-0.001 && whitePoint.x<0.33411 + 0.001) &&
699 (whitePoint.y>0.34877-0.005 && whitePoint.y<0.34877 + 0.005)){
700 name="D55";
701 return name;
702 }
703 //D60 (0.3217, 0.3378) (~6000K) (ACES colorspace default)
704 if ((whitePoint.x>0.3217-0.001 && whitePoint.x<0.3217 + 0.001) &&
705 (whitePoint.y>0.3378-0.005 && whitePoint.y<0.3378 + 0.005)){
706 name="D60";
707 return name;
708 }
709 //D65 (0.31382, 0.33100) (6504K) (Noon Daylight, default for computer and tv screens, sRGB default)
710 //Elle's are old school with 0.3127 and 0.3289
711 if ((whitePoint.x>0.31382-0.002 && whitePoint.x<0.31382 + 0.002) &&
712 (whitePoint.y>0.33100-0.005 && whitePoint.y<0.33100 + 0.002)){
713 name="D65";
714 return name;
715 }
716 //D75 (0.29968, 0.31740) (7504K) (North sky Daylight)
717 if ((whitePoint.x>0.29968-0.001 && whitePoint.x<0.29968 + 0.001) &&
718 (whitePoint.y>0.31740-0.005 && whitePoint.y<0.31740 + 0.005)){
719 name="D75";
720 return name;
721 }
722 //E (1/3, 1/3) (5454K) (Equal Energy. CIERGB default)
723 if ((whitePoint.x>(1.0/3.0)-0.001 && whitePoint.x<(1.0/3.0) + 0.001) &&
724 (whitePoint.y>(1.0/3.0)-0.001 && whitePoint.y<(1.0/3.0) + 0.001)){
725 name="E";
726 return name;
727 }
728 //The F series seems to sorta overlap with the D series, so I'll just leave them in comment here.//
729 //F1 (0.31811, 0.33559) (6430K) (Daylight Fluorescent)
730 //F2 (0.37925, 0.36733) (4230K) (Cool White Fluorescent)
731 //F3 (0.41761, 0.38324) (3450K) (White Fluorescent)
732 //F4 (0.44920, 0.39074) (2940K) (Warm White Fluorescent)
733 //F5 (0.31975, 0.34246) (6350K) (Daylight Fluorescent)
734 //F6 (0.38660, 0.37847) (4150K) (Lite White Fluorescent)
735 //F7 (0.31569, 0.32960) (6500K) (D65 simulator, Daylight simulator)
736 //F8 (0.34902, 0.35939) (5000K) (D50 simulator)
737 //F9 (0.37829, 0.37045) (4150K) (Cool White Deluxe Fluorescent)
738 //F10 (0.35090, 0.35444) (5000K) (Philips TL85, Ultralume 50)
739 //F11 (0.38541, 0.37123) (4000K) (Philips TL84, Ultralume 40)
740 //F12 (0.44256, 0.39717) (3000K) (Philips TL83, Ultralume 30)
741
742 return name;
743}
744
746{
747 QString check = "";
748 if (d->colorSpaceSelector->lstProfile->currentItem()) {
749 check = d->colorSpaceSelector->lstProfile->currentItem()->text();
750 } else if (d->colorSpaceSelector->lstProfile->item(0)) {
751 check = d->colorSpaceSelector->lstProfile->item(0)->text();
752 }
753 return KoColorSpaceRegistry::instance()->colorSpace(d->colorSpaceSelector->cmbColorModels->currentItem().id(),
754 d->colorSpaceSelector->cmbColorDepth->currentItem().id(),
755 check);
756}
757
759{
760 d->colorSpaceSelector->cmbColorModels->setCurrent(id);
762 fillCmbDepths(id);
763}
764
766{
767 d->colorSpaceSelector->cmbColorDepth->setCurrent(id);
769}
770
772{
773 QList<QListWidgetItem *> Items= d->colorSpaceSelector->lstProfile->findItems(name, Qt::MatchStartsWith);
774 d->colorSpaceSelector->lstProfile->setCurrentItem(Items.at(0));
775}
776
778{
779 if (!colorSpace) {
780 return;
781 }
782 setCurrentColorModel(colorSpace->colorModelId());
783 setCurrentColorDepth(colorSpace->colorDepthId());
784 setCurrentProfile(colorSpace->profile()->name());
785}
786
788{
789 bool valid = d->colorSpaceSelector->lstProfile->count() != 0;
790 emit(selectionChanged(valid));
791 if (valid) {
793 }
794}
795
797{
798 KoFileDialog dialog(this, KoFileDialog::OpenFiles, "OpenDocumentICC");
799 dialog.setCaption(i18n("Install Color Profiles"));
800 dialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
801 dialog.setMimeTypeFilters(QStringList() << "application/vnd.iccprofile", "application/vnd.iccprofile");
802 QStringList profileNames = dialog.filenames();
803
805 Q_ASSERT(iccEngine);
806
807 QString saveLocation = KoResourcePaths::saveLocation("icc_profiles");
808
809 Q_FOREACH (const QString &profileName, profileNames) {
810 QUrl file(profileName);
811 if (!QFile::copy(profileName, saveLocation + file.fileName())) {
812 dbgKrita << "Could not install profile!";
813 return;
814 }
815 iccEngine->addProfile(saveLocation + file.fileName());
816
817 }
818
820}
QList< QString > QStringList
const KoID Float32BitsColorDepthID("F32", ki18n("32-bit float/channel"))
const KoID Float64BitsColorDepthID("F64", ki18n("64-bit float/channel"))
const KoID Float16BitsColorDepthID("F16", ki18n("16-bit float/channel"))
const KoID Integer8BitsColorDepthID("U8", ki18n("8-bit integer/channel"))
const KoID Integer16BitsColorDepthID("U16", ki18n("16-bit integer/channel"))
TransferCharacteristics
The transferCharacteristics enum Enum of transfer characteristics, follows ITU H.273 for values 0 to ...
void setCurrentColorSpace(const KoColorSpace *colorSpace)
KisAdvancedColorSpaceSelector(QWidget *parent, const QString &caption)
void selectionChanged(bool valid)
QString nameWhitePoint(KoColorimetryUtils::xyY whitePoint)
static KoColorSpaceEngineRegistry * instance()
virtual KoID colorModelId() const =0
virtual KoID colorDepthId() const =0
virtual const KoColorProfile * profile() const =0
QPolygonF estimatedTRCXYY() const
T get(const QString &id) const
Definition KoID.h:30
static QString saveLocation(const QString &type, const QString &suffix=QString(), bool create=true)
#define dbgKrita
Definition kis_debug.h:45
#define koIcon(name)
Use these macros for icons without any issues.
Definition kis_icon.h:25
static QString getTransferCharacteristicName(TransferCharacteristics curve)
getTransferCharacteristicName
virtual void linearizeFloatValue(QVector< qreal > &Value) const =0
virtual KoColorimetryUtils::xyY getWhitePointxyY() const =0
virtual QVector< qreal > getEstimatedTRC() const =0
virtual QVector< KoColorimetryUtils::xyY > getColorantsxyY() const =0
virtual TransferCharacteristics getTransferCharacteristics() const
getTransferCharacteristics This function should be subclassed at some point so we can get the value f...
virtual const KoColorProfile * addProfile(const QString &filename)=0
QString colorSpaceId(const QString &colorModelId, const QString &colorDepthId) const
QList< KoID > colorDepthList(const KoID &colorModelId, ColorSpaceListVisibility option) const
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile)
static KoColorSpaceRegistry * instance()
QString defaultProfileForColorSpace(const QString &colorSpaceId) const
QList< const KoColorProfile * > profilesFor(const QString &csID) const
@ OnlyUserVisible
Only user visible color space.