1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 01:27:34 +00:00

LibGfx: Allow for different {x,y}-radii in FastBoxBlurFilter

Use different specified radii for the two seperate passes.

The gaussian approximation is not changed to accept two parameters since
the math is not exactly straight forward and therefore something for a
later patch. For now, let's progress!
This commit is contained in:
Tobias Christiansen 2022-03-16 14:03:28 +01:00 committed by Andreas Kling
parent 5f063e832e
commit 64cc482f8a
2 changed files with 24 additions and 16 deletions

View file

@ -28,8 +28,13 @@ FastBoxBlurFilter::FastBoxBlurFilter(Bitmap& bitmap)
{
}
// Based on the super fast blur algorithm by Quasimondo, explored here: https://stackoverflow.com/questions/21418892/understanding-super-fast-blur-algorithm
void FastBoxBlurFilter::apply_single_pass(size_t radius)
{
apply_single_pass(radius, radius);
}
// Based on the super fast blur algorithm by Quasimondo, explored here: https://stackoverflow.com/questions/21418892/understanding-super-fast-blur-algorithm
void FastBoxBlurFilter::apply_single_pass(size_t radius_x, size_t radius_y)
{
auto format = m_bitmap.format();
VERIFY(format == BitmapFormat::BGRA8888 || format == BitmapFormat::BGRx8888);
@ -52,7 +57,8 @@ void FastBoxBlurFilter::apply_single_pass(size_t radius)
int height = m_bitmap.height();
int width = m_bitmap.width();
int div = 2 * radius + 1;
int div_x = 2 * radius_x + 1;
int div_y = 2 * radius_y + 1;
Vector<u8, 1024> intermediate_red;
Vector<u8, 1024> intermediate_green;
@ -72,7 +78,7 @@ void FastBoxBlurFilter::apply_single_pass(size_t radius)
size_t sum_alpha = 0;
// Setup sliding window
for (int i = -(int)radius; i <= (int)radius; ++i) {
for (int i = -(int)radius_x; i <= (int)radius_x; ++i) {
auto color_at_px = get_pixel_function(clamp(i, 0, width - 1), y);
sum_red += red_value(color_at_px);
sum_green += green_value(color_at_px);
@ -81,13 +87,13 @@ void FastBoxBlurFilter::apply_single_pass(size_t radius)
}
// Slide horizontally
for (int x = 0; x < width; ++x) {
intermediate_red[y * width + x] = (sum_red / div);
intermediate_green[y * width + x] = (sum_green / div);
intermediate_blue[y * width + x] = (sum_blue / div);
intermediate_alpha[y * width + x] = (sum_alpha / div);
intermediate_red[y * width + x] = (sum_red / div_x);
intermediate_green[y * width + x] = (sum_green / div_x);
intermediate_blue[y * width + x] = (sum_blue / div_x);
intermediate_alpha[y * width + x] = (sum_alpha / div_x);
auto leftmost_x_coord = max(x - (int)radius, 0);
auto rightmost_x_coord = min(x + (int)radius + 1, width - 1);
auto leftmost_x_coord = max(x - (int)radius_x, 0);
auto rightmost_x_coord = min(x + (int)radius_x + 1, width - 1);
auto leftmost_x_color = get_pixel_function(leftmost_x_coord, y);
auto rightmost_x_color = get_pixel_function(rightmost_x_coord, y);
@ -111,7 +117,7 @@ void FastBoxBlurFilter::apply_single_pass(size_t radius)
size_t sum_alpha = 0;
// Setup sliding window
for (int i = -(int)radius; i <= (int)radius; ++i) {
for (int i = -(int)radius_y; i <= (int)radius_y; ++i) {
int offset = clamp(i, 0, height - 1) * width + x;
sum_red += intermediate_red[offset];
sum_green += intermediate_green[offset];
@ -121,15 +127,15 @@ void FastBoxBlurFilter::apply_single_pass(size_t radius)
for (int y = 0; y < height; ++y) {
auto color = Color(
sum_red / div,
sum_green / div,
sum_blue / div,
sum_alpha / div);
sum_red / div_y,
sum_green / div_y,
sum_blue / div_y,
sum_alpha / div_y);
set_pixel_function(x, y, color);
auto topmost_y_coord = max(y - (int)radius, 0);
auto bottommost_y_coord = min(y + (int)radius + 1, height - 1);
auto topmost_y_coord = max(y - (int)radius_y, 0);
auto bottommost_y_coord = min(y + (int)radius_y + 1, height - 1);
sum_red += intermediate_red[x + bottommost_y_coord * width];
sum_red -= intermediate_red[x + topmost_y_coord * width];

View file

@ -15,6 +15,8 @@ public:
FastBoxBlurFilter(Bitmap&);
void apply_single_pass(size_t radius);
void apply_single_pass(size_t radius_x, size_t radius_y);
void apply_three_passes(size_t radius);
private: