From b208c0b805d204e0ec7ae008e1224361e89c5642 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sun, 26 Jan 2020 17:22:45 +0200 Subject: [PATCH] Added: Creating texture from data:image/type --- code/nel/include/nel/gui/view_renderer.h | 2 + code/nel/src/gui/view_bitmap.cpp | 2 +- code/nel/src/gui/view_renderer.cpp | 98 ++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 1 deletion(-) diff --git a/code/nel/include/nel/gui/view_renderer.h b/code/nel/include/nel/gui/view_renderer.h index 4194a59fa..aefbb315f 100644 --- a/code/nel/include/nel/gui/view_renderer.h +++ b/code/nel/include/nel/gui/view_renderer.h @@ -267,6 +267,8 @@ namespace NLGUI bool bReleasable=true ); + // Create texture from dataURL "data:image/png;base64," string + sint32 createTextureFromDataURL(const std::string &data, bool uploadDXTC=true, bool bReleasable=true); // change position of a sub-texture (inside its big texture) from the sub-texture filename void updateTexturePos(const std::string &texturefileName, diff --git a/code/nel/src/gui/view_bitmap.cpp b/code/nel/src/gui/view_bitmap.cpp index 633a8856b..8922d5c4e 100644 --- a/code/nel/src/gui/view_bitmap.cpp +++ b/code/nel/src/gui/view_bitmap.cpp @@ -481,7 +481,7 @@ namespace NLGUI } } else - _TextureId.setTexture (toLower(TxName).c_str (), _TxtOffsetX, _TxtOffsetY, _TxtWidth, _TxtHeight, false); + _TextureId.setTexture (TxName.c_str (), _TxtOffsetX, _TxtOffsetY, _TxtWidth, _TxtHeight, false); } // ---------------------------------------------------------------------------- diff --git a/code/nel/src/gui/view_renderer.cpp b/code/nel/src/gui/view_renderer.cpp index 5dabede88..4c2db062a 100644 --- a/code/nel/src/gui/view_renderer.cpp +++ b/code/nel/src/gui/view_renderer.cpp @@ -24,6 +24,8 @@ #include "nel/misc/file.h" #include "nel/misc/uv.h" #include "nel/misc/hierarchical_timer.h" +#include "nel/misc/base64.h" +#include "nel/misc/md5.h" using namespace NLMISC; using namespace std; @@ -998,6 +1000,10 @@ namespace NLGUI ) { if (sGlobalTextureName.empty()) return -1; + + if (startsWith(sGlobalTextureName, "data:image/")) + return createTextureFromDataURL(sGlobalTextureName, uploadDXTC, bReleasable); + // Look if already existing string sLwrGTName = toLower(sGlobalTextureName); TGlobalTextureList::iterator ite = _GlobalTextures.begin(); @@ -1062,6 +1068,93 @@ namespace NLGUI return TextID; } + sint32 CViewRenderer::createTextureFromDataURL(const std::string &data, bool uploadDXTC, bool bReleasable) + { + if (!startsWith(data, "data:image/")) + return -1; + + size_t pos = data.find(";base64,"); + if (pos == std::string::npos) + { + nlwarning("Failed to parse dataURL (not base64?) '%s'", data.c_str()); + return -1; + } + + std::string md5hash = getMD5((uint8 *)data.c_str(), (uint32)data.size()).toString(); + + TGlobalTextureList::iterator ite = _GlobalTextures.begin(); + while (ite != _GlobalTextures.end()) + { + if (md5hash == ite->Name) + break; + ite++; + } + + // If global texture not exists create it + if (ite == _GlobalTextures.end()) + { + std::string decoded = base64::decode(data.substr(pos + 8)); + if (decoded.empty()) + { + nlwarning("base64 decode failed '%s'", data.substr(pos + 8).c_str()); + return -1; + } + + // + CMemStream buf; + if (buf.isReading()) buf.invert(); + buf.serialBuffer((uint8 *)(decoded.data()), decoded.size()); + buf.invert(); + + CBitmap btm; + btm.load(buf); + + SGlobalTexture gtTmp; + gtTmp.FromGlobaleTexture = false; + + gtTmp.Width = gtTmp.DefaultWidth = btm.getWidth();; + gtTmp.Height = gtTmp.DefaultHeight = btm.getHeight(); + + if (gtTmp.Width == 0 || gtTmp.Height == 0) + { + nlwarning("Failed to load the texture '%s', please check image format", data.c_str()); + return -1; + } + + UTextureMem *texture = driver->createTextureMem(btm.getWidth(), btm.getHeight(), CBitmap::RGBA); + if (!texture) + { + nlwarning("Failed to create mem texture (%d,%d)", btm.getWidth(), btm.getHeight()); + return -1; + } + + memcpy(texture->getPointer(), btm.getPixels().getPtr(), btm.getSize() * 4); + + gtTmp.Texture = texture; + gtTmp.Name = md5hash; + gtTmp.Texture->setFilterMode(UTexture::Nearest, UTexture::NearestMipMapOff); + gtTmp.Texture->setReleasable(bReleasable); + if(uploadDXTC) + gtTmp.Texture->setUploadFormat(UTexture::DXTC5); + + _GlobalTextures.push_back(gtTmp); + ite = _GlobalTextures.end(); + ite--; + } + + // Add a texture with reference to the i th global texture + SImage iTmp; + + // Set default parameters + iTmp.Name = data; + iTmp.GlobalTexturePtr = &(*ite); + iTmp.UVMin = CUV(0.f , 0.f); + iTmp.UVMax = CUV(1.f , 1.f); + sint32 TextID = addSImage(iTmp); + + return TextID; + } + void CViewRenderer::updateTexturePos(const std::string &texturefileName, sint32 offsetX /*=0*/, sint32 offsetY /*=0*/, sint32 width /*=-1*/, sint32 height /*=-1*/) { sint32 id = getTextureIdFromName (texturefileName); @@ -1159,6 +1252,11 @@ namespace NLGUI { driver->deleteTextureFile (tf); } + else + { + UTextureMem *tf = dynamic_cast(iteGT->Texture); + if (tf) driver->deleteTextureMem(tf); + } _GlobalTextures.erase (iteGT); return; }