mirror of
https://github.com/KLayout/klayout.git
synced 2026-09-02 10:57:51 +02:00
WIP: HSV support in lay::Color
This commit is contained in:
@@ -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 ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user