diff --git a/examples/interstate75/interstate75_rainbow.cpp b/examples/interstate75/interstate75_rainbow.cpp index 5e012562..b44babf7 100644 --- a/examples/interstate75/interstate75_rainbow.cpp +++ b/examples/interstate75/interstate75_rainbow.cpp @@ -42,13 +42,10 @@ int main() { uint8_t hue_map[hub75.width][3]; for(uint i = 0; i < hub75.width; i++) { - uint8_t r=0; - uint8_t g=0; - uint8_t b=0; - graphics.from_hsv(i / (float) hub75.width, 1.0f, 0.7f, r, g, b); - hue_map[i][0] = r; - hue_map[i][1] = g; - hue_map[i][2] = b; + RGB p = RGB::from_hsv(i / (float) hub75.width, 1.0f, 0.7f); + hue_map[i][0] = p.r; + hue_map[i][1] = p.g; + hue_map[i][2] = p.b; } hub75.start(dma_complete); diff --git a/examples/pico_display_2/pico_display_2_demo.cpp b/examples/pico_display_2/pico_display_2_demo.cpp index ad9d9bdf..826e60bf 100644 --- a/examples/pico_display_2/pico_display_2_demo.cpp +++ b/examples/pico_display_2/pico_display_2_demo.cpp @@ -21,26 +21,6 @@ Button button_b(PicoDisplay2::B); Button button_x(PicoDisplay2::X); Button button_y(PicoDisplay2::Y); -// HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel -// Outputs are rgb in the range 0-255 for each channel -void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) { - float i = floor(h * 6.0f); - float f = h * 6.0f - i; - v *= 255.0f; - uint8_t p = v * (1.0f - s); - uint8_t q = v * (1.0f - f * s); - uint8_t t = v * (1.0f - (1.0f - f) * s); - - switch (int(i) % 6) { - case 0: r = v; g = t; b = p; break; - case 1: r = q; g = v; b = p; break; - case 2: r = p; g = v; b = t; break; - case 3: r = p; g = q; b = v; break; - case 4: r = t; g = p; b = v; break; - case 5: r = v; g = p; b = q; break; - } -} - int main() { st7789.set_backlight(255); @@ -107,10 +87,10 @@ int main() { // Since HSV takes a float from 0.0 to 1.0 indicating hue, // then we can divide millis by the number of milliseconds - // we want a full colour cycle to take. 5000 = 5 sec. - uint8_t r = 0, g = 0, b = 0; - from_hsv((float)millis() / 5000.0f, 1.0f, 0.5f + sinf(millis() / 100.0f / 3.14159f) * 0.5f, r, g, b); - led.set_rgb(r, g, b); + // we want a full colour cycle to take. 5000 = 5 sec + RGB p = RGB::from_hsv((float)millis() / 5000.0f, 1.0f, 0.5f + sinf(millis() / 100.0f / 3.14159f) * 0.5f); + + led.set_rgb(p.r, p.g, p.b); graphics.set_pen(WHITE); diff --git a/examples/pico_enc_explorer/pico_enc_explorer.cpp b/examples/pico_enc_explorer/pico_enc_explorer.cpp index 608e5d66..7fdd71c2 100644 --- a/examples/pico_enc_explorer/pico_enc_explorer.cpp +++ b/examples/pico_enc_explorer/pico_enc_explorer.cpp @@ -24,32 +24,11 @@ static const uint8_t STEPS_PER_REV = 24; BreakoutEncoder enc; bool toggle = false; -// HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel -// Outputs are rgb in the range 0-255 for each channel -void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) { - float i = floor(h * 6.0f); - float f = h * 6.0f - i; - v *= 255.0f; - uint8_t p = v * (1.0f - s); - uint8_t q = v * (1.0f - f * s); - uint8_t t = v * (1.0f - (1.0f - f) * s); - - switch (int(i) % 6) { - case 0: r = v; g = t; b = p; break; - case 1: r = q; g = v; b = p; break; - case 2: r = p; g = v; b = t; break; - case 3: r = p; g = q; b = v; break; - case 4: r = t; g = p; b = v; break; - case 5: r = v; g = p; b = q; break; - } -} - void count_changed(int16_t count) { printf("Count: %d\n", count); float h = (count % STEPS_PER_REV) / (float)STEPS_PER_REV; - uint8_t r, g, b; - from_hsv(h, 1.0f, 1.0f, r, g, b); - enc.set_led(r, g, b); + RGB p = RGB::from_hsv(h, 1.0f, 1.0f); + enc.set_led(p.r, p.g, p.b); graphics.set_pen(BLACK); graphics.clear(); @@ -58,7 +37,7 @@ void count_changed(int16_t count) { graphics.set_pen(RED); std::ostringstream ss; ss << "R = "; - ss << (int)r; + ss << (int)(p.r); std::string s(ss.str()); graphics.text(s, Point(10, 10), 220, 6); } @@ -67,7 +46,7 @@ void count_changed(int16_t count) { graphics.set_pen(GREEN); std::ostringstream ss; ss << "G = "; - ss << (int)g; + ss << (int)(p.g); std::string s(ss.str()); graphics.text(s, Point(10, 70), 220, 6); } @@ -76,7 +55,7 @@ void count_changed(int16_t count) { graphics.set_pen(BLUE); std::ostringstream ss; ss << "B = "; - ss << (int)b; + ss << (int)(p.b); std::string s(ss.str()); graphics.text(s, Point(10, 130), 220, 6); } @@ -84,12 +63,12 @@ void count_changed(int16_t count) { { // Shouldn't really use create_pen in-line. // In default (RGB332) palette mode this will lookup the nearest 8-bit colour - graphics.set_pen(graphics.create_pen(r, g, b)); + graphics.set_pen(graphics.create_pen(p.r, p.g, p.b)); std::ostringstream ss; ss << "#"; - ss << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << (int)r; - ss << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << (int)g; - ss << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << (int)b; + ss << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << (int)(p.r); + ss << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << (int)(p.g); + ss << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << (int)(p.b); std::string s(ss.str()); graphics.text(s, Point(10, 190), 220, 5); } diff --git a/examples/pico_pot_explorer/pico_pot_explorer.cpp b/examples/pico_pot_explorer/pico_pot_explorer.cpp index 96c98d24..f062924d 100644 --- a/examples/pico_pot_explorer/pico_pot_explorer.cpp +++ b/examples/pico_pot_explorer/pico_pot_explorer.cpp @@ -24,26 +24,6 @@ I2C i2c(PICO_EXPLORER); BreakoutPotentiometer pot(&i2c); bool toggle = false; -// HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel -// Outputs are rgb in the range 0-255 for each channel -void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) { - float i = floor(h * 6.0f); - float f = h * 6.0f - i; - v *= 255.0f; - uint8_t p = v * (1.0f - s); - uint8_t q = v * (1.0f - f * s); - uint8_t t = v * (1.0f - (1.0f - f) * s); - - switch (int(i) % 6) { - case 0: r = v; g = t; b = p; break; - case 1: r = q; g = v; b = p; break; - case 2: r = p; g = v; b = t; break; - case 3: r = p; g = q; b = v; break; - case 4: r = t; g = p; b = v; break; - case 5: r = v; g = p; b = q; break; - } -} - int main() { #ifdef PICO_DEFAULT_LED_PIN gpio_init(PICO_DEFAULT_LED_PIN); @@ -66,9 +46,8 @@ int main() { float percent = pot.read(); printf("Percent: %d\n", (int)(percent * 100)); - uint8_t r = 0, g = 0, b = 0; - from_hsv(percent, 1.0f, 1.0f, r, g, b); - pot.set_led(r, g, b); + RGB p = RGB::from_hsv(percent, 1.0f, 1.0f); + pot.set_led(p.r, p.g, p.b); graphics.set_pen(BLACK); graphics.clear(); @@ -77,7 +56,7 @@ int main() { graphics.set_pen(RED); std::ostringstream ss; ss << "R = "; - ss << (int)r; + ss << (int)(p.r); std::string s(ss.str()); graphics.text(s, Point(10, 10), 220, 6); } @@ -86,7 +65,7 @@ int main() { graphics.set_pen(GREEN); std::ostringstream ss; ss << "G = "; - ss << (int)g; + ss << (int)(p.g); std::string s(ss.str()); graphics.text(s, Point(10, 70), 220, 6); } @@ -95,7 +74,7 @@ int main() { graphics.set_pen(BLUE); std::ostringstream ss; ss << "B = "; - ss << (int)b; + ss << (int)(p.b); std::string s(ss.str()); graphics.text(s, Point(10, 130), 220, 6); } @@ -103,12 +82,12 @@ int main() { { // Shouldn't really use create_pen in-line. // In default (RGB332) palette mode this will lookup the nearest 8-bit colour - graphics.set_pen(graphics.create_pen(r, g, b)); + graphics.set_pen(graphics.create_pen(p.r, p.g, p.b)); std::ostringstream ss; ss << "#"; - ss << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << (int)r; - ss << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << (int)g; - ss << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << (int)b; + ss << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << (int)(p.r); + ss << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << (int)(p.g); + ss << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << (int)(p.b); std::string s(ss.str()); graphics.text(s, Point(10, 190), 220, 5); } diff --git a/examples/pico_unicorn/demo.cpp b/examples/pico_unicorn/demo.cpp index 53757347..3ec174fb 100644 --- a/examples/pico_unicorn/demo.cpp +++ b/examples/pico_unicorn/demo.cpp @@ -9,25 +9,6 @@ using namespace pimoroni; PicoUnicorn pico_unicorn; -void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) { - float i = floor(h * 6.0f); - float f = h * 6.0f - i; - v *= 255.0f; - uint8_t p = v * (1.0f - s); - uint8_t q = v * (1.0f - f * s); - uint8_t t = v * (1.0f - (1.0f - f) * s); - - switch (int(i) % 6) { - case 0: r = v; g = t; b = p; break; - case 1: r = q; g = v; b = p; break; - case 2: r = p; g = v; b = t; break; - case 3: r = p; g = q; b = v; break; - case 4: r = t; g = p; b = v; break; - case 5: r = v; g = p; b = q; break; - } - } - - int main() { pico_unicorn.init(); @@ -46,21 +27,6 @@ int main() { if(pico_unicorn.is_pressed(pico_unicorn.X)) { x_pressed = true; } if(pico_unicorn.is_pressed(pico_unicorn.Y)) { y_pressed = true; } - /* - for(uint8_t y = 0; y < 7; y++) { - for(uint8_t x = 0; x < 16; x++) { - uint8_t r, g, b; - float h = float(x) / 63.0f + float(i) / 500.0f; - h = h - float(int(h)); - float s = 1.0f;//(sin(float(i) / 200.0f) * 0.5f) + 0.5f; - float v = (float(y) / 8.0f) + 0.05f; - from_hsv(h, s, v, r, g, b); - - pico_unicorn.set_pixel(x, y, r, g, b); - j = j + 1; - } - }*/ - pico_unicorn.clear(); if(a_pressed & b_pressed & x_pressed & y_pressed) { diff --git a/examples/tufty2040/tufty2040_drawing.cpp b/examples/tufty2040/tufty2040_drawing.cpp index 48f68e2b..af5287d1 100644 --- a/examples/tufty2040/tufty2040_drawing.cpp +++ b/examples/tufty2040/tufty2040_drawing.cpp @@ -43,26 +43,6 @@ uint32_t time() { return to_ms_since_boot(t); } -// HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel -// Outputs are rgb in the range 0-255 for each channel -void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) { - float i = floor(h * 6.0f); - float f = h * 6.0f - i; - v *= 255.0f; - uint8_t p = v * (1.0f - s); - uint8_t q = v * (1.0f - f * s); - uint8_t t = v * (1.0f - (1.0f - f) * s); - - switch (int(i) % 6) { - case 0: r = v; g = t; b = p; break; - case 1: r = q; g = v; b = p; break; - case 2: r = p; g = v; b = t; break; - case 3: r = p; g = q; b = v; break; - case 4: r = t; g = p; b = v; break; - case 5: r = v; g = p; b = q; break; - } -} - int main() { st7789.set_backlight(255); diff --git a/libraries/pico_graphics/pico_graphics.cpp b/libraries/pico_graphics/pico_graphics.cpp index 674b3850..1995573d 100644 --- a/libraries/pico_graphics/pico_graphics.cpp +++ b/libraries/pico_graphics/pico_graphics.cpp @@ -4,24 +4,6 @@ namespace pimoroni { const uint8_t dither16_pattern[16] = {0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5}; - void PicoGraphics::from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) { - float i = floor(h * 6.0f); - float f = h * 6.0f - i; - v *= 255.0f; - uint8_t p = v * (1.0f - s); - uint8_t q = v * (1.0f - f * s); - uint8_t t = v * (1.0f - (1.0f - f) * s); - - switch (int(i) % 6) { - case 0: r = v; g = t; b = p; break; - case 1: r = q; g = v; b = p; break; - case 2: r = p; g = v; b = t; break; - case 3: r = p; g = q; b = v; break; - case 4: r = t; g = p; b = v; break; - case 5: r = v; g = p; b = q; break; - } - } - int PicoGraphics::update_pen(uint8_t i, uint8_t r, uint8_t g, uint8_t b) {return -1;}; int PicoGraphics::reset_pen(uint8_t i) {return -1;}; int PicoGraphics::create_pen(uint8_t r, uint8_t g, uint8_t b) {return -1;}; diff --git a/libraries/pico_graphics/pico_graphics.hpp b/libraries/pico_graphics/pico_graphics.hpp index 68a2ddd8..71d18ac3 100644 --- a/libraries/pico_graphics/pico_graphics.hpp +++ b/libraries/pico_graphics/pico_graphics.hpp @@ -45,6 +45,25 @@ namespace pimoroni { g((c >> 8) & 0xff), b(c & 0xff) {} constexpr RGB(int16_t r, int16_t g, int16_t b) : r(r), g(g), b(b) {} + + static RGB from_hsv(float h, float s, float v) { + float i = floor(h * 6.0f); + float f = h * 6.0f - i; + v *= 255.0f; + uint8_t p = v * (1.0f - s); + uint8_t q = v * (1.0f - f * s); + uint8_t t = v * (1.0f - (1.0f - f) * s); + + switch (int(i) % 6) { + case 0: return RGB(v, t, p); + case 1: return RGB(q, v, p); + case 2: return RGB(p, v, t); + case 3: return RGB(p, q, v); + case 4: return RGB(t, p, v); + case 5: return RGB(v, p, q); + default: return RGB(0, 0, 0); + } + } constexpr RGB operator+ (const RGB& c) const {return RGB(r + c.r, g + c.g, b + c.b);} constexpr RGB& operator+=(const RGB& c) {r += c.r; g += c.g; b += c.b; return *this;} @@ -271,7 +290,6 @@ namespace pimoroni { void polygon(const std::vector &points); void triangle(Point p1, Point p2, Point p3); void line(Point p1, Point p2); - void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b); void thick_line(Point p1, Point p2, uint thickness); protected: @@ -551,6 +569,7 @@ namespace pimoroni { void set_pen(uint8_t r, uint8_t g, uint8_t b) override; void set_thickness(uint t) override {}; int create_pen(uint8_t r, uint8_t g, uint8_t b) override; + int create_pen_hsv(float h, float s, float v) override; void set_pixel(const Point &p) override; void set_pixel_span(const Point &p, uint l) override; diff --git a/libraries/pico_graphics/pico_graphics_pen_inky7.cpp b/libraries/pico_graphics/pico_graphics_pen_inky7.cpp index 821a4538..bc9854c7 100644 --- a/libraries/pico_graphics/pico_graphics_pen_inky7.cpp +++ b/libraries/pico_graphics/pico_graphics_pen_inky7.cpp @@ -15,6 +15,9 @@ namespace pimoroni { int PicoGraphics_PenInky7::create_pen(uint8_t r, uint8_t g, uint8_t b) { return RGB(r, g, b).to_rgb888() | 0x010101; } + int PicoGraphics_PenInky7::create_pen_hsv(float h, float s, float v) { + return RGB::from_hsv(h, s, v).to_rgb888(); + } void PicoGraphics_PenInky7::set_pixel(const Point &p) { if ((color & 0x010101) == 0x010101) { set_pixel_dither(p, RGB(color)); diff --git a/libraries/pico_graphics/pico_graphics_pen_p4.cpp b/libraries/pico_graphics/pico_graphics_pen_p4.cpp index fd6eb633..68b3d62c 100644 --- a/libraries/pico_graphics/pico_graphics_pen_p4.cpp +++ b/libraries/pico_graphics/pico_graphics_pen_p4.cpp @@ -45,11 +45,8 @@ namespace pimoroni { return -1; } int PicoGraphics_PenP4::create_pen_hsv(float h, float s, float v) { - uint8_t r; - uint8_t g; - uint8_t b; - from_hsv(h, s, v, r, g, b); - return create_pen(r, g, b); + RGB p = RGB::from_hsv(h, s, v); + return create_pen(p.r, p.g, p.b); } int PicoGraphics_PenP4::reset_pen(uint8_t i) { palette[i] = {0, 0, 0}; diff --git a/libraries/pico_graphics/pico_graphics_pen_p8.cpp b/libraries/pico_graphics/pico_graphics_pen_p8.cpp index 92b4d698..f7d0be73 100644 --- a/libraries/pico_graphics/pico_graphics_pen_p8.cpp +++ b/libraries/pico_graphics/pico_graphics_pen_p8.cpp @@ -40,11 +40,8 @@ namespace pimoroni { return -1; } int PicoGraphics_PenP8::create_pen_hsv(float h, float s, float v) { - uint8_t r; - uint8_t g; - uint8_t b; - from_hsv(h, s, v, r, g, b); - return create_pen(r, g, b); + RGB p = RGB::from_hsv(h, s, v); + return create_pen(p.r, p.g, p.b); } int PicoGraphics_PenP8::reset_pen(uint8_t i) { palette[i] = {0, 0, 0}; diff --git a/libraries/pico_graphics/pico_graphics_pen_rgb332.cpp b/libraries/pico_graphics/pico_graphics_pen_rgb332.cpp index 022f1291..668e484d 100644 --- a/libraries/pico_graphics/pico_graphics_pen_rgb332.cpp +++ b/libraries/pico_graphics/pico_graphics_pen_rgb332.cpp @@ -19,11 +19,7 @@ namespace pimoroni { return rgb_to_rgb332(r, g, b); } int PicoGraphics_PenRGB332::create_pen_hsv(float h, float s, float v) { - uint8_t r; - uint8_t g; - uint8_t b; - from_hsv(h, s, v, r, g, b); - return rgb_to_rgb332(r, g, b); + return RGB::from_hsv(h, s, v).to_rgb332(); } void PicoGraphics_PenRGB332::set_pixel(const Point &p) { uint8_t *buf = (uint8_t *)frame_buffer; diff --git a/libraries/pico_graphics/pico_graphics_pen_rgb565.cpp b/libraries/pico_graphics/pico_graphics_pen_rgb565.cpp index 5d1cf57a..f17c6be4 100644 --- a/libraries/pico_graphics/pico_graphics_pen_rgb565.cpp +++ b/libraries/pico_graphics/pico_graphics_pen_rgb565.cpp @@ -19,11 +19,7 @@ namespace pimoroni { return RGB(r, g, b).to_rgb565(); } int PicoGraphics_PenRGB565::create_pen_hsv(float h, float s, float v) { - uint8_t r; - uint8_t g; - uint8_t b; - from_hsv(h, s, v, r, g, b); - return RGB(r, g, b).to_rgb565(); + return RGB::from_hsv(h, s, v).to_rgb565(); } void PicoGraphics_PenRGB565::set_pixel(const Point &p) { uint16_t *buf = (uint16_t *)frame_buffer; diff --git a/libraries/pico_graphics/pico_graphics_pen_rgb888.cpp b/libraries/pico_graphics/pico_graphics_pen_rgb888.cpp index 9758f49f..6cc9d2ad 100644 --- a/libraries/pico_graphics/pico_graphics_pen_rgb888.cpp +++ b/libraries/pico_graphics/pico_graphics_pen_rgb888.cpp @@ -19,11 +19,7 @@ namespace pimoroni { return RGB(r, g, b).to_rgb888(); } int PicoGraphics_PenRGB888::create_pen_hsv(float h, float s, float v) { - uint8_t r; - uint8_t g; - uint8_t b; - from_hsv(h, s, v, r, g, b); - return RGB(r, g, b).to_rgb888(); + return RGB::from_hsv(h, s, v).to_rgb888(); } void PicoGraphics_PenRGB888::set_pixel(const Point &p) { uint32_t *buf = (uint32_t *)frame_buffer;