42cf5bc1 |
1 | // Created by: NW,JPB,CAL |
2 | // Copyright (c) 1991-1999 Matra Datavision |
3 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
4 | // |
5 | // This file is part of Open CASCADE Technology software library. |
6 | // |
7 | // This library is free software; you can redistribute it and/or modify it under |
8 | // the terms of the GNU Lesser General Public License version 2.1 as published |
9 | // by the Free Software Foundation, with special exception defined in the file |
10 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
11 | // distribution for complete text of the license and disclaimer of any warranty. |
12 | // |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
15 | |
16 | #ifndef _Quantity_Color_HeaderFile |
17 | #define _Quantity_Color_HeaderFile |
18 | |
19 | #include <Standard.hxx> |
20 | #include <Standard_DefineAlloc.hxx> |
21 | #include <Standard_Handle.hxx> |
42cf5bc1 |
22 | #include <Standard_ShortReal.hxx> |
59ee34ef |
23 | |
42cf5bc1 |
24 | #include <Quantity_NameOfColor.hxx> |
42cf5bc1 |
25 | #include <Quantity_TypeOfColor.hxx> |
59ee34ef |
26 | #include <TCollection_AsciiString.hxx> |
b6472664 |
27 | #include <NCollection_Vec4.hxx> |
aaf8d6a9 |
28 | |
29 | //! This class allows the definition of an RGB color as triplet of 3 normalized floating point values (red, green, blue). |
ba00aab7 |
30 | //! |
31 | //! Although Quantity_Color can be technically used for pass-through storage of RGB triplet in any color space, |
32 | //! other OCCT interfaces taking/returning Quantity_Color would expect them in linear space. |
33 | //! Therefore, take a look into methods converting to and from non-linear sRGB color space, if needed; |
34 | //! for instance, application usually providing color picking within 0..255 range in sRGB color space. |
aaf8d6a9 |
35 | class Quantity_Color |
42cf5bc1 |
36 | { |
37 | public: |
38 | |
39 | DEFINE_STANDARD_ALLOC |
40 | |
aaf8d6a9 |
41 | //! Creates Quantity_NOC_YELLOW color (for historical reasons). |
42 | Quantity_Color() : myRgb (valuesOf (Quantity_NOC_YELLOW, Quantity_TOC_RGB)) {} |
43 | |
59ee34ef |
44 | //! Creates the color from enumeration value. |
aaf8d6a9 |
45 | Quantity_Color (const Quantity_NameOfColor theName) : myRgb (valuesOf (theName, Quantity_TOC_RGB)) {} |
46 | |
82cf4904 |
47 | //! Creates a color according to the definition system theType. |
aaf8d6a9 |
48 | //! Throws exception if values are out of range. |
14b741b0 |
49 | Standard_EXPORT Quantity_Color (const Standard_Real theC1, |
50 | const Standard_Real theC2, |
51 | const Standard_Real theC3, |
82cf4904 |
52 | const Quantity_TypeOfColor theType); |
b6472664 |
53 | |
14b741b0 |
54 | //! Define color from linear RGB values. |
b6472664 |
55 | Standard_EXPORT explicit Quantity_Color (const NCollection_Vec3<float>& theRgb); |
56 | |
aaf8d6a9 |
57 | //! Returns the name of the nearest color from the Quantity_NameOfColor enumeration. |
58 | Standard_EXPORT Quantity_NameOfColor Name() const; |
59 | |
60 | //! Updates the color from specified named color. |
61 | void SetValues (const Quantity_NameOfColor theName) { myRgb = valuesOf (theName, Quantity_TOC_RGB); } |
62 | |
14b741b0 |
63 | //! Return the color as vector of 3 float elements. |
64 | const NCollection_Vec3<float>& Rgb () const { return myRgb; } |
65 | |
aaf8d6a9 |
66 | //! Return the color as vector of 3 float elements. |
67 | operator const NCollection_Vec3<float>&() const { return myRgb; } |
68 | |
14b741b0 |
69 | //! Returns in theC1, theC2 and theC3 the components of this color |
70 | //! according to the color system definition theType. |
71 | Standard_EXPORT void Values (Standard_Real& theC1, |
72 | Standard_Real& theC2, |
73 | Standard_Real& theC3, |
aaf8d6a9 |
74 | const Quantity_TypeOfColor theType) const; |
75 | |
82cf4904 |
76 | //! Updates a color according to the mode specified by theType. |
aaf8d6a9 |
77 | //! Throws exception if values are out of range. |
14b741b0 |
78 | Standard_EXPORT void SetValues (const Standard_Real theC1, |
79 | const Standard_Real theC2, |
80 | const Standard_Real theC3, |
82cf4904 |
81 | const Quantity_TypeOfColor theType); |
aaf8d6a9 |
82 | |
83 | //! Returns the Red component (quantity of red) of the color within range [0.0; 1.0]. |
84 | Standard_Real Red() const { return myRgb.r(); } |
85 | |
82cf4904 |
86 | //! Returns the Green component (quantity of green) of the color within range [0.0; 1.0]. |
aaf8d6a9 |
87 | Standard_Real Green() const { return myRgb.g(); } |
88 | |
89 | //! Returns the Blue component (quantity of blue) of the color within range [0.0; 1.0]. |
90 | Standard_Real Blue() const { return myRgb.b(); } |
91 | |
82cf4904 |
92 | //! Returns the Hue component (hue angle) of the color |
93 | //! in degrees within range [0.0; 360.0], 0.0 being Red. |
94 | //! -1.0 is a special value reserved for grayscale color (S should be 0.0) |
ba00aab7 |
95 | Standard_Real Hue() const { return Convert_LinearRGB_To_HLS (myRgb)[0]; } |
aaf8d6a9 |
96 | |
82cf4904 |
97 | //! Returns the Light component (value of the lightness) of the color within range [0.0; 1.0]. |
ba00aab7 |
98 | Standard_Real Light() const { return Convert_LinearRGB_To_HLS (myRgb)[1]; } |
aaf8d6a9 |
99 | |
100 | //! Increases or decreases the intensity (variation of the lightness). |
101 | //! The delta is a percentage. Any value greater than zero will increase the intensity. |
102 | //! The variation is expressed as a percentage of the current value. |
103 | Standard_EXPORT void ChangeIntensity (const Standard_Real theDelta); |
104 | |
82cf4904 |
105 | //! Returns the Saturation component (value of the saturation) of the color within range [0.0; 1.0]. |
ba00aab7 |
106 | Standard_Real Saturation() const { return Convert_LinearRGB_To_HLS (myRgb)[2]; } |
b6472664 |
107 | |
aaf8d6a9 |
108 | //! Increases or decreases the contrast (variation of the saturation). |
109 | //! The delta is a percentage. Any value greater than zero will increase the contrast. |
110 | //! The variation is expressed as a percentage of the current value. |
111 | Standard_EXPORT void ChangeContrast (const Standard_Real theDelta); |
b6472664 |
112 | |
aaf8d6a9 |
113 | //! Returns TRUE if the distance between two colors is greater than Epsilon(). |
ba00aab7 |
114 | Standard_Boolean IsDifferent (const Quantity_Color& theOther) const { return (SquareDistance (theOther) > Epsilon() * Epsilon()); } |
aaf8d6a9 |
115 | |
116 | //! Alias to IsDifferent(). |
117 | Standard_Boolean operator!= (const Quantity_Color& theOther) const { return IsDifferent (theOther); } |
118 | |
119 | //! Returns TRUE if the distance between two colors is no greater than Epsilon(). |
ba00aab7 |
120 | Standard_Boolean IsEqual (const Quantity_Color& theOther) const { return (SquareDistance (theOther) <= Epsilon() * Epsilon()); } |
aaf8d6a9 |
121 | |
122 | //! Alias to IsEqual(). |
123 | Standard_Boolean operator== (const Quantity_Color& theOther) const { return IsEqual (theOther); } |
42cf5bc1 |
124 | |
aaf8d6a9 |
125 | //! Returns the distance between two colors. It's a value between 0 and the square root of 3 (the black/white distance). |
126 | Standard_Real Distance (const Quantity_Color& theColor) const |
127 | { |
128 | return (NCollection_Vec3<Standard_Real> (myRgb) - NCollection_Vec3<Standard_Real> (theColor.myRgb)).Modulus(); |
129 | } |
130 | |
131 | //! Returns the square of distance between two colors. |
132 | Standard_Real SquareDistance (const Quantity_Color& theColor) const |
133 | { |
134 | return (NCollection_Vec3<Standard_Real> (myRgb) - NCollection_Vec3<Standard_Real> (theColor.myRgb)).SquareModulus(); |
135 | } |
136 | |
137 | //! Returns the percentage change of contrast and intensity between this and another color. |
138 | //! <DC> and <DI> are percentages, either positive or negative. |
139 | //! The calculation is with respect to this color. |
140 | //! If <DC> is positive then <me> is more contrasty. |
141 | //! If <DI> is positive then <me> is more intense. |
142 | Standard_EXPORT void Delta (const Quantity_Color& theColor, |
143 | Standard_Real& DC, Standard_Real& DI) const; |
144 | |
14b741b0 |
145 | //! Returns the value of the perceptual difference between this color |
146 | //! and @p theOther, computed using the CIEDE2000 formula. |
147 | //! The difference is in range [0, 100.], with 1 approximately corresponding |
148 | //! to the minimal percievable difference (usually difference 5 or greater is |
149 | //! needed for the difference to be recognizable in practice). |
150 | Standard_EXPORT Standard_Real DeltaE2000 (const Quantity_Color& theOther) const; |
151 | |
aaf8d6a9 |
152 | public: |
153 | |
154 | //! Returns the color from Quantity_NameOfColor enumeration nearest to specified RGB values. |
155 | static Quantity_NameOfColor Name (const Standard_Real theR, const Standard_Real theG, const Standard_Real theB) |
156 | { |
157 | const Quantity_Color aColor (theR, theG, theB, Quantity_TOC_RGB); |
158 | return aColor.Name(); |
159 | } |
160 | |
161 | //! Returns the name of the color identified by the given Quantity_NameOfColor enumeration value. |
162 | Standard_EXPORT static Standard_CString StringName (const Quantity_NameOfColor theColor); |
163 | |
42cf5bc1 |
164 | //! Finds color from predefined names. |
aaf8d6a9 |
165 | //! For example, the name of the color which corresponds to "BLACK" is Quantity_NOC_BLACK. |
166 | //! Returns FALSE if name is unknown. |
42cf5bc1 |
167 | Standard_EXPORT static Standard_Boolean ColorFromName (const Standard_CString theName, Quantity_NameOfColor& theColor); |
f9b30c0d |
168 | |
169 | //! Finds color from predefined names. |
f9b30c0d |
170 | //! @param theColorNameString the color name |
171 | //! @param theColor a found color |
172 | //! @return false if the color name is unknown, or true if the search by color name was successful |
173 | static Standard_Boolean ColorFromName (const Standard_CString theColorNameString, Quantity_Color& theColor) |
174 | { |
175 | Quantity_NameOfColor aColorName = Quantity_NOC_BLACK; |
176 | if (!ColorFromName (theColorNameString, aColorName)) |
177 | { |
178 | return false; |
179 | } |
180 | theColor = aColorName; |
181 | return true; |
182 | } |
183 | |
14b741b0 |
184 | public: |
185 | //!@name Routines converting colors between different encodings and color spaces |
186 | |
aaf8d6a9 |
187 | //! Parses the string as a hex color (like "#FF0" for short sRGB color, or "#FFFF00" for sRGB color) |
f9b30c0d |
188 | //! @param theHexColorString the string to be parsed |
189 | //! @param theColor a color that is a result of parsing |
190 | //! @return true if parsing was successful, or false otherwise |
191 | Standard_EXPORT static bool ColorFromHex (const Standard_CString theHexColorString, Quantity_Color& theColor); |
192 | |
59ee34ef |
193 | //! Returns hex sRGB string in format "#FFAAFF". |
9196ea9d |
194 | static TCollection_AsciiString ColorToHex (const Quantity_Color& theColor, |
195 | const bool theToPrefixHash = true) |
59ee34ef |
196 | { |
ba00aab7 |
197 | NCollection_Vec3<Standard_ShortReal> anSRgb = Convert_LinearRGB_To_sRGB ((NCollection_Vec3<Standard_ShortReal> )theColor); |
9196ea9d |
198 | NCollection_Vec3<Standard_Integer> anSRgbInt (anSRgb * 255.0f + NCollection_Vec3<Standard_ShortReal> (0.5f)); |
59ee34ef |
199 | char aBuff[10]; |
9196ea9d |
200 | Sprintf (aBuff, theToPrefixHash ? "#%02X%02X%02X" : "%02X%02X%02X", |
201 | anSRgbInt.r(), anSRgbInt.g(), anSRgbInt.b()); |
59ee34ef |
202 | return aBuff; |
203 | } |
204 | |
aaf8d6a9 |
205 | //! Converts sRGB components into HLS ones. |
206 | Standard_EXPORT static NCollection_Vec3<float> Convert_sRGB_To_HLS (const NCollection_Vec3<float>& theRgb); |
207 | |
42cf5bc1 |
208 | //! Converts HLS components into RGB ones. |
aaf8d6a9 |
209 | Standard_EXPORT static NCollection_Vec3<float> Convert_HLS_To_sRGB (const NCollection_Vec3<float>& theHls); |
210 | |
211 | //! Converts Linear RGB components into HLS ones. |
212 | static NCollection_Vec3<float> Convert_LinearRGB_To_HLS (const NCollection_Vec3<float>& theRgb) |
213 | { |
214 | return Convert_sRGB_To_HLS (Convert_LinearRGB_To_sRGB (theRgb)); |
215 | } |
216 | |
217 | //! Converts HLS components into linear RGB ones. |
218 | static NCollection_Vec3<float> Convert_HLS_To_LinearRGB (const NCollection_Vec3<float>& theHls) |
219 | { |
220 | return Convert_sRGB_To_LinearRGB (Convert_HLS_To_sRGB (theHls)); |
221 | } |
222 | |
14b741b0 |
223 | //! Converts linear RGB components into CIE Lab ones. |
224 | Standard_EXPORT static NCollection_Vec3<float> Convert_LinearRGB_To_Lab (const NCollection_Vec3<float>& theRgb); |
225 | |
226 | //! Converts CIE Lab components into CIE Lch ones. |
227 | Standard_EXPORT static NCollection_Vec3<float> Convert_Lab_To_Lch (const NCollection_Vec3<float>& theLab); |
228 | |
229 | //! Converts CIE Lab components into linear RGB ones. |
230 | //! Note that the resulting values may be out of the valid range for RGB. |
231 | Standard_EXPORT static NCollection_Vec3<float> Convert_Lab_To_LinearRGB (const NCollection_Vec3<float>& theLab); |
232 | |
233 | //! Converts CIE Lch components into CIE Lab ones. |
234 | Standard_EXPORT static NCollection_Vec3<float> Convert_Lch_To_Lab (const NCollection_Vec3<float>& theLch); |
235 | |
aaf8d6a9 |
236 | //! Convert the color value to ARGB integer value, with alpha equals to 0. |
237 | //! So the output is formatted as 0x00RRGGBB. |
ba00aab7 |
238 | //! Note that this unpacking does NOT involve non-linear sRGB -> linear RGB conversion, |
239 | //! as would be usually expected for RGB color packed into 4 bytes. |
aaf8d6a9 |
240 | //! @param theColor [in] color to convert |
241 | //! @param theARGB [out] result color encoded as integer |
242 | static void Color2argb (const Quantity_Color& theColor, |
243 | Standard_Integer& theARGB) |
244 | { |
245 | const NCollection_Vec3<Standard_Integer> aColor (static_cast<Standard_Integer> (255.0f * theColor.myRgb.r() + 0.5f), |
246 | static_cast<Standard_Integer> (255.0f * theColor.myRgb.g() + 0.5f), |
247 | static_cast<Standard_Integer> (255.0f * theColor.myRgb.b() + 0.5f)); |
248 | theARGB = (((aColor.r() & 0xff) << 16) |
249 | | ((aColor.g() & 0xff) << 8) |
250 | | (aColor.b() & 0xff)); |
251 | } |
252 | |
ba00aab7 |
253 | //! Convert integer ARGB value to Color. Alpha bits are ignored. |
254 | //! Note that this packing does NOT involve linear -> non-linear sRGB conversion, |
255 | //! as would be usually expected to preserve higher (for human eye) color precision in 4 bytes. |
aaf8d6a9 |
256 | static void Argb2color (const Standard_Integer theARGB, |
257 | Quantity_Color& theColor) |
258 | { |
259 | const NCollection_Vec3<Standard_Real> aColor (static_cast <Standard_Real> ((theARGB & 0xff0000) >> 16), |
260 | static_cast <Standard_Real> ((theARGB & 0x00ff00) >> 8), |
261 | static_cast <Standard_Real> ((theARGB & 0x0000ff))); |
ba00aab7 |
262 | theColor.SetValues (aColor.r() / 255.0, aColor.g() / 255.0, aColor.b() / 255.0, Quantity_TOC_sRGB); |
aaf8d6a9 |
263 | } |
264 | |
aaf8d6a9 |
265 | //! Convert linear RGB component into sRGB using OpenGL specs formula (double precision), also known as gamma correction. |
266 | static Standard_Real Convert_LinearRGB_To_sRGB (Standard_Real theLinearValue) |
267 | { |
268 | return theLinearValue <= 0.0031308 |
269 | ? theLinearValue * 12.92 |
270 | : Pow (theLinearValue, 1.0/2.4) * 1.055 - 0.055; |
271 | } |
272 | |
273 | //! Convert linear RGB component into sRGB using OpenGL specs formula (single precision), also known as gamma correction. |
274 | static float Convert_LinearRGB_To_sRGB (float theLinearValue) |
275 | { |
276 | return theLinearValue <= 0.0031308f |
277 | ? theLinearValue * 12.92f |
278 | : powf (theLinearValue, 1.0f/2.4f) * 1.055f - 0.055f; |
279 | } |
280 | |
281 | //! Convert sRGB component into linear RGB using OpenGL specs formula (double precision), also known as gamma correction. |
282 | static Standard_Real Convert_sRGB_To_LinearRGB (Standard_Real thesRGBValue) |
283 | { |
284 | return thesRGBValue <= 0.04045 |
285 | ? thesRGBValue / 12.92 |
286 | : Pow ((thesRGBValue + 0.055) / 1.055, 2.4); |
287 | } |
288 | |
289 | //! Convert sRGB component into linear RGB using OpenGL specs formula (single precision), also known as gamma correction. |
290 | static float Convert_sRGB_To_LinearRGB (float thesRGBValue) |
291 | { |
292 | return thesRGBValue <= 0.04045f |
293 | ? thesRGBValue / 12.92f |
294 | : powf ((thesRGBValue + 0.055f) / 1.055f, 2.4f); |
295 | } |
296 | |
297 | //! Convert linear RGB components into sRGB using OpenGL specs formula. |
298 | template<typename T> |
299 | static NCollection_Vec3<T> Convert_LinearRGB_To_sRGB (const NCollection_Vec3<T>& theRGB) |
300 | { |
301 | return NCollection_Vec3<T> (Convert_LinearRGB_To_sRGB (theRGB.r()), |
302 | Convert_LinearRGB_To_sRGB (theRGB.g()), |
303 | Convert_LinearRGB_To_sRGB (theRGB.b())); |
304 | } |
305 | |
306 | //! Convert sRGB components into linear RGB using OpenGL specs formula. |
307 | template<typename T> |
308 | static NCollection_Vec3<T> Convert_sRGB_To_LinearRGB (const NCollection_Vec3<T>& theRGB) |
309 | { |
310 | return NCollection_Vec3<T> (Convert_sRGB_To_LinearRGB (theRGB.r()), |
311 | Convert_sRGB_To_LinearRGB (theRGB.g()), |
312 | Convert_sRGB_To_LinearRGB (theRGB.b())); |
313 | } |
314 | |
aaf8d6a9 |
315 | //! Convert linear RGB component into sRGB using approximated uniform gamma coefficient 2.2. |
316 | static float Convert_LinearRGB_To_sRGB_approx22 (float theLinearValue) { return powf (theLinearValue, 2.2f); } |
317 | |
318 | //! Convert sRGB component into linear RGB using approximated uniform gamma coefficient 2.2 |
319 | static float Convert_sRGB_To_LinearRGB_approx22 (float thesRGBValue) { return powf (thesRGBValue, 1.0f/2.2f); } |
320 | |
321 | //! Convert linear RGB components into sRGB using approximated uniform gamma coefficient 2.2 |
322 | static NCollection_Vec3<float> Convert_LinearRGB_To_sRGB_approx22 (const NCollection_Vec3<float>& theRGB) |
323 | { |
324 | return NCollection_Vec3<float> (Convert_LinearRGB_To_sRGB_approx22 (theRGB.r()), |
325 | Convert_LinearRGB_To_sRGB_approx22 (theRGB.g()), |
326 | Convert_LinearRGB_To_sRGB_approx22 (theRGB.b())); |
327 | } |
328 | |
329 | //! Convert sRGB components into linear RGB using approximated uniform gamma coefficient 2.2 |
330 | static NCollection_Vec3<float> Convert_sRGB_To_LinearRGB_approx22 (const NCollection_Vec3<float>& theRGB) |
331 | { |
332 | return NCollection_Vec3<float> (Convert_sRGB_To_LinearRGB_approx22 (theRGB.r()), |
333 | Convert_sRGB_To_LinearRGB_approx22 (theRGB.g()), |
334 | Convert_sRGB_To_LinearRGB_approx22 (theRGB.b())); |
335 | } |
336 | |
ba00aab7 |
337 | //! Converts HLS components into sRGB ones. |
aaf8d6a9 |
338 | static void HlsRgb (const Standard_Real theH, const Standard_Real theL, const Standard_Real theS, |
339 | Standard_Real& theR, Standard_Real& theG, Standard_Real& theB) |
340 | { |
341 | const NCollection_Vec3<float> anRgb = Convert_HLS_To_sRGB (NCollection_Vec3<float> ((float )theH, (float )theL, (float )theS)); |
342 | theR = anRgb[0]; |
343 | theG = anRgb[1]; |
344 | theB = anRgb[2]; |
345 | } |
346 | |
ba00aab7 |
347 | //! Converts sRGB components into HLS ones. |
aaf8d6a9 |
348 | static void RgbHls (const Standard_Real theR, const Standard_Real theG, const Standard_Real theB, |
349 | Standard_Real& theH, Standard_Real& theL, Standard_Real& theS) |
350 | { |
351 | const NCollection_Vec3<float> aHls = Convert_sRGB_To_HLS (NCollection_Vec3<float> ((float )theR, (float )theG, (float )theB)); |
352 | theH = aHls[0]; |
353 | theL = aHls[1]; |
354 | theS = aHls[2]; |
355 | } |
356 | |
14b741b0 |
357 | public: |
358 | |
359 | //! Returns the value used to compare two colors for equality; 0.0001 by default. |
360 | Standard_EXPORT static Standard_Real Epsilon(); |
361 | |
362 | //! Set the value used to compare two colors for equality. |
363 | Standard_EXPORT static void SetEpsilon (const Standard_Real theEpsilon); |
42cf5bc1 |
364 | |
0904aa63 |
365 | //! Dumps the content of me into the stream |
bc73b006 |
366 | Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const; |
0904aa63 |
367 | |
42cf5bc1 |
368 | private: |
369 | |
aaf8d6a9 |
370 | //! Returns the values of a predefined color according to the mode. |
371 | Standard_EXPORT static NCollection_Vec3<float> valuesOf (const Quantity_NameOfColor theName, |
372 | const Quantity_TypeOfColor theType); |
373 | |
374 | private: |
375 | |
376 | NCollection_Vec3<float> myRgb; |
42cf5bc1 |
377 | |
42cf5bc1 |
378 | }; |
379 | |
42cf5bc1 |
380 | #endif // _Quantity_Color_HeaderFile |