LVGL 8.2 display png image from file system

Important: unclear posts may not receive useful answers.

ints.

Description

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

ESP32nodeMCU

What LVGL version are you using?

LVGL8.2 , arduino framework, platformIO

What do you want to achieve?

I want to display png image from file system

What have you tried so far?

My LCD driver and touch driver are validated so i will focus on my filesystem driver
i have downloaded and installed lv_png.h for gitHub :GitHub - lvgl/lv_lib_png: PNG decoder for LVGL
the sources files are into the src directory of my project

//setting done into lv_conf.h:
#define LV_USE_PNG 1

#define LV_USE_FS 1

#define LV_USE_FS_STDIO 'F'
#define LV_PNG_USE_LV_FILESYSTEM  1

// main file
#include <lvgl.h>

#include <TFT_eSPI.h>

#include"GT911.h"

#include"ui.h"

#include "mbedtls/base64.h"

//#include <SD_MMC.h>

#include <FS.h>

#include <SD.h>

#include "lv_lib_png/lv_png.h"

:

//file system callbacks
 void * SDopen_cb(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode){

    Serial.print("ds sd open");
     Serial.print("path:");
     Serial.println(path);
    File *file = new File(SD.open(path, FILE_READ));
    Serial.println(file->available());
    if (!(*file)) {
        Serial.print("impossible d ouvrir fichier: ");
        Serial.println(path);
        delete file;
        return NULL; // Return NULL on failure
    }
    Serial.print("file size :");
    Serial.println(file->size());
   
    
      file->seek(0);
      return (file);
  
    } 

    //Callback to close a file                  
   static lv_fs_res_t SDclose_cb(lv_fs_drv_t * drv, void * file_p){
   
       Serial.println("dans close");
       
        File *file = (File *)file_p;
        file->close();
        return LV_FS_RES_OK;
    } 
     //Callback to read a file           
  static lv_fs_res_t SDread_cb(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br){
  
    File *file = (File *)file_p;
    
   static uint32_t file_pos = 0; // Static variable to keep track of the file position
       *br = file->read((uint8_t *)buf, btr);
 
    return LV_FS_RES_OK;
  }              
    //Callback to seek in a file (Move cursor) 
  static lv_fs_res_t SDseek_cb(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence){

      Serial.println("dans seek");
       //File  *file = *reinterpret_cast<File **>(file_p);
       File *file = (File *)file_p;
    uint32_t new_pos;

    switch (whence) {
        case LV_FS_SEEK_SET:
            new_pos = pos;
            break;
        case LV_FS_SEEK_CUR:
            new_pos = file->position() + pos;
            break;
        case LV_FS_SEEK_END:
            new_pos = file->size() - pos;
            break;
        default:
            return LV_FS_RES_INV_PARAM;
    }

    // Seek to the new position
    if (!file->seek(new_pos)) {
        return LV_FS_RES_UNKNOWN;
    }
    
    return LV_FS_RES_OK;
    }  
    // callback to write a file
 
 lv_fs_res_t SDtell_cb(lv_fs_drv_t *drv, void *file_p, uint32_t *pos_p) {
    (void)drv; /*Unused*/
     Serial.println("SDtell_cb");
    File *file = (File *)file_p;
    *pos_p = file->position();
    return LV_FS_RES_OK;
}

bool SDready_cb(lv_fs_drv_t *drv){
  return true;
}


//filesystem initialization ,declaration...
    lv_png_init(); `
   _lv_fs_init();
    static lv_fs_drv_t fs_drv;                   /*Needs to be static or global*/
    lv_fs_drv_init(&fs_drv);                     /*Basic initialization*/

    fs_drv.letter = 'F';                         /*An uppercase letter to identify the drive */
    //fs_drv.cache_size = my_cache_size_fs;           /*Cache size for reading in bytes. 0 to not cache.*/
    fs_drv.cache_size = 0;
    fs_drv.ready_cb=SDready_cb;
    fs_drv.open_cb = SDopen_cb;                 /*Callback to open a file */
    fs_drv.close_cb = SDclose_cb;               /*Callback to close a file */
    fs_drv.read_cb = SDread_cb;                 /*Callback to read a file */
    fs_drv.seek_cb = SDseek_cb;                 /*Callback to seek in a file (Move cursor) */
    fs_drv.tell_cb = SDtell_cb;                 /*Callback to tell the cursor position  */
    lv_fs_drv_register(&fs_drv);
    

//UI configuration:
screenMain = lv_obj_create(NULL);
  //lv_group_t *group1 = lv_group_create();
  //lv_group_add_obj(group1, lv_scr_act());
  //lv_indev_set_group(indev1, group1);

  label = lv_label_create(screenMain);
  lv_label_set_text(label, "test sdcard");
  lv_obj_set_size(label, 240, 40);
  lv_obj_set_pos(label, 0, 15);

 
 
  img=lv_img_create(screenMain);
  lv_obj_set_width(img, 214);
  lv_obj_set_height(img, 184);
  lv_obj_set_pos(img, 32, 100);
  lv_img_cache_invalidate_src(NULL);
  lv_img_set_src(img,"F:/photo.png");
 
  btn1 = lv_btn_create(screenMain);
  lv_obj_add_event_cb(btn1, event_handler_btn,LV_EVENT_ALL,NULL);
  lv_obj_set_width(btn1, 200);
  lv_obj_set_height(btn1, 32);
  lv_obj_set_pos(btn1, 100, 320);
  lv_obj_t * label1 = lv_label_create(btn1);
  lv_label_set_text(label1, "load image");




  lv_scr_load(screenMain);



void loop()
{
    lv_timer_handler(); /* let the GUI do its work */
    //delay(1);
}

LVGL return :
error 78: failed to open file for reading`, but if i use a .bin file as source for image LVGL is able to open the file and display it to the screen.
This error code seems to be not from by openfile callback.
Please help me

Code to reproduce

Add a code snippet which can run in the simulator. It should contain only the relevant code that compiles without errors when separated from your main code base.

The code block(s) should be formatted like:

/*You code here*/

Screenshot and/or video

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

Can you please format the code more clearly, so that it’s readable?
Is your SDopen_cb function getting called? Is it printing anything?

Hi,
Thanks for your feedback.
I have tried to format the code for a better understanding.
Yes my SDopen_cb is getting called.
First the generic function fom lv_fs.c is called,(lv_fs_res_t lv_fs_open(lv_fs_file_t * file_p, const char * path, lv_fs_mode_t mode) and the SDopen_cb is called from this point.
i have some doubt about how to include and use lv_png.h in my project, in LVGL8.2 (porting for esp32,arduino framework) there is lv_png.h,lv_png.c,lodepng.h,lodepng.c into te followed repository:
.pio\libdeps\esp32dev\lvgl\src\extra\libs\png
Maybe i should i not use the lv_png library from github

In general, you should include lvgl.h, then call obvously lv_init() and lv_png_init() then this code

img=lv_img_create(screenMain);
  lv_obj_set_width(img, 214);
  lv_obj_set_height(img, 184);
  lv_obj_set_pos(img, 32, 100);
  lv_img_cache_invalidate_src(NULL);
  lv_img_set_src(img,"F:/photo.png");

should work, so there’s no need for this #include "lv_lib_png/lv_png.h"
Also, do not forget, to use the lvgl png decoder you need to enable it in your lv_conf.h, as explained in the linked docs.

I have enabled lvgl png decoder and file system by these lines (lv_conf.h) :

`#define LV_USE_PNG 1`
#define LV_USE_FS 1
#define LV_USE_FS_STDIO 'F'
#define LV_PNG_USE_LV_FILESYSTEM  1

but if i try to use lodepng_decode_file into my code , my compiler doesnt recognize the function.
error message: identifier “lodepng_decode_file” is undefined.
Does I have to generate a static library from lodepng.c and ls_png.c ??

Why do you want to use lodepng_decode_file? Is the lv_img_set_src not enough to display it?

I confirm that :
with the updated of # included I dont have error 78 cannot open file
with this code :
img=lv_img_create(screenMain);
lv_obj_set_width(img, 214);
lv_obj_set_height(img, 184);
lv_obj_set_pos(img, 32, 100);
lv_img_cache_invalidate_src(NULL);
lv_img_set_src(img,“F:/photo.bin”);

i can display the image ( image is binary file from lvgl image converter)

with this one :
lv_img_set_src(img,“F:/photo.png”);

image is not displaying ( image is png format image, RGB32)

In my application, png image are send via mobile app and stocked into sd card , so i need a way to display png image from sdcard

I understand, you want to display images from file system - but at least as far as I’m aware to do so it should be enough to use

lv_png_init();
lv_obj_t * img;
img = lv_img_create(lv_scr_act());
lv_img_set_src(img, "F:/img.png");

so I don’t understand why do you feel the need to use the png lib directly, as it’s already incorporated in lvgl. What is the error you get while trying to use the png file? ‘cannot open’?

the png image is not display

Img wigdet display “no data message”.
i have no error message , i know my callbacks file system are called , but the png image is not display

The only thing that comes to my mind is do you have LV_IMG_CACHE_DEF_SIZE in lv_conf.h set to at least 1? If this doesn’t help, then I’m out of ideas, sorry :frowning:

thank you for you help , do you define an other variable for the LV_IMG_CACHE , like a buffer or something like that?

it s a issue due to memory available.
lv_img_set_src(img,“F:/photo2.png”) log when try to call default pngdecoder:

[Info]  (2.223, +58)     lv_mem_alloc: couldn't allocate memory (24676 bytes)   (in lv_mem.c line #140)
[Info]  (2.224, +1)      lv_mem_alloc: used:  30596 ( 94 %), frag:   0 %, biggest free:   2172  (in lv_mem.c line #146)
[Warn]  (2.232, +8)      decoder_open: error 83: memory allocation failed
        (in lv_png.c line #160)

I will change memory partition and share resulst and new memory setting here, if there are revelant.
thanks

Is it the issue with the memory partition of the file system or do you just not have enough RAM then? Just asking out of curiosity :wink:

I have the same problem with the pngs showing No data, were you able to find a solution that you can share? Greetings

hi,
I will give you feedback during the day

1 Like

I appreciate any help, to stop reading the message “No data”, thanks