From 7f6b1b9059a3537726e0cda706a1898bd8e9ac8e Mon Sep 17 00:00:00 2001 From: Daniel Thompson Date: Mon, 18 May 2020 22:17:51 +0100 Subject: [PATCH] draw565: Switch to a different palette for RLE 2-bit images This is an incompatible change... older 2-bit images will need to be re-encoded to display correctly. --- res/app_icon.png | Bin 7124 -> 6996 bytes tools/rle_encode.py | 110 +++++++++++++++++++++++++++++++++++++++- wasp/apps/gameoflife.py | 6 +-- wasp/draw565.py | 30 +++++++---- wasp/icons.py | 100 ++++++++++++++++++------------------ 5 files changed, 181 insertions(+), 65 deletions(-) diff --git a/res/app_icon.png b/res/app_icon.png index 574f75fe221e251189f06146a45601aa10da4f12..438cded3db82a24de8fa3c8994bd4c69d248e1cf 100644 GIT binary patch delta 6915 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 delta 7116 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 )RMDy|112S1vRPR2!Ii!B; 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 3 + rg = i // 6 + rgb565 += ((rg % 6) * (0x33 << 3)) & 0x07e0 + rgb565 += ((rg // 6) * (0x33 << 8)) & 0xf800 + elif i < 252: + i -= 216 + rgb565 = (0x7f + (( i % 3) * 0x33)) >> 3 + rg = i // 3 + rgb565 += ((0x4c << 3) + ((rg % 4) * (0x33 << 3))) & 0x07e0 + rgb565 += ((0x7f << 8) + ((rg // 4) * (0x33 << 8))) & 0xf800 + else: + i -= 252 + gr6 = (0x2c + (0x10 * i)) >> 2 + gr5 = gr6 >> 1 + rgb565 = (gr5 << 11) + (gr6 << 5) + gr5 + + return rgb565 + +class ReverseCLUT: + def __init__(self, clut): + l = [] + for i in range(256): + l.append(clut(i)) + self.clut = tuple(l) + self.lookup = {} + + def __call__(self, rgb888): + """Compare rgb888 to every element of the CLUT and pick the + closest match. + """ + if rgb888 in self.lookup: + return self.lookup[rgb888] + + best = 200000 + index = -1 + clut = self.clut + r = rgb888 >> 16 + g = (rgb888 >> 8) & 0xff + b = rgb888 & 0xff + + for i in range(256): + candidate = clut[i] + rd = r - (candidate >> 16) + gd = g - ((candidate >> 8) & 0xff) + bd = b - (candidate & 0xff) + # This is the Euclidian distance (squared) + distance = rd * rd + gd * gd + bd * bd + if distance < best: + best = distance + index = i + + self.lookup[rgb888] = index + #print(f'# #{rgb888:06x} -> #{clut8_rgb888(index):06x}') + return index + def varname(p): return os.path.basename(os.path.splitext(p)[0]) @@ -62,15 +165,18 @@ def encode_2bit(im): assert(im.width <= 255) assert(im.height <= 255) + full_palette = ReverseCLUT(clut8_rgb888) + rle = [] rl = 0 px = pixels[0, 0] - palette = [0, 0xfc, 0x2d, 0xff] + # black, grey25, grey50, white + palette = [0, 254, 219, 215] next_color = 1 def encode_pixel(px, rl): nonlocal next_color - px = (px[0] & 0xe0) | ((px[1] & 0xe0) >> 3) | ((px[2] & 0xc0) >> 6) + px = full_palette((px[0] << 16) + (px[1] << 8) + px[2]) if px not in palette: rle.append(next_color << 6) rle.append(px) diff --git a/wasp/apps/gameoflife.py b/wasp/apps/gameoflife.py index 080c214..80c5528 100644 --- a/wasp/apps/gameoflife.py +++ b/wasp/apps/gameoflife.py @@ -118,11 +118,11 @@ def game_of_life(b, xmax: int, ymax: int, nb): icon = ( b'\x02' b'`@' - b'?\xff\xff\xee@\xd7B\x02B\x02B?\x16L?\x15' + b'?\xff\xff\xee@\xf8B\x02B\x02B?\x16L?\x15' b'L?\x16B\x02B\x02B?\x1bB?\x1eD?\x1d' - b'D?\x1eB?\x17\x80\xbe\x82\x02\x82\x06\x82\x02\x82?' + b'D?\x1eB?\x17\x80\xee\x82\x02\x82\x06\x82\x02\x82?' b'\x0e\x88\x04\x88?\r\x88\x04\x88?\x0e\x82\x02\x82\x06B' - b'\x02\x82?\x03\xc0\x97\xc2\x02\xc2\x02\xc2\x02\xc2\x02\xc2\x02' + b'\x02\x82?\x03\xc0\x89\xc2\x02\xc2\x02\xc2\x02\xc2\x02\xc2\x02' b'\xc2\x02\xc2\x02\xc2\x02\xc2\x02\xc2\x02\xc25\xec4\xec5' b'\xc2\x02\xc2\x02\xc2\x02\xc2\x02\xc2\x02\xc2\x02\xc2\x02\xc2\x02' b'\xc2\x02\xc2\x02\xc2*B\x02B\x12\xc2\x06B\x06\xc2\x12' diff --git a/wasp/draw565.py b/wasp/draw565.py index e7914b8..21b23ed 100644 --- a/wasp/draw565.py +++ b/wasp/draw565.py @@ -35,15 +35,25 @@ def _bitblit(bitbuf, pixels, bgfg: int, count: int): pxp += 1 @micropython.viper -def _expand_rgb(eightbit: int) -> int: - r = eightbit >> 5 - r = (r << 2) | (r >> 1) - g = (eightbit >> 2) & 7 - g *= 9 - b = eightbit & 3 - b *= 10 +def _clut8_rgb565(i: int) -> int: + if i < 216: + rgb565 = (( i % 6) * 0x33) >> 3 + rg = i // 6 + rgb565 += ((rg % 6) * (0x33 << 3)) & 0x07e0 + rgb565 += ((rg // 6) * (0x33 << 8)) & 0xf800 + elif i < 252: + i -= 216 + rgb565 = (0x7f + (( i % 3) * 0x33)) >> 3 + rg = i // 3 + rgb565 += ((0x4c << 3) + ((rg % 4) * (0x33 << 3))) & 0x07e0 + rgb565 += ((0x7f << 8) + ((rg // 4) * (0x33 << 8))) & 0xf800 + else: + i -= 252 + gr6 = (0x2c + (0x10 * i)) >> 2 + gr5 = gr6 >> 1 + rgb565 = (gr5 << 11) + (gr6 << 5) + gr5 - return (r << 11) | (g << 5) | b + return rgb565 @micropython.viper def _fill(mv, color: int, count: int, offset: int): @@ -183,7 +193,7 @@ class Draw565(object): sx *= 2 sy //= 2 - palette = array.array('H', (0, 0xfffe, 0x7bef, 0xffff)) + palette = array.array('H', (0, 0x4a69, 0x7bef, 0xffff)) next_color = 1 rl = 0 buf = memoryview(display.linebuffer)[0:2*sx] @@ -204,7 +214,7 @@ class Draw565(object): if op >= 255: continue else: - palette[next_color] = _expand_rgb(op) + palette[next_color] = _clut8_rgb565(op) if next_color < 3: next_color += 1 else: diff --git a/wasp/icons.py b/wasp/icons.py index 9bfa92a..dec982a 100644 --- a/wasp/icons.py +++ b/wasp/icons.py @@ -21,10 +21,10 @@ bomb = ( app = ( b'\x02' b'`@' - b'\x1e@md