Skip to content

Commit 178938d

Browse files
committed
⚡️ Extend bitmap compression
Followup to #26419
1 parent a8313c3 commit 178938d

File tree

3 files changed

+33
-23
lines changed

3 files changed

+33
-23
lines changed

Marlin/src/lcd/dogm/marlinui_DOGM.cpp

+11-6
Original file line numberDiff line numberDiff line change
@@ -127,19 +127,19 @@ bool MarlinUI::detected() { return true; }
127127
#else
128128
const u8g_pgm_uint8_t * const bmp = (u8g_pgm_uint8_t*)pgm_read_ptr(&custom_bootscreen_animation[frame]);
129129
#endif
130-
#elif ENABLED(COMPACT_CUSTOM_BOOTSCREEN)
130+
#elif ANY(COMPACT_CUSTOM_BOOTSCREEN, COMPACT_CUSTOM_BOOTSCREEN_EXT)
131131
#define BMPSIZE (CUSTOM_BOOTSCREEN_BMP_BYTEWIDTH * CUSTOM_BOOTSCREEN_BMPHEIGHT)
132132
uint8_t bmp[BMPSIZE];
133133
uint8_t *bmp_rle = (uint8_t*)custom_start_bmp_rle;
134134
#else
135135
const u8g_pgm_uint8_t * const bmp = custom_start_bmp;
136136
#endif
137137

138-
#if ENABLED(COMPACT_CUSTOM_BOOTSCREEN)
138+
#if ANY(COMPACT_CUSTOM_BOOTSCREEN, COMPACT_CUSTOM_BOOTSCREEN_EXT)
139139

140140
uint8_t *dst = (uint8_t*)bmp;
141141

142-
auto rle_nybble = [&](const uint16_t i) {
142+
auto rle_nybble = [&](const uint16_t i) -> uint8_t {
143143
const uint8_t b = bmp_rle[i / 2];
144144
return (i & 1 ? b & 0xF : b >> 4);
145145
};
@@ -149,8 +149,13 @@ bool MarlinUI::detected() { return true; }
149149
while (outindex < BMPSIZE * 8) {
150150
int16_t c = rle_nybble(inindex++);
151151
if (c == 15) {
152-
c = 16 * rle_nybble(inindex) + rle_nybble(inindex + 1) + 15; // From 16 to 270
153-
inindex += 2;
152+
const uint8_t d = rle_nybble(inindex++), e = rle_nybble(inindex++);
153+
#if ENABLED(COMPACT_CUSTOM_BOOTSCREEN_EXT)
154+
if (d == 15)
155+
c = 256 + 16 * e + rle_nybble(inindex++) - 1;
156+
else
157+
#endif
158+
c = 16 * d + e + 15; // From 16 to 270
154159
}
155160
while (c-- >= 0) {
156161
const uint8_t bitind = outindex & 7,
@@ -162,7 +167,7 @@ bool MarlinUI::detected() { return true; }
162167
bitstate ^= 0x80;
163168
}
164169

165-
#endif // COMPACT_CUSTOM_BOOTSCREEN
170+
#endif // COMPACT_CUSTOM_BOOTSCREEN || COMPACT_CUSTOM_BOOTSCREEN_EXT
166171

167172
u8g.TERN(COMPACT_CUSTOM_BOOTSCREEN, drawBitmap, drawBitmapP)
168173
(left, top, CUSTOM_BOOTSCREEN_BMP_BYTEWIDTH, CUSTOM_BOOTSCREEN_BMPHEIGHT, bmp);

Marlin/src/lcd/lcdprint.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
* Return the number of characters emitted
4646
*/
4747
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*/) {
48-
const uint8_t prop = USE_WIDE_GLYPH ? 2 : 1;
4948
const uint8_t *p = (uint8_t*)ptpl;
5049
char *o = outstr;
5150
int8_t n = maxlen;

buildroot/share/scripts/rle_compress_bitmap.py

+22-16
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ def bitwise_rle_encode(data):
7474

7575
def get_bit(data, n): return 1 if (data[n // 8] & (0x80 >> (n & 7))) else 0
7676

77+
isext = False
7778
bitslen = len(data) * 8
7879
bitstate = get_bit(data, 0)
7980
rledata = [ bitstate ]
@@ -84,18 +85,19 @@ def get_bit(data, n): return 1 if (data[n // 8] & (0x80 >> (n & 7))) else 0
8485
if i < bitslen: b = get_bit(data, i)
8586
runlen += 1
8687
if bitstate != b or i == bitslen:
87-
if i > 11 * 56 * 8: print(f'Bit change at index {i} with runlen={runlen}')
88-
if runlen >= 16:
88+
if runlen >= 272:
89+
isext = True
90+
rem = runlen & 0xFF
91+
rledata += [ 15, 15, rem // 16, rem % 16 ]
92+
elif runlen >= 16:
8993
rledata += [ 15, runlen // 16 - 1, runlen % 16 ]
90-
if i > 11 * 56 * 8: print(f'Storing {[ 15, runlen // 16 - 1, runlen % 16 ]}')
9194
else:
9295
rledata += [ runlen - 1 ]
93-
if i > 11 * 56 * 8: print(f'Storing {[ runlen ]}')
9496
bitstate ^= 1
9597
runlen = 0
9698
i += 1
9799

98-
print("\nrledata", rledata)
100+
#print("\nrledata", rledata)
99101

100102
encoded = []
101103
ri = 0
@@ -107,9 +109,9 @@ def get_bit(data, n): return 1 if (data[n // 8] & (0x80 >> (n & 7))) else 0
107109
ri += 2
108110

109111
print("\nencoded", encoded)
110-
return encoded
112+
return encoded, isext
111113

112-
def bitwise_rle_decode(rledata, invert=0):
114+
def bitwise_rle_decode(isext, rledata, invert=0):
113115
expanded = []
114116
for n in rledata: expanded += [ n >> 4, n & 0xF ]
115117

@@ -123,7 +125,12 @@ def bitwise_rle_decode(rledata, invert=0):
123125
if i == 1: bitstate = c ; continue
124126

125127
if c == 15:
126-
c = 16 * expanded[i] + expanded[i + 1] + 15
128+
d = expanded[i] ; e = expanded[i + 1]
129+
if isext and d == 15:
130+
c = 256 + 16 * e + expanded[i + 2] - 1
131+
i += 1
132+
else:
133+
c = 16 * d + e + 15
127134
i += 2
128135

129136
for _ in range(c, -1, -1):
@@ -143,7 +150,7 @@ def bitwise_rle_decode(rledata, invert=0):
143150

144151
return decoded
145152

146-
def rle_emit(ofile, arrname, rledata, rawsize):
153+
def rle_emit(ofile, arrname, rledata, rawsize, isext):
147154

148155
outstr = ''
149156
rows = [ rledata[i:i+16] for i in range(0, len(rledata), 16) ]
@@ -153,21 +160,20 @@ def rle_emit(ofile, arrname, rledata, rawsize):
153160

154161
outstr = outstr[:-2]
155162
size = len(rledata)
156-
ofile.write("\n// Saves %i bytes\n%s %s_rle[%d] PROGMEM = {\n%s\n};\n" % (rawsize - size, datatype, arrname, size, outstr))
163+
defname = 'COMPACT_CUSTOM_BOOTSCREEN_EXT' if isext else 'COMPACT_CUSTOM_BOOTSCREEN'
164+
ofile.write(f"\n// Saves {rawsize - size} bytes\n#define {defname}\n{datatype} {arrname}_rle[{size}] PROGMEM = {{\n{outstr}\n}};\n")
157165

158166
# Encode the data, write it out, close the file
159-
rledata = bitwise_rle_encode(raw_data)
160-
rle_emit(ofile, arrname, rledata, len(raw_data))
167+
rledata, isext = bitwise_rle_encode(raw_data)
168+
rle_emit(ofile, arrname, rledata, len(raw_data), isext)
161169
ofile.close()
162170

163171
# Validate that code properly compressed (and decompressed) the data
164-
checkdata = bitwise_rle_decode(rledata)
165-
badindex = -1
172+
checkdata = bitwise_rle_decode(isext, rledata)
166173
for i in range(0, len(checkdata)):
167174
if raw_data[i] != checkdata[i]:
168-
badindex = i
175+
print(f'Data mismatch at byte offset {i} (should be {raw_data[i]} but got {checkdata[i]})')
169176
break
170-
if badindex >= 0: print(f'Data mismatch at byte {badindex}')
171177

172178
if len(sys.argv) <= 2:
173179
print('Usage: rle_compress_bitmap.py INPUT_FILE OUTPUT_FILE')

0 commit comments

Comments
 (0)