Fix dividing by zero crashes in texture modifiers

This commit is contained in:
cx384 2024-01-07 21:49:26 +01:00 committed by GitHub
parent 2c390b5473
commit 2766c70ad3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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
@ -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.
@ -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);
@ -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));
@ -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
@ -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) {
@ -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);
@ -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"
@ -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
@ -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;
@ -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
@ -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);