Commit 3d172bca0ee034edb261958f6d93407a621531a5

Authored by Jojo-1000
Committed by Moritz Wirger
1 parent ce0d8213

Add conversion from RGB to HueSaturation.

Co-authored-by: Adam Honse <calcprogrammer1@gmail.com>
include/hueplusplus/ColorUnits.h
... ... @@ -126,6 +126,12 @@ struct RGB
126 126 //!
127 127 //! Performs gamma correction so the light color matches the screen color better.
128 128 XYBrightness toXY(const ColorGamut& gamut) const;
  129 +
  130 + //! \brief Convert to HueSaturation
  131 + //!
  132 + //! To get the correct color, set brightness to max(r,g,b).
  133 + HueSaturation toHueSaturation() const;
  134 +
129 135 //! \brief Create from XYBrightness
130 136 //!
131 137 //! Performs gamma correction so the light color matches the screen color better.
... ... @@ -143,9 +149,9 @@ struct RGB
143 149 };
144 150  
145 151 //! \brief Const function that converts Kelvin to Mired.
146   - //!
147   - //! \param kelvin Unsigned integer value in Kelvin
148   - //! \return Unsigned integer value in Mired
  152 +//!
  153 +//! \param kelvin Unsigned integer value in Kelvin
  154 +//! \return Unsigned integer value in Mired
149 155 unsigned int kelvinToMired(unsigned int kelvin);
150 156  
151 157 //! \brief Const function that converts Mired to Kelvin.
... ...
src/ColorUnits.cpp
... ... @@ -142,17 +142,55 @@ XYBrightness RGB::toXY(const ColorGamut&amp; gamut) const
142 142 return xy;
143 143 }
144 144  
  145 +HueSaturation RGB::toHueSaturation() const
  146 +{
  147 + const uint8_t cmax = std::max(r, std::max(g, b));
  148 + const uint8_t cmin = std::min(r, std::min(g, b));
  149 + const float diff = cmax - cmin;
  150 +
  151 + int h = -1;
  152 + int s = -1;
  153 +
  154 + if (cmax == cmin)
  155 + {
  156 + h = 0;
  157 + }
  158 + else if (cmax == r)
  159 + {
  160 + h = (int)(9307 * ((g - b) / diff) + 65535) % 65535;
  161 + }
  162 + else if (cmax == g)
  163 + {
  164 + h = (int)(12750 * ((b - r) / diff) + 25500) % 65535;
  165 + }
  166 + else if (cmax == b)
  167 + {
  168 + h = (int)(10710 * ((r - g) / diff) + 46920) % 65535;
  169 + }
  170 +
  171 + if (cmax == 0)
  172 + {
  173 + s = 0;
  174 + }
  175 + else
  176 + {
  177 + s = std::round((diff / cmax) * 254);
  178 + }
  179 +
  180 + return {h, s};
  181 +}
  182 +
145 183 RGB RGB::fromXY(const XYBrightness& xy)
146 184 {
147 185 if (xy.brightness < 1e-4)
148 186 {
149   - return RGB{ 0,0,0 };
  187 + return RGB {0, 0, 0};
150 188 }
151 189 const float z = 1.f - xy.xy.x - xy.xy.y;
152 190 // use a fixed luminosity and rescale the resulting rgb values using brightness
153 191 // randomly sampled conversions shown a minimum difference between original values
154 192 // and values after rgb -> xy -> rgb conversion for Y = 0.3
155   - // (r-r')^2, (g-g')^2, (b-b')^2:
  193 + // (r-r')^2, (g-g')^2, (b-b')^2:
156 194 // 4.48214, 4.72039, 3.12141
157 195 // Max. Difference:
158 196 // 9, 9, 8
... ...
test/test_ColorUnits.cpp
... ... @@ -108,7 +108,7 @@ TEST(RGB, toXY)
108 108 EXPECT_FLOAT_EQ(xy.brightness, 1.f);
109 109 }
110 110 {
111   - const RGB black{ 0,0,0 };
  111 + const RGB black {0, 0, 0};
112 112 XYBrightness xy = black.toXY(gamut::maxGamut);
113 113 EXPECT_FLOAT_EQ(xy.xy.x, 0.32272673f);
114 114 EXPECT_FLOAT_EQ(xy.xy.y, 0.32902291f);
... ... @@ -116,6 +116,34 @@ TEST(RGB, toXY)
116 116 }
117 117 }
118 118  
  119 +TEST(RGB, toHueSaturation)
  120 +{
  121 + {
  122 + const RGB red {255, 0, 0};
  123 + HueSaturation hs = red.toHueSaturation();
  124 + EXPECT_EQ(0, hs.hue);
  125 + EXPECT_EQ(254, hs.saturation);
  126 + }
  127 + {
  128 + const RGB darkGreen{64, 128, 128 };
  129 + HueSaturation hs = darkGreen.toHueSaturation();
  130 + EXPECT_EQ(38250, hs.hue);
  131 + EXPECT_EQ(127, hs.saturation);
  132 + }
  133 + {
  134 + const RGB white {255, 255, 255};
  135 + HueSaturation hs = white.toHueSaturation();
  136 + EXPECT_EQ(0, hs.hue);
  137 + EXPECT_EQ(0, hs.saturation);
  138 + }
  139 + {
  140 + const RGB black {0, 0, 0};
  141 + HueSaturation hs = black.toHueSaturation();
  142 + EXPECT_EQ(0, hs.hue);
  143 + EXPECT_EQ(0, hs.saturation);
  144 + }
  145 +}
  146 +
119 147 TEST(RGB, fromXY)
120 148 {
121 149 {
... ... @@ -130,7 +158,7 @@ TEST(RGB, fromXY)
130 158 EXPECT_FLOAT_EQ(xyRed.brightness, reversed.brightness);
131 159 }
132 160 {
133   - const XYBrightness xyWhite{ {0.32272673f, 0.32902291f}, 1.f };
  161 + const XYBrightness xyWhite {{0.32272673f, 0.32902291f}, 1.f};
134 162 const RGB white = RGB::fromXY(xyWhite);
135 163 EXPECT_EQ(255, white.r);
136 164 EXPECT_EQ(255, white.g);
... ... @@ -143,7 +171,7 @@ TEST(RGB, fromXY)
143 171 {
144 172 const XYBrightness xyRed {{0.70060623f, 0.299301f}, 1.f};
145 173 const RGB red = RGB::fromXY(xyRed, gamut::gamutB);
146   - const RGB red2 = RGB::fromXY({ gamut::gamutB.corrected(xyRed.xy), xyRed.brightness });
  174 + const RGB red2 = RGB::fromXY({gamut::gamutB.corrected(xyRed.xy), xyRed.brightness});
147 175 EXPECT_EQ(red2.r, red.r);
148 176 EXPECT_EQ(red2.g, red.g);
149 177 EXPECT_EQ(red2.b, red.b);
... ... @@ -186,7 +214,6 @@ TEST(RGB, fromXY)
186 214 EXPECT_LE(maxDiffR, 81);
187 215 EXPECT_LE(maxDiffG, 81);
188 216 EXPECT_LE(maxDiffB, 64);
189   -
190 217 }
191 218  
192 219 TEST(ColorUnits, kelvinToMired)
... ...