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