From cc1dcd9d29af20817cc5a6206faa7bf93bf9f706 Mon Sep 17 00:00:00 2001 From: Mimoja Date: Mon, 19 Jun 2023 16:40:08 +0200 Subject: [PATCH] ESP: split esp2buffer into two calls Sprite rendering is the most heap hungry operation in during content generation. This can lead to ESP panics as the exception for the failing "new" is not handled. To further half the required the memory we are doing it in two passes for black and red independant. While this add a few ms to the rendering the main time of the rendering is writing to the FS anyways so the overhead neglectable after all. Signed-off-by: Mimoja --- ESP32_AP-Flasher/src/makeimage.cpp | 53 ++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/ESP32_AP-Flasher/src/makeimage.cpp b/ESP32_AP-Flasher/src/makeimage.cpp index 1cc77192..639a5c1a 100644 --- a/ESP32_AP-Flasher/src/makeimage.cpp +++ b/ESP32_AP-Flasher/src/makeimage.cpp @@ -74,11 +74,7 @@ uint32_t colorDistance(const Color &c1, const Color &c2, const Error &e1) { return 3 * r_diff * r_diff + 6 * g_diff * g_diff + 1 * b_diff * b_diff; } -void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) { - long t = millis(); - Storage.begin(); - - fs::File f_out = contentFS->open(fileout, "w"); +uint8_t *spr2color(TFT_eSprite &spr, imgParam &imageParams, size_t *buffer_size, bool is_red) { bool dither = true; uint8_t rotate = imageParams.rotate; @@ -90,11 +86,13 @@ void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) { bufh = spr.width(); } - int bufferSize = (bufw * bufh) / 8; - uint8_t *blackBuffer = new uint8_t[bufferSize]; - uint8_t *redBuffer = new uint8_t[bufferSize]; - memset(blackBuffer, 0, bufferSize); - memset(redBuffer, 0, bufferSize); + *buffer_size = (bufw * bufh) / 8; + uint8_t *buffer = (uint8_t*) malloc(*buffer_size); + if (!buffer) { + Serial.println("Fallied to allocated buffer"); + return nullptr; + } + memset(buffer, 0, *buffer_size); std::vector palette = { {255, 255, 255}, // White @@ -147,15 +145,16 @@ void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) { // this looks a bit ugly, but it's performing better than shorter notations switch (best_color_index) { case 1: - blackBuffer[byteIndex] |= (1 << bitIndex); + if(!is_red) + buffer[byteIndex] |= (1 << bitIndex); break; case 2: imageParams.hasRed = true; - redBuffer[byteIndex] |= (1 << bitIndex); + if(is_red) + buffer[byteIndex] |= (1 << bitIndex); break; case 3: - blackBuffer[byteIndex] |= (1 << bitIndex); - redBuffer[byteIndex] |= (1 << bitIndex); + buffer[byteIndex] |= (1 << bitIndex); imageParams.hasRed = true; break; } @@ -199,14 +198,32 @@ void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) { } memcpy(error_bufferold, error_buffernew, bufw * sizeof(Error)); } + delete[] error_buffernew; delete[] error_bufferold; - f_out.write(blackBuffer, bufferSize); - if (imageParams.hasRed) f_out.write(redBuffer, bufferSize); + return buffer; +} - delete[] blackBuffer; - delete[] redBuffer; +void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) { + long t = millis(); + Storage.begin(); + + fs::File f_out = contentFS->open(fileout, "w"); + size_t bufferSize; + + uint8_t *blackBuffer = (uint8_t*) spr2color(spr, imageParams, &bufferSize, false); + if(!blackBuffer) + return; + f_out.write(blackBuffer, bufferSize); + free(blackBuffer); + if (imageParams.hasRed) { + uint8_t *redBuffer = (uint8_t*) spr2color(spr, imageParams, &bufferSize, true); + if(!redBuffer) + return; + f_out.write(redBuffer, bufferSize); + free(redBuffer); + } f_out.close(); Serial.println("finished writing buffer " + String(millis() - t) + "ms");