Receiving a bytearry and display it as image?

Description

I receive a byte array, which contains the image I want to draw on the screen.
Formaat is a png.

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

ESP32

What LVGL version are you using?

latest

What do you want to achieve?

receive the byte array, and copy this bytearry into a “format” which can handle lvgl, and draws as image
to the screen.

Thanks

If you convert it to RBG you can copy it to an lv_image. The specific format will depend on your display (most likely ARGB for 32 bits or RGB16 for 16 bits).

There may be an utility in the library that do the conversion, like the one done by the online tools.

If you use https://github.com/lvgl/lv_lib_png I think you could do it like this:

lv_img_dsc_t my_png = {
  .header.always_zero = 0,
  .header.w = <image width>,
  .header.h = <image height>,
  .data_size = <your png byte array size>,
  .header.cf = LV_IMG_CF_RAW_ALPHA,
  .data = <your png byte array>,
};
lv_img_set_src(img_obj, &my_png);

/* later */
lv_img_cache_invalidate_src(&my_png); /* to ensure that the new PNG is decoded */

thanks for your suggestion, I think, the image size is dynamic…
But should be doable with your code as well !?
data_size = length of array and data a pointer.

Hmm, something is still missing… maybe some one can give me a hint.

Still on esp32 :slight_smile:

During the setup I load a “normal” image from img_desc struct.

imgNavigation = lv_img_create(parent, NULL);
lv_img_set_src(imgNavigation, &nav_destination);
lv_obj_align(imgNavigation, NULL, LV_ALIGN_IN_TOP_LEFT, 20, 20);

var’s…

uint8_t* nav_destination_src;    // --> pointer for image source
static lv_img_dsc_t nav_dest_png;   // --> struct

fill out during setup, what we know.

  nav_dest_png.header.always_zero = 0;
  nav_dest_png.header.w = 95;
  nav_dest_png.header.h = 95;
  nav_dest_png.header.cf = LV_IMG_CF_RAW_ALPHA;
  nav_dest_png.data_size = 0;
  nav_dest_png.data = nav_destination_src;

this is done when byte array is arrived.
(the minus 6, is end of packages detection)

  nav_destination_src = (uint8_t*)malloc(NaviMsg.length() - 6);
  nav_dest_png.data_size = NaviMsg.length() - 6;
  NaviMsg.getBytes(nav_destination_src, NaviMsg.length() - 6);

  lv_img_set_src(imgNavigation, &nav_dest_png);
  lv_img_cache_invalidate_src(&nav_dest_png);
  lv_obj_align(imgNavigation, NULL, LV_ALIGN_IN_TOP_LEFT, 20, 20);

this is a example from my byte array content

⸮PNG

⸮IDATx⸮⸮⸮⸮k\U⸮⸮⸮S⸮⸮ R⸮oЂ⸮+⸮⸮UhI|⸮⸮⸮⸮/ ⸮⸮⸮]⸮⸮⸮op⸮**W⸮F$`)E⸮⸮@+⸮4⸮⸮⸮⸮J⸮E⸮j⸮⸮⸮⸮h⸮f⸮⸮⸮⸮⸮⸮⸮y⸮w⸮}r⸮N2⸮⸮s⸮9⸮s⸮9⸮uI⸮\⸮⸮cT⸮r0*I7s⸮⸮⸮k⸮2$⸮⸮}⸮,I⸮n⸮⸮⸮⸮⸮⸮⸮oIҌo@B⸮n⸮tV⸮⸮%ݞ⸮⸮MgM⸮Y*⸮⸮⸮-⸮b⸮⸮⸮⸮⸮⸮H⸮y⸮VS⸮[⸮8⸮⸮⸮⸮f⸮;`⸮⸮⸮⸮⸮⸮J:7b⸮=⸮Kz⸮7 ⸮⸮[$⸮3⸮⸮%⸮⸮⸮⸮6<⸮⸮j⸮⸮⸮-⸮X7⸮⸮⸮T|ϲ⸮⸮⸮Hڭp⸮w⸮⸮⸮n⸮⸮ܯuÐ⸮M⸮
T+Q⸮⸮⸮⸮⸮o⸮y@⸮⸮⸮a⸮I⸮T8N⸮j5Ez-h*w⸮S⸮⸮'U_⸮)⸮V8]5⸮s⸮(
⸮⸮⸮]⸮⸮⸮⸮"⸮Qm⸮
⸮⸮G!⸮⸮[⸮z.H⸮ΝM2
⸮⸮;⸮j.I⸮⸮t⸮⸮⸮W$⸮/⸮⸮⸮ujoA⸮,⸮}A3⸮⸮⸮⸮⸮ӿ⸮a⸮-9~x⸮8r⸮	⸮=⸮`⸮e⸮⸮⸮)⸮v⸮iIک⸮{⥒s^⸮y⸮⸮⸮"ד⸮)⸮@⸮$⸮aI⸮⸮[⸮u@⸮sua⸮⸮2⸮E3S⸮f⸮⸮a|⸮1⸮⸮5I{c׌⸮4|I;⸮7⸮⸮SO⸮g⸮Y⸮⸮~^⸮8⸮⸮⸮ʟ⸮⸮⸮⸮⸮G⸮⸮⸮⸮⸮"⸮p*r⸮pϸ⸮'u⸮⸮ȱ⸮⸮⸮Gm5E⸮⸮0
'⸮]⸮⸮⸮AR⸮?a⸮Pr⸮⸮⸮?⸮D1⸮U⸮i⸮X⸮)?⸮⸮⸮'i⸮fv⸮p⸮⸮6d⸮2⸮⸮P⸮?⸮⸮oe|f⸮⸮߁aͬ⸮⸮⸮⸮cf⸮W⸮
⸮⸮⸮V⸮⸮2⸮5⸮⸮⸮}⸮⸮n+?⸮⸮l.u-⸮⸮⸮]⸮S⸮V⸮⸮⸮'%⸮U⸮G⸮⸮⸮⸮?⸮6I'⸮⸮⸮*⸮IW⸮⸮⸮⸮⸮⸮⸮E⸮좤ׁ»⸮	⸮$ph⸮q⸮0<<⸮&⸮nz⸮⸮⸮⸮⸮P⸮⸮U⸮⸮⸮l⸮g
⸮⸮g⸮⸮g⸮⸮g⸮⸮g⸮⸮g⸮⸮g⸮⸮g⸮⸮g⸮⸮g⸮⸮g⸮⸮g⸮⸮g⸮⸮gT⸮⸮⸮⸮t(⸮⸮ẇ⸮Y5⸮$⸮A⸮⸮a⸮⸮ى⸮⸮8⸮\5⸮⸮⸮⸮⸮⸮⸮⸮M]O⸮t⸮⸮̖⸮⸮⸮⸮⸮⸮9?#?#?#?#?#?⸮&5?⸮⸮⸮⸮?⸮⸮b⸮z⸮Ф⸮?<Ybܛ⸮ۉk⸮D⸮¿⸮⸮ĸOSR?jf⸮⸮g⸮⸮g⸮⸮g⸮⸮g⸮⸮gԤ7YW⸮⸮h⸮⸮⸮oq⸮9⸮s⸮9⸮⸮⸮⸮"⸮⸮=w2?

I assume you just get “No data” or something similar displayed on the screen? You will need to initialize the PNG decoder once before displaying the first image - not sure if you are doing that already or not.

Ok, tested a little bit more…

	lv_obj_t * img = lv_img_create(parent, NULL);
	//lv_img_set_src(img, "C:/Users/p-haf/Desktop/maps_png/logo.png");
	nav_dest_png.header.always_zero = 0;
	nav_dest_png.header.w = 95;
	nav_dest_png.header.h = 95;
	nav_dest_png.data_size = sizeof(myByteArray);
	nav_dest_png.header.cf = LV_IMG_CF_RAW_ALPHA;
	nav_dest_png.data = myByteArray;

	lv_img_set_src(img, &nav_dest_png);
	lv_img_cache_invalidate_src(&img);
	lv_obj_align(img, NULL, LV_ALIGN_IN_TOP_MID, 20, 20);

If I doing it in this way (myByteArray, contains byte :slight_smile: ), I got the png drawn.
But to be honest, I thought, the header information and size will come from the inbuild decoder !?

Is there a other way, to extract width, height from raw image ?

Thanks

I believe with the current API you have to supply it the width and height if you are using a byte array. You could try passing 0 for those options but I don’t think it will work.

On windows with VS2019 and simulator it works, now on esp always no data…

What I’m doing for testing on esp…

define my hex-byte array raw png…

const uint8_t myByteArray[] =
{
0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x5F, 0x08, 0x06, 0x00, 0x00, 0x00, 0x8E, 0x4C, 0x1B,

the my init of decoder

  lv_png_init();

then my drawing…

  imgMaps = lv_img_create(screen, NULL);

  nav_dest_png.header.always_zero = 0;
  nav_dest_png.header.w = 95;
  nav_dest_png.header.h = 95;
  nav_dest_png.data_size = sizeof(myByteArray);
  nav_dest_png.header.cf = LV_IMG_CF_RAW_ALPHA;
  nav_dest_png.data = myByteArray;
  
  lv_img_set_src(imgMaps, &nav_dest_png);
  lv_img_cache_invalidate_src(&imgMaps);
  lv_obj_align(imgMaps, NULL, LV_ALIGN_IN_TOP_LEFT, 20, 20);

You only need to invalidate the cache if/when you change the underlying image, and you should call that on the image source (&nav_dest_png) not the image object. If your compiler is configured correctly it should give you a warning/error about that.

Maybe the incorrect cache call is causing problems.

some logs, only the image with source from array… raw png as hex…

Trace: lv_init started 	(lv_obj.c #179 lv_init())
Info: lv_init ready 	(lv_obj.c #237 lv_init())
Trace: Screen create started 	(lv_obj.c #279 lv_obj_create())
Info: Object create ready 	(lv_obj.c #470 lv_obj_create())
Trace: Screen create started 	(lv_obj.c #279 lv_obj_create())
Info: Object create ready 	(lv_obj.c #470 lv_obj_create())
Trace: Screen create started 	(lv_obj.c #279 lv_obj_create())
Info: Object create ready 	(lv_obj.c #470 lv_obj_create())
Trace: container create started 	(lv_cont.c #70 lv_cont_create())
Trace: Screen create started 	(lv_obj.c #279 lv_obj_create())
Info: Object create ready 	(lv_obj.c #470 lv_obj_create())
Info: container created 	(lv_cont.c #118 lv_cont_create())
Info: lv_png_init done 	(lv_png.c #58 lv_png_init())
Trace: image create started 	(lv_img.c #62 lv_img_create())
Trace: Object create started 	(lv_obj.c #311 lv_obj_create())
Info: Object create ready 	(lv_obj.c #470 lv_obj_create())
Info: image created 	(lv_img.c #127 lv_img_create())
Info: lv_img_set_src:  `LV_IMG_SRC_VARIABLE` type found 	(lv_img.c #180 lv_img_set_src())
maps image drawn
Trace: lv_task_handler started 	(lv_task.c #74 lv_task_handler())
Trace: lv_refr_task: started 	(lv_refr.c #177 _lv_disp_refr_task())
Trace: lv_img_design: start to draw image 	(lv_img.c #664 lv_img_design())
Info: image draw: cache miss, cached to an empty entry 	(lv_img_cache.c #122 _lv_img_cache_open())
Info: decoder_open done 	(lv_png.c #141 decoder_open())
Info: decoder_open it's a LV_IMG_SRC_VARIABLE 	(lv_png.c #183 decoder_open())
Warn: Image draw cannot open the image resource 	(lv_img_cache.c #131 _lv_img_cache_open())
Info: decoder_close done 	(lv_png.c #207 decoder_close())
Warn: Image draw error 	(lv_draw_img.c #87 lv_draw_img())
Trace: lv_img_design: start to draw image 	(lv_img.c #664 lv_img_design())
Info: image draw: cache miss, cached to an empty entry 	(lv_img_cache.c #122 _lv_img_cache_open())
Info: decoder_open done 	(lv_png.c #141 decoder_open())
Info: decoder_open it's a LV_IMG_SRC_VARIABLE 	(lv_png.c #183 decoder_open())
Warn: Image draw cannot open the image resource 	(lv_img_cache.c #131 _lv_img_cache_open())
Info: decoder_close done 	(lv_png.c #207 decoder_close())
Warn: Image draw error 	(lv_draw_img.c #87 lv_draw_img())
Trace: lv_img_design: start to draw image 	(lv_img.c #664 lv_img_design())
Info: image draw: cache miss, cached to an empty entry 	(lv_img_cache.c #122 _lv_img_cache_open())
Info: decoder_open done 	(lv_png.c #141 decoder_open())
Info: decoder_open it's a LV_IMG_SRC_VARIABLE 	(lv_png.c #183 decoder_open())
Warn: Image draw cannot open the image resource 	(lv_img_cache.c #131 _lv_img_cache_open())
Info: decoder_close done 	(lv_png.c #207 decoder_close())
Warn: Image draw error 	(lv_draw_img.c #87 lv_draw_img())
Trace: lv_img_design: start to draw image 	(lv_img.c #664 lv_img_design())
Info: image draw: cache miss, cached to an empty entry 	(lv_img_cache.c #122 _lv_img_cache_open())
Info: decoder_open done 	(lv_png.c #141 decoder_open())
Info: decoder_open it's a LV_IMG_SRC_VARIABLE 	(lv_png.c #183 decoder_open())
Warn: Image draw cannot open the image resource 	(lv_img_cache.c #131 _lv_img_cache_open())
Info: decoder_close done 	(lv_png.c #207 decoder_close())
Warn: Image draw error 	(lv_draw_img.c #87 lv_draw_img())
Trace: lv_img_design: start to draw image 	(lv_img.c #664 lv_img_design())
Info: image draw: cache miss, cached to an empty entry 	(lv_img_cache.c #122 _lv_img_cache_open())
Info: decoder_open done 	(lv_png.c #141 decoder_open())
Info: decoder_open it's a LV_IMG_SRC_VARIABLE 	(lv_png.c #183 decoder_open())
Warn: Image draw cannot open the image resource 	(lv_img_cache.c #131 _lv_img_cache_open())
Info: decoder_close done 	(lv_png.c #207 decoder_close())
Warn: Image draw error 	(lv_draw_img.c #87 lv_draw_img())
Trace: lv_img_design: start to draw image 	(lv_img.c #664 lv_img_design())
Info: image draw: cache miss, cached to an empty entry 	(lv_img_cache.c #122 _lv_img_cache_open())
Info: decoder_open done 	(lv_png.c #141 decoder_open())
Info: decoder_open it's a LV_IMG_SRC_VARIABLE 	(lv_png.c #183 decoder_open())
Warn: Image draw cannot open the image resource 	(lv_img_cache.c #131 _lv_img_cache_open())
Info: decoder_close done 	(lv_png.c #207 decoder_close())
Warn: Image draw error 	(lv_draw_img.c #87 lv_draw_img())
Trace: lv_img_design: start to draw image 	(lv_img.c #664 lv_img_design())
Info: image draw: cache miss, cached to an empty entry 	(lv_img_cache.c #122 _lv_img_cache_open())

Try stepping through decoder_open; it looks like it finds the file but then decides it can’t be opened. Maybe there isn’t enough memory available?

Yes, not enough memory was my problem.
Stepping down to png-decoder library…

Any hints, for saving memory ?
I reduced in lv_conf all what I didn’t need…

By the way, is there a setting for label, that can scroll the text content from top to down.
Thanks.

The usual strategy is to delete objects that aren’t visible and create them as needed, however, I assume for testing purposes that the image is the only object currently on your screen.

The PNG decoder is fairly resource-intensive so you may want to look into receiving the bytes as a bitmap instead. How much RAM and what size of image are you working with?

The best solution is probably putting the label on a page.

Is there a decoder around for java (android) ?
Then I can send the png already in the correct format…!
I’m on a esp32 4MB and this is 2MB for APP and 2MB for SPIFFS