File indexing completed on 2024-05-12 15:59:31
0001 /* 0002 * SPDX-FileCopyrightText: 2005 Boudewijn Rempt <boud@valdyas.org> 0003 * SPDX-FileCopyrightText: 2007 Thomas Zander <zander@kde.org> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 #ifndef KOCOLOR_H 0008 #define KOCOLOR_H 0009 0010 #include <QColor> 0011 #include <QMetaType> 0012 #include <QtGlobal> 0013 #include "kritapigment_export.h" 0014 #include "KoColorConversionTransformation.h" 0015 #include "KoColorSpaceRegistry.h" 0016 #include "KoColorSpaceTraits.h" 0017 #include <boost/operators.hpp> 0018 0019 0020 class QDomDocument; 0021 class QDomElement; 0022 0023 class KoColorProfile; 0024 class KoColorSpace; 0025 0026 /** 0027 * A KoColor describes a color in a certain colorspace. The color is stored in a buffer 0028 * that can be manipulated by the function of the color space. 0029 */ 0030 class KRITAPIGMENT_EXPORT KoColor : public boost::equality_comparable<KoColor> 0031 { 0032 0033 public: 0034 /// Create an empty KoColor. It will be valid, but also black and transparent 0035 KoColor(); 0036 0037 /// Create a null KoColor. It will be valid, but all channels will be set to 0 0038 explicit KoColor(const KoColorSpace * colorSpace); 0039 0040 /// Create a KoColor from a QColor. The QColor is immediately converted to native. The QColor 0041 /// is assumed to have the current monitor profile. 0042 KoColor(const QColor & color, const KoColorSpace * colorSpace); 0043 0044 /// Create a KoColor using a native color strategy. The data is copied. 0045 KoColor(const quint8 * data, const KoColorSpace * colorSpace); 0046 0047 /// Create a KoColor by converting src into another colorspace 0048 KoColor(const KoColor &src, const KoColorSpace * colorSpace); 0049 0050 /// Copy constructor -- deep copies the colors. 0051 KoColor(const KoColor &rhs) 0052 : m_colorSpace(rhs.m_colorSpace) 0053 , m_size(rhs.m_size) 0054 , m_metadata(rhs.m_metadata) 0055 { 0056 memcpy(m_data, rhs.m_data, m_size); 0057 } 0058 0059 /** 0060 * assignment operator to copy the data from the param color into this one. 0061 * @param rhs the color we are going to copy 0062 * @return this color 0063 */ 0064 inline KoColor &operator=(const KoColor &rhs) { 0065 if (&rhs == this) { 0066 return *this; 0067 } 0068 0069 m_colorSpace = rhs.m_colorSpace; 0070 m_metadata = rhs.m_metadata; 0071 m_size = rhs.m_size; 0072 memcpy(m_data, rhs.m_data, m_size); 0073 0074 assertPermanentColorspace(); 0075 0076 return *this; 0077 } 0078 0079 bool operator==(const KoColor &other) const; 0080 0081 /// return the current colorSpace 0082 const KoColorSpace * colorSpace() const { 0083 return m_colorSpace; 0084 } 0085 0086 /// return the current profile 0087 const KoColorProfile *profile() const; 0088 0089 /// Convert this KoColor to the specified colorspace. If the specified colorspace is the 0090 /// same as the original colorspace, do nothing 0091 void convertTo(const KoColorSpace * cs, 0092 KoColorConversionTransformation::Intent renderingIntent, 0093 KoColorConversionTransformation::ConversionFlags conversionFlags); 0094 0095 void convertTo(const KoColorSpace * cs); 0096 0097 /// Copies this color and converts it to the specified colorspace. If the specified colorspace is the 0098 /// same as the original colorspace, just returns a copy 0099 KoColor convertedTo(const KoColorSpace * cs, 0100 KoColorConversionTransformation::Intent renderingIntent, 0101 KoColorConversionTransformation::ConversionFlags conversionFlags) const; 0102 0103 /// Copies this color and converts it to the specified colorspace. If the specified colorspace is the 0104 /// same as the original colorspace, just returns a copy 0105 KoColor convertedTo(const KoColorSpace * cs) const; 0106 0107 0108 0109 /// assign new profile without converting pixel data 0110 void setProfile(const KoColorProfile *profile); 0111 0112 /// Replace the existing color data, and colorspace with the specified data. 0113 /// The data is copied. 0114 void setColor(const quint8 * data, const KoColorSpace * colorSpace = 0); 0115 0116 /// Convert the color from src and replace the value of the current color with the converted data. 0117 /// Don't convert the color if src and this have the same colorspace. 0118 void fromKoColor(const KoColor& src); 0119 0120 /// a convenience method for the above. 0121 void toQColor(QColor *c) const; 0122 /// a convenience method for the above. 0123 QColor toQColor() const; 0124 0125 /** 0126 * Convenient function to set the opacity of the color. 0127 */ 0128 void setOpacity(quint8 alpha); 0129 void setOpacity(qreal alpha); 0130 /** 0131 * Convenient function that return the opacity of the color 0132 */ 0133 quint8 opacityU8() const; 0134 qreal opacityF() const; 0135 0136 /// Convenient function for converting from a QColor 0137 void fromQColor(const QColor& c); 0138 0139 /** 0140 * @return the buffer associated with this color object to be used with the 0141 * transformation object created by the color space of this KoColor 0142 * or to copy to a different buffer from the same color space 0143 */ 0144 quint8 * data() { 0145 return m_data; 0146 } 0147 0148 /** 0149 * @return the buffer associated with this color object to be used with the 0150 * transformation object created by the color space of this KoColor 0151 * or to copy to a different buffer from the same color space 0152 */ 0153 const quint8 * data() const { 0154 return m_data; 0155 } 0156 0157 0158 /** 0159 * Channelwise subtracts \p value from *this and stores the result in *this 0160 * 0161 * Throws a safe assert if the colorspaces of the two colors are different 0162 */ 0163 void subtract(const KoColor &value); 0164 0165 /** 0166 * Channelwise subtracts \p value from a copy of *this and returns the result 0167 * 0168 * Throws a safe assert if the colorspaces of the two colors are different 0169 */ 0170 KoColor subtracted(const KoColor &value) const; 0171 0172 /** 0173 * Channelwise adds \p value to *this and stores the result in *this 0174 * 0175 * Throws a safe assert if the colorspaces of the two colors are different 0176 */ 0177 void add(const KoColor &value); 0178 0179 /** 0180 * Channelwise adds \p value to a copy of *this and returns the result 0181 * 0182 * Throws a safe assert if the colorspaces of the two colors are different 0183 */ 0184 KoColor added(const KoColor &value) const; 0185 0186 /** 0187 * Serialize this color following Create's swatch color specification available 0188 * at https://web.archive.org/web/20110826002520/http://create.freedesktop.org/wiki/Swatches_-_color_file_format/Draft 0189 * 0190 * This function doesn't create the \<color /\> element but rather the \<CMYK /\>, 0191 * \<sRGB /\>, \<RGB /\> ... elements. It is assumed that colorElt is the \<color /\> 0192 * element. 0193 * 0194 * @param colorElt root element for the serialization, it is assumed that this 0195 * element is \<color /\> 0196 * @param doc is the document containing colorElt 0197 */ 0198 void toXML(QDomDocument& doc, QDomElement& colorElt) const; 0199 0200 /** 0201 * Unserialize a color following Create's swatch color specification available 0202 * at https://web.archive.org/web/20110826002520/http://create.freedesktop.org/wiki/Swatches_-_color_file_format/Draft 0203 * 0204 * @param elt the element to unserialize (\<CMYK /\>, \<sRGB /\>, \<RGB /\>) 0205 * @param channelDepthId the bit depth is unspecified by the spec, this allow to select 0206 * a preferred bit depth for creating the KoColor object (if that 0207 * bit depth isn't available, this function will randomly select 0208 * an other bit depth) 0209 * @return the unserialize color, or an empty color object if the function failed 0210 * to unserialize the color 0211 */ 0212 static KoColor fromXML(const QDomElement& elt, const QString & channelDepthId); 0213 0214 /** 0215 * Unserialize a color following Create's swatch color specification available 0216 * at https://web.archive.org/web/20110826002520/http://create.freedesktop.org/wiki/Swatches_-_color_file_format/Draft 0217 * 0218 * @param elt the element to unserialize (\<CMYK /\>, \<sRGB /\>, \<RGB /\>) 0219 * @param channelDepthId the bit depth is unspecified by the spec, this allow to select 0220 * a preferred bit depth for creating the KoColor object (if that 0221 * bit depth isn't available, this function will randomly select 0222 * an other bit depth) 0223 * @param ok If a an error occurs, *ok is set to false; otherwise it's set to true 0224 * @return the unserialize color, or an empty color object if the function failed 0225 * to unserialize the color 0226 */ 0227 static KoColor fromXML(const QDomElement& elt, const QString & channelDepthId, bool* ok); 0228 0229 0230 /** 0231 * @brief toXML creates a string with XML that represents the current color. The XML 0232 * is extended with a "channeldepth" attribute so we can restore the color to the same 0233 * channel depth. 0234 * @return a valid XML document in a string 0235 */ 0236 QString toXML() const; 0237 0238 /** 0239 * @brief fromXML restores a KoColor from a string saved with toXML(). If the 0240 * string does not contain the "channeldepth" attribute, 16 bit integer is assumed. 0241 * @param xml a valid XML document 0242 * @return a new KoColor object 0243 */ 0244 static KoColor fromXML(const QString &xml); 0245 0246 /** 0247 * @brief toSVG11 0248 * @param profileList list of profiles, this will map the profile to a name, so it may be embedded. 0249 * @return a color definition string with both a srgb hexcode fallback as well as a icc-color definition. 0250 */ 0251 QString toSVG11(QHash<QString, const KoColorProfile *> *profileList) const; 0252 0253 /** 0254 * @brief fromSVG11 0255 * Parses a color attribute value and returns a KoColor. SVG defines the colorprofiles elsewhere 0256 * in the file, so this function expects you to first figure out the profiles and which colorspaces 0257 * these match to, and it will then use those colorspaces to generate the kocolor. If it cannot find 0258 * the appropriate colorspace, it will return the color fallback. If that doesn't work, an empty KoColor. 0259 * This function ignores url() values. Colors will be F32 unless they are lab and cmyk, in which case they'll 0260 * be U16. 0261 * 0262 * https://www.w3.org/TR/SVG11/types.html#DataTypeColor for hex, rgb() and colornames 0263 * https://www.w3.org/TR/SVG11/types.html#DataTypeICCColor for icc-color() 0264 * https://www.w3.org/TR/SVG11/painting.html#SpecifyingPaint 0265 * 0266 * @param value the content of the svg color value 0267 * @param profileList list of KoColorProfiles that were found inside the svg file, with the reference names. 0268 * @param current the current color. 0269 * @return a KoColor as parsed from the value string. 0270 */ 0271 static KoColor fromSVG11(const QString value, QHash<QString, const KoColorProfile*> profileList, KoColor current = KoColor()); 0272 0273 /** 0274 * @brief toQString create a user-visible string of the channel names and the channel values 0275 * @param color the color to create the string from 0276 * @return a string that can be used to display the values of this color to the user. 0277 */ 0278 static QString toQString(const KoColor &color); 0279 0280 /** 0281 * store the given key, value pair in a KoColor. 0282 */ 0283 void addMetadata(QString key, QVariant value); 0284 0285 /** 0286 * Get a map with all the metadata 0287 * The metadata is used by parsing functions to store extra data, 0288 * like for example spot color names, or the original parsing model. 0289 */ 0290 QMap<QString, QVariant> metadata() const; 0291 0292 /** 0293 * @brief clearMetadata 0294 * clear th metadata map inside the KoColor. 0295 */ 0296 void clearMetadata(); 0297 0298 #ifndef NODEBUG 0299 /// use qDebug calls to print internal info 0300 void dump() const; 0301 #endif 0302 0303 private: 0304 inline void assertPermanentColorspace() { 0305 #ifndef NODEBUG 0306 if (m_colorSpace) { 0307 Q_ASSERT(*m_colorSpace == *KoColorSpaceRegistry::instance()->permanentColorspace(m_colorSpace)); 0308 } 0309 #endif 0310 } 0311 0312 const KoColorSpace *m_colorSpace; 0313 quint8 m_data[MAX_PIXEL_SIZE]; 0314 quint8 m_size; 0315 QMap<QString, QVariant> m_metadata; 0316 }; 0317 0318 Q_DECLARE_METATYPE(KoColor) 0319 0320 KRITAPIGMENT_EXPORT QDebug operator<<(QDebug dbg, const KoColor &color); 0321 0322 0323 #endif