From 178938d9574a37638cf752b9d09791027ea8a97e Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Mon, 13 Nov 2023 23:05:59 -0600 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20Extend=20bitmap=20compress?= =?UTF-8?q?ion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Followup to #26419 --- Marlin/src/lcd/dogm/marlinui_DOGM.cpp | 17 ++++++--- Marlin/src/lcd/lcdprint.cpp | 1 - .../share/scripts/rle_compress_bitmap.py | 38 +++++++++++-------- 3 files changed, 33 insertions(+), 23 deletions(-) diff --git a/Marlin/src/lcd/dogm/marlinui_DOGM.cpp b/Marlin/src/lcd/dogm/marlinui_DOGM.cpp index 7b81b3637d..1b53bb4bbe 100644 --- a/Marlin/src/lcd/dogm/marlinui_DOGM.cpp +++ b/Marlin/src/lcd/dogm/marlinui_DOGM.cpp @@ -127,7 +127,7 @@ bool MarlinUI::detected() { return true; } #else const u8g_pgm_uint8_t * const bmp = (u8g_pgm_uint8_t*)pgm_read_ptr(&custom_bootscreen_animation[frame]); #endif - #elif ENABLED(COMPACT_CUSTOM_BOOTSCREEN) + #elif ANY(COMPACT_CUSTOM_BOOTSCREEN, COMPACT_CUSTOM_BOOTSCREEN_EXT) #define BMPSIZE (CUSTOM_BOOTSCREEN_BMP_BYTEWIDTH * CUSTOM_BOOTSCREEN_BMPHEIGHT) uint8_t bmp[BMPSIZE]; uint8_t *bmp_rle = (uint8_t*)custom_start_bmp_rle; @@ -135,11 +135,11 @@ bool MarlinUI::detected() { return true; } const u8g_pgm_uint8_t * const bmp = custom_start_bmp; #endif - #if ENABLED(COMPACT_CUSTOM_BOOTSCREEN) + #if ANY(COMPACT_CUSTOM_BOOTSCREEN, COMPACT_CUSTOM_BOOTSCREEN_EXT) uint8_t *dst = (uint8_t*)bmp; - auto rle_nybble = [&](const uint16_t i) { + auto rle_nybble = [&](const uint16_t i) -> uint8_t { const uint8_t b = bmp_rle[i / 2]; return (i & 1 ? b & 0xF : b >> 4); }; @@ -149,8 +149,13 @@ bool MarlinUI::detected() { return true; } while (outindex < BMPSIZE * 8) { int16_t c = rle_nybble(inindex++); if (c == 15) { - c = 16 * rle_nybble(inindex) + rle_nybble(inindex + 1) + 15; // From 16 to 270 - inindex += 2; + const uint8_t d = rle_nybble(inindex++), e = rle_nybble(inindex++); + #if ENABLED(COMPACT_CUSTOM_BOOTSCREEN_EXT) + if (d == 15) + c = 256 + 16 * e + rle_nybble(inindex++) - 1; + else + #endif + c = 16 * d + e + 15; // From 16 to 270 } while (c-- >= 0) { const uint8_t bitind = outindex & 7, @@ -162,7 +167,7 @@ bool MarlinUI::detected() { return true; } bitstate ^= 0x80; } - #endif // COMPACT_CUSTOM_BOOTSCREEN + #endif // COMPACT_CUSTOM_BOOTSCREEN || COMPACT_CUSTOM_BOOTSCREEN_EXT u8g.TERN(COMPACT_CUSTOM_BOOTSCREEN, drawBitmap, drawBitmapP) (left, top, CUSTOM_BOOTSCREEN_BMP_BYTEWIDTH, CUSTOM_BOOTSCREEN_BMPHEIGHT, bmp); diff --git a/Marlin/src/lcd/lcdprint.cpp b/Marlin/src/lcd/lcdprint.cpp index c84a695c78..8642d84315 100644 --- a/Marlin/src/lcd/lcdprint.cpp +++ b/Marlin/src/lcd/lcdprint.cpp @@ -45,7 +45,6 @@ * Return the number of characters emitted */ lcd_uint_t expand_u8str_P(char * const outstr, PGM_P const ptpl, const int8_t ind, const char *cstr/*=nullptr*/, FSTR_P const fstr/*=nullptr*/, const lcd_uint_t maxlen/*=LCD_WIDTH*/) { - const uint8_t prop = USE_WIDE_GLYPH ? 2 : 1; const uint8_t *p = (uint8_t*)ptpl; char *o = outstr; int8_t n = maxlen; diff --git a/buildroot/share/scripts/rle_compress_bitmap.py b/buildroot/share/scripts/rle_compress_bitmap.py index 8f5436fa2e..8ad3ecfaae 100755 --- a/buildroot/share/scripts/rle_compress_bitmap.py +++ b/buildroot/share/scripts/rle_compress_bitmap.py @@ -74,6 +74,7 @@ def addCompressedData(input_file, output_file): def get_bit(data, n): return 1 if (data[n // 8] & (0x80 >> (n & 7))) else 0 + isext = False bitslen = len(data) * 8 bitstate = get_bit(data, 0) rledata = [ bitstate ] @@ -84,18 +85,19 @@ def addCompressedData(input_file, output_file): if i < bitslen: b = get_bit(data, i) runlen += 1 if bitstate != b or i == bitslen: - if i > 11 * 56 * 8: print(f'Bit change at index {i} with runlen={runlen}') - if runlen >= 16: + if runlen >= 272: + isext = True + rem = runlen & 0xFF + rledata += [ 15, 15, rem // 16, rem % 16 ] + elif runlen >= 16: rledata += [ 15, runlen // 16 - 1, runlen % 16 ] - if i > 11 * 56 * 8: print(f'Storing {[ 15, runlen // 16 - 1, runlen % 16 ]}') else: rledata += [ runlen - 1 ] - if i > 11 * 56 * 8: print(f'Storing {[ runlen ]}') bitstate ^= 1 runlen = 0 i += 1 - print("\nrledata", rledata) + #print("\nrledata", rledata) encoded = [] ri = 0 @@ -107,9 +109,9 @@ def addCompressedData(input_file, output_file): ri += 2 print("\nencoded", encoded) - return encoded + return encoded, isext - def bitwise_rle_decode(rledata, invert=0): + def bitwise_rle_decode(isext, rledata, invert=0): expanded = [] for n in rledata: expanded += [ n >> 4, n & 0xF ] @@ -123,7 +125,12 @@ def addCompressedData(input_file, output_file): if i == 1: bitstate = c ; continue if c == 15: - c = 16 * expanded[i] + expanded[i + 1] + 15 + d = expanded[i] ; e = expanded[i + 1] + if isext and d == 15: + c = 256 + 16 * e + expanded[i + 2] - 1 + i += 1 + else: + c = 16 * d + e + 15 i += 2 for _ in range(c, -1, -1): @@ -143,7 +150,7 @@ def addCompressedData(input_file, output_file): return decoded - def rle_emit(ofile, arrname, rledata, rawsize): + def rle_emit(ofile, arrname, rledata, rawsize, isext): outstr = '' rows = [ rledata[i:i+16] for i in range(0, len(rledata), 16) ] @@ -153,21 +160,20 @@ def addCompressedData(input_file, output_file): outstr = outstr[:-2] size = len(rledata) - ofile.write("\n// Saves %i bytes\n%s %s_rle[%d] PROGMEM = {\n%s\n};\n" % (rawsize - size, datatype, arrname, size, outstr)) + defname = 'COMPACT_CUSTOM_BOOTSCREEN_EXT' if isext else 'COMPACT_CUSTOM_BOOTSCREEN' + ofile.write(f"\n// Saves {rawsize - size} bytes\n#define {defname}\n{datatype} {arrname}_rle[{size}] PROGMEM = {{\n{outstr}\n}};\n") # Encode the data, write it out, close the file - rledata = bitwise_rle_encode(raw_data) - rle_emit(ofile, arrname, rledata, len(raw_data)) + rledata, isext = bitwise_rle_encode(raw_data) + rle_emit(ofile, arrname, rledata, len(raw_data), isext) ofile.close() # Validate that code properly compressed (and decompressed) the data - checkdata = bitwise_rle_decode(rledata) - badindex = -1 + checkdata = bitwise_rle_decode(isext, rledata) for i in range(0, len(checkdata)): if raw_data[i] != checkdata[i]: - badindex = i + print(f'Data mismatch at byte offset {i} (should be {raw_data[i]} but got {checkdata[i]})') break - if badindex >= 0: print(f'Data mismatch at byte {badindex}') if len(sys.argv) <= 2: print('Usage: rle_compress_bitmap.py INPUT_FILE OUTPUT_FILE')