Skip to content

Commit d7c645d

Browse files
committed
finally fixed the rgb to hsv conversion
added format option of hsv to the hsv class, so that no conversion has to be made, when you just need the value of it's members, but if you need it from an rgb color, you have to convert nevertheless
1 parent c277723 commit d7c645d

File tree

2 files changed

+32
-22
lines changed

2 files changed

+32
-22
lines changed

src/helper/color.cpp

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,21 @@
77

88
#include <fmt/format.h>
99

10-
11-
#include <iostream>
12-
1310
[[nodiscard]] Color HSVColor::to_rgb_color() const {
1411
return Color{ *this };
1512
}
1613

1714
[[nodiscard]] std::string HSVColor::to_string() const {
18-
return to_rgb_color().to_string(Color::SerializeMode::HSV);
15+
return fmt::format("hsva({:.2f}, {:.5f}, {:.5f}, {:#2x})", h, s, v, a);
16+
}
17+
18+
19+
std::ostream& HSVColor::operator<<(std::ostream& os) const {
20+
os << to_string();
21+
return os;
1922
}
2023

24+
2125
helper::expected<Color, std::string> Color::from_string(const std::string& value) {
2226

2327
const auto result = detail::get_color_from_string(value);
@@ -35,7 +39,8 @@ namespace {
3539
if (value < static_cast<T>(0.0)) {
3640
// see https://math.stackexchange.com/questions/2179579/how-can-i-find-a-mod-with-negative-number
3741
T result = value;
38-
while (result < 0) {
42+
//TODO: maybe this is possible faster?
43+
while (result < static_cast<T>(0.0)) {
3944
result += divisor;
4045
}
4146
return result;
@@ -47,34 +52,37 @@ namespace {
4752
// taken carefully from https://math.stackexchange.com/questions/556341/rgb-to-hsv-color-conversion-algorithm
4853
// and modified and sped up, by optimizing it manually
4954
[[nodiscard]] HSVColor Color::to_hsv_color() const {
50-
constexpr auto max_d = static_cast<double>(0xFF);
51-
const double r_d = static_cast<double>(r) / max_d;
52-
const double g_d = static_cast<double>(g) / max_d;
53-
const double b_d = static_cast<double>(b) / max_d;
55+
using FloatType = double; //for more precision use "long double" here
56+
constexpr auto max_d = static_cast<FloatType>(0xFF);
57+
const auto r_d = static_cast<FloatType>(r) / max_d;
58+
const auto g_d = static_cast<FloatType>(g) / max_d;
59+
const auto b_d = static_cast<FloatType>(b) / max_d;
5460

55-
const double min = std::min({ r_d, g_d, b_d });
56-
const double max = std::max({ r_d, g_d, b_d });
57-
const double delta = max - min;
61+
const auto min = std::min<FloatType>({ r_d, g_d, b_d });
62+
const auto max = std::max<FloatType>({ r_d, g_d, b_d });
63+
const auto delta = max - min;
5864

59-
double h_temp = 0.0;
65+
FloatType h_temp = 0.0;
6066
if (min == max) {
6167
h_temp = 0.0;
62-
} else if (r >= max) { // > is bogus, just keeps compiler happy
63-
h_temp = (g - b) / delta; // between yellow & magenta
64-
} else if (g >= max) {
65-
h_temp = 2.0 + ((b - r) / delta); // between cyan & yellow
68+
} else if (r_d >= max) { // > is bogus, just keeps compiler happy
69+
h_temp = fmod_always_positive<FloatType>(
70+
(g_d - b_d) / delta, static_cast<FloatType>(6.0)
71+
); // between yellow & magenta
72+
} else if (g_d >= max) {
73+
h_temp = 2.0 + ((b_d - r_d) / delta); // between cyan & yellow
6674
} else {
67-
h_temp = 4.0 + ((r - g) / delta); // between magenta & cyan
75+
h_temp = 4.0 + ((r_d - g_d) / delta); // between magenta & cyan
6876
}
6977

7078
// use custom fmod, that always result in a positive value
71-
const double h = fmod_always_positive(h_temp, 6.0) * 60.0; //degrees
79+
const FloatType h = h_temp * static_cast<FloatType>(60.0); //degrees
7280

73-
const double s = max == 0.0 ? 0.0 : delta / max;
81+
const FloatType s = max == static_cast<FloatType>(0.0) ? static_cast<FloatType>(0.0) : delta / max;
7482

7583
//v = max
7684

77-
return HSVColor{ h, s, max, a };
85+
return HSVColor{ static_cast<double>(h), static_cast<double>(s), static_cast<double>(max), a };
7886
}
7987

8088
//Note: this output formats are all deserializable by the from_string method!
@@ -89,7 +97,7 @@ namespace {
8997
}
9098
case SerializeMode::HSV: {
9199
const auto color = to_hsv_color();
92-
return fmt::format("hsva({:.2f}, {:.5f}, {:.5f}, {:#2x})", color.h, color.s, color.v, color.a);
100+
return color.to_string();
93101
}
94102
default:
95103
utils::unreachable();

src/helper/color.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ struct HSVColor {
5252
[[nodiscard]] Color to_rgb_color() const;
5353

5454
[[nodiscard]] std::string to_string() const;
55+
56+
std::ostream& operator<<(std::ostream& os) const;
5557
};
5658

5759
struct Color {

0 commit comments

Comments
 (0)