forked from Mirrorlandia_minetest/minetest
Inline g/setPixel in imageCleanTransparent (#14323)
This commit is contained in:
parent
c81e0b7433
commit
4843890c56
@ -65,20 +65,27 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/* 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 <bool IS_A8R8G8B8>
|
||||
static void imageCleanTransparentWithInlining(video::IImage *src, u32 threshold)
|
||||
{
|
||||
core::dimension2d<u32> dim = src->getDimension();
|
||||
void *const src_data = src->getData();
|
||||
const core::dimension2d<u32> dim = src->getDimension();
|
||||
|
||||
auto get_pixel = [src, src_data, dim](u32 x, u32 y) -> video::SColor {
|
||||
if constexpr (IS_A8R8G8B8) {
|
||||
return reinterpret_cast<u32 *>(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<u32 *>(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<true>(src, threshold);
|
||||
else
|
||||
imageCleanTransparentWithInlining<false>(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
|
||||
|
Loading…
Reference in New Issue
Block a user