Perceptual Color

helperconversion.h
1// SPDX-FileCopyrightText: Lukas Sommer <sommerluk@gmail.com>
2// SPDX-License-Identifier: BSD-2-Clause OR MIT
3
4#ifndef HELPERCONVERSION_H
5#define HELPERCONVERSION_H
6
7#include "helperqttypes.h"
8#include "lchdouble.h"
9#include <lcms2.h>
10#include <qcolor.h>
11#include <qglobal.h>
12#include <type_traits>
13
14#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
15#include <qtmetamacros.h>
16#endif
17
18/** @internal
19 *
20 * @file
21 *
22 * Provides type conversions. */
23
24namespace PerceptualColor
25{
26
27Q_NAMESPACE
28
29/** @brief Identifiers for color models.
30 *
31 * @internal
32 *
33 * @note Maybe
34 * <a href="https://doc-snapshots.qt.io/qt6-dev/qcolorspace.html#ColorModel-enum">
35 * <tt>enum QColorSpace::NamedColorSpace</tt></a> might also be useful in
36 * the future.
37 */
38enum class ColorModel {
39 CielabD50, /**< The Cielab color space using a D50 illuminant.
40 Lightness: [0, 100].<br/>
41 a: unbound.<br/>
42 b: unbound. */
43 CielchD50, /**< The Cielch color space using a D50 illuminant.
44 Lightness: [0, 100].<br/>
45 Chroma: unbound.<br/>
46 Hue: [0, 360[. */
47 Hsl360_1_1, /**< Some color space using the HSL color model.
48 Hue: [0, 360[.<br/>
49 Saturation: [0, 1].<br/>
50 Lightness: [0, 1]. */
51 Hwb360_1_1, /**< Some color space using the HWB color model.
52 Hue: [0, 360[.<br/>
53 Whiteness: [0, 1].<br/>
54 Blackness: [0, 1]. */
55 Invalid, /**< Represents invalid data. */
56 OklabD65, /**< The Oklab color space, which by definition always and
57 exclusively uses a D65 illuminant.
58
59 Lightness: [0, 1].<br/>
60 a: unbound.<br/>
61 b: unbound. */
62 OklchD65, /**< The Oklch color space, which by definition always and
63 exclusively uses a D65 illuminant.
64
65 Lightness: [0, 1].<br/>
66 Chroma: unbound.<br/>
67 Hue: [0, 360[. */
68 Rgb1, /**< Some color space using the Rgb color space.
69 R: [0, 1].<br/>
70 G: [0, 1].<br/>
71 B: [0, 1]. */
72 XyzD50, /**< The Xyz color space using a D50 illuminant.
73 X: unbound.<br/>
74 Y: [0, 1]. Diffuse white has a luminance (Y) of 1.0<br/>
75 Z: unbound. */
76 XyzD65 /**< The Xzy color space using a D65 illuminant.
77 X: unbound.<br/>
78 Y: [0, 1]. Diffuse white has a luminance (Y) of 1.0<br/>
79 Z: unbound. */
80};
81Q_ENUM_NS(ColorModel)
82
83#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
84uint qHash(const ColorModel t, uint seed = 0); // clazy:exclude=qt6-qhash-signature
85#endif
86
87/** @internal
88 *
89 * @brief Converts from <tt>[0, 1]</tt> to <tt>[0, 255]</tt>.
90 *
91 * @param original A value on a scale <tt>[0, 1]</tt>.
92 *
93 * @returns Value converted to the scale <tt>[0, 255]</tt>, applying correct
94 * rounding. Out-of-range values are bound to the valid range. */
95template<typename T>
96[[nodiscard]] constexpr quint8 fromFloatingToEightBit(const T &original)
97{
98 static_assert( //
99 std::is_floating_point<T>::value, //
100 "Template fromFloatingToEightBit() only works with floating point types");
101 const int rounded = qRound(original * 255);
102 const auto bounded = qBound<int>(0, rounded, 255);
103 return static_cast<quint8>(bounded);
104}
105
106/** @internal
107 *
108 * @brief Like <tt>QColor::fromRgbF</tt> but for all floating point types.
109 *
110 * @param red Red component. Range: <tt>[0, 1]</tt>
111 * @param green See above.
112 * @param blue See above.
113 * @returns A corresponding <tt>QColor</tt> object. */
114template<typename T>
115[[nodiscard]] QColor qColorFromRgbDouble(T red, T green, T blue)
116{
117 static_assert( //
118 std::is_floating_point<T>::value, //
119 "Template fromFloatingToEightBit() only works with floating point types");
120 return QColor::fromRgbF(static_cast<QColorFloatType>(red), //
121 static_cast<QColorFloatType>(green), //
122 static_cast<QColorFloatType>(blue));
123}
124
125[[nodiscard]] cmsCIELab toCmsLab(const cmsCIELCh &value);
126
127[[nodiscard]] cmsCIELCh toCmsLch(const LchDouble &value);
128
129[[nodiscard]] LchDouble toLchDouble(const cmsCIELCh &value);
130
131[[nodiscard]] LchDouble toLchDouble(const cmsCIELab &value);
132
133/** @internal
134 *
135 * @brief White point D65 for 2°-observer.
136 *
137 * According to
138 * <a href="https://en.wikipedia.org/w/index.php?title=Illuminant_D65&oldid=1100467073#Definition">
139 * Wikipedia</a>:
140 *
141 * > “Using the standard 2° observer […] of D65 […] Normalizing for
142 * > relative luminance (i.e. set Y=100), the XYZ tristimulus
143 * > values are:<br/>
144 * > X = 95.047<br/>
145 * > Y = 100<br/>
146 * > Z = 108.883”
147 *
148 * Normalizing this to Y = 1 as expected by LittleCMS, gives this value. */
149// TODO xxx This seems to be not longer used!?
150constexpr cmsCIEXYZ whitePointD65TwoDegree{0.95047, 1.00000, 1.08883};
151
152} // namespace PerceptualColor
153
154#endif // HELPERCONVERSION_H
The namespace of this library.
ColorModel
Identifiers for color models.
@ OklabD65
The Oklab color space, which by definition always and exclusively uses a D65 illuminant.
@ XyzD50
The Xyz color space using a D50 illuminant.
@ CielabD50
The Cielab color space using a D50 illuminant.
@ OklchD65
The Oklch color space, which by definition always and exclusively uses a D65 illuminant.
@ Hsl360_1_1
Some color space using the HSL color model.
@ Invalid
Represents invalid data.
@ XyzD65
The Xzy color space using a D65 illuminant.
@ Rgb1
Some color space using the Rgb color space.
@ CielchD50
The Cielch color space using a D50 illuminant.
@ Hwb360_1_1
Some color space using the HWB color model.
QColor fromRgbF(float r, float g, float b, float a)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jul 26 2024 11:50:27 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.