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

Add embedded PNG texture modifier (#11498)

This commit is contained in:
hecks 2021-10-13 17:51:37 +02:00 committed by GitHub
parent fe5cb2cdfb
commit 02292e03e4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 126 additions and 35 deletions

View file

@ -33,6 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "imagefilters.h"
#include "guiscalingfilter.h"
#include "renderingengine.h"
#include "util/base64.h"
/*
A cache from texture name to texture path
@ -1059,6 +1060,45 @@ static std::string unescape_string(const std::string &str, const char esc = '\\'
return out;
}
void blitBaseImage(video::IImage* &src, video::IImage* &dst)
{
//infostream<<"Blitting "<<part_of_name<<" on base"<<std::endl;
// Size of the copied area
core::dimension2d<u32> dim = src->getDimension();
//core::dimension2d<u32> dim(16,16);
// Position to copy the blitted to in the base image
core::position2d<s32> pos_to(0,0);
// Position to copy the blitted from in the blitted image
core::position2d<s32> pos_from(0,0);
// Blit
/*image->copyToWithAlpha(baseimg, pos_to,
core::rect<s32>(pos_from, dim),
video::SColor(255,255,255,255),
NULL);*/
core::dimension2d<u32> dim_dst = dst->getDimension();
if (dim == dim_dst) {
blit_with_alpha(src, dst, pos_from, pos_to, dim);
} else if (dim.Width * dim.Height < dim_dst.Width * dim_dst.Height) {
// Upscale overlying image
video::IImage *scaled_image = RenderingEngine::get_video_driver()->
createImage(video::ECF_A8R8G8B8, dim_dst);
src->copyToScaling(scaled_image);
blit_with_alpha(scaled_image, dst, pos_from, pos_to, dim_dst);
scaled_image->drop();
} else {
// Upscale base image
video::IImage *scaled_base = RenderingEngine::get_video_driver()->
createImage(video::ECF_A8R8G8B8, dim);
dst->copyToScaling(scaled_base);
dst->drop();
dst = scaled_base;
blit_with_alpha(src, dst, pos_from, pos_to, dim);
}
}
bool TextureSource::generateImagePart(std::string part_of_name,
video::IImage *& baseimg)
{
@ -1122,41 +1162,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
// Else blit on base.
else
{
//infostream<<"Blitting "<<part_of_name<<" on base"<<std::endl;
// Size of the copied area
core::dimension2d<u32> dim = image->getDimension();
//core::dimension2d<u32> dim(16,16);
// Position to copy the blitted to in the base image
core::position2d<s32> pos_to(0,0);
// Position to copy the blitted from in the blitted image
core::position2d<s32> pos_from(0,0);
// Blit
/*image->copyToWithAlpha(baseimg, pos_to,
core::rect<s32>(pos_from, dim),
video::SColor(255,255,255,255),
NULL);*/
core::dimension2d<u32> dim_dst = baseimg->getDimension();
if (dim == dim_dst) {
blit_with_alpha(image, baseimg, pos_from, pos_to, dim);
} else if (dim.Width * dim.Height < dim_dst.Width * dim_dst.Height) {
// Upscale overlying image
video::IImage *scaled_image = RenderingEngine::get_video_driver()->
createImage(video::ECF_A8R8G8B8, dim_dst);
image->copyToScaling(scaled_image);
blit_with_alpha(scaled_image, baseimg, pos_from, pos_to, dim_dst);
scaled_image->drop();
} else {
// Upscale base image
video::IImage *scaled_base = RenderingEngine::get_video_driver()->
createImage(video::ECF_A8R8G8B8, dim);
baseimg->copyToScaling(scaled_base);
baseimg->drop();
baseimg = scaled_base;
blit_with_alpha(image, baseimg, pos_from, pos_to, dim);
}
blitBaseImage(image, baseimg);
}
//cleanup
image->drop();
@ -1784,6 +1790,43 @@ bool TextureSource::generateImagePart(std::string part_of_name,
baseimg->drop();
baseimg = img;
}
/*
[png:base64
Decodes a PNG image in base64 form.
Use minetest.encode_png and minetest.encode_base64
to produce a valid string.
*/
else if (str_starts_with(part_of_name, "[png:")) {
Strfnd sf(part_of_name);
sf.next(":");
std::string png;
{
std::string blob = sf.next("");
if (!base64_is_valid(blob)) {
errorstream << "generateImagePart(): "
<< "malformed base64 in '[png'"
<< std::endl;
return false;
}
png = base64_decode(blob);
}
auto *device = RenderingEngine::get_raw_device();
auto *fs = device->getFileSystem();
auto *vd = device->getVideoDriver();
auto *memfile = fs->createMemoryReadFile(png.data(), png.size(), "__temp_png");
video::IImage* pngimg = vd->createImageFromFile(memfile);
memfile->drop();
if (baseimg) {
blitBaseImage(pngimg, baseimg);
} else {
core::dimension2d<u32> dim = pngimg->getDimension();
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
pngimg->copyTo(baseimg);
}
pngimg->drop();
}
else
{
errorstream << "generateImagePart(): Invalid "