diff --git a/libs/gfx/include/psemek/gfx/color.hpp b/libs/gfx/include/psemek/gfx/color.hpp index 9fbd4c39..7bec7f28 100644 --- a/libs/gfx/include/psemek/gfx/color.hpp +++ b/libs/gfx/include/psemek/gfx/color.hpp @@ -317,35 +317,67 @@ namespace psemek::gfx return generic_color{dark(c.c, darkness)}; } - template requires (std::is_floating_point_v && (N == 3 || N == 4)) - T hue(math::vector const & c) + template + math::vector rgb_to_hsv(math::vector const & rgb) { - T max = std::max({c[0], c[1], c[2]}); - T min = std::min({c[0], c[1], c[2]}); + T max = std::max({rgb[0], rgb[1], rgb[2]}); + T min = std::min({rgb[0], rgb[1], rgb[2]}); T delta = max - min; - if (delta == T{0}) - return T{0}; + T hue = T{0}; - T result; + if (delta > T{0}) + { + if (rgb[0] > rgb[1] && rgb[0] > rgb[2]) + { + hue = (rgb[1] - rgb[2]) / delta; + } + else if (rgb[1] > rgb[2]) + { + hue = 2.f + (rgb[2] - rgb[0]) / delta; + } + else + { + hue = 4.f + (rgb[0] - rgb[1]) / delta; + } + } - if (c[0] > c[1] && c[0] > c[2]) - { - result = (c[1] - c[2]) / delta; - } - else if (c[1] > c[2]) - { - result = 2.f + (c[2] - c[0]) / delta; - } + hue *= math::rad(60); + + if (hue < 0) + hue += math::rad(360); + + math::vector result; + result[0] = hue; + result[1] = (max > T{0}) ? (delta / max) : T{0}; + result[2] = max; + + return result; + } + + template + math::vector hsv_to_rgb(math::vector const & hsv) + { + auto c = hsv[1] * hsv[2]; + auto x = c * (T{1} - std::abs(std::fmod(hsv[0] / math::rad(60), 2.f) - 1.f)); + auto m = hsv[2] - c; + + math::vector result; + + if (hsv[0] < math::rad(60)) + result = {c, x, T{0}}; + else if (hsv[0] < math::rad(120)) + result = {x, c, T{0}}; + else if (hsv[0] < math::rad(180)) + result = {T{0}, c, x}; + else if (hsv[0] < math::rad(240)) + result = {T{0}, x, c}; + else if (hsv[0] < math::rad(300)) + result = {x, T{0}, c}; else - { - result = 4.f + (c[0] - c[1]) / delta; - } + result = {c, T{0}, x}; - result *= math::rad(60); - - if (result < 0) - result += math::rad(360); + result += math::vector{m, m, m}; return result; }