mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 06:27:45 +00:00
LibGfx+PixelPaint: Fix distortions in convolutions with size != 4 or 5
This commit is contained in:
parent
95434d70ed
commit
93f4388e45
3 changed files with 32 additions and 12 deletions
|
@ -121,14 +121,15 @@ template<size_t N>
|
||||||
struct FilterParameters<Gfx::SpatialGaussianBlurFilter<N>> {
|
struct FilterParameters<Gfx::SpatialGaussianBlurFilter<N>> {
|
||||||
static OwnPtr<typename Gfx::SpatialGaussianBlurFilter<N>::Parameters> get()
|
static OwnPtr<typename Gfx::SpatialGaussianBlurFilter<N>::Parameters> get()
|
||||||
{
|
{
|
||||||
|
constexpr static ssize_t offset = N / 2;
|
||||||
Matrix<N, float> kernel;
|
Matrix<N, float> kernel;
|
||||||
auto sigma = 1.0f;
|
auto sigma = 1.0f;
|
||||||
auto s = 2.0f * sigma * sigma;
|
auto s = 2.0f * sigma * sigma;
|
||||||
|
|
||||||
for (auto x = -(ssize_t)N / 2; x <= (ssize_t)N / 2; x++) {
|
for (auto x = -offset; x <= offset; x++) {
|
||||||
for (auto y = -(ssize_t)N / 2; y <= (ssize_t)N / 2; y++) {
|
for (auto y = -offset; y <= offset; y++) {
|
||||||
auto r = sqrt(x * x + y * 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,7 @@ public:
|
||||||
class ApplyCache {
|
class ApplyCache {
|
||||||
template<size_t>
|
template<size_t>
|
||||||
friend class GenericConvolutionFilter;
|
friend class GenericConvolutionFilter;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RefPtr<Gfx::Bitmap> m_target;
|
RefPtr<Gfx::Bitmap> m_target;
|
||||||
};
|
};
|
||||||
|
@ -120,23 +121,24 @@ public:
|
||||||
Bitmap* render_target_bitmap = (&target != &source) ? &target : apply_cache.m_target.ptr();
|
Bitmap* render_target_bitmap = (&target != &source) ? &target : apply_cache.m_target.ptr();
|
||||||
|
|
||||||
// FIXME: Help! I am naive!
|
// FIXME: Help! I am naive!
|
||||||
|
constexpr static ssize_t offset = N / 2;
|
||||||
for (auto i_ = 0; i_ < target_rect.width(); ++i_) {
|
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_) {
|
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);
|
FloatVector3 value(0, 0, 0);
|
||||||
for (auto k = 0; k < 4; ++k) {
|
for (auto k = 0l; k < (ssize_t)N; ++k) {
|
||||||
auto ki = i + k - 2;
|
auto ki = i + k - offset;
|
||||||
if (i < source_rect.x() || i > source_rect.right()) {
|
if (ki < source_rect.x() || ki > source_rect.right()) {
|
||||||
if (parameters.should_wrap())
|
if (parameters.should_wrap())
|
||||||
ki = (ki + source.size().width()) % source.size().width(); // TODO: fix up using source_rect
|
ki = (ki + source.size().width()) % source.size().width(); // TODO: fix up using source_rect
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto l = 0; l < 4; ++l) {
|
for (auto l = 0l; l < (ssize_t)N; ++l) {
|
||||||
auto lj = j + l - 2;
|
auto lj = j + l - offset;
|
||||||
if (j < source_rect.y() || j > source_rect.bottom()) {
|
if (lj < source_rect.y() || lj > source_rect.bottom()) {
|
||||||
if (parameters.should_wrap())
|
if (parameters.should_wrap())
|
||||||
lj = (lj + source.size().height()) % source.size().height(); // TODO: fix up using source_rect
|
lj = (lj + source.size().height()) % source.size().height(); // TODO: fix up using source_rect
|
||||||
else
|
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()));
|
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()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,23 @@ public:
|
||||||
return *this * inv_length;
|
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()
|
void normalize()
|
||||||
{
|
{
|
||||||
T inv_length = 1 / length();
|
T inv_length = 1 / length();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue