forked from Mirrorlandia_minetest/minetest
Fix dividing by zero crashes in texture modifiers
This commit is contained in:
parent
2c390b5473
commit
2766c70ad3
@ -1598,6 +1598,13 @@ bool TextureSource::generateImagePart(std::string part_of_name,
|
|||||||
u32 frame_count = stoi(sf.next(":"));
|
u32 frame_count = stoi(sf.next(":"));
|
||||||
u32 frame_index = 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){
|
if (baseimg == NULL){
|
||||||
errorstream<<"generateImagePart(): baseimg != NULL "
|
errorstream<<"generateImagePart(): baseimg != NULL "
|
||||||
<<"for part_of_name=\""<<part_of_name
|
<<"for part_of_name=\""<<part_of_name
|
||||||
@ -1659,7 +1666,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
|
|||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
[multiply:color
|
[multiply:color
|
||||||
or
|
or
|
||||||
[screen:color
|
[screen:color
|
||||||
Multiply and Screen blend modes are basic blend modes for darkening and lightening
|
Multiply and Screen blend modes are basic blend modes for darkening and lightening
|
||||||
images, respectively.
|
images, respectively.
|
||||||
@ -1685,7 +1692,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
|
|||||||
if (!parseColorString(color_str, color, false))
|
if (!parseColorString(color_str, color, false))
|
||||||
return false;
|
return false;
|
||||||
if (str_starts_with(part_of_name, "[multiply:")) {
|
if (str_starts_with(part_of_name, "[multiply:")) {
|
||||||
apply_multiplication(baseimg, v2u32(0, 0),
|
apply_multiplication(baseimg, v2u32(0, 0),
|
||||||
baseimg->getDimension(), color);
|
baseimg->getDimension(), color);
|
||||||
} else {
|
} else {
|
||||||
apply_screen(baseimg, v2u32(0, 0), baseimg->getDimension(), color);
|
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 x0 = stoi(sf.next(","));
|
||||||
u32 y0 = 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> img_dim = baseimg->getDimension();
|
||||||
core::dimension2d<u32> tile_dim(v2u32(img_dim) / v2u32(w0, h0));
|
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
|
[hsl:hue:saturation:lightness
|
||||||
or
|
or
|
||||||
[colorizehsl:hue:saturation:lightness
|
[colorizehsl:hue:saturation:lightness
|
||||||
|
|
||||||
Adjust the hue, saturation, and lightness of the base image. Like
|
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
|
will be converted to a grayscale image as though seen through a
|
||||||
colored glass, like "Colorize" in GIMP.
|
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:")) {
|
str_starts_with(part_of_name, "[colorizehsl:")) {
|
||||||
|
|
||||||
if (baseimg == nullptr) {
|
if (baseimg == nullptr) {
|
||||||
@ -1995,7 +2009,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
|
|||||||
|
|
||||||
Strfnd sf(part_of_name);
|
Strfnd sf(part_of_name);
|
||||||
sf.next(":");
|
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 saturation = sf.at_end() ? defaultSaturation : mystoi(sf.next(":"), -100, 1000);
|
||||||
s32 lightness = sf.at_end() ? 0 : mystoi(sf.next(":"), -100, 100);
|
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
|
[overlay:filename
|
||||||
or
|
or
|
||||||
[hardlight:filename
|
[hardlight:filename
|
||||||
|
|
||||||
"A.png^[hardlight:B.png" is the same as "B.png^[overlay:A.Png"
|
"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 contrast = mystoi(sf.next(":"), -127, 127);
|
||||||
s32 brightness = sf.at_end() ? 0 : 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);
|
baseimg->getDimension(), brightness, contrast);
|
||||||
}
|
}
|
||||||
else
|
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 blend_layer_pos = hardlight ? dst_pos : blend_pos;
|
||||||
v2s32 base_layer_pos = hardlight ? blend_pos : dst_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++) {
|
for (u32 x = 0; x < size.X; x++) {
|
||||||
s32 base_x = x + base_layer_pos.X;
|
s32 base_x = x + base_layer_pos.X;
|
||||||
s32 base_y = y + base_layer_pos.Y;
|
s32 base_y = y + base_layer_pos.Y;
|
||||||
|
|
||||||
video::SColor blend_c =
|
video::SColor blend_c =
|
||||||
blend_layer->getPixel(x + blend_layer_pos.X, y + blend_layer_pos.Y);
|
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_r = blend_c.getRed() / 255.0;
|
||||||
double blend_g = blend_c.getGreen() / 255.0;
|
double blend_g = blend_c.getGreen() / 255.0;
|
||||||
double blend_b = blend_c.getBlue() / 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.
|
Adjust the brightness and contrast of the base image.
|
||||||
|
|
||||||
Conceptually like GIMP's "Brightness-Contrast" feature but allows brightness to be
|
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)
|
// (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_c = core::clamp(contrast, -127, 127) / 128.0;
|
||||||
double norm_b = core::clamp(brightness, -127, 127) / 127.0;
|
double norm_b = core::clamp(brightness, -127, 127) / 127.0;
|
||||||
|
|
||||||
// Scale brightness so its range is -127.5 to 127.5, otherwise brightness
|
// 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.
|
// adjustments will outputs values from 0.5 to 254.5 instead of 0 to 255.
|
||||||
double scaled_b = brightness * 127.5 / 127;
|
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.
|
// to the brightness setting.
|
||||||
// This allows the texture modifier to used as a brightness modifier without
|
// 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.
|
// the user having to calculate a contrast to avoid clipping at that brightness.
|
||||||
double slope = 1 - fabs(norm_b);
|
double slope = 1 - fabs(norm_b);
|
||||||
|
|
||||||
// Apply the user's contrast adjustment to the calculated slope, such that
|
// Apply the user's contrast adjustment to the calculated slope, such that
|
||||||
// -127 will make it near-vertical and +127 will make it horizontal
|
// -127 will make it near-vertical and +127 will make it horizontal
|
||||||
double angle = atan(slope);
|
double angle = atan(slope);
|
||||||
|
Loading…
Reference in New Issue
Block a user