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
|
template <bool IS_A8R8G8B8>
|
||||||
* appearing at borders when blending. This is because many PNG optimizers
|
static void imageCleanTransparentWithInlining(video::IImage *src, u32 threshold)
|
||||||
* 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)
|
|
||||||
{
|
{
|
||||||
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);
|
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.
|
// Note: loop y around x for better cache locality.
|
||||||
for (u32 ctry = 0; ctry < dim.Height; ctry++)
|
for (u32 ctry = 0; ctry < dim.Height; ctry++)
|
||||||
for (u32 ctrx = 0; ctrx < dim.Width; ctrx++) {
|
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);
|
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
|
// Add RGB values weighted by alpha IF the pixel is opaque, otherwise
|
||||||
// use full weight since we want to propagate colors.
|
// 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();
|
u32 a = d.getAlpha() <= threshold ? 255 : d.getAlpha();
|
||||||
ss += a;
|
ss += a;
|
||||||
sr += a * d.getRed();
|
sr += a * d.getRed();
|
||||||
@ -135,11 +142,11 @@ void imageCleanTransparent(video::IImage *src, u32 threshold)
|
|||||||
|
|
||||||
// Set pixel to average weighted by alpha
|
// Set pixel to average weighted by alpha
|
||||||
if (ss > 0) {
|
if (ss > 0) {
|
||||||
video::SColor c = src->getPixel(ctrx, ctry);
|
video::SColor c = get_pixel(ctrx, ctry);
|
||||||
c.setRed(sr / ss);
|
c.setRed(sr / ss);
|
||||||
c.setGreen(sg / ss);
|
c.setGreen(sg / ss);
|
||||||
c.setBlue(sb / ss);
|
c.setBlue(sb / ss);
|
||||||
src->setPixel(ctrx, ctry, c);
|
set_pixel(ctrx, ctry, c);
|
||||||
newmap.set(ctrx, ctry);
|
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
|
/* 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
|
* anti-aliasing; treat pixels as crisp rectangles, but blend them at boundaries
|
||||||
* to prevent non-integer scaling ratio artifacts. Note that this may cause
|
* to prevent non-integer scaling ratio artifacts. Note that this may cause
|
||||||
|
Loading…
Reference in New Issue
Block a user