feat(scripts/LVGLImage.py): adds RGB565 dithering support (#7582)

This commit is contained in:
Kevin Schlosser
2025-01-20 15:31:38 -07:00
committed by GitHub
parent 7f0dfc6e3f
commit 2cdcf8d729

View File

@@ -497,6 +497,7 @@ class LVGLImage:
data: bytes = b'') -> None:
self.stride = 0 # default no valid stride value
self.premultiplied = False
self.rgb565_dither = False
self.set_data(cf, w, h, data)
def __repr__(self) -> str:
@@ -838,13 +839,15 @@ class LVGLImage:
def from_png(self,
filename: str,
cf: ColorFormat = None,
background: int = 0x00_00_00):
background: int = 0x00_00_00,
rgb565_dither=False):
"""
Create lvgl image from png file.
If cf is none, used I1/2/4/8 based on palette size
"""
self.background = background
self.rgb565_dither = rgb565_dither
if cf is None: # guess cf from filename
# split filename string and match with ColorFormat to check
@@ -996,6 +999,7 @@ class LVGLImage:
color |= (g >> 2) << 5
color |= (b >> 3) << 0
return uint16_t(color)
elif cf == ColorFormat.RGB565A8:
def pack(r, g, b, a):
@@ -1017,14 +1021,25 @@ class LVGLImage:
w, h, rows, _ = reader.asRGBA8()
rawdata = bytearray()
alpha = bytearray()
for row in rows:
for y, row in enumerate(rows):
R = row[0::4]
G = row[1::4]
B = row[2::4]
A = row[3::4]
for r, g, b, a in zip(R, G, B, A):
for x, (r, g, b, a) in enumerate(zip(R, G, B, A)):
if cf == ColorFormat.RGB565A8:
alpha += uint8_t(a)
if (
self.rgb565_dither and
cf in (ColorFormat.RGB565, ColorFormat.RGB565A8, ColorFormat.ARGB8565)
):
treshold_id = ((y & 7) << 3) + (x & 7)
r = min(r + red_thresh[treshold_id], 0xFF) & 0xF8
g = min(g + green_thresh[treshold_id], 0xFF) & 0xFC
b = min(b + blue_thresh[treshold_id], 0xFF) & 0xF8
rawdata += pack(r, g, b, a)
if cf == ColorFormat.RGB565A8:
@@ -1033,6 +1048,40 @@ class LVGLImage:
self.set_data(cf, w, h, rawdata)
red_thresh = [
1, 7, 3, 5, 0, 8, 2, 6,
7, 1, 5, 3, 8, 0, 6, 2,
3, 5, 0, 8, 2, 6, 1, 7,
5, 3, 8, 0, 6, 2, 7, 1,
0, 8, 2, 6, 1, 7, 3, 5,
8, 0, 6, 2, 7, 1, 5, 3,
2, 6, 1, 7, 3, 5, 0, 8,
6, 2, 7, 1, 5, 3, 8, 0
]
green_thresh = [
1, 3, 2, 2, 3, 1, 2, 2,
2, 2, 0, 4, 2, 2, 4, 0,
3, 1, 2, 2, 1, 3, 2, 2,
2, 2, 4, 0, 2, 2, 0, 4,
1, 3, 2, 2, 3, 1, 2, 2,
2, 2, 0, 4, 2, 2, 4, 0,
3, 1, 2, 2, 1, 3, 2, 2,
2, 2, 4, 0, 2, 2, 0, 4
]
blue_thresh = [
5, 3, 8, 0, 6, 2, 7, 1,
3, 5, 0, 8, 2, 6, 1, 7,
8, 0, 6, 2, 7, 1, 5, 3,
0, 8, 2, 6, 1, 7, 3, 5,
6, 2, 7, 1, 5, 3, 8, 0,
2, 6, 1, 7, 3, 5, 0, 8,
7, 1, 5, 3, 8, 0, 6, 2,
1, 7, 3, 5, 0, 8, 2, 6
]
class RLEHeader:
def __init__(self, blksize: int, len: int):
@@ -1212,7 +1261,8 @@ class PNGConverter:
align: int = 1,
premultiply: bool = False,
compress: CompressMethod = CompressMethod.NONE,
keep_folder=True) -> None:
keep_folder=True,
rgb565_dither=False) -> None:
self.files = files
self.cf = cf
self.ofmt = ofmt
@@ -1223,6 +1273,7 @@ class PNGConverter:
self.premultiply = premultiply
self.compress = compress
self.background = background
self.rgb565_dither = rgb565_dither
def _replace_ext(self, input, ext):
if self.keep_folder:
@@ -1241,8 +1292,9 @@ class PNGConverter:
img = RAWImage().from_file(f, self.cf)
img.to_c_array(self._replace_ext(f, ".c"))
else:
img = LVGLImage().from_png(f, self.cf, background=self.background)
img = LVGLImage().from_png(f, self.cf, background=self.background, rgb565_dither=self.rgb565_dither)
img.adjust_stride(align=self.align)
if self.premultiply:
img.premultiply()
output.append((f, img))
@@ -1275,6 +1327,9 @@ def main():
"RAW", "RAW_ALPHA"
])
parser.add_argument('--rgb565dither', action='store_true',
help="use dithering to correct banding in gradients", default=False)
parser.add_argument('--premultiply', action='store_true',
help="pre-multiply color with alpha", default=False)
@@ -1334,7 +1389,8 @@ def main():
align=args.align,
premultiply=args.premultiply,
compress=compress,
keep_folder=False)
keep_folder=False,
rgb565_dither=args.rgb565dither)
output = converter.convert()
for f, img in output:
logging.info(f"len: {img.data_len} for {path.basename(f)} ")
@@ -1347,7 +1403,8 @@ def test():
f = "pngs/cogwheel.RGB565A8.png"
img = LVGLImage().from_png(f,
cf=ColorFormat.ARGB8565,
background=0xFF_FF_00)
background=0xFF_FF_00,
rgb565_dither=True)
img.adjust_stride(align=16)
img.premultiply()
img.to_bin("output/cogwheel.ARGB8565.bin")