How to load PNG file from sd card to lv_img's object?

Description

By this article https://blog.littlevgl.com/2018-10-05/png_converter.

I can decode sd’s png file to png_decoded data by lodepng_decode_file() ,
but when set src to lv_img’s obj, the result that shown on the TFT seems a mistake.
How to fix the issue?

(The code as the following part.)

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

  • ESP32
  • lvgl 6.0.2

What do you want to achieve?

Wish to display sd’ png_file correctly.

What have you tried so far?

Code to reproduce

  const char*     png_filename = "/sd/images/08.PNG";  // this png file is PNG_RGBA8 type
  static uint8_t* png_decoded;
  uint32_t        png_width, png_height; 
  LodePNG_format  png_format=PNG_BADFORMAT;

  uint8_t error = lodepng_decode_file(&png_decoded, &png_width, &png_height, &png_format, png_filename ); 
  if(error)  {
    Serial.println(lodepng_error_text(error));
    return;
  }

  Serial.printf("PNG : %s ; wxh : %dx%d ; format : %d\n", png_filename, png_width, png_height, png_format);

  static lv_img_dsc_t png_dsc;
  png_dsc.header.always_zero  = 0;                          /*It must be zero*/
  png_dsc.header.cf           = LV_IMG_CF_TRUE_COLOR_ALPHA;      /*Set the color format*/
  png_dsc.header.w            = png_width;
  png_dsc.header.h            = png_height;
  png_dsc.data_size           = png_width * png_height * 4;
  png_dsc.data                = png_decoded;

  lv_obj_t * img_obj = lv_img_create(lv_scr_act(), NULL);     /*Create the an image object in LittlevGL*/
  lv_img_set_src(img_obj, &png_dsc); 

The result on serial monitor :

PNG : /sd/images/08.PNG ; wxh : 320x240 ; format : 3

( format 3 is PNG_RGBA8 )

Screenshot and/or video

The result on TFT’s screen.

PHOTO_20190927_124143

Hi,

I’ve update the mentioned blog post.
See this section

It’s much easier to just png_decoder_init() and use the pass the filename to lv_img_set_src().

1 Like

Already can display png file ,
however the color of any picture is strange from original file.

Screenshot

image

CODE

  lv_obj_t * img_obj = lv_img_create(lv_scr_act(), NULL); 
  lv_img_set_src(img_obj, "/sd/images/04.png");

Take a look at convert_color_depth() in png_decoder.c. Probable Red and Blue needs to be swapped.

2 Likes

OK, done by swapping between red and blue.

Another question,
If the png file is RGB-888 type (not RGBA-8888 type) ,
in the function decoder_info() , I must set

from

header->cf = LV_IMG_CF_RAW_ALPHA;

to

header->cf = LV_IMG_CF_RAW;

And in function convert_color_depth() , must impliment

from

img[i*3 + 2] = img_argb[i].ch.alpha;
img[i*3 + 1] = c.full >> 8;
img[i*3 + 0] = c.full & 0xFF;

to

img[i*2 + 1] = c.full >> 8;
img[i*2 + 0] = c.full & 0xFF;

Isn’t it ?

I didn’t try it but it seems correct.

1 Like

When I set image to lv_img’s obj like this

lv_obj_t * img_obj = lv_img_create(lv_scr_act(), NULL); 
lv_img_set_src(img_obj, "/sd/images/04.png");

If the other time, I want to change the img_obj to another png_file again ,
by calling lv_img_set_src() like this,

lv_img_set_src(img_obj, "/sd/images/05.png");

Or some situations , I want to delete img_obj by lv_obj_del()

The question is ,
does the lv_img’s obj automatically free previous allocated png_decoded data?
If not, how to free previous allocated png_decoded data?

Thank you.

If LV_IMG_CACHE_DEF_SIZE 1 then only 1 image will be kept opened.
Learn more here: https://docs.littlevgl.com/en/html/overview/image.html#image-caching

1 Like

And how about when img_obj is deleted bylv_obj_del() ?
does the img_obj automatically free previous allocated png_decoded data?

On deleting the image remains open. It’s because the same image source can be used by multiple image objects.
You can clean the cache manually on delete.

1 Like

Thank you very much.

You’re welcome!

1 Like

Do you know how to load JPG file from SD card?

I have the same problem,could you help me?