Image from SD card without proper FS driver

Description

In some cases I am using LVGL on platforms that have preety basic fs support and do not implement fseek and ftell. But lvgl needs ftell and fseek acording to docs. Can i read it with my code and just pass readed buffer to lv_img_set_src?

What MCU/Processor/Board and compiler are you using?

I am using lvgl as a bootloader GUI. Bootloader is based on little kernel

What LVGL version are you using?

latest mastert

What do you want to achieve?

Displaying image with this partitialy working driver.

What have you tried so far?

unsigned char *buf;
    filehandle *entry_file_handle = NULL;
    fs_mount("/boot", "ext2", "mmc1p1");
    off_t entry_file_size = fs_get_file_size("/boot/test");
    buf = malloc(entry_file_size + 1);
    fs_open_file("/boot/test", &entry_file_handle);
    fs_read_file(entry_file_handle, buf, 0, entry_file_size);
    fs_close_file(entry_file_handle);
    list_btn = lv_list_add_btn(list1,  buf, "\nExtras\n");

Code to reproduce

Screenshot and/or video

If possible, add screenshots and/or videos about the current state.

It is possible to construct an image descriptor (which contains a header plus the data size and pointer) in memory and then use lv_img_set_src(obj, img_dsc); to display it. I’ve used it to the download an image over HTTP and display that in LVGL.

If you store the image as a .BIN file using the Image Converter then the first 4 bytes of the image will already contain the image header and the remainder is the pixel data. If you use another file-type you need to construct a header and point it to a pixel data buffer.

e.g. if image.bin contains:

[ header ]      +         [ pixel data ]
^lv_img_header_t struct   ^filesize - sizeof(lv_img_header_t)

In memory you need an img_dsc which is a struct that consists of 3 fields:

    lv_img_header_t header;    // read sizeof(lv_img_header_t) from the file
    uint32_t data_size;        // filesize - sizeof(lv_img_header_t)
    const uint8_t * data;      // pointer to a buffer with the rest of the file

The general flow (untested and without error checking) would be something like this:

    filehandle *entry_file_handle = NULL;
    fs_mount("/boot", "ext2", "mmc1p1");

    off_t entry_file_size = fs_get_file_size("/boot/test");
    off_t header_len      = sizeof(lv_img_header_t);          // file header struct
    off_t buf_len         = entry_file_size - header_len;     // file size minus header size
    
    lv_img_dsc_t* img_dsc = malloc(sizeof(lv_img_dsc_t));     // image descriptor struct
    unsigned char *buf    = malloc(buf_len);                  // pixel data only

    fs_open_file("/boot/test", &entry_file_handle);
    fs_read_file(entry_file_handle, img_dsc, 0, header_len);  // read header struct (first 4 bytes)
    fs_read_file(entry_file_handle, buf , 0, buf_len);        // read pixel data (remainder)
    fs_close_file(entry_file_handle);

    // img_dsc->header should already be fine. Print its contents to make sure...
    img_dsc->data      = buf;
    img_dsc->data_size = buf_len;

    lv_img_set_src(obj, img_dsc);

Now, if the image were to be a .PNG file then the buffer would contain the whole file and you would set the header fields manually:

    img_dsc->header.cf          = LV_IMG_CF_RAW_ALPHA;
    img_dsc->header.always_zero = 0;
    img_dsc->header.reserved    = 0;
    img_dsc->header.w           = buf[19] + (buf[18] << 8);  // extract image dimensions from the data
    img_dsc->header.h           = buf[23] + (buf[22] << 8);
    img_dsc->data               = buf;
    img_dsc->data_size          = entry_file_size;

Thanks, will try and report result.