File indexing completed on 2024-05-12 04:44:30

0001 // SPDX-FileCopyrightText: Lukas Sommer <sommerluk@gmail.com>
0002 // SPDX-License-Identifier: BSD-2-Clause OR MIT
0003 
0004 #ifndef CIELCHD50VALUES_H
0005 #define CIELCHD50VALUES_H
0006 
0007 #include "lchdouble.h"
0008 
0009 namespace PerceptualColor
0010 {
0011 /** @internal
0012  *
0013  * @brief CIELCH-D50 default values
0014  *
0015  * The @ref lchrangerationale "range of CIELCh-D50 values" it known.
0016  * But what could be useful default values? This struct provides some
0017  * proposals. All values are <tt>constexpr</tt>. */
0018 struct CielchD50Values final {
0019 public:
0020     /** @brief Maximum chroma value as defined in @ref lchrangerationale. */
0021     static constexpr int maximumChroma = 255;
0022     /** @brief Neutral chroma value
0023      *
0024      *  For chroma, a neutral value of 0 might be a good
0025      *  choice because it is less likely to make  out-of-gamut problems on
0026      *  any lightness (except maybe extreme white or extreme black). And
0027      *  it results in an achromatic color and is therefore perceived as
0028      *  neutral. */
0029     static constexpr int neutralChroma = 0;
0030     /** @brief Neutral hue value
0031      *
0032      *  For the hue, a default value of 0 might be used by convention. */
0033     static constexpr int neutralHue = 0;
0034     /** @brief Neutral lightness value
0035      *
0036      *  For the lightness, a neutral value of 50 seems a good choice as it
0037      *  is half the way in the defined lightness range of <tt>[0, 100]</tt>
0038      *  (thought not all gamuts offer the hole range of <tt>[0, 100]</tt>). As
0039      *  it is quite in the middle of the gamut solid, it allows for quite big
0040      *  values for chroma at different hues without falling out-of-gamut.
0041      *  Combined with a chroma of 0, it also approximates the color with
0042      *  the highest possible contrast against the hole surface of the
0043      *  gamut solid; this is interesting for background colors of
0044      *  gamut diagrams. */
0045     static constexpr int neutralLightness = 50;
0046     /** @brief Neutral gray color as Lab value.
0047      *
0048      * Neutral gray is a good choice for the background, as it is equally
0049      * distant from black and white, and also quite distant from any
0050      * saturated color.
0051      *
0052      * @todo Given that this might be used quite often, it could be useful
0053      * to provide the corresponding RGB value within @ref RgbColorSpace
0054      * as a property, returning a variable that is initialized on first
0055      * usage. */
0056     static constexpr LchDouble neutralGray{neutralLightness, //
0057                                            neutralChroma, //
0058                                            neutralHue};
0059     /** @brief Versatile chroma value in
0060      * <a href="http://www.littlecms.com/">LittleCMS</a>’ build-in
0061      * sRGB gamut
0062      *
0063      *  Depending on the use case, there might be an alternative to
0064      *  the neutral gray @ref neutralChroma. For a lightness of 50, this
0065      *  value is the maximum chroma available at all possible hues within
0066      *  a usual sRGB gamut.
0067      *
0068      *  @sa @ref neutralChroma
0069      *
0070      * @todo This value should be removed in favor of using individual
0071      * values for each gamut. */
0072     static constexpr int srgbVersatileChroma = 32;
0073     /** @brief Versatile initial color for widgets in
0074      * <a href="http://www.littlecms.com/">LittleCMS</a>’ build-in
0075      * sRGB gamut
0076      *
0077      * This provides a colorful (non-gray) initial color.
0078      *
0079      * The lightness and the chroma value are somewhere in the middle of
0080      * the valid range. In sRGB this is always a valid value pair, even if
0081      * the hue changes. Both, lightness and chroma, are linear ranges,
0082      * so it seems appropriate to have values somewhere in the middle
0083      * as initial color: The widgets will display the handles somewhere
0084      * in the middle, which is easier to spot for new users than having
0085      * them at the very beginning or the very end.
0086      *
0087      * The hue range is not linear, but circular – and so are the widgets
0088      * displaying him: The handle has the same visibility, wherever he is
0089      * and whatever the hue value is. Therefore, we use 0° as default value
0090      * which seems to be the natural choice.
0091      *
0092      * @note An alternative to 0° might be 180°. If the lightness is 50%,
0093      * among 0°, 90°, 180° and 270°, it’s 180° that has the lowest possible
0094      * maximum chroma. So when choose 180°, with a given chroma, the resulting
0095      * color is more vivid and clean than those at 0°, 90° and 270°. */
0096     static constexpr LchDouble srgbVersatileInitialColor = {neutralLightness, srgbVersatileChroma, neutralHue};
0097 
0098 private:
0099     /** @brief Delete the constructor to disallow creating an instance
0100      * of this class. */
0101     CielchD50Values() = delete;
0102 };
0103 
0104 } // namespace PerceptualColor
0105 
0106 #endif // CIELCHD50VALUES_H