|
| 1 | +# |
| 2 | +# Important: |
| 3 | +# This is a JS specific version of imagetools.py |
| 4 | +# without native emitter since JS port doesnt support |
| 5 | +# "native" and "viper" decorators. |
| 6 | +# Other ports should use the imagetools.py from /lib |
| 7 | +# |
| 8 | +# |
| 9 | +# Library of functions for image manipulation. |
| 10 | +# Can be used with lodepng to decode PNG images: |
| 11 | +# |
| 12 | +# from imagetools import get_png_info, open_png |
| 13 | +# decoder = lv.img.decoder_create() |
| 14 | +# decoder.info_cb = get_png_info |
| 15 | +# decoder.open_cb = open_png |
| 16 | +# |
| 17 | + |
| 18 | +import lvgl as lv |
| 19 | +import lodepng as png |
| 20 | +import struct |
| 21 | + |
| 22 | +COLOR_SIZE = lv.color_t.__SIZE__ |
| 23 | +COLOR_IS_SWAPPED = hasattr(lv.color_t().ch,'green_h') |
| 24 | + |
| 25 | +class lodepng_error(RuntimeError): |
| 26 | + def __init__(self, err): |
| 27 | + if type(err) is int: |
| 28 | + super().__init__(png.error_text(err)) |
| 29 | + else: |
| 30 | + super().__init__(err) |
| 31 | + |
| 32 | +# Parse PNG file header |
| 33 | +# Taken from https://github.com/shibukawa/i
10000
magesize_py/blob/ffef30c1a4715c5acf90e8945ceb77f4a2ed2d45/imagesize.py#L63-L85 |
| 34 | + |
| 35 | +def get_png_info(decoder, src, header): |
| 36 | + # Only handle variable image types |
| 37 | + |
| 38 | + if lv.img.src_get_type(src) != lv.img.SRC.VARIABLE: |
| 39 | + return lv.RES.INV |
| 40 | + |
| 41 | + png_header = bytes(lv.img_dsc_t.__cast__(src).data.__dereference__(24)) |
| 42 | + |
| 43 | + if png_header.startswith(b'\211PNG\r\n\032\n'): |
| 44 | + if png_header[12:16] == b'IHDR': |
| 45 | + start = 16 |
| 46 | + # Maybe this is for an older PNG version. |
| 47 | + else: |
| 48 | + start = 8 |
| 49 | + try: |
| 50 | + width, height = struct.unpack(">LL", png_header[start:start+8]) |
| 51 | + except struct.error: |
| 52 | + return lv.RES.INV |
| 53 | + else: |
| 54 | + return lv.RES.INV |
| 55 | + |
| 56 | + header.always_zero = 0 |
| 57 | + header.w = width |
| 58 | + header.h = height |
| 59 | + header.cf = lv.img.CF.TRUE_COLOR_ALPHA |
| 60 | + |
| 61 | + return lv.RES.OK |
| 62 | + |
| 63 | +def convert_rgba8888_to_bgra8888(img_view): |
| 64 | + for i in range(0, len(img_view), lv.color_t.__SIZE__): |
| 65 | + ch = lv.color_t.__cast__(img_view[i:i]).ch |
| 66 | + ch.red, ch.blue = ch.blue, ch.red |
| 67 | + |
| 68 | +# Read and parse PNG file |
| 69 | + |
| 70 | +def open_png(decoder, dsc): |
| 71 | + img_dsc = lv.img_dsc_t.__cast__(dsc.src) |
| 72 | + png_data = img_dsc.data |
| 73 | + png_size = img_dsc.data_size |
| 74 | + png_decoded = png.C_Pointer() |
| 75 | + png_width = png.C_Pointer() |
| 76 | + png_height = png.C_Pointer() |
883F
| 77 | + error = png.decode32(png_decoded, png_width, png_height, png_data, png_size); |
| 78 | + if error: |
| 79 | + raise lodepng_error(error) |
| 80 | + img_size = png_width.int_val * png_height.int_val * 4 |
| 81 | + img_data = png_decoded.ptr_val |
| 82 | + img_view = img_data.__dereference__(img_size) |
| 83 | + |
| 84 | + if COLOR_SIZE == 4: |
| 85 | + convert_rgba8888_to_bgra8888(img_view) |
| 86 | + else: |
| 87 | + raise lodepng_error("Error: Color mode not supported yet!") |
| 88 | + |
| 89 | + dsc.img_data = img_data |
| 90 | + return lv.RES.OK |
| 91 | + |
0 commit comments