KoColor.h 10.3 KB
Newer Older
1 2
/*
 *  Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org>
Thomas Zander's avatar
Thomas Zander committed
3
 *  Copyright (C) 2007 Thomas Zander <zander@kde.org>
4
 *
5 6 7 8
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
9
 *
10 11 12 13
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
14
 *
15 16 17 18 19
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
*/
20 21
#ifndef KOCOLOR_H
#define KOCOLOR_H
22

23 24
#include <QColor>
#include <QMetaType>
25
#include <QtGlobal>
26
#include "kritapigment_export.h"
27
#include "KoColorConversionTransformation.h"
28 29
#include "KoColorSpaceRegistry.h"
#include "KoColorSpaceTraits.h"
30
#include <boost/operators.hpp>
31

32

33 34 35
class QDomDocument;
class QDomElement;

Cyrille Berger's avatar
Cyrille Berger committed
36 37
class KoColorProfile;
class KoColorSpace;
38

39
/**
Cyrille Berger's avatar
dox++  
Cyrille Berger committed
40 41
 * A KoColor describes a color in a certain colorspace. The color is stored in a buffer
 * that can be manipulated by the function of the color space.
42
 */
43
class KRITAPIGMENT_EXPORT KoColor : public boost::equality_comparable<KoColor>
44
{
45 46 47

public:
    /// Create an empty KoColor. It will be valid, but also black and transparent
48
    KoColor();
49

50
    /// Create a null KoColor. It will be valid, but all channels will be set to 0
51
    explicit KoColor(const KoColorSpace * colorSpace);
52

53 54
    /// Create a KoColor from a QColor. The QColor is immediately converted to native. The QColor
    /// is assumed to have the current monitor profile.
55
    KoColor(const QColor & color, const KoColorSpace * colorSpace);
56 57

    /// Create a KoColor using a native color strategy. The data is copied.
58
    KoColor(const quint8 * data, const KoColorSpace * colorSpace);
59 60

    /// Create a KoColor by converting src into another colorspace
61
    KoColor(const KoColor &src, const KoColorSpace * colorSpace);
62

63
    /// Copy constructor -- deep copies the colors.
64 65 66
    KoColor(const KoColor & rhs) {
        *this = rhs;
    }
67

Thomas Zander's avatar
Thomas Zander committed
68 69
    /**
     * assignment operator to copy the data from the param color into this one.
Yuri Chornoivan's avatar
Yuri Chornoivan committed
70
     * @param rhs the color we are going to copy
Thomas Zander's avatar
Thomas Zander committed
71 72
     * @return this color
     */
73 74 75 76 77 78 79 80 81 82 83 84 85
    inline KoColor &operator=(const KoColor &rhs) {
        if (&rhs == this) {
            return *this;
        }

        m_colorSpace = rhs.m_colorSpace;
        m_size = rhs.m_size;
        memcpy(m_data, rhs.m_data, m_size);

        assertPermanentColorspace();

        return *this;
    }
86

87
    bool operator==(const KoColor &other) const;
88

Thomas Zander's avatar
Thomas Zander committed
89
    /// return the current colorSpace
90 91 92
    const KoColorSpace * colorSpace() const {
        return m_colorSpace;
    }
93

Thomas Zander's avatar
Thomas Zander committed
94
    /// return the current profile
95
    const KoColorProfile *profile() const;
96 97

    /// Convert this KoColor to the specified colorspace. If the specified colorspace is the
98
    /// same as the original colorspace, do nothing
99 100 101 102
    void convertTo(const KoColorSpace * cs,
                   KoColorConversionTransformation::Intent renderingIntent,
                   KoColorConversionTransformation::ConversionFlags conversionFlags);

103
    void convertTo(const KoColorSpace * cs);
104

105 106 107 108 109 110 111 112 113 114 115 116
    /// Copies this color and converts it to the specified colorspace. If the specified colorspace is the
    /// same as the original colorspace, just returns a copy
    KoColor convertedTo(const KoColorSpace * cs,
                        KoColorConversionTransformation::Intent renderingIntent,
                        KoColorConversionTransformation::ConversionFlags conversionFlags) const;

    /// Copies this color and converts it to the specified colorspace. If the specified colorspace is the
    /// same as the original colorspace, just returns a copy
    KoColor convertedTo(const KoColorSpace * cs) const;



117 118 119
    /// assign new profile without converting pixel data
    void setProfile(const KoColorProfile *profile);

120
    /// Replace the existing color data, and colorspace with the specified data.
Boudewijn Rempt's avatar
Boudewijn Rempt committed
121
    /// The data is copied.
122
    void setColor(const quint8 * data, const KoColorSpace * colorSpace = 0);
Thomas Zander's avatar
Thomas Zander committed
123

124 125 126
    /// Convert the color from src and replace the value of the current color with the converted data.
    /// Don't convert the color if src and this have the same colorspace.
    void fromKoColor(const KoColor& src);
Thomas Zander's avatar
Thomas Zander committed
127 128 129 130 131

    /// a convenience method for the above.
    void toQColor(QColor *c) const;
    /// a convenience method for the above.
    QColor toQColor() const;
132

133 134 135
    /**
     * Convenient function to set the opacity of the color.
     */
136
    void setOpacity(quint8 alpha);
137
    void setOpacity(qreal alpha);
138 139 140
    /**
     * Convenient function that return the opacity of the color
     */
141 142
    quint8 opacityU8() const;
    qreal opacityF() const;
143

144
    /// Convenient function for converting from a QColor
145
    void fromQColor(const QColor& c);
146

Cyrille Berger's avatar
dox++  
Cyrille Berger committed
147 148 149 150 151
    /**
     * @return the buffer associated with this color object to be used with the
     *         transformation object created by the color space of this KoColor
     *         or to copy to a different buffer from the same color space
     */
152 153 154
    quint8 * data() {
        return m_data;
    }
Thomas Zander's avatar
Thomas Zander committed
155

Cyrille Berger's avatar
dox++  
Cyrille Berger committed
156 157 158 159 160
    /**
     * @return the buffer associated with this color object to be used with the
     *         transformation object created by the color space of this KoColor
     *         or to copy to a different buffer from the same color space
     */
161 162 163
    const quint8 * data() const {
        return m_data;
    }
164

165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193

    /**
     * Channelwise subtracts \p value from *this and stores the result in *this
     *
     * Throws a safe assert if the colorspaces of the two colors are different
     */
    void subtract(const KoColor &value);

    /**
     * Channelwise subtracts \p value from a copy of *this and returns the result
     *
     * Throws a safe assert if the colorspaces of the two colors are different
     */
    KoColor subtracted(const KoColor &value) const;

    /**
     * Channelwise adds \p value to *this and stores the result in *this
     *
     * Throws a safe assert if the colorspaces of the two colors are different
     */
    void add(const KoColor &value);

    /**
     * Channelwise adds \p value to a copy of *this and returns the result
     *
     * Throws a safe assert if the colorspaces of the two colors are different
     */
    KoColor added(const KoColor &value) const;

194 195
    /**
     * Serialize this color following Create's swatch color specification available
Yuri Chornoivan's avatar
Yuri Chornoivan committed
196
     * at https://web.archive.org/web/20110826002520/http://create.freedesktop.org/wiki/Swatches_-_colour_file_format/Draft
197
     *
Yuri Chornoivan's avatar
Yuri Chornoivan committed
198 199
     * This function doesn't create the \<color /\> element but rather the \<CMYK /\>,
     * \<sRGB /\>, \<RGB /\> ... elements. It is assumed that colorElt is the \<color /\>
200
     * element.
201
     *
202
     * @param colorElt root element for the serialization, it is assumed that this
Yuri Chornoivan's avatar
Yuri Chornoivan committed
203
     *                 element is \<color /\>
204 205 206
     * @param doc is the document containing colorElt
     */
    void toXML(QDomDocument& doc, QDomElement& colorElt) const;
207

208 209
    /**
     * Unserialize a color following Create's swatch color specification available
Yuri Chornoivan's avatar
Yuri Chornoivan committed
210
     * at https://web.archive.org/web/20110826002520/http://create.freedesktop.org/wiki/Swatches_-_colour_file_format/Draft
211
     *
Yuri Chornoivan's avatar
Yuri Chornoivan committed
212
     * @param elt the element to unserialize (\<CMYK /\>, \<sRGB /\>, \<RGB /\>)
213
     * @param channelDepthId the bit depth is unspecified by the spec, this allow to select
214 215 216 217 218 219
     *                   a preferred bit depth for creating the KoColor object (if that
     *                   bit depth isn't available, this function will randomly select
     *                   an other bit depth)
     * @return the unserialize color, or an empty color object if the function failed
     *         to unserialize the color
     */
220
    static KoColor fromXML(const QDomElement& elt, const QString & channelDepthId);
221

222 223
    /**
     * Unserialize a color following Create's swatch color specification available
Yuri Chornoivan's avatar
Yuri Chornoivan committed
224
     * at https://web.archive.org/web/20110826002520/http://create.freedesktop.org/wiki/Swatches_-_colour_file_format/Draft
225
     *
Yuri Chornoivan's avatar
Yuri Chornoivan committed
226
     * @param elt the element to unserialize (\<CMYK /\>, \<sRGB /\>, \<RGB /\>)
227
     * @param channelDepthId the bit depth is unspecified by the spec, this allow to select
228 229 230 231 232 233 234
     *                   a preferred bit depth for creating the KoColor object (if that
     *                   bit depth isn't available, this function will randomly select
     *                   an other bit depth)
     * @param ok If a an error occurs, *ok is set to false; otherwise it's set to true
     * @return the unserialize color, or an empty color object if the function failed
     *         to unserialize the color
     */
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
    static KoColor fromXML(const QDomElement& elt, const QString & channelDepthId, bool* ok);


    /**
     * @brief toXML creates a string with XML that represents the current color. The XML
     * is extended with a "channeldepth" attribute so we can restore the color to the same
     * channel depth.
     * @return a valid XML document in a string
     */
    QString toXML() const;

    /**
     * @brief fromXML restores a KoColor from a string saved with toXML(). If the
     * string does not contain the "channeldepth" attribute, 16 bit integer is assumed.
     * @param xml a valid XML document
     * @return a new KoColor object
     */
    static KoColor fromXML(const QString &xml);
253

254 255 256 257 258
    /**
     * @brief toQString create a user-visible string of the channel names and the channel values
     * @param color the color to create the string from
     * @return a string that can be used to display the values of this color to the user.
     */
259 260
    static QString toQString(const KoColor &color);

Thomas Zander's avatar
Thomas Zander committed
261
#ifndef NODEBUG
Boudewijn Rempt's avatar
Boudewijn Rempt committed
262
    /// use qDebug calls to print internal info
263
    void dump() const;
Thomas Zander's avatar
Thomas Zander committed
264
#endif
265

266
private:
267 268 269 270 271 272 273 274 275 276 277
    inline void assertPermanentColorspace() {
#ifndef NODEBUG
        if (m_colorSpace) {
            Q_ASSERT(*m_colorSpace == *KoColorSpaceRegistry::instance()->permanentColorspace(m_colorSpace));
        }
#endif
    }

    const KoColorSpace *m_colorSpace;
    quint8 m_data[MAX_PIXEL_SIZE];
    quint8 m_size;
278 279
};

280
Q_DECLARE_METATYPE(KoColor)
281

282 283 284
KRITAPIGMENT_EXPORT QDebug operator<<(QDebug dbg, const KoColor &color);


285
#endif