From b65ca374850b66da22450149536dc113faa8ec21 Mon Sep 17 00:00:00 2001 From: Djuri Baars Date: Thu, 19 Dec 2024 22:09:33 +0100 Subject: [PATCH] First attempt of gzip decompression with miniz --- src/lib/epd.cpp | 38 +++++++++++++++++++++--- src/lib/epd.hpp | 2 +- src/lib/gzip_decompressor.hpp | 55 +++++++++++++++++++++++++++++++++++ src/lib/shared.cpp | 23 ++++++++++++++- src/lib/shared.hpp | 5 +++- 5 files changed, 116 insertions(+), 7 deletions(-) create mode 100644 src/lib/gzip_decompressor.hpp diff --git a/src/lib/epd.cpp b/src/lib/epd.cpp index 2b30f26..681eebd 100644 --- a/src/lib/epd.cpp +++ b/src/lib/epd.cpp @@ -165,8 +165,41 @@ void refreshFromMemory() } } +const unsigned char* decIcons[5]; + void setupDisplays() { + for (int i = 0; i < 1; i++) { + + const size_t compressedSize = 408; + + // Get required output buffer size + size_t decompressedSize = GzipDecompressor::getDecompressedSize(epd_icons_pickaxe, compressedSize); + if (decompressedSize == 0) { + Serial.println("Failed to get decompressed size"); + continue; + } + + // Allocate output buffer + uint8_t* decompressedData = (uint8_t*)malloc(decompressedSize); + if (!decompressedData) { + Serial.println("Failed to allocate memory"); + continue; + } + + // Decompress + if (GzipDecompressor::decompressData(epd_icons_pickaxe, compressedSize, + decompressedData, &decompressedSize)) { + Serial.println("Decompression successful"); + // Use decompressedData here + } else { + Serial.printf("Decompression failed, Compressed: %d, Decompressed: %d\n", compressedSize, decompressedSize); + } + + free(decompressedData); + } + + std::lock_guard lockMcp(mcpMutex); for (uint i = 0; i < NUM_SCREENS; i++) @@ -614,10 +647,7 @@ void renderIcon(const uint dispNum, const String &text, bool partial) iconIndex = 4; } - - - - displays[dispNum].drawInvertedBitmap(0,0, epd_icons_allArray[iconIndex], 122, 250, getFgColor()); + // displays[dispNum].drawInvertedBitmap(0,0, decIcons[iconIndex], 122, 250, getFgColor()); // displays[dispNum].drawInvertedBitmap(0,0, getOceanIcon(), 122, 250, getFgColor()); diff --git a/src/lib/epd.hpp b/src/lib/epd.hpp index 1194cf1..6fee6c0 100644 --- a/src/lib/epd.hpp +++ b/src/lib/epd.hpp @@ -3,7 +3,7 @@ #include #include #include - +#include "gzip_decompressor.hpp" #include #include diff --git a/src/lib/gzip_decompressor.hpp b/src/lib/gzip_decompressor.hpp new file mode 100644 index 0000000..30827de --- /dev/null +++ b/src/lib/gzip_decompressor.hpp @@ -0,0 +1,55 @@ +#include "rom/miniz.h" + +class GzipDecompressor { +private: + static const size_t CHUNK_SIZE = 1024; // Adjust based on your needs + +public: + // Returns decompressed size or 0 if failed + static size_t getDecompressedSize(const uint8_t* input, size_t inputSize) { + size_t decompSize = 0; + // Last 4 bytes of gzip contain decompressed size + if (inputSize >= 4) { + decompSize = (input[inputSize - 1] << 24) | + (input[inputSize - 2] << 16) | + (input[inputSize - 3] << 8) | + (input[inputSize - 4]); + } + return decompSize; + } + + static bool decompressData(const uint8_t* input, size_t inputSize, + uint8_t* output, size_t* outputSize) { + tinfl_decompressor decomp; + tinfl_init(&decomp); + + size_t inPos = 0; + size_t outPos = 0; + + // Skip gzip header (usually 10 bytes) + if (inputSize > 10) { + inPos = 10; + } + + while (inPos < inputSize - 8) { // -8 for footer + size_t inBytes = inputSize - inPos - 8; // Don't read footer + size_t outBytes = *outputSize - outPos; + + tinfl_status status = tinfl_decompress(&decomp, + &input[inPos], &inBytes, + output, &output[outPos], &outBytes, + TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); + + inPos += inBytes; + outPos += outBytes; + + if (status == TINFL_STATUS_DONE) { + *outputSize = outPos; + return true; + } else if (status < 0) { + return false; + } + } + return false; + } +}; \ No newline at end of file diff --git a/src/lib/shared.cpp b/src/lib/shared.cpp index 3422ff8..6c6a156 100644 --- a/src/lib/shared.cpp +++ b/src/lib/shared.cpp @@ -151,4 +151,25 @@ String calculateSHA256(WiFiClient *stream, size_t contentLength) { // uint8_t *pUncompressed; // pUncompressed = (uint8_t *)malloc(iUncompSize+4); // zt.gunzip((uint8_t *)ocean_logo_comp, ocean_logo_size, pUncompressed); -// } \ No newline at end of file +// } + +void decompressData(const uint8_t* input, size_t inputSize, uint8_t* output, size_t outputSize) { + tinfl_decompressor decomp; + tinfl_init(&decomp); + + size_t inPos = 0; + size_t outPos = 0; + + while (inPos < inputSize) { + size_t inBytes = inputSize - inPos; + size_t outBytes = outputSize - outPos; + + tinfl_decompress(&decomp, + &input[inPos], &inBytes, + output, &output[outPos], &outBytes, + TINFL_FLAG_PARSE_ZLIB_HEADER); + + inPos += inBytes; + outPos += outBytes; + } +} \ No newline at end of file diff --git a/src/lib/shared.hpp b/src/lib/shared.hpp index 4753764..e34d3ac 100644 --- a/src/lib/shared.hpp +++ b/src/lib/shared.hpp @@ -12,6 +12,7 @@ #include #include "esp_crt_bundle.h" #include +#include #include #include @@ -91,4 +92,6 @@ struct ScreenMapping { }; String calculateSHA256(uint8_t* data, size_t len); -String calculateSHA256(WiFiClient *stream, size_t contentLength); \ No newline at end of file +String calculateSHA256(WiFiClient *stream, size_t contentLength); + +void decompressData(const uint8_t* input, size_t inputSize, uint8_t* output, size_t outputSize); \ No newline at end of file