fix: Add framebuffer release/realloc and improved lazy indexing (#2563)
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <HalDisplay.h>
|
||||
#include <HalStorage.h>
|
||||
#include <InflateReader.h>
|
||||
#include <InflateStream.h>
|
||||
#include <Logging.h>
|
||||
|
||||
#include <cstdio>
|
||||
@@ -174,9 +174,8 @@ void writeBmpHeader2bit(Print& bmpOut, const int width, const int height) {
|
||||
} // namespace
|
||||
|
||||
// Context for streaming PNG decompression
|
||||
// IMPORTANT: reader must be the first field - the uzlib callback casts uzlib_uncomp* to PngDecodeContext*
|
||||
struct PngDecodeContext {
|
||||
InflateReader reader; // Must be first — callback casts uzlib_uncomp* to PngDecodeContext*
|
||||
InflateStream reader;
|
||||
HalFile* file;
|
||||
|
||||
// PNG image properties
|
||||
@@ -195,7 +194,7 @@ struct PngDecodeContext {
|
||||
uint32_t chunkBytesRemaining; // bytes left in current IDAT chunk
|
||||
bool idatFinished; // no more IDAT chunks
|
||||
|
||||
// File read buffer for feeding uzlib
|
||||
// File read buffer for feeding the inflate stream
|
||||
uint8_t readBuf[2048];
|
||||
|
||||
// Palette for indexed color (type 3)
|
||||
@@ -229,21 +228,21 @@ static bool findNextIdatChunk(PngDecodeContext& ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
// uzlib callback: reads the next batch of IDAT data from the file
|
||||
static int pngIdatReadCallback(uzlib_uncomp* uncomp) {
|
||||
auto* ctx = reinterpret_cast<PngDecodeContext*>(uncomp);
|
||||
// Fill callback: reads the next batch of IDAT data from the file
|
||||
static size_t pngIdatFillCallback(void* vctx, const uint8_t** data) {
|
||||
auto* ctx = static_cast<PngDecodeContext*>(vctx);
|
||||
|
||||
if (ctx->idatFinished) return -1;
|
||||
if (ctx->idatFinished) return 0;
|
||||
|
||||
// Skip 4-byte CRC and find next IDAT chunk when current chunk is exhausted
|
||||
while (ctx->chunkBytesRemaining == 0) {
|
||||
if (!ctx->file->seekCur(4)) { // skip 4-byte CRC of previous IDAT
|
||||
ctx->idatFinished = true;
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
if (!findNextIdatChunk(*ctx)) {
|
||||
ctx->idatFinished = true;
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,18 +250,15 @@ static int pngIdatReadCallback(uzlib_uncomp* uncomp) {
|
||||
size_t toRead = sizeof(ctx->readBuf);
|
||||
if (toRead > ctx->chunkBytesRemaining) toRead = ctx->chunkBytesRemaining;
|
||||
|
||||
int bytesRead = ctx->file->read(ctx->readBuf, toRead);
|
||||
const int bytesRead = ctx->file->read(ctx->readBuf, toRead);
|
||||
if (bytesRead <= 0) {
|
||||
ctx->idatFinished = true;
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx->chunkBytesRemaining -= bytesRead;
|
||||
|
||||
// Give uzlib the buffer (skip first byte since we return it directly)
|
||||
uncomp->source = ctx->readBuf + 1;
|
||||
uncomp->source_limit = ctx->readBuf + bytesRead;
|
||||
return ctx->readBuf[0];
|
||||
*data = ctx->readBuf;
|
||||
return static_cast<size_t>(bytesRead);
|
||||
}
|
||||
|
||||
// Decode one scanline: decompress filter byte + raw bytes, then unfilter
|
||||
@@ -555,16 +551,16 @@ bool PngToBmpConverter::pngFileToBmpStreamInternal(HalFile& pngFile, Print& bmpO
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize streaming decompressor with 32KB ring buffer for back-reference history
|
||||
// Initialize streaming decompressor with 32KB window for back-reference history
|
||||
if (!ctx.reader.init(true)) {
|
||||
LOG_ERR("PNG", "Failed to init inflate reader");
|
||||
LOG_ERR("PNG", "Failed to init inflate stream");
|
||||
free(ctx.currentRow);
|
||||
free(ctx.previousRow);
|
||||
return false;
|
||||
}
|
||||
ctx.reader.setReadCallback(pngIdatReadCallback);
|
||||
// PNG IDAT data is zlib-wrapped: consume the 2-byte zlib header (CMF + FLG)
|
||||
ctx.reader.skipZlibHeader();
|
||||
ctx.reader.setFill(pngIdatFillCallback, &ctx);
|
||||
// PNG IDAT data is zlib-wrapped (2-byte header + trailing adler32)
|
||||
ctx.reader.setZlibWrapped();
|
||||
|
||||
// Calculate output dimensions (same logic as JpegToBmpConverter)
|
||||
int outWidth = width;
|
||||
|
||||
Reference in New Issue
Block a user