diff --git a/TSE_Core/src/elements/Texture.cpp b/TSE_Core/src/elements/Texture.cpp index 2e24ad1..d4b36da 100644 --- a/TSE_Core/src/elements/Texture.cpp +++ b/TSE_Core/src/elements/Texture.cpp @@ -148,6 +148,176 @@ void TSE::Texture::GetPixel(const Vector2 &pos, Color &c) const GetPixel(pos.x, pos.y, c); } +TSE::Texture TSE::Texture::CutOut(const Vector2 &pos, Vector2 &size) const +{ + Texture result = Texture(0,0); + if(bmp == nullptr) + { + TSE_ERROR("Failed to cut out texture. Source bitmap was nullptr."); + Texture::makeError(result); + return result; + } + + const int left = static_cast(pos.x); + const int top = static_cast(pos.y); + const int width = static_cast(size.x); + const int height = static_cast(size.y); + + if(width <= 0 || height <= 0) + { + TSE_ERROR("Failed to cut out texture. Size must be greater than 0."); + Texture::makeError(result); + return result; + } + + const int texWidth = static_cast(Width()); + const int texHeight = static_cast(Height()); + if(left < 0 || top < 0 || left + width > texWidth || top + height > texHeight) + { + TSE_ERROR("Failed to cut out texture. Region out of bounds."); + Texture::makeError(result); + return result; + } + + FIBITMAP* cut = FreeImage_Copy(bmp, left, top, left + width, top + height); + if(cut == nullptr) + { + TSE_ERROR("Failed to cut out texture. FreeImage_Copy returned nullptr."); + Texture::makeError(result); + return result; + } + + Texture out = Texture(width, height, Bpp); + if(out.bmp != nullptr) + FreeImage_Unload(out.bmp); + out.bmp = cut; + out.imagePtr = FreeImage_GetBits(cut); + out.Bpp = Bpp; + out.chanels = chanels; + out.Size = Vector2(width, height); + out.Apply(); + return out; +} + +TSE::Texture TSE::Texture::Upscale(const Vector2 &size) const +{ + Texture result = Texture(0,0); + if(bmp == nullptr) + { + TSE_ERROR("Failed to upscale texture. Source bitmap was nullptr."); + Texture::makeError(result); + return result; + } + + const int width = static_cast(size.x); + const int height = static_cast(size.y); + if(width <= 0 || height <= 0) + { + TSE_ERROR("Failed to upscale texture. Size must be greater than 0."); + Texture::makeError(result); + return result; + } + + FIBITMAP* scaled = FreeImage_Rescale(bmp, width, height, FILTER_NEAREST); + if(scaled == nullptr) + { + TSE_ERROR("Failed to upscale texture. FreeImage_Rescale returned nullptr."); + Texture::makeError(result); + return result; + } + + Texture out = Texture(width, height, Bpp); + if(out.bmp != nullptr) + FreeImage_Unload(out.bmp); + out.bmp = scaled; + out.imagePtr = FreeImage_GetBits(scaled); + out.Bpp = Bpp; + out.chanels = chanels; + out.Size = Vector2(width, height); + out.Apply(); + return out; +} + +TSE::Texture TSE::Texture::Downscale(const Vector2 &size) const +{ + Texture result = Texture(0,0); + if(bmp == nullptr) + { + TSE_ERROR("Failed to downscale texture. Source bitmap was nullptr."); + Texture::makeError(result); + return result; + } + + const int width = static_cast(size.x); + const int height = static_cast(size.y); + if(width <= 0 || height <= 0) + { + TSE_ERROR("Failed to downscale texture. Size must be greater than 0."); + Texture::makeError(result); + return result; + } + + FIBITMAP* scaled = FreeImage_Rescale(bmp, width, height, FILTER_NEAREST); + if(scaled == nullptr) + { + TSE_ERROR("Failed to downscale texture. FreeImage_Rescale returned nullptr."); + Texture::makeError(result); + return result; + } + + Texture out = Texture(width, height, Bpp); + if(out.bmp != nullptr) + FreeImage_Unload(out.bmp); + out.bmp = scaled; + out.imagePtr = FreeImage_GetBits(scaled); + out.Bpp = Bpp; + out.chanels = chanels; + out.Size = Vector2(width, height); + out.Apply(); + return out; +} + +void TSE::Texture::PasteIn(const Vector2 &pos, Texture &t) +{ + if(bmp == nullptr) + { + TSE_ERROR("Failed to paste texture. Destination bitmap was nullptr."); + return; + } + if(t.bmp == nullptr) + { + TSE_ERROR("Failed to paste texture. Source bitmap was nullptr."); + return; + } + if(Bpp != t.Bpp) + { + TSE_ERROR("Failed to paste texture. Source and destination Bpp do not match."); + return; + } + + const int left = static_cast(pos.x); + const int top = static_cast(pos.y); + const int srcWidth = static_cast(t.Width()); + const int srcHeight = static_cast(t.Height()); + const int texWidth = static_cast(Width()); + const int texHeight = static_cast(Height()); + + if(left < 0 || top < 0 || left + srcWidth > texWidth || top + srcHeight > texHeight) + { + TSE_ERROR("Failed to paste texture. Region out of bounds."); + return; + } + + if(!FreeImage_Paste(bmp, t.bmp, left, top, 256)) + { + TSE_ERROR("Failed to paste texture. FreeImage_Paste returned false."); + return; + } + + imagePtr = FreeImage_GetBits(bmp); + Apply(); +} + void TSE::Texture::SetPixelNoApply(const Vector2 &pos, const Color &c) { SetPixelNoApply(pos.x, pos.y, c); diff --git a/TSE_Core/src/elements/Texture.hpp b/TSE_Core/src/elements/Texture.hpp index 8ad3426..543668c 100644 --- a/TSE_Core/src/elements/Texture.hpp +++ b/TSE_Core/src/elements/Texture.hpp @@ -38,6 +38,10 @@ namespace TSE byte* GetImagePtr() const; void SetPixel(const Vector2& pos, const Color& c); void GetPixel(const Vector2& pos, Color& c) const; + Texture CutOut(const Vector2& pos, Vector2& size) const; + Texture Upscale(const Vector2& size) const; + Texture Downscale(const Vector2& size) const; + void PasteIn(const Vector2& pos, Texture& t); void SetPixelNoApply(const Vector2& pos, const Color& c); void ToSprite(Sprite& s); void SetChanels(const byte& ch);