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