1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Minor improvements to image algorithms

- loop Y around X
- use float over double
This commit is contained in:
sfan5 2025-05-03 11:59:08 +02:00 committed by Lars Müller
parent 486fb7cc4d
commit 377fa5bb14
2 changed files with 41 additions and 41 deletions

View file

@ -229,8 +229,8 @@ static video::SColor imageAverageColorInline(const video::IImage *src)
// limit runtime cost
const u32 stepx = std::max(1U, dim.Width / 16),
stepy = std::max(1U, dim.Height / 16);
for (u32 x = 0; x < dim.Width; x += stepx) {
for (u32 y = 0; y < dim.Height; y += stepy) {
for (u32 y = 0; y < dim.Height; y += stepy) {
for (u32 x = 0; x < dim.Width; x += stepx) {
video::SColor c = get_pixel(x, y);
if (c.getAlpha() > 0) {
total++;
@ -261,15 +261,15 @@ video::SColor imageAverageColor(const video::IImage *img)
void imageScaleNNAA(video::IImage *src, const core::rect<s32> &srcrect, video::IImage *dest)
{
double sx, sy, minsx, maxsx, minsy, maxsy, area, ra, ga, ba, aa, pw, ph, pa;
f32 sx, sy, minsx, maxsx, minsy, maxsy, area, ra, ga, ba, aa, pw, ph, pa;
u32 dy, dx;
video::SColor pxl;
// Cache rectangle boundaries.
double sox = srcrect.UpperLeftCorner.X * 1.0;
double soy = srcrect.UpperLeftCorner.Y * 1.0;
double sw = srcrect.getWidth() * 1.0;
double sh = srcrect.getHeight() * 1.0;
const f32 sox = srcrect.UpperLeftCorner.X;
const f32 soy = srcrect.UpperLeftCorner.Y;
const f32 sw = srcrect.getWidth();
const f32 sh = srcrect.getHeight();
// Walk each destination image pixel.
// Note: loop y around x for better cache locality.
@ -302,8 +302,8 @@ void imageScaleNNAA(video::IImage *src, const core::rect<s32> &srcrect, video::I
aa = 0;
// Loop over the integral pixel positions described by those bounds.
for (sy = floor(minsy); sy < maxsy; sy++)
for (sx = floor(minsx); sx < maxsx; sx++) {
for (sy = std::floor(minsy); sy < maxsy; sy++)
for (sx = std::floor(minsx); sx < maxsx; sx++) {
// Calculate width, height, then area of dest pixel
// that's covered by this source pixel.
@ -331,10 +331,10 @@ void imageScaleNNAA(video::IImage *src, const core::rect<s32> &srcrect, video::I
// Set the destination image pixel to the average color.
if (area > 0) {
pxl.setRed(ra / area + 0.5);
pxl.setGreen(ga / area + 0.5);
pxl.setBlue(ba / area + 0.5);
pxl.setAlpha(aa / area + 0.5);
pxl.setRed(ra / area + 0.5f);
pxl.setGreen(ga / area + 0.5f);
pxl.setBlue(ba / area + 0.5f);
pxl.setAlpha(aa / area + 0.5f);
} else {
pxl.setRed(0);
pxl.setGreen(0);

View file

@ -601,7 +601,7 @@ static void apply_hue_saturation(video::IImage *dst, v2u32 dst_pos, v2u32 size,
}
// Apply the specified HSL adjustments
hsl.Hue = fmod(hsl.Hue + hue, 360);
hsl.Hue = fmodf(hsl.Hue + hue, 360);
if (hsl.Hue < 0)
hsl.Hue += 360;
@ -632,19 +632,19 @@ static void apply_overlay(video::IImage *blend, video::IImage *dst,
video::SColor blend_c =
blend_layer->getPixel(x + blend_layer_pos.X, y + blend_layer_pos.Y);
video::SColor base_c = base_layer->getPixel(base_x, base_y);
double blend_r = blend_c.getRed() / 255.0;
double blend_g = blend_c.getGreen() / 255.0;
double blend_b = blend_c.getBlue() / 255.0;
double base_r = base_c.getRed() / 255.0;
double base_g = base_c.getGreen() / 255.0;
double base_b = base_c.getBlue() / 255.0;
f32 blend_r = blend_c.getRed() / 255.0f;
f32 blend_g = blend_c.getGreen() / 255.0f;
f32 blend_b = blend_c.getBlue() / 255.0f;
f32 base_r = base_c.getRed() / 255.0f;
f32 base_g = base_c.getGreen() / 255.0f;
f32 base_b = base_c.getBlue() / 255.0f;
base_c.set(
base_c.getAlpha(),
// Do a Multiply blend if less that 0.5, otherwise do a Screen blend
(u32)((base_r < 0.5 ? 2 * base_r * blend_r : 1 - 2 * (1 - base_r) * (1 - blend_r)) * 255),
(u32)((base_g < 0.5 ? 2 * base_g * blend_g : 1 - 2 * (1 - base_g) * (1 - blend_g)) * 255),
(u32)((base_b < 0.5 ? 2 * base_b * blend_b : 1 - 2 * (1 - base_b) * (1 - blend_b)) * 255)
(u32)((base_r < 0.5f ? 2 * base_r * blend_r : 1 - 2 * (1 - base_r) * (1 - blend_r)) * 255),
(u32)((base_g < 0.5f ? 2 * base_g * blend_g : 1 - 2 * (1 - base_g) * (1 - blend_g)) * 255),
(u32)((base_b < 0.5f ? 2 * base_b * blend_b : 1 - 2 * (1 - base_b) * (1 - blend_b)) * 255)
);
dst->setPixel(base_x, base_y, base_c);
}
@ -659,38 +659,38 @@ static void apply_overlay(video::IImage *blend, video::IImage *dst,
static void apply_brightness_contrast(video::IImage *dst, v2u32 dst_pos, v2u32 size,
s32 brightness, s32 contrast)
{
video::SColor dst_c;
// Only allow normalized contrast to get as high as 127/128 to avoid infinite slope.
// (we could technically allow -128/128 here as that would just result in 0 slope)
double norm_c = core::clamp(contrast, -127, 127) / 128.0;
double norm_b = core::clamp(brightness, -127, 127) / 127.0;
f32 norm_c = core::clamp(contrast, -127, 127) / 128.0f;
f32 norm_b = core::clamp(brightness, -127, 127) / 127.0f;
// Scale brightness so its range is -127.5 to 127.5, otherwise brightness
// adjustments will outputs values from 0.5 to 254.5 instead of 0 to 255.
double scaled_b = brightness * 127.5 / 127;
f32 scaled_b = brightness * 127.5f / 127;
// Calculate a contrast slope such that that no colors will get clamped due
// to the brightness setting.
// This allows the texture modifier to used as a brightness modifier without
// the user having to calculate a contrast to avoid clipping at that brightness.
double slope = 1 - fabs(norm_b);
f32 slope = 1 - std::fabs(norm_b);
// Apply the user's contrast adjustment to the calculated slope, such that
// -127 will make it near-vertical and +127 will make it horizontal
double angle = atan(slope);
f32 angle = std::atan(slope);
angle += norm_c <= 0
? norm_c * angle // allow contrast slope to be lowered to 0
: norm_c * (M_PI_2 - angle); // allow contrast slope to be raised almost vert.
slope = tan(angle);
slope = std::tan(angle);
double c = slope <= 1
? -slope * 127.5 + 127.5 + scaled_b // shift up/down when slope is horiz.
: -slope * (127.5 - scaled_b) + 127.5; // shift left/right when slope is vert.
f32 c = slope <= 1
? -slope * 127.5f + 127.5f + scaled_b // shift up/down when slope is horiz.
: -slope * (127.5f - scaled_b) + 127.5f; // shift left/right when slope is vert.
// add 0.5 to c so that when the final result is cast to int, it is effectively
// rounded rather than trunc'd.
c += 0.5;
c += 0.5f;
video::SColor dst_c;
for (u32 y = dst_pos.Y; y < dst_pos.Y + size.Y; y++)
for (u32 x = dst_pos.X; x < dst_pos.X + size.X; x++) {
dst_c = dst->getPixel(x, y);
@ -805,7 +805,7 @@ static void draw_crack(video::IImage *crack, video::IImage *dst,
static void brighten(video::IImage *image)
{
if (image == NULL)
if (!image)
return;
core::dimension2d<u32> dim = image->getDimension();
@ -814,9 +814,9 @@ static void brighten(video::IImage *image)
for (u32 x=0; x<dim.Width; x++)
{
video::SColor c = image->getPixel(x,y);
c.setRed(0.5 * 255 + 0.5 * (float)c.getRed());
c.setGreen(0.5 * 255 + 0.5 * (float)c.getGreen());
c.setBlue(0.5 * 255 + 0.5 * (float)c.getBlue());
c.setRed(127.5f + 0.5f * c.getRed());
c.setGreen(127.5f + 0.5f * c.getGreen());
c.setBlue(127.5f + 0.5f * c.getBlue());
image->setPixel(x,y,c);
}
}
@ -881,7 +881,7 @@ static core::dimension2du imageTransformDimension(u32 transform, core::dimension
static void imageTransform(u32 transform, video::IImage *src, video::IImage *dst)
{
if (src == NULL || dst == NULL)
if (!src || !dst)
return;
core::dimension2d<u32> dstdim = dst->getDimension();
@ -1280,7 +1280,7 @@ bool ImageSource::generateImagePart(std::string_view part_of_name,
video::IImage *img_left = generateImage(imagename_left, source_image_names);
video::IImage *img_right = generateImage(imagename_right, source_image_names);
if (img_top == NULL || img_left == NULL || img_right == NULL) {
if (!img_top || !img_left || !img_right) {
errorstream << "generateImagePart(): Failed to create textures"
<< " for inventorycube \"" << part_of_name << "\""
<< std::endl;
@ -1896,7 +1896,7 @@ video::IImage* ImageSource::generateImage(std::string_view name,
}
// If no resulting image, print a warning
if (baseimg == NULL) {
if (!baseimg) {
errorstream << "generateImage(): baseimg is NULL (attempted to"
" create texture \"" << name << "\")" << std::endl;
} else if (baseimg->getDimension().Width == 0 ||