From 6cd04636c133a6a103a35d8c35bcad844233a487 Mon Sep 17 00:00:00 2001 From: Bart Beumer Date: Tue, 11 Nov 2025 19:56:39 +0000 Subject: [PATCH] WIP add color --- applications/http-mandelbrot/src/main.cpp | 16 ++- bmrshared/include/bmrshared/color.hpp | 138 ++++++++++++++++++++++ 2 files changed, 150 insertions(+), 4 deletions(-) create mode 100644 bmrshared/include/bmrshared/color.hpp diff --git a/applications/http-mandelbrot/src/main.cpp b/applications/http-mandelbrot/src/main.cpp index db06ae3..86a8fb2 100644 --- a/applications/http-mandelbrot/src/main.cpp +++ b/applications/http-mandelbrot/src/main.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -155,16 +156,23 @@ void fractal( constexpr int max_iterations = 255; - boost::gil::gray8_image_t image(pixel_width,pixel_height); + boost::gil::rgb8_image_t image(pixel_width,pixel_height); auto view = boost::gil::view(image); - boost::gil::fill_pixels(view, boost::gil::gray8_pixel_t(0)); + boost::gil::fill_pixels(view, boost::gil::rgb8_pixel_t(0)); auto painter = [&](int x, int y, int num_iter) -> void { if(x >= 0 && y >= 0 && x < pixel_width && y < pixel_height) { + bmrshared::color c({.h=(num_iter*5)%360,.s=(0.5+(num_iter/200.0)), .v=1.0}); + auto crgb = c.rgb(); + uint8_t r = crgb.r * 255; + uint8_t g = crgb.g * 255; + uint8_t b = crgb.b * 255; + + const auto iter = view.at({x, y}); - boost::gil::color_convert(boost::gil::gray8_pixel_t(num_iter), *iter); + boost::gil::color_convert(boost::gil::rgb8_pixel_t(r,g,b), *iter); } }; @@ -245,7 +253,7 @@ int main(int argc, char **argv) std::vector threads; - while(threads.size() < 16) + while(threads.size() < 4) { threads.emplace_back([&ioc]{ioc.run();}); } diff --git a/bmrshared/include/bmrshared/color.hpp b/bmrshared/include/bmrshared/color.hpp new file mode 100644 index 0000000..82df346 --- /dev/null +++ b/bmrshared/include/bmrshared/color.hpp @@ -0,0 +1,138 @@ +// GNU Lesser General Public License v3.0 +// Copyright (c) 2023 Bart Beumer +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License v3.0 as published by +// the Free Software Foundation. +// +#pragma once +#include +#include +#include + + +namespace bmrshared +{ +class color +{ +public: + struct color_hsv + { + double h; + double s; + double v; + }; + + struct color_rgb + { + double r; + double g; + double b; + }; + + color() = delete; + ~color() = default; + constexpr color(const color&) = default; + constexpr color(color&&) = default; + constexpr color& operator=(const color&) = default; + constexpr color& operator=(color&&) = default; + + constexpr color(const color_hsv& c) + : m_rgb() + , m_hsv(c) + {} + + constexpr color(const color_rgb& c) + : m_rgb(c) + , m_hsv() + {} + + constexpr const color_rgb& rgb() const + { + if (!m_rgb) + { + m_rgb = calculate_rgb(*m_hsv); + } + return *m_rgb; + } + + constexpr const color_hsv& hsv() const + { + if (!m_hsv) + { + m_hsv = calculate_hsv(*m_rgb); + } + return *m_hsv; + } + +private: + static constexpr color_hsv calculate_hsv(const color_rgb& c) + { + color_hsv r{.h = 0.0, .s = 0.0, .v = 0.0}; + double min = std::min(c.r, std::min(c.g,c.b)); + r.v = std::max(c.r, std::max(c.g,c.b)); + double delta = r.v - min; + r.s = (r.v <= 0.0) ? 0.0 : (delta / r.v); + if (r.s <= 0.0) + { + r.h = 0.0; + } + else + { + if (c.r == r.v) + { + r.h = (c.g - c.b) / delta; + } + else if (c.g == r.v) + { + r.h = 2.0 + (c.b - c.r) / delta; + } + else if (c.b == r.v) + { + r.h = 4.0 + (c.r - c.g) / delta; + } + r.h*=60.0; + if (r.h < 0.0) + { + r.h +=360.0; + } + } + return r; + } + + static constexpr color_rgb calculate_rgb(const color_hsv& in) + { + double C = in.s * in.v; + double X = C*(1-std::fabs(std::fmod(in.h/60.0, 2)-1)); + double m = in.v-C; + + color_rgb result{.r = 0.0, .g = 0.0, .b = 0.0}; + if(in.h >= 0.0 && in.h < 60.0){ + result = {.r = C, .g = X, .b = 0.0}; + } + else if(in.h >= 60.0 && in.h < 120.0){ + result = {.r = X, .g = C, . b = 0.0}; + } + else if(in.h >= 120.0 && in.h < 180.0){ + result = {.r = 0.0, .g = C, .b = X}; + } + else if(in.h >= 180.0 && in.h < 240.0){ + result = {.r = 0.0, .g = X, .b = C}; + } + else if(in.h >= 240.0 && in.h < 300.0){ + result = {.r = X, .g = 0.0, .b = C}; + } + else{ + result = {.r = C, .g = 0.0, .b = X}; + } + result.r+=m; + result.g+=m; + result.b+=m; + + return result; + } + + mutable std::optional m_rgb; + mutable std::optional m_hsv; +}; +}