diff options
author | crupest <crupest@outlook.com> | 2022-03-10 21:17:17 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2022-03-10 21:17:17 +0800 |
commit | 168817476f85e8dbc04c06691a73a7d75c4858d5 (patch) | |
tree | 1c32d53c75bf4305a39423c51e5f4c92deba0ecc | |
parent | a9558215aef3b0ad67dc73788305e1b46bc872b5 (diff) | |
download | cru-168817476f85e8dbc04c06691a73a7d75c4858d5.tar.gz cru-168817476f85e8dbc04c06691a73a7d75c4858d5.tar.bz2 cru-168817476f85e8dbc04c06691a73a7d75c4858d5.zip |
...
-rw-r--r-- | include/cru/platform/Color.h | 16 | ||||
-rw-r--r-- | src/platform/Color.cpp | 80 |
2 files changed, 95 insertions, 1 deletions
diff --git a/include/cru/platform/Color.h b/include/cru/platform/Color.h index 4e35ae63..2e8c0ebe 100644 --- a/include/cru/platform/Color.h +++ b/include/cru/platform/Color.h @@ -2,8 +2,8 @@ #include "cru/common/Base.h" #include "cru/platform/Base.h" -#include "cru/common/String.h" #include "cru/common/Format.h" +#include "cru/common/String.h" #include <cstdint> #include <optional> @@ -262,4 +262,18 @@ inline String ToString(const Color& color) { return cru::Format(u"rgba({}, {}, {}, {})", color.red, color.green, color.blue, color.alpha); } + +struct CRU_PLATFORM_API HslColor { + HslColor() = default; + HslColor(float h, float s, float l, float a = 1.0f) + : h(h), s(s), l(l), a(a) {} + HslColor(const Color& rgb); + + operator Color() const; + + float h; + float s; + float l; + float a; +}; } // namespace cru::platform diff --git a/src/platform/Color.cpp b/src/platform/Color.cpp index b39865a8..dd1736ca 100644 --- a/src/platform/Color.cpp +++ b/src/platform/Color.cpp @@ -1,5 +1,7 @@ #include "cru/platform/Color.h" +#include <algorithm> +#include <cmath> #include <cstdint> #include <gsl/gsl> #include <optional> @@ -245,4 +247,82 @@ std::optional<Color> GetPredefinedColorByName(StringView name) { return std::nullopt; } } + +HslColor::HslColor(const Color& color) { + float rgb[3] = {color.red / 255.f, color.green / 255.f, color.blue / 255.f}; + float& r = rgb[0]; + float& g = rgb[1]; + float& b = rgb[2]; + + int max_index = 0; + int min_index = 0; + + if (r > g) { + max_index = r > b ? 0 : 2; + min_index = g < b ? 1 : 2; + } else { + max_index = g > b ? 1 : 2; + min_index = r < b ? 0 : 2; + } + + float max = rgb[max_index]; + float min = rgb[min_index]; + + float delta = max - min; + + if (delta == 0) { + h = 0.f; + } else if (max_index == 0) { + h = 60.f * std::fmod((g - b) / delta, 6.f); + } else if (max_index == 1) { + h = 60.f * ((b - r) / delta + 2.f); + } else { + h = 60.f * ((r - g) / delta + 4.f); + } + + l = (max + min) / 2.f; + + s = delta == 0 ? 0 : delta / (1 - std::abs(2 * l - 1)); + + a = color.alpha / 255.f; +} + +HslColor::operator Color() const { + Expects(h >= 0.f && h <= 360.f); + Expects(s >= 0.f && s <= 1.f); + Expects(l >= 0.f && l <= 1.f); + + float c = (1 - std::abs(2 * l - 1)) * s; + float x = c * (1 - std::abs(std::fmod(h / 60.f, 2.f) - 1)); + float m = l - c / 2; + + float rgb[3] = {0.f, 0.f, 0.f}; + + if (h >= 0.f && h < 60.f) { + rgb[0] = c; + rgb[1] = x; + } else if (h >= 60.f && h < 120.f) { + rgb[0] = x; + rgb[1] = c; + } else if (h >= 120.f && h < 180.f) { + rgb[1] = c; + rgb[2] = x; + } else if (h >= 180.f && h < 240.f) { + rgb[1] = x; + rgb[2] = c; + } else if (h >= 240.f && h < 300.f) { + rgb[0] = x; + rgb[2] = c; + } else if (h >= 300.f && h < 360.f) { + rgb[0] = c; + rgb[2] = x; + } + + for (int i = 0; i < 3; ++i) { + rgb[i] += m; + rgb[i] *= 255.f; + } + + return Color(rgb[0] + 0.5f, rgb[1] + 0.5f, rgb[2] + 0.5f, a * 255.f + 0.5f); +} } // namespace cru::platform |