Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-07-29 09:16:12

0001 // Created by: NW,JPB,CAL
0002 // Copyright (c) 1991-1999 Matra Datavision
0003 // Copyright (c) 1999-2014 OPEN CASCADE SAS
0004 //
0005 // This file is part of Open CASCADE Technology software library.
0006 //
0007 // This library is free software; you can redistribute it and/or modify it under
0008 // the terms of the GNU Lesser General Public License version 2.1 as published
0009 // by the Free Software Foundation, with special exception defined in the file
0010 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0011 // distribution for complete text of the license and disclaimer of any warranty.
0012 //
0013 // Alternatively, this file may be used under the terms of Open CASCADE
0014 // commercial license or contractual agreement.
0015 
0016 #ifndef _Quantity_Color_HeaderFile
0017 #define _Quantity_Color_HeaderFile
0018 
0019 #include <Standard.hxx>
0020 #include <Standard_DefineAlloc.hxx>
0021 #include <Standard_Handle.hxx>
0022 #include <Standard_HashUtils.hxx>
0023 #include <Standard_ShortReal.hxx>
0024 
0025 #include <Quantity_NameOfColor.hxx>
0026 #include <Quantity_TypeOfColor.hxx>
0027 #include <NCollection_Vec4.hxx>
0028 
0029 //! This class allows the definition of an RGB color as triplet of 3 normalized floating point
0030 //! values (red, green, blue).
0031 //!
0032 //! Although Quantity_Color can be technically used for pass-through storage of RGB triplet in any
0033 //! color space, other OCCT interfaces taking/returning Quantity_Color would expect them in linear
0034 //! space. Therefore, take a look into methods converting to and from non-linear sRGB color space,
0035 //! if needed; for instance, application usually providing color picking within 0..255 range in sRGB
0036 //! color space.
0037 class Quantity_Color
0038 {
0039 public:
0040   DEFINE_STANDARD_ALLOC
0041 
0042   //! Creates Quantity_NOC_YELLOW color (for historical reasons).
0043   Quantity_Color()
0044       : myRgb(valuesOf(Quantity_NOC_YELLOW, Quantity_TOC_RGB))
0045   {
0046   }
0047 
0048   //! Creates the color from enumeration value.
0049   Quantity_Color(const Quantity_NameOfColor theName)
0050       : myRgb(valuesOf(theName, Quantity_TOC_RGB))
0051   {
0052   }
0053 
0054   //! Creates a color according to the definition system theType.
0055   //! Throws exception if values are out of range.
0056   Standard_EXPORT Quantity_Color(const Standard_Real        theC1,
0057                                  const Standard_Real        theC2,
0058                                  const Standard_Real        theC3,
0059                                  const Quantity_TypeOfColor theType);
0060 
0061   //! Define color from linear RGB values.
0062   Standard_EXPORT explicit Quantity_Color(const NCollection_Vec3<float>& theRgb);
0063 
0064   //! Returns the name of the nearest color from the Quantity_NameOfColor enumeration.
0065   Standard_EXPORT Quantity_NameOfColor Name() const;
0066 
0067   //! Updates the color from specified named color.
0068   void SetValues(const Quantity_NameOfColor theName)
0069   {
0070     myRgb = valuesOf(theName, Quantity_TOC_RGB);
0071   }
0072 
0073   //! Return the color as vector of 3 float elements.
0074   const NCollection_Vec3<float>& Rgb() const { return myRgb; }
0075 
0076   //! Return the color as vector of 3 float elements.
0077   operator const NCollection_Vec3<float>&() const { return myRgb; }
0078 
0079   //! Returns in theC1, theC2 and theC3 the components of this color
0080   //! according to the color system definition theType.
0081   Standard_EXPORT void Values(Standard_Real&             theC1,
0082                               Standard_Real&             theC2,
0083                               Standard_Real&             theC3,
0084                               const Quantity_TypeOfColor theType) const;
0085 
0086   //! Updates a color according to the mode specified by theType.
0087   //! Throws exception if values are out of range.
0088   Standard_EXPORT void SetValues(const Standard_Real        theC1,
0089                                  const Standard_Real        theC2,
0090                                  const Standard_Real        theC3,
0091                                  const Quantity_TypeOfColor theType);
0092 
0093   //! Returns the Red component (quantity of red) of the color within range [0.0; 1.0].
0094   Standard_Real Red() const { return myRgb.r(); }
0095 
0096   //! Returns the Green component (quantity of green) of the color within range [0.0; 1.0].
0097   Standard_Real Green() const { return myRgb.g(); }
0098 
0099   //! Returns the Blue component (quantity of blue) of the color within range [0.0; 1.0].
0100   Standard_Real Blue() const { return myRgb.b(); }
0101 
0102   //! Returns the Hue component (hue angle) of the color
0103   //! in degrees within range [0.0; 360.0], 0.0 being Red.
0104   //! -1.0 is a special value reserved for grayscale color (S should be 0.0)
0105   Standard_Real Hue() const { return Convert_LinearRGB_To_HLS(myRgb)[0]; }
0106 
0107   //! Returns the Light component (value of the lightness) of the color within range [0.0; 1.0].
0108   Standard_Real Light() const { return Convert_LinearRGB_To_HLS(myRgb)[1]; }
0109 
0110   //! Increases or decreases the intensity (variation of the lightness).
0111   //! The delta is a percentage. Any value greater than zero will increase the intensity.
0112   //! The variation is expressed as a percentage of the current value.
0113   Standard_EXPORT void ChangeIntensity(const Standard_Real theDelta);
0114 
0115   //! Returns the Saturation component (value of the saturation) of the color within range
0116   //! [0.0; 1.0].
0117   Standard_Real Saturation() const { return Convert_LinearRGB_To_HLS(myRgb)[2]; }
0118 
0119   //! Increases or decreases the contrast (variation of the saturation).
0120   //! The delta is a percentage. Any value greater than zero will increase the contrast.
0121   //! The variation is expressed as a percentage of the current value.
0122   Standard_EXPORT void ChangeContrast(const Standard_Real theDelta);
0123 
0124   //! Returns TRUE if the distance between two colors is greater than Epsilon().
0125   Standard_Boolean IsDifferent(const Quantity_Color& theOther) const
0126   {
0127     return (SquareDistance(theOther) > Epsilon() * Epsilon());
0128   }
0129 
0130   //! Alias to IsDifferent().
0131   Standard_Boolean operator!=(const Quantity_Color& theOther) const
0132   {
0133     return IsDifferent(theOther);
0134   }
0135 
0136   //! Returns TRUE if the distance between two colors is no greater than Epsilon().
0137   Standard_Boolean IsEqual(const Quantity_Color& theOther) const
0138   {
0139     return (SquareDistance(theOther) <= Epsilon() * Epsilon());
0140   }
0141 
0142   //! Alias to IsEqual().
0143   Standard_Boolean operator==(const Quantity_Color& theOther) const { return IsEqual(theOther); }
0144 
0145   //! Returns the distance between two colors. It's a value between 0 and the square root of 3 (the
0146   //! black/white distance).
0147   Standard_Real Distance(const Quantity_Color& theColor) const
0148   {
0149     return (NCollection_Vec3<Standard_Real>(myRgb)
0150             - NCollection_Vec3<Standard_Real>(theColor.myRgb))
0151       .Modulus();
0152   }
0153 
0154   //! Returns the square of distance between two colors.
0155   Standard_Real SquareDistance(const Quantity_Color& theColor) const
0156   {
0157     return (NCollection_Vec3<Standard_Real>(myRgb)
0158             - NCollection_Vec3<Standard_Real>(theColor.myRgb))
0159       .SquareModulus();
0160   }
0161 
0162   //! Returns the percentage change of contrast and intensity between this and another color.
0163   //! <DC> and <DI> are percentages, either positive or negative.
0164   //! The calculation is with respect to this color.
0165   //! If <DC> is positive then <me> is more contrasty.
0166   //! If <DI> is positive then <me> is more intense.
0167   Standard_EXPORT void Delta(const Quantity_Color& theColor,
0168                              Standard_Real&        DC,
0169                              Standard_Real&        DI) const;
0170 
0171   //! Returns the value of the perceptual difference between this color
0172   //! and @p theOther, computed using the CIEDE2000 formula.
0173   //! The difference is in range [0, 100.], with 1 approximately corresponding
0174   //! to the minimal perceivable difference (usually difference 5 or greater is
0175   //! needed for the difference to be recognizable in practice).
0176   Standard_EXPORT Standard_Real DeltaE2000(const Quantity_Color& theOther) const;
0177 
0178 public:
0179   //! Returns the color from Quantity_NameOfColor enumeration nearest to specified RGB values.
0180   static Quantity_NameOfColor Name(const Standard_Real theR,
0181                                    const Standard_Real theG,
0182                                    const Standard_Real theB)
0183   {
0184     const Quantity_Color aColor(theR, theG, theB, Quantity_TOC_RGB);
0185     return aColor.Name();
0186   }
0187 
0188   //! Returns the name of the color identified by the given Quantity_NameOfColor enumeration value.
0189   Standard_EXPORT static Standard_CString StringName(const Quantity_NameOfColor theColor);
0190 
0191   //! Finds color from predefined names.
0192   //! For example, the name of the color which corresponds to "BLACK" is Quantity_NOC_BLACK.
0193   //! Returns FALSE if name is unknown.
0194   Standard_EXPORT static Standard_Boolean ColorFromName(const Standard_CString theName,
0195                                                         Quantity_NameOfColor&  theColor);
0196 
0197   //! Finds color from predefined names.
0198   //! @param theColorNameString the color name
0199   //! @param theColor a found color
0200   //! @return false if the color name is unknown, or true if the search by color name was successful
0201   static Standard_Boolean ColorFromName(const Standard_CString theColorNameString,
0202                                         Quantity_Color&        theColor)
0203   {
0204     Quantity_NameOfColor aColorName = Quantity_NOC_BLACK;
0205     if (!ColorFromName(theColorNameString, aColorName))
0206     {
0207       return false;
0208     }
0209     theColor = aColorName;
0210     return true;
0211   }
0212 
0213 public:
0214   //!@name Routines converting colors between different encodings and color spaces
0215 
0216   //! Parses the string as a hex color (like "#FF0" for short sRGB color, or "#FFFF00" for sRGB
0217   //! color)
0218   //! @param theHexColorString the string to be parsed
0219   //! @param theColor a color that is a result of parsing
0220   //! @return true if parsing was successful, or false otherwise
0221   Standard_EXPORT static bool ColorFromHex(const Standard_CString theHexColorString,
0222                                            Quantity_Color&        theColor);
0223 
0224   //! Returns hex sRGB string in format "#FFAAFF".
0225   static TCollection_AsciiString ColorToHex(const Quantity_Color& theColor,
0226                                             const bool            theToPrefixHash = true)
0227   {
0228     NCollection_Vec3<Standard_ShortReal> anSRgb =
0229       Convert_LinearRGB_To_sRGB((NCollection_Vec3<Standard_ShortReal>)theColor);
0230     NCollection_Vec3<Standard_Integer> anSRgbInt(anSRgb * 255.0f
0231                                                  + NCollection_Vec3<Standard_ShortReal>(0.5f));
0232     char                               aBuff[10];
0233     Sprintf(aBuff,
0234             theToPrefixHash ? "#%02X%02X%02X" : "%02X%02X%02X",
0235             anSRgbInt.r(),
0236             anSRgbInt.g(),
0237             anSRgbInt.b());
0238     return aBuff;
0239   }
0240 
0241   //! Converts sRGB components into HLS ones.
0242   Standard_EXPORT static NCollection_Vec3<float> Convert_sRGB_To_HLS(
0243     const NCollection_Vec3<float>& theRgb);
0244 
0245   //! Converts HLS components into RGB ones.
0246   Standard_EXPORT static NCollection_Vec3<float> Convert_HLS_To_sRGB(
0247     const NCollection_Vec3<float>& theHls);
0248 
0249   //! Converts Linear RGB components into HLS ones.
0250   static NCollection_Vec3<float> Convert_LinearRGB_To_HLS(const NCollection_Vec3<float>& theRgb)
0251   {
0252     return Convert_sRGB_To_HLS(Convert_LinearRGB_To_sRGB(theRgb));
0253   }
0254 
0255   //! Converts HLS components into linear RGB ones.
0256   static NCollection_Vec3<float> Convert_HLS_To_LinearRGB(const NCollection_Vec3<float>& theHls)
0257   {
0258     return Convert_sRGB_To_LinearRGB(Convert_HLS_To_sRGB(theHls));
0259   }
0260 
0261   //! Converts linear RGB components into CIE Lab ones.
0262   Standard_EXPORT static NCollection_Vec3<float> Convert_LinearRGB_To_Lab(
0263     const NCollection_Vec3<float>& theRgb);
0264 
0265   //! Converts CIE Lab components into CIE Lch ones.
0266   Standard_EXPORT static NCollection_Vec3<float> Convert_Lab_To_Lch(
0267     const NCollection_Vec3<float>& theLab);
0268 
0269   //! Converts CIE Lab components into linear RGB ones.
0270   //! Note that the resulting values may be out of the valid range for RGB.
0271   Standard_EXPORT static NCollection_Vec3<float> Convert_Lab_To_LinearRGB(
0272     const NCollection_Vec3<float>& theLab);
0273 
0274   //! Converts CIE Lch components into CIE Lab ones.
0275   Standard_EXPORT static NCollection_Vec3<float> Convert_Lch_To_Lab(
0276     const NCollection_Vec3<float>& theLch);
0277 
0278   //! Convert the color value to ARGB integer value, with alpha equals to 0.
0279   //! So the output is formatted as 0x00RRGGBB.
0280   //! Note that this unpacking does NOT involve non-linear sRGB -> linear RGB conversion,
0281   //! as would be usually expected for RGB color packed into 4 bytes.
0282   //! @param[in] theColor  color to convert
0283   //! @param[out] theARGB  result color encoded as integer
0284   static void Color2argb(const Quantity_Color& theColor, Standard_Integer& theARGB)
0285   {
0286     const NCollection_Vec3<Standard_Integer> aColor(
0287       static_cast<Standard_Integer>(255.0f * theColor.myRgb.r() + 0.5f),
0288       static_cast<Standard_Integer>(255.0f * theColor.myRgb.g() + 0.5f),
0289       static_cast<Standard_Integer>(255.0f * theColor.myRgb.b() + 0.5f));
0290     theARGB = (((aColor.r() & 0xff) << 16) | ((aColor.g() & 0xff) << 8) | (aColor.b() & 0xff));
0291   }
0292 
0293   //! Convert integer ARGB value to Color. Alpha bits are ignored.
0294   //! Note that this packing does NOT involve linear -> non-linear sRGB conversion,
0295   //! as would be usually expected to preserve higher (for human eye) color precision in 4 bytes.
0296   static void Argb2color(const Standard_Integer theARGB, Quantity_Color& theColor)
0297   {
0298     const NCollection_Vec3<Standard_Real> aColor(
0299       static_cast<Standard_Real>((theARGB & 0xff0000) >> 16),
0300       static_cast<Standard_Real>((theARGB & 0x00ff00) >> 8),
0301       static_cast<Standard_Real>((theARGB & 0x0000ff)));
0302     theColor.SetValues(aColor.r() / 255.0,
0303                        aColor.g() / 255.0,
0304                        aColor.b() / 255.0,
0305                        Quantity_TOC_sRGB);
0306   }
0307 
0308   //! Convert linear RGB component into sRGB using OpenGL specs formula (double precision), also
0309   //! known as gamma correction.
0310   static Standard_Real Convert_LinearRGB_To_sRGB(Standard_Real theLinearValue)
0311   {
0312     return theLinearValue <= 0.0031308 ? theLinearValue * 12.92
0313                                        : Pow(theLinearValue, 1.0 / 2.4) * 1.055 - 0.055;
0314   }
0315 
0316   //! Convert linear RGB component into sRGB using OpenGL specs formula (single precision), also
0317   //! known as gamma correction.
0318   static float Convert_LinearRGB_To_sRGB(float theLinearValue)
0319   {
0320     return theLinearValue <= 0.0031308f ? theLinearValue * 12.92f
0321                                         : powf(theLinearValue, 1.0f / 2.4f) * 1.055f - 0.055f;
0322   }
0323 
0324   //! Convert sRGB component into linear RGB using OpenGL specs formula (double precision), also
0325   //! known as gamma correction.
0326   static Standard_Real Convert_sRGB_To_LinearRGB(Standard_Real thesRGBValue)
0327   {
0328     return thesRGBValue <= 0.04045 ? thesRGBValue / 12.92
0329                                    : Pow((thesRGBValue + 0.055) / 1.055, 2.4);
0330   }
0331 
0332   //! Convert sRGB component into linear RGB using OpenGL specs formula (single precision), also
0333   //! known as gamma correction.
0334   static float Convert_sRGB_To_LinearRGB(float thesRGBValue)
0335   {
0336     return thesRGBValue <= 0.04045f ? thesRGBValue / 12.92f
0337                                     : powf((thesRGBValue + 0.055f) / 1.055f, 2.4f);
0338   }
0339 
0340   //! Convert linear RGB components into sRGB using OpenGL specs formula.
0341   template <typename T>
0342   static NCollection_Vec3<T> Convert_LinearRGB_To_sRGB(const NCollection_Vec3<T>& theRGB)
0343   {
0344     return NCollection_Vec3<T>(Convert_LinearRGB_To_sRGB(theRGB.r()),
0345                                Convert_LinearRGB_To_sRGB(theRGB.g()),
0346                                Convert_LinearRGB_To_sRGB(theRGB.b()));
0347   }
0348 
0349   //! Convert sRGB components into linear RGB using OpenGL specs formula.
0350   template <typename T>
0351   static NCollection_Vec3<T> Convert_sRGB_To_LinearRGB(const NCollection_Vec3<T>& theRGB)
0352   {
0353     return NCollection_Vec3<T>(Convert_sRGB_To_LinearRGB(theRGB.r()),
0354                                Convert_sRGB_To_LinearRGB(theRGB.g()),
0355                                Convert_sRGB_To_LinearRGB(theRGB.b()));
0356   }
0357 
0358   //! Convert linear RGB component into sRGB using approximated uniform gamma coefficient 2.2.
0359   static float Convert_LinearRGB_To_sRGB_approx22(float theLinearValue)
0360   {
0361     return powf(theLinearValue, 2.2f);
0362   }
0363 
0364   //! Convert sRGB component into linear RGB using approximated uniform gamma coefficient 2.2
0365   static float Convert_sRGB_To_LinearRGB_approx22(float thesRGBValue)
0366   {
0367     return powf(thesRGBValue, 1.0f / 2.2f);
0368   }
0369 
0370   //! Convert linear RGB components into sRGB using approximated uniform gamma coefficient 2.2
0371   static NCollection_Vec3<float> Convert_LinearRGB_To_sRGB_approx22(
0372     const NCollection_Vec3<float>& theRGB)
0373   {
0374     return NCollection_Vec3<float>(Convert_LinearRGB_To_sRGB_approx22(theRGB.r()),
0375                                    Convert_LinearRGB_To_sRGB_approx22(theRGB.g()),
0376                                    Convert_LinearRGB_To_sRGB_approx22(theRGB.b()));
0377   }
0378 
0379   //! Convert sRGB components into linear RGB using approximated uniform gamma coefficient 2.2
0380   static NCollection_Vec3<float> Convert_sRGB_To_LinearRGB_approx22(
0381     const NCollection_Vec3<float>& theRGB)
0382   {
0383     return NCollection_Vec3<float>(Convert_sRGB_To_LinearRGB_approx22(theRGB.r()),
0384                                    Convert_sRGB_To_LinearRGB_approx22(theRGB.g()),
0385                                    Convert_sRGB_To_LinearRGB_approx22(theRGB.b()));
0386   }
0387 
0388   //! Converts HLS components into sRGB ones.
0389   static void HlsRgb(const Standard_Real theH,
0390                      const Standard_Real theL,
0391                      const Standard_Real theS,
0392                      Standard_Real&      theR,
0393                      Standard_Real&      theG,
0394                      Standard_Real&      theB)
0395   {
0396     const NCollection_Vec3<float> anRgb =
0397       Convert_HLS_To_sRGB(NCollection_Vec3<float>((float)theH, (float)theL, (float)theS));
0398     theR = anRgb[0];
0399     theG = anRgb[1];
0400     theB = anRgb[2];
0401   }
0402 
0403   //! Converts sRGB components into HLS ones.
0404   static void RgbHls(const Standard_Real theR,
0405                      const Standard_Real theG,
0406                      const Standard_Real theB,
0407                      Standard_Real&      theH,
0408                      Standard_Real&      theL,
0409                      Standard_Real&      theS)
0410   {
0411     const NCollection_Vec3<float> aHls =
0412       Convert_sRGB_To_HLS(NCollection_Vec3<float>((float)theR, (float)theG, (float)theB));
0413     theH = aHls[0];
0414     theL = aHls[1];
0415     theS = aHls[2];
0416   }
0417 
0418 public:
0419   //! Returns the value used to compare two colors for equality; 0.0001 by default.
0420   Standard_EXPORT static Standard_Real Epsilon();
0421 
0422   //! Set the value used to compare two colors for equality.
0423   Standard_EXPORT static void SetEpsilon(const Standard_Real theEpsilon);
0424 
0425   //! Dumps the content of me into the stream
0426   Standard_EXPORT void DumpJson(Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
0427 
0428   //! Inits the content of me from the stream
0429   Standard_EXPORT Standard_Boolean InitFromJson(const Standard_SStream& theSStream,
0430                                                 Standard_Integer&       theStreamPos);
0431 
0432 private:
0433   //! Returns the values of a predefined color according to the mode.
0434   Standard_EXPORT static NCollection_Vec3<float> valuesOf(const Quantity_NameOfColor theName,
0435                                                           const Quantity_TypeOfColor theType);
0436 
0437 private:
0438   NCollection_Vec3<float> myRgb;
0439 };
0440 
0441 namespace std
0442 {
0443 template <>
0444 struct hash<Quantity_Color>
0445 {
0446   std::size_t operator()(const Quantity_Color& theColor) const noexcept
0447   {
0448     unsigned char aByteArr[3] = {static_cast<unsigned char>(255 * theColor.Red()),
0449                                  static_cast<unsigned char>(255 * theColor.Green()),
0450                                  static_cast<unsigned char>(255 * theColor.Blue())};
0451     return opencascade::hashBytes(aByteArr, sizeof(aByteArr));
0452   }
0453 };
0454 } // namespace std
0455 
0456 #endif // _Quantity_Color_HeaderFile