From 4843890c565bc54d67d65a01610f81eb3875d996 Mon Sep 17 00:00:00 2001 From: DS Date: Thu, 15 Feb 2024 19:38:23 +0100 Subject: [PATCH] Inline g/setPixel in imageCleanTransparent (#14323) --- src/client/imagefilters.cpp | 60 ++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/src/client/imagefilters.cpp b/src/client/imagefilters.cpp index ed8483fcfaa9..320af1fc8e80 100644 --- a/src/client/imagefilters.cpp +++ b/src/client/imagefilters.cpp @@ -65,20 +65,27 @@ class Bitmap { } }; -/* Fill in RGB values for transparent pixels, to correct for odd colors - * appearing at borders when blending. This is because many PNG optimizers - * like to discard RGB values of transparent pixels, but when blending then - * with non-transparent neighbors, their RGB values will show up nonetheless. - * - * This function modifies the original image in-place. - * - * Parameter "threshold" is the alpha level below which pixels are considered - * transparent. Should be 127 when the texture is used with ALPHA_CHANNEL_REF, - * 0 when alpha blending is used. - */ -void imageCleanTransparent(video::IImage *src, u32 threshold) +template +static void imageCleanTransparentWithInlining(video::IImage *src, u32 threshold) { - core::dimension2d dim = src->getDimension(); + void *const src_data = src->getData(); + const core::dimension2d dim = src->getDimension(); + + auto get_pixel = [src, src_data, dim](u32 x, u32 y) -> video::SColor { + if constexpr (IS_A8R8G8B8) { + return reinterpret_cast(src_data)[y*dim.Width + x]; + } else { + return src->getPixel(x, y); + } + }; + auto set_pixel = [src, src_data, dim](u32 x, u32 y, video::SColor color) { + if constexpr (IS_A8R8G8B8) { + u32 *dest = &reinterpret_cast(src_data)[y*dim.Width + x]; + *dest = color.color; + } else { + src->setPixel(x, y, color); + } + }; Bitmap bitmap(dim.Width, dim.Height); @@ -86,7 +93,7 @@ void imageCleanTransparent(video::IImage *src, u32 threshold) // Note: loop y around x for better cache locality. for (u32 ctry = 0; ctry < dim.Height; ctry++) for (u32 ctrx = 0; ctrx < dim.Width; ctrx++) { - if (src->getPixel(ctrx, ctry).getAlpha() > threshold) + if (get_pixel(ctrx, ctry).getAlpha() > threshold) bitmap.set(ctrx, ctry); } @@ -125,7 +132,7 @@ void imageCleanTransparent(video::IImage *src, u32 threshold) // Add RGB values weighted by alpha IF the pixel is opaque, otherwise // use full weight since we want to propagate colors. - video::SColor d = src->getPixel(sx, sy); + video::SColor d = get_pixel(sx, sy); u32 a = d.getAlpha() <= threshold ? 255 : d.getAlpha(); ss += a; sr += a * d.getRed(); @@ -135,11 +142,11 @@ void imageCleanTransparent(video::IImage *src, u32 threshold) // Set pixel to average weighted by alpha if (ss > 0) { - video::SColor c = src->getPixel(ctrx, ctry); + video::SColor c = get_pixel(ctrx, ctry); c.setRed(sr / ss); c.setGreen(sg / ss); c.setBlue(sb / ss); - src->setPixel(ctrx, ctry, c); + set_pixel(ctrx, ctry, c); newmap.set(ctrx, ctry); } } @@ -154,6 +161,25 @@ void imageCleanTransparent(video::IImage *src, u32 threshold) } } +/* Fill in RGB values for transparent pixels, to correct for odd colors + * appearing at borders when blending. This is because many PNG optimizers + * like to discard RGB values of transparent pixels, but when blending then + * with non-transparent neighbors, their RGB values will show up nonetheless. + * + * This function modifies the original image in-place. + * + * Parameter "threshold" is the alpha level below which pixels are considered + * transparent. Should be 127 when the texture is used with ALPHA_CHANNEL_REF, + * 0 when alpha blending is used. + */ +void imageCleanTransparent(video::IImage *src, u32 threshold) +{ + if (src->getColorFormat() == video::ECF_A8R8G8B8) + imageCleanTransparentWithInlining(src, threshold); + else + imageCleanTransparentWithInlining(src, threshold); +} + /* Scale a region of an image into another image, using nearest-neighbor with * anti-aliasing; treat pixels as crisp rectangles, but blend them at boundaries * to prevent non-integer scaling ratio artifacts. Note that this may cause