How to display image?Example1 and example2 got some error

Hi,
When try example with m5stack based on eso32 I got some error.

example1:
My code:

with open('img/blue_flower_32.bin','rb') as f:
  img_data = f.read()

# Pixel format: Fix 0xFF: 8 bit, Red: 8 bit, Green: 8 bit, Blue: 8 bit

# Create a screen with a draggable image

scr = lv.obj()
img = lv.img(scr)
img.align(scr, lv.ALIGN.CENTER, 0, 0)
img_dsc = lv.img_dsc_t(
    {
        "header": {"always_zero": 0, "w": 100, "h": 75, "cf": lv.img.CF.TRUE_COLOR},
        "data_size": len(img_data),
        "data": img_data,
    }
)

img.set_src(img_dsc)
img.set_drag(False)

# Load the screen and display image

lv.scr_load(scr)

The result:

example2
my code:

def get_png_info(decoder, src, header):
    # Only handle variable image types

    if lv.img.src_get_type(src) != lv.img.SRC.VARIABLE:
        return lv.RES.INV

    png_header = bytes(lv.img_dsc_t.cast(src).data.__dereference__(24))

    if png_header.startswith(b'\211PNG\r\n\032\n') and png_header[12:16] == b'IHDR':
        try:
            width, height = struct.unpack(">LL", png_header[16:24])
        except struct.error:
            return lv.RES.INV
    
    # Maybe this is for an older PNG version.
    
    elif png_header.startswith(b'\211PNG\r\n\032\n'):
        # Check to see if we have the right content type
        try:
            width, height = struct.unpack(">LL", png_header[8:16])
        except struct.error:
            return lv.RES.INV
    else:
        return lv.RES.INV

    header.always_zero = 0
    header.w = width
    header.h = height
    header.cf = lv.img.CF.TRUE_COLOR_ALPHA

    # print("width=%d, height=%d" % (header.w, header.h))

    return lv.RES.OK


# Read and parse PNG file

def open_png(decoder, dsc):
    img_dsc = lv.img_dsc_t.cast(dsc.src)
    png_data = img_dsc.data
    png_size = img_dsc.data_size
    png_decoded = png.C_Pointer()
    png_width = png.C_Pointer()
    png_height = png.C_Pointer()
    error = png.decode32(png_decoded, png_width, png_height, png_data, png_size);
    if error:
        return None # LV_IMG_DECODER_OPEN_FAIL
    img_size = png_width.int_val * png_height.int_val * lv.color_t.SIZE
    img_data = png_decoded.ptr_val

    # Convert png RGBA-big-endian format to lvgl ARGB-little-endian
    # Eventually - this means swapping red and blue.
    # More info on https://forumtest.littlevgl.com/t/png-decoding-why-red-and-blue-are-swapped/72

    img_view = img_data.__dereference__(img_size)
    for i in range(0, img_size, lv.color_t.SIZE):
        ch = lv.color_t.cast(img_view[i:i]).ch
        ch.red, ch.blue = ch.blue, ch.red

    dsc.img_data = img_data
    return lv.RES.OK

# Register new image decoder

decoder = lv.img.decoder_create()
decoder.info_cb = get_png_info
decoder.open_cb = open_png

# Create a screen with a draggable image

with open('img/png_decoder_test.png','rb') as f:
  png_data = f.read()

png_img_dsc = lv.img_dsc_t({
    'data_size': len(png_data),
    'data': png_data 
})

scr = lv.obj()

# Create an image on the left using the decoder

lv.img.cache_set_size(2)
img1 = lv.img(scr)
img1.align(scr, lv.ALIGN.IN_LEFT_MID, -50, 0)
img1.set_src(png_img_dsc)
img1.set_drag(True)

# Create an image on the right directly without the decoder

img2 = lv.img(scr)
img2.align(scr, lv.ALIGN.IN_RIGHT_MID, 0, 0)
raw_dsc = lv.img_dsc_t()
get_png_info(None, png_img_dsc, raw_dsc.header)
dsc = lv.img_decoder_dsc_t({'src': png_img_dsc})
if open_png(None, dsc) == lv.RES.OK:
    raw_dsc.data = dsc.img_data
    raw_dsc.data_size = raw_dsc.header.w * raw_dsc.header.h * lv.color_t.SIZE
    img2.set_src(raw_dsc)
    img2.set_drag(True)

# Load the screen and display image

lv.scr_load(scr)

The result:

  • lv.img.cache_set_size(2)
    TypeError: argument has wrong type

  • get_png_info
    TypeError: argument has wrong type

I check the C code:

/*
 * lvgl extension definition for:
 * void lv_img_cache_set_size(uint16_t new_slot_num)
 */
 
STATIC mp_obj_t mp_lv_img_cache_set_size(size_t mp_n_args, const mp_obj_t *mp_args)
{
    uint16_t new_slot_num = (uint16_t)mp_obj_get_int(mp_args[0]);
    lv_img_cache_set_size(new_slot_num);
    return mp_const_none;
}

STATIC MP_DEFINE_CONST_LV_FUN_OBJ_VAR(mp_lv_img_cache_set_size_obj, 1, mp_lv_img_cache_set_size, lv_img_cache_set_size);

It looks like this is correct, but why is it wrong?

Share some pictures~




Both examples work well on the online simulator:

But both examples are assuming 32bit color format, which is incompatible with ili9341 of the m5stack.

There is a better way - using the imagetools library.
The advantages are:

  • Takes care of PNG header and data decoding in several color formats
  • Fast - it uses the viper code emitter for processing the image data.

Here is a usage example: