0030969: Coding Rules - refactor Quantity_Color.cxx color table definition
[occt.git] / src / Quantity / Quantity_Color.hxx
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>
22 #include <Standard_ShortReal.hxx>
23
24 #include <Quantity_NameOfColor.hxx>
25 #include <Quantity_TypeOfColor.hxx>
26 #include <TCollection_AsciiString.hxx>
27 #include <NCollection_Vec4.hxx>
28
29 //! This class allows the definition of an RGB color as triplet of 3 normalized floating point values (red, green, blue).
30 class Quantity_Color
31 {
32 public:
33
34   DEFINE_STANDARD_ALLOC
35
36   //! Creates Quantity_NOC_YELLOW color (for historical reasons).
37   Quantity_Color() : myRgb (valuesOf (Quantity_NOC_YELLOW, Quantity_TOC_RGB)) {}
38
39   //! Creates the color from enumeration value.
40   Quantity_Color (const Quantity_NameOfColor theName) : myRgb (valuesOf (theName, Quantity_TOC_RGB)) {}
41
42   //! Creates a color according to the definition system theType.
43   //! Throws exception if values are out of range.
44   Standard_EXPORT Quantity_Color (const Standard_Real theR1,
45                                   const Standard_Real theR2,
46                                   const Standard_Real theR3,
47                                   const Quantity_TypeOfColor theType);
48
49   //! Define color from RGB values.
50   Standard_EXPORT explicit Quantity_Color (const NCollection_Vec3<float>& theRgb);
51
52   //! Returns the name of the nearest color from the Quantity_NameOfColor enumeration.
53   Standard_EXPORT Quantity_NameOfColor Name() const;
54
55   //! Updates the color from specified named color.
56   void SetValues (const Quantity_NameOfColor theName) { myRgb = valuesOf (theName, Quantity_TOC_RGB); }
57
58   //! Return the color as vector of 3 float elements.
59   operator const NCollection_Vec3<float>&() const { return myRgb; }
60
61   //! Returns in theR1, theR2 and theR3 the components of this color according to the color system definition theType.
62   Standard_EXPORT void Values (Standard_Real& theR1,
63                                Standard_Real& theR2,
64                                Standard_Real& theR3,
65                                const Quantity_TypeOfColor theType) const;
66
67   //! Updates a color according to the mode specified by theType.
68   //! Throws exception if values are out of range.
69   Standard_EXPORT void SetValues (const Standard_Real theR1,
70                                   const Standard_Real theR2,
71                                   const Standard_Real theR3,
72                                   const Quantity_TypeOfColor theType);
73
74   //! Returns the Red component (quantity of red) of the color within range [0.0; 1.0].
75   Standard_Real Red() const { return myRgb.r(); }
76
77   //! Returns the Green component (quantity of green) of the color within range [0.0; 1.0].
78   Standard_Real Green() const { return myRgb.g(); }
79
80   //! Returns the Blue component (quantity of blue) of the color within range [0.0; 1.0].
81   Standard_Real Blue() const { return myRgb.b(); }
82
83   //! Returns the Hue component (hue angle) of the color
84   //! in degrees within range [0.0; 360.0], 0.0 being Red.
85   //! -1.0 is a special value reserved for grayscale color (S should be 0.0)
86   Standard_Real Hue() const { return Convert_sRGB_To_HLS (myRgb)[0]; }
87
88   //! Returns the Light component (value of the lightness) of the color within range [0.0; 1.0].
89   Standard_Real Light() const { return Convert_sRGB_To_HLS (myRgb)[1]; }
90
91   //! Increases or decreases the intensity (variation of the lightness).
92   //! The delta is a percentage. Any value greater than zero will increase the intensity.
93   //! The variation is expressed as a percentage of the current value.
94   Standard_EXPORT void ChangeIntensity (const Standard_Real theDelta);
95
96   //! Returns the Saturation component (value of the saturation) of the color within range [0.0; 1.0].
97   Standard_Real Saturation() const { return Convert_sRGB_To_HLS (myRgb)[2]; }
98
99   //! Increases or decreases the contrast (variation of the saturation).
100   //! The delta is a percentage. Any value greater than zero will increase the contrast.
101   //! The variation is expressed as a percentage of the current value.
102   Standard_EXPORT void ChangeContrast (const Standard_Real theDelta);
103
104   //! Returns TRUE if the distance between two colors is greater than Epsilon().
105   Standard_Boolean IsDifferent (const Quantity_Color& theOther) const { return (Distance (theOther) > Epsilon()); }
106
107   //! Alias to IsDifferent().
108   Standard_Boolean operator!=  (const Quantity_Color& theOther) const { return IsDifferent (theOther); }
109
110   //! Returns TRUE if the distance between two colors is no greater than Epsilon().
111   Standard_Boolean IsEqual    (const Quantity_Color& theOther) const { return (Distance (theOther) <= Epsilon()); }
112
113   //! Alias to IsEqual().
114   Standard_Boolean operator== (const Quantity_Color& theOther) const { return IsEqual (theOther); }
115   
116   //! Returns the distance between two colors. It's a value between 0 and the square root of 3 (the black/white distance).
117   Standard_Real Distance (const Quantity_Color& theColor) const
118   {
119     return (NCollection_Vec3<Standard_Real> (myRgb) - NCollection_Vec3<Standard_Real> (theColor.myRgb)).Modulus();
120   }
121
122   //! Returns the square of distance between two colors.
123   Standard_Real SquareDistance (const Quantity_Color& theColor) const
124   {
125     return (NCollection_Vec3<Standard_Real> (myRgb) - NCollection_Vec3<Standard_Real> (theColor.myRgb)).SquareModulus();
126   }
127
128   //! Returns the percentage change of contrast and intensity between this and another color.
129   //! <DC> and <DI> are percentages, either positive or negative.
130   //! The calculation is with respect to this color.
131   //! If <DC> is positive then <me> is more contrasty.
132   //! If <DI> is positive then <me> is more intense.
133   Standard_EXPORT void Delta (const Quantity_Color& theColor,
134                               Standard_Real& DC, Standard_Real& DI) const;
135
136 public:
137
138   //! Returns the color from Quantity_NameOfColor enumeration nearest to specified RGB values.
139   static Quantity_NameOfColor Name (const Standard_Real theR, const Standard_Real theG, const Standard_Real theB)
140   {
141     const Quantity_Color aColor (theR, theG, theB, Quantity_TOC_RGB);
142     return aColor.Name();
143   }
144
145   //! Returns the name of the color identified by the given Quantity_NameOfColor enumeration value.
146   Standard_EXPORT static Standard_CString StringName (const Quantity_NameOfColor theColor);
147
148   //! Finds color from predefined names.
149   //! For example, the name of the color which corresponds to "BLACK" is Quantity_NOC_BLACK.
150   //! Returns FALSE if name is unknown.
151   Standard_EXPORT static Standard_Boolean ColorFromName (const Standard_CString theName, Quantity_NameOfColor& theColor);
152
153   //! Finds color from predefined names.
154   //! @param theColorNameString the color name
155   //! @param theColor a found color
156   //! @return false if the color name is unknown, or true if the search by color name was successful
157   static Standard_Boolean ColorFromName (const Standard_CString theColorNameString, Quantity_Color& theColor)
158   {
159     Quantity_NameOfColor aColorName = Quantity_NOC_BLACK;
160     if (!ColorFromName (theColorNameString, aColorName))
161     {
162       return false;
163     }
164     theColor = aColorName;
165     return true;
166   }
167
168   //! Parses the string as a hex color (like "#FF0" for short sRGB color, or "#FFFF00" for sRGB color)
169   //! @param theHexColorString the string to be parsed
170   //! @param theColor a color that is a result of parsing
171   //! @return true if parsing was successful, or false otherwise
172   Standard_EXPORT static bool ColorFromHex (const Standard_CString theHexColorString, Quantity_Color& theColor);
173
174   //! Returns hex sRGB string in format "#FFAAFF".
175   static TCollection_AsciiString ColorToHex (const Quantity_Color& theColor,
176                                              const bool theToPrefixHash = true)
177   {
178     NCollection_Vec3<Standard_ShortReal> anSRgb = (NCollection_Vec3<Standard_ShortReal> )theColor;
179     NCollection_Vec3<Standard_Integer> anSRgbInt (anSRgb * 255.0f + NCollection_Vec3<Standard_ShortReal> (0.5f));
180     char aBuff[10];
181     Sprintf (aBuff, theToPrefixHash ? "#%02X%02X%02X" : "%02X%02X%02X",
182              anSRgbInt.r(), anSRgbInt.g(), anSRgbInt.b());
183     return aBuff;
184   }
185
186   //! Converts sRGB components into HLS ones.
187   Standard_EXPORT static NCollection_Vec3<float> Convert_sRGB_To_HLS (const NCollection_Vec3<float>& theRgb);
188
189   //! Converts HLS components into RGB ones.
190   Standard_EXPORT static NCollection_Vec3<float> Convert_HLS_To_sRGB (const NCollection_Vec3<float>& theHls);
191
192   //! Converts Linear RGB components into HLS ones.
193   static NCollection_Vec3<float> Convert_LinearRGB_To_HLS (const NCollection_Vec3<float>& theRgb)
194   {
195     return Convert_sRGB_To_HLS (Convert_LinearRGB_To_sRGB (theRgb));
196   }
197
198   //! Converts HLS components into linear RGB ones.
199   static NCollection_Vec3<float> Convert_HLS_To_LinearRGB (const NCollection_Vec3<float>& theHls)
200   {
201     return Convert_sRGB_To_LinearRGB (Convert_HLS_To_sRGB (theHls));
202   }
203
204   //! Convert the color value to ARGB integer value, with alpha equals to 0.
205   //! So the output is formatted as 0x00RRGGBB.
206   //! @param theColor [in] color to convert
207   //! @param theARGB [out] result color encoded as integer
208   static void Color2argb (const Quantity_Color& theColor,
209                           Standard_Integer& theARGB)
210   {
211     const NCollection_Vec3<Standard_Integer> aColor (static_cast<Standard_Integer> (255.0f * theColor.myRgb.r() + 0.5f),
212                                                      static_cast<Standard_Integer> (255.0f * theColor.myRgb.g() + 0.5f),
213                                                      static_cast<Standard_Integer> (255.0f * theColor.myRgb.b() + 0.5f));
214     theARGB = (((aColor.r() & 0xff) << 16)
215              | ((aColor.g() & 0xff) << 8)
216              |  (aColor.b() & 0xff));
217   }
218
219   //! Convert integer ARGB value to Color. Alpha bits are ignored
220   static void Argb2color (const Standard_Integer theARGB,
221                           Quantity_Color& theColor)
222   {
223     const NCollection_Vec3<Standard_Real> aColor (static_cast <Standard_Real> ((theARGB & 0xff0000) >> 16),
224                                                   static_cast <Standard_Real> ((theARGB & 0x00ff00) >> 8),
225                                                   static_cast <Standard_Real> ((theARGB & 0x0000ff)));
226     theColor.SetValues (aColor.r() / 255.0, aColor.g() / 255.0, aColor.b() / 255.0, Quantity_TOC_RGB);
227   }
228
229 public:
230
231   //! Convert linear RGB component into sRGB using OpenGL specs formula (double precision), also known as gamma correction.
232   static Standard_Real Convert_LinearRGB_To_sRGB (Standard_Real theLinearValue)
233   {
234     return theLinearValue <= 0.0031308
235          ? theLinearValue * 12.92
236          : Pow (theLinearValue, 1.0/2.4) * 1.055 - 0.055;
237   }
238
239   //! Convert linear RGB component into sRGB using OpenGL specs formula (single precision), also known as gamma correction.
240   static float Convert_LinearRGB_To_sRGB (float theLinearValue)
241   {
242     return theLinearValue <= 0.0031308f
243          ? theLinearValue * 12.92f
244          : powf (theLinearValue, 1.0f/2.4f) * 1.055f - 0.055f;
245   }
246
247   //! Convert sRGB component into linear RGB using OpenGL specs formula (double precision), also known as gamma correction.
248   static Standard_Real Convert_sRGB_To_LinearRGB (Standard_Real thesRGBValue)
249   {
250     return thesRGBValue <= 0.04045
251          ? thesRGBValue / 12.92
252          : Pow ((thesRGBValue + 0.055) / 1.055, 2.4);
253   }
254
255   //! Convert sRGB component into linear RGB using OpenGL specs formula (single precision), also known as gamma correction.
256   static float Convert_sRGB_To_LinearRGB (float thesRGBValue)
257   {
258     return thesRGBValue <= 0.04045f
259          ? thesRGBValue / 12.92f
260          : powf ((thesRGBValue + 0.055f) / 1.055f, 2.4f);
261   }
262
263   //! Convert linear RGB components into sRGB using OpenGL specs formula.
264   template<typename T>
265   static NCollection_Vec3<T> Convert_LinearRGB_To_sRGB (const NCollection_Vec3<T>& theRGB)
266   {
267     return NCollection_Vec3<T> (Convert_LinearRGB_To_sRGB (theRGB.r()),
268                                 Convert_LinearRGB_To_sRGB (theRGB.g()),
269                                 Convert_LinearRGB_To_sRGB (theRGB.b()));
270   }
271
272   //! Convert sRGB components into linear RGB using OpenGL specs formula.
273   template<typename T>
274   static NCollection_Vec3<T> Convert_sRGB_To_LinearRGB (const NCollection_Vec3<T>& theRGB)
275   {
276     return NCollection_Vec3<T> (Convert_sRGB_To_LinearRGB (theRGB.r()),
277                                 Convert_sRGB_To_LinearRGB (theRGB.g()),
278                                 Convert_sRGB_To_LinearRGB (theRGB.b()));
279   }
280
281 public:
282
283   //! Convert linear RGB component into sRGB using approximated uniform gamma coefficient 2.2.
284   static float Convert_LinearRGB_To_sRGB_approx22 (float theLinearValue) { return powf (theLinearValue, 2.2f); }
285
286   //! Convert sRGB component into linear RGB using approximated uniform gamma coefficient 2.2
287   static float Convert_sRGB_To_LinearRGB_approx22 (float thesRGBValue) { return powf (thesRGBValue, 1.0f/2.2f); }
288
289   //! Convert linear RGB components into sRGB using approximated uniform gamma coefficient 2.2
290   static NCollection_Vec3<float> Convert_LinearRGB_To_sRGB_approx22 (const NCollection_Vec3<float>& theRGB)
291   {
292     return NCollection_Vec3<float> (Convert_LinearRGB_To_sRGB_approx22 (theRGB.r()),
293                                     Convert_LinearRGB_To_sRGB_approx22 (theRGB.g()),
294                                     Convert_LinearRGB_To_sRGB_approx22 (theRGB.b()));
295   }
296
297   //! Convert sRGB components into linear RGB using approximated uniform gamma coefficient 2.2
298   static NCollection_Vec3<float> Convert_sRGB_To_LinearRGB_approx22 (const NCollection_Vec3<float>& theRGB)
299   {
300     return NCollection_Vec3<float> (Convert_sRGB_To_LinearRGB_approx22 (theRGB.r()),
301                                     Convert_sRGB_To_LinearRGB_approx22 (theRGB.g()),
302                                     Convert_sRGB_To_LinearRGB_approx22 (theRGB.b()));
303   }
304
305 public:
306
307   //! Returns the value used to compare two colors for equality; 0.0001 by default.
308   Standard_EXPORT static Standard_Real Epsilon();
309
310   //! Set the value used to compare two colors for equality.
311   Standard_EXPORT static void SetEpsilon (const Standard_Real theEpsilon);
312
313   //! Converts HLS components into RGB ones.
314   static void HlsRgb (const Standard_Real theH, const Standard_Real theL, const Standard_Real theS,
315                       Standard_Real& theR, Standard_Real& theG, Standard_Real& theB)
316   {
317     const NCollection_Vec3<float> anRgb = Convert_HLS_To_sRGB (NCollection_Vec3<float> ((float )theH, (float )theL, (float )theS));
318     theR = anRgb[0];
319     theG = anRgb[1];
320     theB = anRgb[2];
321   }
322
323   //! Converts RGB components into HLS ones.
324   static void RgbHls (const Standard_Real theR, const Standard_Real theG, const Standard_Real theB,
325                       Standard_Real& theH, Standard_Real& theL, Standard_Real& theS)
326   {
327     const NCollection_Vec3<float> aHls = Convert_sRGB_To_HLS (NCollection_Vec3<float> ((float )theR, (float )theG, (float )theB));
328     theH = aHls[0];
329     theL = aHls[1];
330     theS = aHls[2];
331   }
332
333   //! Internal test
334   Standard_EXPORT static void Test();
335
336   //! Dumps the content of me into the stream
337   Standard_EXPORT void DumpJson (Standard_OStream& theOStream, const Standard_Integer theDepth = -1) const;
338
339 private:
340
341   //! Returns the values of a predefined color according to the mode.
342   Standard_EXPORT static NCollection_Vec3<float> valuesOf (const Quantity_NameOfColor theName,
343                                                            const Quantity_TypeOfColor theType);
344
345 private:
346
347   NCollection_Vec3<float> myRgb;
348
349 };
350
351 #endif // _Quantity_Color_HeaderFile