Skip to content
Permalink
Browse files

Add an option to colorize to respect the destination alpha

Also, rework the colorizing code to be more efficient.
  • Loading branch information
Samuel Sieb authored and kwolekr committed Apr 3, 2016
1 parent 66af984 commit 01ae43c48009f816f4649fae2f7f6997452aa6cf
Showing with 56 additions and 16 deletions.
  1. +7 −2 doc/lua_api.txt
  2. +49 −14 src/client/tile.cpp
@@ -357,8 +357,13 @@ The mask is applied using binary AND.
#### `[colorize:<color>:<ratio>`
Colorize the textures with the given color.
`<color>` is specified as a `ColorString`.
`<ratio>` is an int ranging from 0 to 255, and specifies how much of the
color to apply. If ommitted, the alpha will be used.
`<ratio>` is an int ranging from 0 to 255 or the word "`alpha`". If
it is an int, then it specifies how far to interpolate between the
colors where 0 is only the texture color and 255 is only `<color>`. If
omitted, the alpha of `<color>` will be used as the ratio. If it is
the word "`alpha`", then the alpha of the color will be multiplied with
the alpha of the texture with the RGB of the color replacing the RGB of
the texture.

Sounds
------
@@ -558,6 +558,13 @@ static void blit_with_alpha_overlay(video::IImage *src, video::IImage *dst,
static void blit_with_interpolate_overlay(video::IImage *src, video::IImage *dst,
v2s32 src_pos, v2s32 dst_pos, v2u32 size, int ratio);

// Apply a color to an image. Uses an int (0-255) to calculate the ratio.
// If the ratio is 255 or -1 and keep_alpha is true, then it multiples the
// color alpha with the destination alpha.
// Otherwise, any pixels that are not fully transparent get the color alpha.
static void apply_colorize(video::IImage *dst, v2s32 dst_pos, v2u32 size,
video::SColor color, int ratio, bool keep_alpha);

// Apply a mask to an image
static void apply_mask(video::IImage *mask, video::IImage *dst,
v2s32 mask_pos, v2s32 dst_pos, v2u32 size);
@@ -1639,27 +1646,17 @@ bool TextureSource::generateImagePart(std::string part_of_name,

video::SColor color;
int ratio = -1;
bool keep_alpha = false;

if (!parseColorString(color_str, color, false))
return false;

if (is_number(ratio_str))
ratio = mystoi(ratio_str, 0, 255);
else if (ratio_str == "alpha")
keep_alpha = true;

core::dimension2d<u32> dim = baseimg->getDimension();
video::IImage *img = driver->createImage(video::ECF_A8R8G8B8, dim);

if (!img) {
errorstream << "generateImagePart(): Could not create image "
<< "for part_of_name=\"" << part_of_name
<< "\", cancelling." << std::endl;
return false;
}

img->fill(video::SColor(color));
// Overlay the colored image
blit_with_interpolate_overlay(img, baseimg, v2s32(0,0), v2s32(0,0), dim, ratio);
img->drop();
apply_colorize(baseimg, v2s32(0, 0), baseimg->getDimension(), color, ratio, keep_alpha);
}
else if (str_starts_with(part_of_name, "[applyfiltersformesh"))
{
@@ -1783,6 +1780,44 @@ static void blit_with_interpolate_overlay(video::IImage *src, video::IImage *dst
}
}

/*
Apply color to destination
*/
static void apply_colorize(video::IImage *dst, v2s32 dst_pos, v2u32 size,
video::SColor color, int ratio, bool keep_alpha)
{
u32 alpha = color.getAlpha();
video::SColor dst_c;
if ((ratio == -1 && alpha == 255) || ratio == 255) { // full replacement of color
if (keep_alpha) { // replace the color with alpha = dest alpha * color alpha
dst_c = color;
for (s32 y = dst_pos.Y; y < dst_pos.Y + size.Y; y++)
for (s32 x = dst_pos.X; x < dst_pos.X + size.X; x++) {
u32 dst_alpha = dst->getPixel(x, y).getAlpha();
if (dst_alpha > 0) {
dst_c.setAlpha(dst_alpha * alpha / 255);
dst->setPixel(x, y, dst_c);
}
}
} else { // replace the color including the alpha
for (s32 y = dst_pos.Y; y < dst_pos.Y + size.Y; y++)
for (s32 x = dst_pos.X; x < dst_pos.X + size.X; x++)
if (dst->getPixel(x, y).getAlpha() > 0)
dst->setPixel(x, y, color);
}
} else { // interpolate between the color and destination
float interp = (ratio == -1 ? color.getAlpha() / 255.0f : ratio / 255.0f);
for (s32 y = dst_pos.Y; y < dst_pos.Y + size.Y; y++)
for (s32 x = dst_pos.X; x < dst_pos.X + size.X; x++) {
dst_c = dst->getPixel(x, y);
if (dst_c.getAlpha() > 0) {
dst_c = color.getInterpolated(dst_c, interp);
dst->setPixel(x, y, dst_c);
}
}
}
}

/*
Apply mask to destination
*/

1 comment on commit 01ae43c

@est31

This comment has been minimized.

Copy link
Contributor

@est31 est31 commented on 01ae43c Apr 6, 2016

@kwolekr can you please tell who gave the second 👍 to this change?

The compiler warnings this commit added are fixed fortunately, but the documentation of the new feature is a bit weird and needs improvement.

Its good to have you back after your pause but the rules didn't change since then, and this feature certainly isn't trivial.

It would be great if you could motivate another dev to +1 this commit (or another dev already +1ed it) in the next three days, and get possibly suggested changes/fixes merged. If no dev +1es it in that time, I'll revert the commit (and the commit that fixes the compilation warnings, because otherwise stuff wont work anymore).

Please respond in this thread (I'm not closely reading every IRC line) or the pull request #3899.

Please sign in to comment.
You can’t perform that action at this time.