From 963fa72e417006bd787f8ef26aa2d782b45d3b2a Mon Sep 17 00:00:00 2001 From: tobid7 Date: Mon, 16 Jun 2025 20:50:56 +0200 Subject: [PATCH] # Changes - Fix PD Image - Add some beta RLE Compress Decompress variants --- include/pd/core/io.hpp | 26 ++++++++ source/core/io.cpp | 142 +++++++++++++++++++++++++++++++++++++++++ source/image/image.cpp | 16 +++-- 3 files changed, 178 insertions(+), 6 deletions(-) diff --git a/include/pd/core/io.hpp b/include/pd/core/io.hpp index 7d28595..3bec340 100644 --- a/include/pd/core/io.hpp +++ b/include/pd/core/io.hpp @@ -30,6 +30,12 @@ namespace PD { * Set of File Functions */ namespace IO { +enum RleFmt { + Default = 0, + _16 = 1 << 0, + _32 = 1 << 1, + _64 = 1 << 2, +}; /** * Load a File into an 8Bit Memory Buffer * @param path Path to the File @@ -42,5 +48,25 @@ PD_CORE_API std::vector LoadFile2Mem(const std::string& path); * @return 32Bit Hash */ PD_CORE_API u32 HashMemory(const std::vector& data); +/** + * Function to decrompress RLE buffer + * @param data Data buffer to decompress + */ +PD_CORE_API void DecompressRLE(std::vector& data); +/** + * Function to decrompress Extended RLE Buffer + * @param data Data buffer to decompress + */ +PD_CORE_API void DecompressRLE_Ex(std::vector& data); +/** + * Function to compress data with RLE Algorithm + * @param data Data buf + */ +PD_CORE_API void CompressRLE(std::vector& data); +/** + * Extended RLE Compress function (slower cause searches best format) + * @param data Data buf + */ +PD_CORE_API void CompressRLE_Ex(std::vector& data); } // namespace IO } // namespace PD \ No newline at end of file diff --git a/source/core/io.cpp b/source/core/io.cpp index 6c39f5f..281e972 100644 --- a/source/core/io.cpp +++ b/source/core/io.cpp @@ -23,6 +23,74 @@ SOFTWARE. #include +PD_CORE_API void DecompressRLE16(std::vector& data) { + std::vector cpy = data; + data.clear(); + for (size_t i = 0; i < cpy.size(); i += 3) { + for (size_t j = 0; j < cpy[i + 2]; j++) { + data.push_back(cpy[i]); + data.push_back(cpy[i + 1]); + } + } +} + +PD_CORE_API void DecompressRLE32(std::vector& data) { + std::vector cpy = data; + data.clear(); + for (size_t i = 0; (i + 4) < cpy.size(); i += 5) { + for (size_t j = 0; j < cpy[i + 4]; j++) { + data.push_back(cpy[i]); + data.push_back(cpy[i + 1]); + data.push_back(cpy[i + 2]); + data.push_back(cpy[i + 3]); + } + } +} + +PD_CORE_API void CompressRLE16(std::vector& data) { + std::vector cpy = data; + data.clear(); + size_t i = 0; + while ((i + 1) < cpy.size()) { + PD::u16 v = PD::u16(cpy[i]) | (PD::u16(cpy[i + 1]) << 8); + size_t c = 1; + while ((i + c * 2 + 1) < cpy.size() && + (PD::u16(cpy[i + c * 2]) | (PD::u16(cpy[i + c * 2 + 1])) << 8) == + v && + c < 255) { + c++; // c++ ... + } + data.push_back(PD::u8(v & 0xFF)); + data.push_back(PD::u8((v >> 8) & 0xFF)); + data.push_back(c); + i += c * 2; + } +} + +PD_CORE_API void CompressRLE32(std::vector& data) { + std::vector cpy = data; + data.clear(); + size_t i = 0; + while ((i + 3) < cpy.size()) { + PD::u32 v = PD::u32(cpy[i]) | (PD::u32(cpy[i + 1]) << 8) | + (PD::u32(cpy[i + 2]) << 16) | (PD::u32(cpy[i + 3]) << 24); + size_t c = 1; + while ((i + c * 4 + 3) < cpy.size() && + (PD::u32(cpy[i + c * 4]) | (PD::u32(cpy[i + c * 4 + 1]) << 8) | + (PD::u32(cpy[i + c * 4 + 2]) << 16) | + (PD::u32(cpy[i + c * 4 + 3]) << 24)) == v && + c < 255) { + c++; // c++ ... + } + data.push_back(PD::u8(v & 0xFF)); + data.push_back(PD::u8((v >> 8) & 0xFF)); + data.push_back(PD::u8((v >> 16) & 0xFF)); + data.push_back(PD::u8((v >> 24) & 0xFF)); + data.push_back(c); + i += c * 4; + } +} + namespace PD { namespace IO { PD_CORE_API std::vector LoadFile2Mem(const std::string& path) { @@ -38,6 +106,7 @@ PD_CORE_API std::vector LoadFile2Mem(const std::string& path) { iff.close(); return res; } + PD_CORE_API u32 HashMemory(const std::vector& data) { u32 hash = 4477; for (auto& it : data) { @@ -45,5 +114,78 @@ PD_CORE_API u32 HashMemory(const std::vector& data) { } return hash; } + +PD_CORE_API void DecompressRLE(std::vector& data) { + if ((data.size() % 2) != 0) { + return; + } + std::vector cpy = data; + data.clear(); + for (size_t i = 0; i < cpy.size(); i += 2) { + data.insert(data.end(), cpy[i + 1], cpy[i]); + } +} + +PD_CORE_API void DecompressRLE_Ex(std::vector& data) { + if (!data.size()) { + return; + } + u8 fmt = data[0]; + data.erase(data.begin()); + if (fmt == 0) { + DecompressRLE(data); + } else if (fmt == 1) { + DecompressRLE16(data); + } else if (fmt == 2) { + DecompressRLE32(data); + } + /** unknown returns input data */ +} + +PD_CORE_API void CompressRLE(std::vector& data) { + if (data.empty()) { + /** No exceptions enabled :( */ + return; + } + std::vector cpy = data; + data.clear(); + /** 8-Bit RLE */ + data.push_back(0); + size_t i = 0; + while (i < cpy.size()) { + u8 v = cpy[i]; + u8 c = 1; + while (i + c < cpy.size() && cpy[i + c] == v && c < 255) { + c++; // c++ ... + } + data.push_back(v); + data.push_back(c); + i += c; + } +} + +PD_CORE_API void CompressRLE_Ex(std::vector& data) { + if (data.empty()) { + /** No exceptions enabled :( */ + return; + } + std::vector _8 = data; + std::vector _16 = data; + std::vector _32 = data; + CompressRLE(_8); + CompressRLE16(_16); + CompressRLE32(_32); + if (_16.size() < _8.size() && _16.size() < _32.size()) { + _16.insert(_16.begin(), 1); + data = _16; + return; + } else if (_32.size() < _8.size()) { + _32.insert(_32.begin(), 2); + data = _32; + return; + } + _8.insert(_8.begin(), 0); + data = _8; +} } // namespace IO } // namespace PD \ No newline at end of file diff --git a/source/image/image.cpp b/source/image/image.cpp index 0346270..070b8d0 100644 --- a/source/image/image.cpp +++ b/source/image/image.cpp @@ -78,22 +78,25 @@ PD_IMAGE_API void Image::Copy(const std::vector& buf, int w, int h, } PD_IMAGE_API void Image::Convert(Image::Ref img, Image::Format dst) { - if (img->Fmt() == dst) { + if (img->pFmt == dst) { return; - } else if (img->Fmt() == Image::RGB && dst == Image::BGR) { + } else if (img->pFmt == Image::RGB && dst == Image::BGR) { ImgConvert::ReverseBuf(img->pBuffer, 3, img->pWidth, img->pHeight); - } else if (img->Fmt() == Image::RGB && dst == Image::RGBA) { + img->pFmt = BGR; + } else if (img->pFmt == Image::RGB && dst == Image::RGBA) { std::vector cpy = img->pBuffer; img->pBuffer.resize(img->pWidth * img->pHeight * 4); ImgConvert::RGB24toRGBA32(img->pBuffer, cpy, img->pWidth, img->pHeight); - } else if (img->Fmt() == Image::RGBA && dst == Image::RGB) { + img->pFmt = RGBA; + } else if (img->pFmt == Image::RGBA && dst == Image::RGB) { std::vector cpy = img->pBuffer; img->pBuffer.resize(img->pWidth * img->pHeight * 3); ImgConvert::RGB32toRGBA24(img->pBuffer, cpy, img->pWidth, img->pHeight); - } else if (img->Fmt() == Image::RGBA && dst == Image::RGB565) { + img->pFmt = RGB; + } else if (img->pFmt == Image::RGBA && dst == Image::RGB565) { Convert(img, Image::RGB); Convert(img, Image::RGB565); - } else if (img->Fmt() == Image::RGB && dst == Image::RGB565) { + } else if (img->pFmt == Image::RGB && dst == Image::RGB565) { auto f = [](u8 r, u8 g, u8 b) -> u16 { u16 _r = (r >> 3); u16 _g = (g >> 2); @@ -111,6 +114,7 @@ PD_IMAGE_API void Image::Convert(Image::Ref img, Image::Format dst) { img->pBuffer[dst + 1] = new_px & 0xff; } } + img->pFmt = RGB565; } }