Skip to content

Commit

Permalink
Fix dividing by zero crashes in texture modifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
cx384 committed Jan 7, 2024
1 parent 2c390b5 commit 2766c70
Showing 1 changed file with 27 additions and 13 deletions.
40 changes: 27 additions & 13 deletions src/client/tile.cpp
Expand Up @@ -1598,6 +1598,13 @@ bool TextureSource::generateImagePart(std::string part_of_name,
u32 frame_count = stoi(sf.next(":"));
u32 frame_index = stoi(sf.next(":"));

if (frame_count == 0){
errorstream << "generateImagePart(): invalid frame_count "
<< "for part_of_name=\"" << part_of_name
<< "\", using frame_count = 1 instead." << std::endl;
frame_count = 1;
}

if (baseimg == NULL){
errorstream<<"generateImagePart(): baseimg != NULL "
<<"for part_of_name=\""<<part_of_name
Expand Down Expand Up @@ -1659,7 +1666,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
}
/*
[multiply:color
or
or
[screen:color
Multiply and Screen blend modes are basic blend modes for darkening and lightening
images, respectively.
Expand All @@ -1685,7 +1692,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
if (!parseColorString(color_str, color, false))
return false;
if (str_starts_with(part_of_name, "[multiply:")) {
apply_multiplication(baseimg, v2u32(0, 0),
apply_multiplication(baseimg, v2u32(0, 0),
baseimg->getDimension(), color);
} else {
apply_screen(baseimg, v2u32(0, 0), baseimg->getDimension(), color);
Expand Down Expand Up @@ -1899,6 +1906,13 @@ bool TextureSource::generateImagePart(std::string part_of_name,
u32 x0 = stoi(sf.next(","));
u32 y0 = stoi(sf.next(":"));

if (w0 == 0 || h0 == 0) {
errorstream << "generateImagePart(): invalid width or height "
<< "for part_of_name=\"" << part_of_name
<< "\", cancelling." << std::endl;
return false;
}

core::dimension2d<u32> img_dim = baseimg->getDimension();
core::dimension2d<u32> tile_dim(v2u32(img_dim) / v2u32(w0, h0));

Expand Down Expand Up @@ -1965,7 +1979,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
}
/*
[hsl:hue:saturation:lightness
or
or
[colorizehsl:hue:saturation:lightness
Adjust the hue, saturation, and lightness of the base image. Like
Expand All @@ -1978,7 +1992,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
will be converted to a grayscale image as though seen through a
colored glass, like "Colorize" in GIMP.
*/
else if (str_starts_with(part_of_name, "[hsl:") ||
else if (str_starts_with(part_of_name, "[hsl:") ||
str_starts_with(part_of_name, "[colorizehsl:")) {

if (baseimg == nullptr) {
Expand All @@ -1995,7 +2009,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,

Strfnd sf(part_of_name);
sf.next(":");
s32 hue = mystoi(sf.next(":"), -180, 360);
s32 hue = mystoi(sf.next(":"), -180, 360);
s32 saturation = sf.at_end() ? defaultSaturation : mystoi(sf.next(":"), -100, 1000);
s32 lightness = sf.at_end() ? 0 : mystoi(sf.next(":"), -100, 100);

Expand All @@ -2005,7 +2019,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
}
/*
[overlay:filename
or
or
[hardlight:filename
"A.png^[hardlight:B.png" is the same as "B.png^[overlay:A.Png"
Expand Down Expand Up @@ -2069,7 +2083,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
s32 contrast = mystoi(sf.next(":"), -127, 127);
s32 brightness = sf.at_end() ? 0 : mystoi(sf.next(":"), -127, 127);

apply_brightness_contrast(baseimg, v2u32(0, 0),
apply_brightness_contrast(baseimg, v2u32(0, 0),
baseimg->getDimension(), brightness, contrast);
}
else
Expand Down Expand Up @@ -2347,14 +2361,14 @@ static void apply_overlay(video::IImage *blend, video::IImage *dst,
v2s32 blend_layer_pos = hardlight ? dst_pos : blend_pos;
v2s32 base_layer_pos = hardlight ? blend_pos : dst_pos;

for (u32 y = 0; y < size.Y; y++)
for (u32 y = 0; y < size.Y; y++)
for (u32 x = 0; x < size.X; x++) {
s32 base_x = x + base_layer_pos.X;
s32 base_y = y + base_layer_pos.Y;

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);
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;
Expand All @@ -2373,7 +2387,7 @@ static void apply_overlay(video::IImage *blend, video::IImage *dst,
}
}

/*
/*
Adjust the brightness and contrast of the base image.
Conceptually like GIMP's "Brightness-Contrast" feature but allows brightness to be
Expand All @@ -2387,17 +2401,17 @@ static void apply_brightness_contrast(video::IImage *dst, v2u32 dst_pos, v2u32 s
// (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;

// 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;

// Calculate a contrast slope such that that no colors will get clamped due
// 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);

// 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);
Expand Down

0 comments on commit 2766c70

Please sign in to comment.