mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-10 04:37:55 +08:00
chore(image_converter): add AL88 color format support (#9453)
Signed-off-by: Neo Xu <neo.xu1990@gmail.com>
This commit is contained in:
+47
-2
@@ -117,6 +117,7 @@ class ColorFormat(Enum):
|
||||
A2 = 0x0C
|
||||
A4 = 0x0D
|
||||
A8 = 0x0E
|
||||
AL88 = 0x15
|
||||
ARGB8888 = 0x10
|
||||
XRGB8888 = 0x11
|
||||
RGB565 = 0x12
|
||||
@@ -141,6 +142,7 @@ class ColorFormat(Enum):
|
||||
ColorFormat.A2: 2,
|
||||
ColorFormat.A4: 4,
|
||||
ColorFormat.A8: 8,
|
||||
ColorFormat.AL88: 16,
|
||||
ColorFormat.ARGB8888: 32,
|
||||
ColorFormat.XRGB8888: 32,
|
||||
ColorFormat.RGB565: 16,
|
||||
@@ -182,6 +184,7 @@ class ColorFormat(Enum):
|
||||
@property
|
||||
def has_alpha(self) -> bool:
|
||||
return self.is_alpha_only or self.is_indexed or self in (
|
||||
ColorFormat.AL88,
|
||||
ColorFormat.ARGB8888,
|
||||
ColorFormat.XRGB8888, # const alpha: 0xff
|
||||
ColorFormat.ARGB8565,
|
||||
@@ -276,7 +279,14 @@ def unpack_colors(data: bytes, cf: ColorFormat, w) -> List:
|
||||
ret.append(bit_extend((p >> 11) & 0x1f, 5)) # R
|
||||
ret.append(bit_extend((p >> 5) & 0x3f, 6)) # G
|
||||
ret.append(bit_extend((p >> 0) & 0x1f, 5)) # B
|
||||
|
||||
elif cf == ColorFormat.AL88:
|
||||
# AL88: low 8bit = Luminance, high 8bit = Alpha
|
||||
L = data[0::2] # low byte: luminance
|
||||
A = data[1::2] # high byte: alpha
|
||||
for luma, alpha in zip(L, A):
|
||||
ret.append(luma) # L
|
||||
ret.append(alpha) # A
|
||||
|
||||
elif bpp == 24:
|
||||
if cf == ColorFormat.RGB888:
|
||||
B = data[0::3]
|
||||
@@ -854,6 +864,14 @@ class LVGLImage:
|
||||
greyscale=True,
|
||||
alpha=False)
|
||||
data = self.data
|
||||
elif self.cf == ColorFormat.AL88:
|
||||
# to grayscale with alpha
|
||||
encoder = png.Writer(self.w,
|
||||
self.h,
|
||||
bitdepth=8,
|
||||
greyscale=True,
|
||||
alpha=True)
|
||||
data = unpack_colors(self.data, self.cf, self.w)
|
||||
elif self.cf.is_colormap:
|
||||
encoder = png.Writer(self.w,
|
||||
self.h,
|
||||
@@ -897,6 +915,8 @@ class LVGLImage:
|
||||
self._png_to_indexed(cf, filename)
|
||||
elif cf.is_alpha_only:
|
||||
self._png_to_alpha_only(cf, filename)
|
||||
elif cf == ColorFormat.AL88:
|
||||
self._png_to_al88(cf, filename)
|
||||
elif cf.is_luma_only:
|
||||
self._png_to_luma_only(cf, filename)
|
||||
elif cf.is_colormap:
|
||||
@@ -993,6 +1013,31 @@ class LVGLImage:
|
||||
return 12.92 * y
|
||||
return 1.055 * pow(y, 1 / 2.4) - 0.055
|
||||
|
||||
def _png_to_al88(self, cf: ColorFormat, filename: str):
|
||||
reader = png.Reader(str(filename))
|
||||
w, h, rows, info = reader.asRGBA8()
|
||||
if not info['alpha']:
|
||||
raise FormatError(f"{filename} has no alpha channel")
|
||||
|
||||
rawdata = bytearray()
|
||||
for row in 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):
|
||||
# Calculate luminance using ITU-R BT.709 coefficients
|
||||
r_linear = self.sRGB_to_linear(r / 255.0)
|
||||
g_linear = self.sRGB_to_linear(g / 255.0)
|
||||
b_linear = self.sRGB_to_linear(b / 255.0)
|
||||
luma = 0.2126 * r_linear + 0.7152 * g_linear + 0.0722 * b_linear
|
||||
luma_byte = int(self.linear_to_sRGB(luma) * 255)
|
||||
# AL88: low byte = luminance, high byte = alpha
|
||||
rawdata += uint8_t(luma_byte) # L
|
||||
rawdata += uint8_t(a) # A
|
||||
|
||||
self.set_data(ColorFormat.AL88, w, h, rawdata)
|
||||
|
||||
def _png_to_luma_only(self, cf: ColorFormat, filename: str):
|
||||
reader = png.Reader(str(filename))
|
||||
w, h, rows, info = reader.asRGBA8()
|
||||
@@ -1389,7 +1434,7 @@ def main():
|
||||
"choose from I1/2/4/8"),
|
||||
default="I8",
|
||||
choices=[
|
||||
"L8", "I1", "I2", "I4", "I8", "A1", "A2", "A4", "A8", "ARGB8888",
|
||||
"L8", "I1", "I2", "I4", "I8", "A1", "A2", "A4", "A8", "AL88", "ARGB8888",
|
||||
"XRGB8888", "RGB565", "RGB565_SWAPPED", "RGB565A8", "ARGB8565", "RGB888", "AUTO",
|
||||
"RAW", "RAW_ALPHA", "ARGB8888_PREMULTIPLIED"
|
||||
])
|
||||
|
||||
Reference in New Issue
Block a user