Skip to content

Commit 944de98

Browse files
authored
feat(color): add Rgb(uint32_t hex) constructor and float, decimal, and hex format specifiers (#298)
1 parent f31595a commit 944de98

File tree

3 files changed

+77
-3
lines changed

3 files changed

+77
-3
lines changed

components/color/example/main/color_example.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,30 @@ extern "C" void app_main(void) {
3131
fmt::print(espp::color_code(grey_hsv.rgb()), "Grey HSV: {} --> RGB {}\n", grey_hsv,
3232
grey_hsv.rgb());
3333

34+
// test RGB from hex integer construction
35+
fmt::print("RGB from hex:\n");
36+
fmt::print("--------------\n");
37+
uint32_t red_hex_int = 0xFF0000;
38+
espp::Rgb red_hex(red_hex_int);
39+
fmt::print(espp::color_code(red_hex), "Red from hex: {0:d} == {0:x} ? {1}\n", red_hex,
40+
red_hex.hex() == red_hex_int);
41+
uint32_t green_hex_int = 0x00FF00;
42+
espp::Rgb green_hex(green_hex_int);
43+
fmt::print(espp::color_code(green_hex), "Green from hex: {0:d} == {0:x} ? {1}\n", green_hex,
44+
green_hex.hex() == green_hex_int);
45+
uint32_t blue_hex_int = 0x0000FF;
46+
espp::Rgb blue_hex(blue_hex_int);
47+
fmt::print(espp::color_code(blue_hex), "Blue from hex: {0:d} == {0:x} ? {1}\n", blue_hex,
48+
blue_hex.hex() == blue_hex_int);
49+
uint32_t white_hex_int = 0xFFFFFF;
50+
espp::Rgb white_hex(white_hex_int);
51+
fmt::print(espp::color_code(white_hex), "White from hex: {0:d} == {0:x} ? {1}\n", white_hex,
52+
white_hex.hex() == white_hex_int);
53+
uint32_t grey_hex_int = 0x808080;
54+
espp::Rgb grey_hex(grey_hex_int);
55+
fmt::print(espp::color_code(grey_hex), "Grey from hex: {0:d} == {0:x} ? {1}\n", grey_hex,
56+
grey_hex.hex() == grey_hex_int);
57+
3458
espp::Rgb white(1., 1., 1.);
3559
espp::Rgb black(0., 0., 0.);
3660
espp::Rgb red(1., 0., 0.);

components/color/include/color.hpp

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ class Rgb {
5151
*/
5252
explicit Rgb(const Hsv &hsv);
5353

54+
/**
55+
* @brief Construct an Rgb object from the provided hex value.
56+
* @param hex Hex value to convert to RGB. The hex value should be in the
57+
* format 0xRRGGBB.
58+
*/
59+
explicit Rgb(const uint32_t &hex);
60+
5461
/**
5562
* @brief Assign the values of the provided Rgb object to this Rgb object.
5663
* @param other The Rgb object to copy.
@@ -82,6 +89,12 @@ class Rgb {
8289
* @return An HSV object containing the HSV representation.
8390
*/
8491
Hsv hsv() const;
92+
93+
/**
94+
* @brief Get the hex representation of this RGB color.
95+
* @return The hex representation of this RGB color.
96+
*/
97+
uint32_t hex() const;
8598
};
8699

87100
/**
@@ -163,12 +176,35 @@ class Hsv {
163176
// for allowing easy serialization/printing of the
164177
// Rgb
165178
template <> struct fmt::formatter<espp::Rgb> {
166-
template <typename ParseContext> constexpr auto parse(ParseContext &ctx) const {
167-
return ctx.begin();
179+
// Presentation format: 'f' - floating [0,1] (default), 'd' - integer [0,255], 'x' - hex integer.
180+
char presentation = 'f';
181+
182+
template <typename ParseContext> constexpr auto parse(ParseContext &ctx) {
183+
// Parse the presentation format and store it in the formatter:
184+
auto it = ctx.begin(), end = ctx.end();
185+
if (it != end && (*it == 'f' || *it == 'd' || *it == 'x'))
186+
presentation = *it++;
187+
188+
// TODO: Check if reached the end of the range:
189+
// if (it != end && *it != '}') throw format_error("invalid format");
190+
191+
// Return an iterator past the end of the parsed range:
192+
return it;
168193
}
169194

170195
template <typename FormatContext> auto format(espp::Rgb const &rgb, FormatContext &ctx) const {
171-
return fmt::format_to(ctx.out(), "({}, {}, {})", rgb.r, rgb.g, rgb.b);
196+
switch (presentation) {
197+
case 'f':
198+
return fmt::format_to(ctx.out(), "({}, {}, {})", rgb.r, rgb.g, rgb.b);
199+
case 'd':
200+
return fmt::format_to(ctx.out(), "({}, {}, {})", static_cast<int>(rgb.r * 255),
201+
static_cast<int>(rgb.g * 255), static_cast<int>(rgb.b * 255));
202+
case 'x':
203+
return fmt::format_to(ctx.out(), "{:#08X}", rgb.hex());
204+
default:
205+
// shouldn't get here!
206+
return fmt::format_to(ctx.out(), "({}, {}, {})", rgb.r, rgb.g, rgb.b);
207+
}
172208
}
173209
};
174210

components/color/src/color.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ Rgb::Rgb(const Rgb &rgb)
2424
Rgb::Rgb(const Hsv &hsv)
2525
: Rgb(hsv.rgb()) {}
2626

27+
Rgb::Rgb(const uint32_t &hex) {
28+
r = ((hex >> 16) & 0xFF) / 255.0f;
29+
g = ((hex >> 8) & 0xFF) / 255.0f;
30+
b = (hex & 0xFF) / 255.0f;
31+
}
32+
2733
Rgb &Rgb::operator=(const Hsv &hsv) {
2834
*this = hsv.rgb();
2935
return *this;
@@ -83,6 +89,14 @@ Hsv Rgb::hsv() const {
8389
return HSV;
8490
}
8591

92+
uint32_t Rgb::hex() const {
93+
uint32_t hex = 0;
94+
hex |= static_cast<uint32_t>(r * 255) << 16;
95+
hex |= static_cast<uint32_t>(g * 255) << 8;
96+
hex |= static_cast<uint32_t>(b * 255);
97+
return hex;
98+
}
99+
86100
Hsv::Hsv(const float &_h, const float &_s, const float &_v)
87101
: h(_h)
88102
, s(_s)

0 commit comments

Comments
 (0)