From 80e8c59a1e413436b9b18f0f2e889813af27a6bd Mon Sep 17 00:00:00 2001 From: lisyarus Date: Wed, 23 Sep 2020 20:19:27 +0300 Subject: [PATCH] Templated blur implementation + specializations for color_rgb(a) --- libs/pcg/include/psemek/pcg/blur.hpp | 44 ++++++++++++++++++- libs/pcg/source/blur.cpp | 63 ++++++++++++---------------- 2 files changed, 69 insertions(+), 38 deletions(-) diff --git a/libs/pcg/include/psemek/pcg/blur.hpp b/libs/pcg/include/psemek/pcg/blur.hpp index 3121f518..f27bc494 100644 --- a/libs/pcg/include/psemek/pcg/blur.hpp +++ b/libs/pcg/include/psemek/pcg/blur.hpp @@ -3,9 +3,51 @@ #include #include +#include + namespace psemek::pcg { - gfx::basic_pixmap blur(gfx::basic_pixmap const & p, int size, float sigma, seamless_tag); + namespace detail + { + + std::vector gauss_coeffs(int size, float sigma); + + } + + template + gfx::basic_pixmap blur(gfx::basic_pixmap const & p, int size, float sigma, seamless_tag) + { + gfx::basic_pixmap res({p.width(), p.height()}, T{}); + + auto c = detail::gauss_coeffs(size, sigma); + + for (std::size_t y = 0; y < p.height(); ++y) + { + for (std::size_t x = 0; x < p.width(); ++x) + { + for (int j = - size; j <= size; ++j) + { + for (int i = - size; i <= size; ++i) + { + int ix = (x + i); + while (ix < 0) ix += p.width(); + if (static_cast(ix) >= p.width()) ix = ix % p.width(); + + int iy = (y + j); + while (iy < 0) iy += p.height(); + if (static_cast(iy) >= p.height()) iy = iy % p.height(); + + res(x, y) += p(ix, iy) * c[i + size] * c[j + size]; + } + } + } + } + + return res; + } + + gfx::pixmap_rgb blur(gfx::pixmap_rgb const & p, int size, float sigma, seamless_tag); + gfx::pixmap_rgba blur(gfx::pixmap_rgba const & p, int size, float sigma, seamless_tag); } diff --git a/libs/pcg/source/blur.cpp b/libs/pcg/source/blur.cpp index 8c435625..56f59ca5 100644 --- a/libs/pcg/source/blur.cpp +++ b/libs/pcg/source/blur.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -6,50 +7,38 @@ namespace psemek::pcg { - static std::vector gauss_coeffs(int size, float sigma) + namespace detail { - std::vector res(2 * size + 1); - float sum = 0.f; - for (int i = -size; i <= size; ++i) + + std::vector gauss_coeffs(int size, float sigma) { - float x = (i / sigma); - res[i + size] = std::exp(- x * x); - sum += res[i + size]; + std::vector res(2 * size + 1); + float sum = 0.f; + for (int i = -size; i <= size; ++i) + { + float x = (i / sigma); + res[i + size] = std::exp(- x * x); + sum += res[i + size]; + } + for (auto & c : res) + c /= sum; + return res; } - for (auto & c : res) - c /= sum; - return res; + } - gfx::basic_pixmap blur(gfx::basic_pixmap const & p, int size, float sigma, seamless_tag) + gfx::pixmap_rgb blur(gfx::pixmap_rgb const & p, int size, float sigma, seamless_tag) { - gfx::basic_pixmap res({p.width(), p.height()}, 0.f); + auto converted = util::map([](gfx::color_rgb const & c){ return gfx::to_colorf(c); }, p); + converted = blur(converted, size, sigma, seamless); + return util::map([](geom::vector const & c){ return gfx::to_coloru8(c); }, converted); + } - auto c = gauss_coeffs(size, sigma); - - for (std::size_t y = 0; y < p.height(); ++y) - { - for (std::size_t x = 0; x < p.width(); ++x) - { - for (int j = - size; j <= size; ++j) - { - for (int i = - size; i <= size; ++i) - { - int ix = (x + i); - while (ix < 0) ix += p.width(); - if (static_cast(ix) >= p.width()) ix = ix % p.width(); - - int iy = (y + j); - while (iy < 0) iy += p.height(); - if (static_cast(iy) >= p.height()) iy = iy % p.height(); - - res(x, y) += p(ix, iy) * c[i + size] * c[j + size]; - } - } - } - } - - return res; + gfx::pixmap_rgba blur(gfx::pixmap_rgba const & p, int size, float sigma, seamless_tag) + { + auto converted = util::map([](gfx::color_rgba const & c){ return gfx::to_colorf(c); }, p); + converted = blur(converted, size, sigma, seamless); + return util::map([](geom::vector const & c){ return gfx::to_coloru8(c); }, converted); } }