File indexing completed on 2024-05-19 04:45:51
0001 // SPDX-FileCopyrightText: Lukas Sommer <sommerluk@gmail.com> 0002 // SPDX-License-Identifier: BSD-2-Clause OR MIT 0003 0004 #ifndef HELPERCONVERSION_H 0005 #define HELPERCONVERSION_H 0006 0007 #include "helperqttypes.h" 0008 #include "lchdouble.h" 0009 #include <lcms2.h> 0010 #include <qcolor.h> 0011 #include <qglobal.h> 0012 #include <type_traits> 0013 0014 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) 0015 #include <qtmetamacros.h> 0016 #endif 0017 0018 /** @internal 0019 * 0020 * @file 0021 * 0022 * Provides type conversions. */ 0023 0024 namespace PerceptualColor 0025 { 0026 0027 Q_NAMESPACE 0028 0029 /** @brief Identifiers for color models. */ 0030 enum class ColorModel { 0031 CielabD50, /**< Cielab color space using a D50 illuminant. 0032 Lightness: [0, 100].<br/> 0033 a: unbound.<br/> 0034 b: unbound. */ 0035 CielchD50, /**< Cielch color space using a D50 illuminant. 0036 Lightness: [0, 100].<br/> 0037 Chroma: unbound.<br/> 0038 Hue: [0, 360[. */ 0039 Hsl360_1_1, /**< A HSL color space. 0040 Hue: [0, 360[.<br/> 0041 Saturation: [0, 1].<br/> 0042 Lightness: [0, 1]. */ 0043 Hwb360_1_1, /**< A HWB color space. 0044 Hue: [0, 360[.<br/> 0045 Whiteness: [0, 1].<br/> 0046 Blackness: [0, 1]. */ 0047 Invalid, /**< Represents invalid data. */ 0048 OklabD65, /**< Oklab color space, which by definition always and 0049 exclusively uses a D65 illuminant. 0050 0051 Lightness: [0, 1].<br/> 0052 a: unbound.<br/> 0053 b: unbound. */ 0054 OklchD65, /**< Oklch color space, which by definition always and 0055 exclusively uses a D65 illuminant. 0056 0057 Lightness: [0, 1].<br/> 0058 Chroma: unbound.<br/> 0059 Hue: [0, 360[. */ 0060 Rgb1, /**< An Rgb color space. 0061 R: [0, 1].<br/> 0062 G: [0, 1].<br/> 0063 B: [0, 1]. */ 0064 XyzD50, /**< Xyz color space using a D50 illuminant. 0065 X: unbound.<br/> 0066 Y: [0, 1]. Diffuse white has a luminance (Y) of 1.0<br/> 0067 Z: unbound. */ 0068 XyzD65 /**< Xzy color space using a D65 illuminant. 0069 X: unbound.<br/> 0070 Y: [0, 1]. Diffuse white has a luminance (Y) of 1.0<br/> 0071 Z: unbound. */ 0072 }; 0073 Q_ENUM_NS(ColorModel) 0074 0075 #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) 0076 uint qHash(const ColorModel t, uint seed = 0); // clazy:exclude=qt6-qhash-signature 0077 #endif 0078 0079 /** @internal 0080 * 0081 * @brief Converts from <tt>[0, 1]</tt> to <tt>[0, 255]</tt>. 0082 * 0083 * @param original A value on a scale <tt>[0, 1]</tt>. 0084 * 0085 * @returns Value converted to the scale <tt>[0, 255]</tt>, applying correct 0086 * rounding. Out-of-range values are bound to the valid range. */ 0087 template<typename T> 0088 [[nodiscard]] constexpr quint8 fromFloatingToEightBit(const T &original) 0089 { 0090 static_assert( // 0091 std::is_floating_point<T>::value, // 0092 "Template fromFloatingToEightBit() only works with floating point types"); 0093 const int rounded = qRound(original * 255); 0094 const auto bounded = qBound<int>(0, rounded, 255); 0095 return static_cast<quint8>(bounded); 0096 } 0097 0098 /** @internal 0099 * 0100 * @brief Like <tt>QColor::fromRgbF</tt> but for all floating point types. 0101 * 0102 * @param red Red component. Range: <tt>[0, 1]</tt> 0103 * @param green See above. 0104 * @param blue See above. 0105 * @returns A corresponding <tt>QColor</tt> object. */ 0106 template<typename T> 0107 [[nodiscard]] QColor qColorFromRgbDouble(T red, T green, T blue) 0108 { 0109 static_assert( // 0110 std::is_floating_point<T>::value, // 0111 "Template fromFloatingToEightBit() only works with floating point types"); 0112 return QColor::fromRgbF(static_cast<QColorFloatType>(red), // 0113 static_cast<QColorFloatType>(green), // 0114 static_cast<QColorFloatType>(blue)); 0115 } 0116 0117 [[nodiscard]] cmsCIELab toCmsLab(const cmsCIELCh &value); 0118 0119 [[nodiscard]] cmsCIELCh toCmsLch(const LchDouble &value); 0120 0121 [[nodiscard]] LchDouble toLchDouble(const cmsCIELCh &value); 0122 0123 [[nodiscard]] LchDouble toLchDouble(const cmsCIELab &value); 0124 0125 /** @internal 0126 * 0127 * @brief White point D65 for 2°-observer. 0128 * 0129 * According to 0130 * <a href="https://en.wikipedia.org/w/index.php?title=Illuminant_D65&oldid=1100467073#Definition"> 0131 * Wikipedia</a>: 0132 * 0133 * > “Using the standard 2° observer […] of D65 […] Normalizing for 0134 * > relative luminance (i.e. set Y=100), the XYZ tristimulus 0135 * > values are:<br/> 0136 * > X = 95.047<br/> 0137 * > Y = 100<br/> 0138 * > Z = 108.883” 0139 * 0140 * Normalizing this to Y = 1 as expected by LittleCMS, gives this value. */ 0141 // TODO xxx This seems to be not longer used!? 0142 constexpr cmsCIEXYZ whitePointD65TwoDegree{0.95047, 1.00000, 1.08883}; 0143 0144 } // namespace PerceptualColor 0145 0146 #endif // HELPERCONVERSION_H