1 /*
2  * Copyright (C) 2017 Boudewijn Rempt <boud@valdyas.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 
20 #ifndef MANAGEDCOLOR_H
21 #define MANAGEDCOLOR_H
22 
23 #include <QObject>
24 #include <QVector>
25 #include <QScopedPointer>
26 
27 #include "kritalibkis_export.h"
28 #include "libkis.h"
29 
30 class KoColor;
31 
32 /**
33  * @brief The ManagedColor class is a class to handle colors that are color managed.
34  * A managed color is a color of which we know the model(RGB, LAB, CMYK, etc), the bitdepth and
35  * the specific properties of its colorspace, such as the whitepoint, chromacities, trc, etc, as represented
36  * by the color profile.
37  *
38  * Krita has two color management systems. LCMS and OCIO.
39  * LCMS is the one handling the ICC profile stuff, and the major one handling that ManagedColor deals with.
40  * OCIO support is only in the display of the colors. ManagedColor has some support for it in colorForCanvas()
41  *
42  * All colors in Krita are color managed. QColors are understood as RGB-type colors in the sRGB space.
43  *
44  * We recommend you make a color like this:
45  *
46  * @code
47  * colorYellow = ManagedColor("RGBA", "U8", "")
48  * QVector<float> yellowComponents = colorYellow.components()
49  * yellowComponents[0] = 1.0
50  * yellowComponents[1] = 1.0
51  * yellowComponents[2] = 0
52  * yellowComponents[3] = 1.0
53  *
54  * colorYellow.setComponents(yellowComponents)
55  * QColor yellow = colorYellow.colorForCanvas(canvas)
56  * @endcode
57  */
58 class KRITALIBKIS_EXPORT ManagedColor : public QObject
59 {
60     Q_OBJECT
61 public:
62     /**
63      * @brief ManagedColor
64      * Create a ManagedColor that is black and transparent.
65      */
66     explicit ManagedColor(QObject *parent = 0);
67     /**
68      * @brief ManagedColor create a managed color with the given color space properties.
69      * @see setColorModel() for more details.
70      */
71     ManagedColor(const QString &colorModel, const QString &colorDepth, const QString &colorProfile, QObject *parent = 0);
72     ManagedColor(KoColor color, QObject *parent = 0);
73     ~ManagedColor() override;
74 
75     bool operator==(const ManagedColor &other) const;
76 
77     /**
78      * @brief colorForCanvas
79      * @param canvas the canvas whose color management you'd like to use. In Krita, different views have
80      * separate canvasses, and these can have different OCIO configurations active.
81      * @return the QColor as it would be displaying on the canvas. This result can be used to draw widgets with
82      * the correct configuration applied.
83      */
84     QColor colorForCanvas(Canvas *canvas) const;
85 
86     /**
87      * @brief fromQColor is the (approximate) reverse of colorForCanvas()
88      * @param qcolor the QColor to convert to a KoColor.
89      * @param canvas the canvas whose color management you'd like to use.
90      * @return the approximated ManagedColor, to use for canvas resources.
91      */
92     static ManagedColor *fromQColor(const QColor &qcolor, Canvas *canvas = 0);
93 
94     /**
95      * colorDepth A string describing the color depth of the image:
96      * <ul>
97      * <li>U8: unsigned 8 bits integer, the most common type</li>
98      * <li>U16: unsigned 16 bits integer</li>
99      * <li>F16: half, 16 bits floating point. Only available if Krita was built with OpenEXR</li>
100      * <li>F32: 32 bits floating point</li>
101      * </ul>
102      * @return the color depth.
103      */
104     QString colorDepth() const;
105 
106     /**
107      * @brief colorModel retrieve the current color model of this document:
108      * <ul>
109      * <li>A: Alpha mask</li>
110      * <li>RGBA: RGB with alpha channel (The actual order of channels is most often BGR!)</li>
111      * <li>XYZA: XYZ with alpha channel</li>
112      * <li>LABA: LAB with alpha channel</li>
113      * <li>CMYKA: CMYK with alpha channel</li>
114      * <li>GRAYA: Gray with alpha channel</li>
115      * <li>YCbCrA: YCbCr with alpha channel</li>
116      * </ul>
117      * @return the internal color model string.
118      */
119     QString colorModel() const;
120 
121     /**
122      * @return the name of the current color profile
123      */
124     QString colorProfile() const;
125 
126     /**
127      * @brief setColorProfile set the color profile of the image to the given profile. The profile has to
128      * be registered with krita and be compatible with the current color model and depth; the image data
129      * is <i>not</i> converted.
130      * @param colorProfile
131      * @return false if the colorProfile name does not correspond to to a registered profile or if assigning
132      * the profile failed.
133      */
134     bool setColorProfile(const QString &colorProfile);
135 
136     /**
137      * @brief setColorSpace convert the nodes and the image to the given colorspace. The conversion is
138      * done with Perceptual as intent, High Quality and No LCMS Optimizations as flags and no blackpoint
139      * compensation.
140      *
141      * @param colorModel A string describing the color model of the image:
142      * <ul>
143      * <li>A: Alpha mask</li>
144      * <li>RGBA: RGB with alpha channel (The actual order of channels is most often BGR!)</li>
145      * <li>XYZA: XYZ with alpha channel</li>
146      * <li>LABA: LAB with alpha channel</li>
147      * <li>CMYKA: CMYK with alpha channel</li>
148      * <li>GRAYA: Gray with alpha channel</li>
149      * <li>YCbCrA: YCbCr with alpha channel</li>
150      * </ul>
151      * @param colorDepth A string describing the color depth of the image:
152      * <ul>
153      * <li>U8: unsigned 8 bits integer, the most common type</li>
154      * <li>U16: unsigned 16 bits integer</li>
155      * <li>F16: half, 16 bits floating point. Only available if Krita was built with OpenEXR</li>
156      * <li>F32: 32 bits floating point</li>
157      * </ul>
158      * @param colorProfile a valid color profile for this color model and color depth combination.
159      * @return false the combination of these arguments does not correspond to a colorspace.
160      */
161     bool setColorSpace(const QString &colorModel, const QString &colorDepth, const QString &colorProfile);
162 
163     /**
164      * @brief components
165      * @return a QVector containing the channel/components of this color normalized. This includes the alphachannel.
166      */
167     QVector<float> components() const;
168 
169     /**
170      * @brief componentsOrdered()
171      * @return same as Components, except the values are ordered to the display.
172      */
173     QVector<float> componentsOrdered() const;
174 
175     /**
176      * @brief setComponents
177      * Set the channel/components with normalized values. For integer colorspace, this obviously means the limit
178      * is between 0.0-1.0, but for floating point colorspaces, 2.4 or 103.5 are still meaningful (if bright) values.
179      * @param values the QVector containing the new channel/component values. These should be normalized.
180      */
181     void setComponents(const QVector<float> &values);
182 
183     /**
184      * Serialize this color following Create's swatch color specification available
185      * at https://web.archive.org/web/20110826002520/http://create.freedesktop.org/wiki/Swatches_-_colour_file_format/Draft
186      */
187     QString toXML() const;
188 
189     /**
190      * Unserialize a color following Create's swatch color specification available
191      * at https://web.archive.org/web/20110826002520/http://create.freedesktop.org/wiki/Swatches_-_colour_file_format/Draft
192      *
193      * @param xml an XML color
194      *
195      * @return the unserialized color, or an empty color object if the function failed
196      *         to unserialize the color
197      */
198     void fromXML(const QString &xml);
199 
200     /**
201      * @brief toQString create a user-visible string of the channel names and the channel values
202      * @return a string that can be used to display the values of this color to the user.
203      */
204     QString toQString();
205 
206 
207 private:
208 
209     friend class View;
210     friend class PaletteView;
211     friend class Swatch;
212 
213     KoColor color() const;
214 
215     struct Private;
216     const QScopedPointer<Private> d;
217 
218 };
219 
220 #endif // MANAGEDCOLOR_H
221