From 93f4388e45e5506c01b8317e7d5989a6f1e313be Mon Sep 17 00:00:00 2001 From: AnotherTest Date: Sun, 4 Oct 2020 22:56:20 +0330 Subject: [PATCH] LibGfx+PixelPaint: Fix distortions in convolutions with size != 4 or 5 --- Applications/PixelPaint/FilterParams.h | 7 ++++--- .../LibGfx/Filters/GenericConvolutionFilter.h | 20 ++++++++++--------- Libraries/LibGfx/Vector3.h | 17 ++++++++++++++++ 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/Applications/PixelPaint/FilterParams.h b/Applications/PixelPaint/FilterParams.h index 0739ed8831..8d174c0989 100644 --- a/Applications/PixelPaint/FilterParams.h +++ b/Applications/PixelPaint/FilterParams.h @@ -121,14 +121,15 @@ template struct FilterParameters> { static OwnPtr::Parameters> get() { + constexpr static ssize_t offset = N / 2; Matrix kernel; auto sigma = 1.0f; auto s = 2.0f * sigma * sigma; - for (auto x = -(ssize_t)N / 2; x <= (ssize_t)N / 2; x++) { - for (auto y = -(ssize_t)N / 2; y <= (ssize_t)N / 2; y++) { + for (auto x = -offset; x <= offset; x++) { + for (auto y = -offset; y <= offset; y++) { auto r = sqrt(x * x + y * y); - kernel.elements()[x + 2][y + 2] = (exp(-(r * r) / s)) / (M_PI * s); + kernel.elements()[x + offset][y + offset] = (exp(-(r * r) / s)) / (M_PI * s); } } diff --git a/Libraries/LibGfx/Filters/GenericConvolutionFilter.h b/Libraries/LibGfx/Filters/GenericConvolutionFilter.h index 73b74c45fa..416f84321a 100644 --- a/Libraries/LibGfx/Filters/GenericConvolutionFilter.h +++ b/Libraries/LibGfx/Filters/GenericConvolutionFilter.h @@ -73,6 +73,7 @@ public: class ApplyCache { template friend class GenericConvolutionFilter; + private: RefPtr m_target; }; @@ -120,23 +121,24 @@ public: Bitmap* render_target_bitmap = (&target != &source) ? &target : apply_cache.m_target.ptr(); // FIXME: Help! I am naive! + constexpr static ssize_t offset = N / 2; for (auto i_ = 0; i_ < target_rect.width(); ++i_) { - auto i = i_ + target_rect.x(); + ssize_t i = i_ + target_rect.x(); for (auto j_ = 0; j_ < target_rect.height(); ++j_) { - auto j = j_ + target_rect.y(); + ssize_t j = j_ + target_rect.y(); FloatVector3 value(0, 0, 0); - for (auto k = 0; k < 4; ++k) { - auto ki = i + k - 2; - if (i < source_rect.x() || i > source_rect.right()) { + for (auto k = 0l; k < (ssize_t)N; ++k) { + auto ki = i + k - offset; + if (ki < source_rect.x() || ki > source_rect.right()) { if (parameters.should_wrap()) ki = (ki + source.size().width()) % source.size().width(); // TODO: fix up using source_rect else continue; } - for (auto l = 0; l < 4; ++l) { - auto lj = j + l - 2; - if (j < source_rect.y() || j > source_rect.bottom()) { + for (auto l = 0l; l < (ssize_t)N; ++l) { + auto lj = j + l - offset; + if (lj < source_rect.y() || lj > source_rect.bottom()) { if (parameters.should_wrap()) lj = (lj + source.size().height()) % source.size().height(); // TODO: fix up using source_rect else @@ -150,7 +152,7 @@ public: } } - // The float->u8 overflow is intentional. + value.clamp(0, 255); render_target_bitmap->set_pixel(i, j, Color(value.x(), value.y(), value.z(), source.get_pixel(i + source_delta_x, j + source_delta_y).alpha())); } } diff --git a/Libraries/LibGfx/Vector3.h b/Libraries/LibGfx/Vector3.h index a0030ad99d..0a93e5075d 100644 --- a/Libraries/LibGfx/Vector3.h +++ b/Libraries/LibGfx/Vector3.h @@ -87,6 +87,23 @@ public: return *this * inv_length; } + Vector3 clamped(T m, T x) const + { + Vector3 copy { *this }; + copy.clamp(m, x); + return copy; + } + + void clamp(T min_value, T max_value) + { + m_x = max(min_value, m_x); + m_y = max(min_value, m_y); + m_z = max(min_value, m_z); + m_x = min(max_value, m_x); + m_y = min(max_value, m_y); + m_z = min(max_value, m_z); + } + void normalize() { T inv_length = 1 / length();