WIP: HSV support in lay::Color

This commit is contained in:
Matthias Koefferlein
2022-04-27 23:03:17 +02:00
parent a6f2528aff
commit 7048dde7b3
12 changed files with 324 additions and 113 deletions
+79
View File
@@ -23,6 +23,7 @@
#include "layColor.h"
#include "tlString.h"
#include "tlMath.h"
#include <ctype.h>
@@ -116,4 +117,82 @@ Color::is_valid () const
return (m_color & 0xff000000) != 0;
}
void
Color::get_hsv (unsigned int &hue, unsigned int &saturation, unsigned int &value) const
{
double r = double (red ()) / 255.0;
double g = double (green ()) / 255.0;
double b = double (blue ()) / 255.0;
double max = std::max (r, std::max (g, b));
double min = std::min (r, std::min (g, b));
double delta = max - min;
value = (unsigned int) tl::round (255.0 * max, 1);
hue = 0;
saturation = 0;
if (! tl::equal (delta, 0.0)) {
saturation = (unsigned int) tl::round (255.0 * delta / max, 1);
double h = 0.0;
if (tl::equal (r, max)) {
h = (g - b) / delta;
} else if (tl::equal (g, max)) {
h = 2.0f + (b - r) / delta;
} else if (tl::equal (b, max)) {
h = 4.0f + (r - g) / delta;
}
h *= 60.0;
if (tl::less (h, 0.0)) {
h += 360.0;
}
hue = (unsigned int) tl::round (h, 1);
}
}
static lay::Color color_d (double r, double g, double b)
{
return lay::Color (tl::round (r * 255.0, 1), tl::round (g * 255.0, 1), tl::round (b * 255.0, 1));
}
lay::Color
Color::from_hsv (unsigned int hue, unsigned int saturation, unsigned int value)
{
if (saturation == 0) {
return lay::Color (value, value, value);
}
hue = (hue + 360) % 360;
double h = double (hue) / 60.0;
double s = double (saturation) / 255.0;
double v = double (value) / 255.0;
int i = int (tl::round_down (h, 1));
double f = (i & 1) != 0 ? h - i : 1.0 - h + i;
double p = v * (1.0 - s);
double q = v * (1.0 - s * f);
switch (i) {
case 0:
return color_d (v, q, p);
case 1:
return color_d (q, v, p);
case 2:
return color_d (p, v, q);
case 3:
return color_d (p, q, v);
case 4:
return color_d (q, p, v);
case 5:
return color_d (v, p, q);
default:
return lay::Color ();
}
}
}
+13
View File
@@ -142,6 +142,19 @@ public:
return (m_color & 0xff);
}
/**
* @brief Gets the HSV color components
* hue: 0..359
* saturation: 0..255
* value: 0..255
*/
void get_hsv (unsigned int &hue, unsigned int &saturation, unsigned int &value) const;
/**
* @brief Creates the color from a HSV color
*/
static lay::Color from_hsv (unsigned int hue, unsigned int saturation, unsigned int value);
private:
color_t m_color;
};
+101
View File
@@ -116,3 +116,104 @@ TEST(7)
EXPECT_EQ (QColor (16, 32, 48, 128).rgb (), 0xff102030);
#endif
}
TEST(8)
{
unsigned int h, s, v;
int ih, is, iv;
lay::Color c = lay::Color (16, 32, 48);
c.get_hsv (h, s, v);
EXPECT_EQ (h, 210);
EXPECT_EQ (s, 170);
EXPECT_EQ (v, 48);
EXPECT_EQ (lay::Color::from_hsv (h, s, v).to_string (), "#102030");
#if defined(HAVE_QT)
QColor qc = QColor (16, 32, 48);
qc.getHsv (&ih, &is, &iv);
EXPECT_EQ (ih, 210);
EXPECT_EQ (is, 170);
EXPECT_EQ (iv, 48);
#endif
c = lay::Color (32, 16, 48);
c.get_hsv (h, s, v);
EXPECT_EQ (h, 270);
EXPECT_EQ (s, 170);
EXPECT_EQ (v, 48);
EXPECT_EQ (lay::Color::from_hsv (h, s, v).to_string (), "#201030");
#if defined(HAVE_QT)
qc = QColor (32, 16, 48);
qc.getHsv (&ih, &is, &iv);
EXPECT_EQ (ih, 270);
EXPECT_EQ (is, 170);
EXPECT_EQ (iv, 48);
#endif
c = lay::Color (32, 48, 16);
c.get_hsv (h, s, v);
EXPECT_EQ (h, 90);
EXPECT_EQ (s, 170);
EXPECT_EQ (v, 48);
EXPECT_EQ (lay::Color::from_hsv (h, s, v).to_string (), "#203010");
#if defined(HAVE_QT)
qc = QColor (32, 48, 16);
qc.getHsv (&ih, &is, &iv);
EXPECT_EQ (ih, 90);
EXPECT_EQ (is, 170);
EXPECT_EQ (iv, 48);
#endif
c = lay::Color (48, 32, 16);
c.get_hsv (h, s, v);
EXPECT_EQ (h, 30);
EXPECT_EQ (s, 170);
EXPECT_EQ (v, 48);
EXPECT_EQ (lay::Color::from_hsv (h, s, v).to_string (), "#302010");
#if defined(HAVE_QT)
qc = QColor (48, 32, 16);
qc.getHsv (&ih, &is, &iv);
EXPECT_EQ (ih, 30);
EXPECT_EQ (is, 170);
EXPECT_EQ (iv, 48);
#endif
c = lay::Color (48, 16, 32);
c.get_hsv (h, s, v);
EXPECT_EQ (h, 330);
EXPECT_EQ (s, 170);
EXPECT_EQ (v, 48);
EXPECT_EQ (lay::Color::from_hsv (h, s, v).to_string (), "#301020");
#if defined(HAVE_QT)
qc = QColor (48, 16, 32);
qc.getHsv (&ih, &is, &iv);
EXPECT_EQ (ih, 330);
EXPECT_EQ (is, 170);
EXPECT_EQ (iv, 48);
#endif
c = lay::Color (16, 48, 32);
c.get_hsv (h, s, v);
EXPECT_EQ (h, 150);
EXPECT_EQ (s, 170);
EXPECT_EQ (v, 48);
EXPECT_EQ (lay::Color::from_hsv (h, s, v).to_string (), "#103020");
#if defined(HAVE_QT)
qc = QColor (16, 48, 32);
qc.getHsv (&ih, &is, &iv);
EXPECT_EQ (ih, 150);
EXPECT_EQ (is, 170);
EXPECT_EQ (iv, 48);
#endif
}