diff --git a/pycardium/modules/py/png.py b/pycardium/modules/py/png.py index 63fa2e1a75b31227358855349e9f1ed944ad8010..a5c460690f867a11266b69886777cb3aac2d2343 100644 --- a/pycardium/modules/py/png.py +++ b/pycardium/modules/py/png.py @@ -1,6 +1,11 @@ import sys_png import color +RGB8 = 0 +RGBA8 = 1 +RGB565 = 2 +RGBA5551 = 3 + def decode(png_data, format="RGB", bg=color.BLACK): """ @@ -8,17 +13,17 @@ def decode(png_data, format="RGB", bg=color.BLACK): :param str format: The intended output format: - - ``RGB``: 24 bit RGB. - - ``RGBA``: 24 bit RGB + 8 bit alpha. - - ``565``: 16 bit RGB. This consumes 1 byte less RAM per pixel than ``RGB``. - - ``565A``: 16 bit RGB + 8 bit alpha. + - ``png.RGB8``: 24 bit RGB. + - ``png.RGBA8``: 24 bit RGB + 8 bit alpha. + - ``png.RGB565``: 16 bit RGB. This consumes 1 byte less RAM per pixel than ``png.RGB8``. + - ``png.RGBA5551``: 15 bit RGB + 1 bit alpha. - Default is ``RGB``. + Default is ``png.RGB8``. :param Color bg: Background color. If the PNG contains an alpha channel but no alpha - channel is requested in the output (``RGB`` or ``565``) + channel is requested in the output (``png.RGB8`` or ``png.RGB565``) this color will be used as the background color. Default is ``Color.BLACK``. @@ -27,7 +32,7 @@ def decode(png_data, format="RGB", bg=color.BLACK): .. versionadded:: 1.17 - **Example with RGB data:** + **Example with RGBA8 data:** .. code-block:: python @@ -36,15 +41,15 @@ def decode(png_data, format="RGB", bg=color.BLACK): # Draw a PNG file to the display f = open("example.png") - w, h, img = png.decode(f.read()) + w, h, img = png.decode(f.read(), png.RGBA8) f.close() with display.open() as d: d.clear() - d.blit(0, 0, w, h, img) + d.blit(0, 0, w, h, img, display.RGBA8) d.update() - **Example with rgb565 data:** + **Example with RGB565 data:** .. code-block:: python @@ -53,24 +58,24 @@ def decode(png_data, format="RGB", bg=color.BLACK): # Draw a PNG file to the display f = open("example.png") - w, h, img = png.decode(f.read(), "565") + w, h, img = png.decode(f.read(), png.RGB565) f.close() with display.open() as d: d.clear() - d.blit(0, 0, w, h, img, True) + d.blit(0, 0, w, h, img, True, display.RGB565) d.update() """ - formats = ("RGB", "RGBA", "565", "565A") + formats = (RGB8, RGBA8, RGB565, RGBA5551) if format not in formats: - raise ValueError("Supported formats: " + ",".join(formats)) + raise ValueError("Output format not supported") - if format == "RGB": - return sys_png.decode(png_data, 0, 0, bg) - if format == "RGBA": - return sys_png.decode(png_data, 0, 1, bg) - if format == "565": + if format == RGB8: return sys_png.decode(png_data, 1, 0, bg) - if format == "565A": + if format == RGBA8: return sys_png.decode(png_data, 1, 1, bg) + if format == RGB565: + return sys_png.decode(png_data, 0, 0, bg) + if format == RGBA5551: + return sys_png.decode(png_data, 0, 1, bg) diff --git a/pycardium/modules/sys_png.c b/pycardium/modules/sys_png.c index 78c819f496b89058da7a287276927286b8f58d00..c6dded0987e0ec6103b4a43caf30d94c9ce844e0 100644 --- a/pycardium/modules/sys_png.c +++ b/pycardium/modules/sys_png.c @@ -36,7 +36,18 @@ static void lode_raise(unsigned int status) } } -static inline uint16_t rgb888_to_rgb565(uint8_t *bytes) +static inline uint16_t rgba8_to_rgba5551(uint8_t *bytes) +{ + uint16_t c = ((bytes[0] & 0b11111000) << 8) | + ((bytes[1] & 0b11111000) << 3) | + ((bytes[2] & 0b11111000) >> 2); + if (bytes[3] > 127) { + c |= 1; + } + return c; +} + +static inline uint16_t rgb8_to_rgb565(uint8_t *bytes) { return ((bytes[0] & 0b11111000) << 8) | ((bytes[1] & 0b11111100) << 3) | (bytes[2] >> 3); @@ -63,10 +74,10 @@ static mp_obj_t mp_png_decode(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t png_info; - mp_obj_t png = args[0]; - mp_obj_t rgb565_out = args[1]; - mp_obj_t alpha_out = args[2]; - mp_obj_t bg = args[3]; + mp_obj_t png = args[0]; + mp_obj_t rgb8_out = args[1]; + mp_obj_t alpha_out = args[2]; + mp_obj_t bg = args[3]; /* Load buffer and ensure it contains enough data */ if (!mp_get_buffer(png, &png_info, MP_BUFFER_READ)) { @@ -128,23 +139,22 @@ static mp_obj_t mp_png_decode(size_t n_args, const mp_obj_t *args) raw_len = w * h * 3; } - if (mp_obj_is_true(rgb565_out)) { + if (!mp_obj_is_true(rgb8_out)) { if (mp_obj_is_true(alpha_out)) { - for (i = 0, j = 0; i < raw_len; i += 4, j += 3) { - uint16_t c = rgb888_to_rgb565(&raw[i]); + for (i = 0, j = 0; i < raw_len; i += 4, j += 2) { + uint16_t c = rgba8_to_rgba5551(&raw[i]); raw[j] = c & 0xFF; raw[j + 1] = c >> 8; raw[j + 2] = raw[i + 3]; } - raw_len = w * h * 3; } else { for (i = 0, j = 0; i < raw_len; i += 3, j += 2) { - uint16_t c = rgb888_to_rgb565(&raw[i]); + uint16_t c = rgb8_to_rgb565(&raw[i]); raw[j] = c & 0xFF; raw[j + 1] = c >> 8; } - raw_len = w * h * 2; } + raw_len = w * h * 2; } if (raw_len != raw_len_original) {