Improve color blur implementation

This commit is contained in:
Nikita Lisitsa 2020-09-23 20:46:03 +03:00
parent 80e8c59a1e
commit 86785a5923
2 changed files with 25 additions and 9 deletions

View file

@ -2,8 +2,10 @@
#include <psemek/gfx/pixmap.hpp> #include <psemek/gfx/pixmap.hpp>
#include <psemek/pcg/seamless.hpp> #include <psemek/pcg/seamless.hpp>
#include <psemek/util/functional.hpp>
#include <vector> #include <vector>
#include <type_traits>
namespace psemek::pcg namespace psemek::pcg
{ {
@ -15,17 +17,20 @@ namespace psemek::pcg
} }
template <typename T> template <typename T, typename To, typename From>
gfx::basic_pixmap<T> blur(gfx::basic_pixmap<T> const & p, int size, float sigma, seamless_tag) gfx::basic_pixmap<T> blur(gfx::basic_pixmap<T> const & p, To && to, From && from, int size, float sigma, seamless_tag)
{ {
gfx::basic_pixmap<T> res({p.width(), p.height()}, T{}); gfx::basic_pixmap<T> res({p.width(), p.height()}, T{});
using R = std::decay_t<decltype(to(*p.begin()))>;
auto c = detail::gauss_coeffs(size, sigma); auto c = detail::gauss_coeffs(size, sigma);
for (std::size_t y = 0; y < p.height(); ++y) for (std::size_t y = 0; y < p.height(); ++y)
{ {
for (std::size_t x = 0; x < p.width(); ++x) for (std::size_t x = 0; x < p.width(); ++x)
{ {
auto v = R{};
for (int j = - size; j <= size; ++j) for (int j = - size; j <= size; ++j)
{ {
for (int i = - size; i <= size; ++i) for (int i = - size; i <= size; ++i)
@ -38,15 +43,22 @@ namespace psemek::pcg
while (iy < 0) iy += p.height(); while (iy < 0) iy += p.height();
if (static_cast<std::size_t>(iy) >= p.height()) iy = iy % p.height(); if (static_cast<std::size_t>(iy) >= p.height()) iy = iy % p.height();
res(x, y) += p(ix, iy) * c[i + size] * c[j + size]; v += to(p(ix, iy)) * c[i + size] * c[j + size];
} }
} }
res(x, y) = from(v);
} }
} }
return res; return res;
} }
template <typename T, typename To, typename From>
gfx::basic_pixmap<T> blur(gfx::basic_pixmap<T> const & p, int size, float sigma, seamless_tag)
{
return blur(p, util::id, util::id, size, sigma, seamless);
}
gfx::pixmap_rgb blur(gfx::pixmap_rgb const & p, int size, float sigma, seamless_tag); 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); gfx::pixmap_rgba blur(gfx::pixmap_rgba const & p, int size, float sigma, seamless_tag);

View file

@ -27,18 +27,22 @@ namespace psemek::pcg
} }
template <typename Pixel>
auto color_blur_impl(gfx::basic_pixmap<Pixel> const & p, int size, float sigma, seamless_tag)
{
auto to = [](auto const & c){ return gfx::to_colorf(c); };
auto from = [](auto const & c){ return gfx::to_coloru8(c); };
return blur(p, to, from, size, sigma, seamless);
}
gfx::pixmap_rgb blur(gfx::pixmap_rgb const & p, int size, float sigma, seamless_tag) gfx::pixmap_rgb blur(gfx::pixmap_rgb const & p, int size, float sigma, seamless_tag)
{ {
auto converted = util::map([](gfx::color_rgb const & c){ return gfx::to_colorf(c); }, p); return color_blur_impl(p, size, sigma, seamless);
converted = blur(converted, size, sigma, seamless);
return util::map([](geom::vector<float, 3> const & c){ return gfx::to_coloru8(c); }, converted);
} }
gfx::pixmap_rgba blur(gfx::pixmap_rgba const & p, int size, float sigma, seamless_tag) 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); return color_blur_impl(p, size, sigma, seamless);
converted = blur(converted, size, sigma, seamless);
return util::map([](geom::vector<float, 4> const & c){ return gfx::to_coloru8(c); }, converted);
} }
} }