Possible issues when using indexed binary images

Hi all,

I am currently playing around with loading images with LVGL, and due to low ram and the fact I am currently using a very simple image I thought I would try to use indexed binary images from the online lvgl image converter.

As a base point, I am using the lvgl 7 micropython bindings on an esp32 using an ili9341 display (as well as another display with a driver based on the one from the ili9341).

When creating the indexed images I used both standard pngs, as well as indexed ones using GIMP as suggested below on the page.

All of the indexed images (2, 4, 16, color as 256 would not fit in the ram) showed on offset, increasing with decreasing size

Origional image:
WFace

2 colour binary image from a standard png

4 colour binary image from a standard png

Additionally, when creating the binary from an indexed png the colours are wrong:

Here is the code used to load the images

scr = lv.obj()

with open('/images/standard/WFace_2bit.bin') as f:
  img_data = f.read()

img_dsc = lv.img_dsc_t(
    {
        "header": {"always_zero": 0, "w": 240, "h": 240, "cf": lv.img.CF.INDEXED_2BIT},
        "data_size": len(img_data),
        "data": img_data,
    }
)

bg = lv.img(scr)
bg.set_src(img_dsc)

lv.scr_load(scr)

Has anyone else had similar issues to this?

** Edit

having done a bit more testing it seems that the amount of pixels the image is offset by is a factor of two in all cases:

  • The 1 bit image had an offset of 32 pixels
  • The 2 bit image had an offset of 16 pixels
  • The 4 bit image had an offset of 8 pixels

The binary format contains a header of 4 bytes. Basically, it’s an img_dsc_t data. So if you want to use the binary format you can do 2 things:

  1. Use LVGL’s file system interface and pass the path to the bin file directly to bg.set_src()
  2. Do it as you did, but skip the first 4 bytes.

Thank you for the reply, and very sorry for the delay I appear to have missed your response

Regarding option one, I have tried doing this but the screen just shows as white. I remember seeing an issue in micropython in reading files directly in set_src but I am not sure where I saw that.

Option 2 does seem to have worked though which I am very grateful for. Is this process listed anywhere?

The only issue I am having with that option is that it appears to be limiting the size of an image I am able to use. This seems to be because when setting the image data to ignore the first 4 bytes it causes a second variable to be created, taking up a lot of space. I have tried adjusting the image by doing either:

img_dsc = lv.img_dsc_t(
    {
        "header": {"always_zero": 0, "w": 240, "h": 240, "cf": lv.img.CF.INDEXED_2BIT},
        "data_size": len(img_data) - 4,
        "data": img_data[4:],
    }
)

or

img_data = img_data[4:]

It’s a little bit complex and there are many places for issues :smiley:

I believe @amirgon can show a magical casting operation that solves it :slight_smile:

Dear Kisvegabor:
If I want to use android and IOS to convert a file to a lvgl image bin file…How do I put the data in the first 4 bytes? the first 2 bytes are the pointer which I can put empty…and the second 2 bytes I need put the size of the image?

Thanks

The first 4 bytes are a lv_img_dsc_t struct byte-by-byte.

Dear Kisvegabor:
Obviously the size of lv_img_dsc_t is over 4 bytes… there are header and data_size???ple help to address it

I’m sorry, I meant lv_img_header_t. So only the info from the header needs to included in the bin file.

Thanks a lot …