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