I would like to apply the snapshot feature https://blog.littlevgl.com/2019-04-25/snapshots
but the lv_arduino flush function does not have same parameters
void my_lv_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
and when I call
lv_obj_invalidate(lv_scr_act());
lv_refr_now(lv_disp_get_default());
It calls several time my_lv_disp_flush
where I put
if(bSnapshot)Serial.printf("%d %d %d %d\n", area->x1,area->x2,area->y1,area->y2);
so I get
09:19:48.422 -> 0 479 0 9
09:19:48.559 -> 0 479 10 19
09:19:48.698 -> 0 479 20 29
09:19:48.868 -> 0 479 30 39
09:19:48.969 -> 0 479 40 49
09:19:49.071 -> 0 479 50 59
09:19:49.207 -> 0 479 60 69
09:19:49.309 -> 0 479 70 79
09:19:49.412 -> 0 479 80 89
09:19:49.515 -> 0 479 90 99
09:19:49.581 -> 0 479 100 109
09:19:49.682 -> 0 479 110 119
09:19:49.785 -> 0 479 120 129
09:19:49.922 -> 0 479 130 139
09:19:50.024 -> 0 479 140 149
09:19:50.127 -> 0 479 150 159
09:19:50.230 -> 0 479 160 169
09:19:50.300 -> 0 479 170 179
09:19:50.404 -> 0 479 180 189
09:19:50.507 -> 0 479 190 199
09:19:50.644 -> 0 479 200 209
09:19:50.746 -> 0 479 210 219
09:19:50.850 -> 0 479 220 229
09:19:50.916 -> 0 479 230 239
09:19:51.019 -> 0 479 240 249
09:19:51.123 -> 0 479 250 259
09:19:51.226 -> 0 479 260 269
09:19:51.363 -> 0 479 270 279
09:19:51.468 -> 0 479 280 289
09:19:51.538 -> 0 479 290 299
09:19:51.708 -> 0 479 300 309
09:19:51.845 -> 0 479 310 319
so I cannot parse all screen at once like https://blog.littlevgl.com/2019-04-25/snapshots suggest
Do I miss something ?
Thank you
Edit I add the flush function FYR
/* Display flushing */
void esp_lv_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
uint16_t c;
if(bSnapshot)Serial.printf("%d %d %d %d\n", area->x1,area->x2,area->y1,area->y2);
tft.startWrite(); /* Start new TFT transaction */
tft.setAddrWindow(area->x1, area->y1, (area->x2 - area->x1 + 1), (area->y2 - area->y1 + 1)); /* set the working window */
for (int y = area->y1; y <= area->y2; y++) {
for (int x = area->x1; x <= area->x2; x++) {
c = color_p->full;
tft.writeColor(c, 1);
if(bSnapshot) {
//write pixel to file
fsSnapFile.write((const uint8_t *)&c, sizeof(uint16_t));
}
color_p++;
}
}
tft.endWrite(); /* terminate TFT transaction */
lv_disp_flush_ready(disp); /* tell lvgl that flushing is done */
}
I got it, the screen parsing is done 10 lines by 10 lines so several call are actually the y parsing all x, 10 lines by 10 lines
my screen is LV_COLOR_DEPTH 16, with LV_COLOR_16_SWAP set to 0
at the end I get 300K file but I am not sure I save the pixel information properly for raw fomat
but I guess not as conversion give me error
luc@luc-VirtualBox:~$ convert -size 480x320 -depth 16 rgba:snapshot.bin snap.bmp
convert-im6.q16: unexpected end-of-file `snapshot.bin': No such file or directory @ error/rgb.c/ReadRGBImage/239.
same with original command
luc@luc-VirtualBox:~$ convert -size 480x320 -depth 8 rgba:snapshot.bin snap.bmp
convert-im6.q16: unexpected end-of-file `snapshot.bin': No such file or directory @ error/rgb.c/ReadRGBImage/239.
snap.bmp is unreadable
any advice would be great, I am not familiar with image manipulation
It’s not guaranteed to be 10 lines (that depends on the size of your display buffer) but yes, the whole screen usually isn’t sent at once. Also, we can end up updating less lines (if we were redrawing a small object, for instance).
Yes I should read more before asking 
after reading code I end up to :
if(bSnapshot) {
fsSnapFile.write((const uint8_t)((color_p->ch.red)*8) );
fsSnapFile.write((const uint8_t)((color_p->ch.green)*4));
fsSnapFile.write((const uint8_t)((color_p->ch.blue)*8));
fsSnapFile.write(0xFF);
}
which do same as uint32_t lv_color_to32(lv_color_t color)
but I get error if I try to use it with *color_p
and I can get the snap

I am sure there is better way to do, sorry for my newbie questions
What error do you get? Did you put lv_color_to32(*color_p)
(asterisk is important) or lv_color_to32(color_p)
(incorrect).
yes this is what I have tried:
lv_color32_t data = (lv_color32_t) lv_color_to32(*color_p);
and I get
error: no matching function for call to 'lv_color32_t::lv_color32_t(uint32_t)'
lv_color32_t data = (lv_color32_t) lv_color_to32(*color_p);
^
In file included from C:\Users\user\Documents\Arduino\libraries\lv_arduino-2.0.3\src/src/lv_hal/lv_hal_disp.h:21:0,
from C:\Users\user\Documents\Arduino\libraries\lv_arduino-2.0.3\src/src/lv_hal/lv_hal.h:16,
from C:\Users\user\Documents\Arduino\libraries\lv_arduino-2.0.3\src/lvgl.h:24,
from C:\Users\user\AppData\Local\Temp\arduino_build_952187\sketch\src\modules\display\advanceddisplay.cpp:28:
c:\users\user\documents\arduino\libraries\lv_arduino-2.0.3\src\src\lv_misc\lv_color.h:144:3: note: candidate: lv_color32_t::lv_color32_t()
} lv_color32_t;
^
c:\users\user\documents\arduino\libraries\lv_arduino-2.0.3\src\src\lv_misc\lv_color.h:144:3: note: candidate expects 0 arguments, 1 provided
c:\users\user\documents\arduino\libraries\lv_arduino-2.0.3\src\src\lv_misc\lv_color.h:144:3: note: candidate: constexpr lv_color32_t::lv_color32_t(const lv_color32_t&)
c:\users\user\documents\arduino\libraries\lv_arduino-2.0.3\src\src\lv_misc\lv_color.h:144:3: note: no known conversion for argument 1 from 'uint32_t {aka unsigned int}' to 'const lv_color32_t&'
c:\users\user\documents\arduino\libraries\lv_arduino-2.0.3\src\src\lv_misc\lv_color.h:144:3: note: candidate: constexpr lv_color32_t::lv_color32_t(lv_color32_t&&)
c:\users\user\documents\arduino\libraries\lv_arduino-2.0.3\src\src\lv_misc\lv_color.h:144:3: note: no known conversion for argument 1 from 'uint32_t {aka unsigned int}' to 'lv_color32_t&&'
which is weird according
#elif LV_COLOR_DEPTH == 16
typedef uint16_t lv_color_int_t;
typedef lv_color16_t lv_color_t;
Or I misunderstand the code
I don’t think you should use lv_color32_t
in this case. You should use uint32_t
. The lv_color_to
functions convert a LittlevGL color structure to a standard RGB value accepted by most other libraries.
uint32_t data = lv_color_to32(*color_p);
Ok according your suggestion I changed to :
if(bSnapshot) {
uint32_t data = lv_color_to32(*color_p);
fsSnapFile.write((const uint8_t *)(&data), sizeof(uint32_t));
}
but :
C:\ImageMagick\ImageMagick-7.0.8-Q16>magick.exe -size 480x320 -depth 8 rgba:snapshot.bin snap.bmp
give me

so I changed the order in command line:
C:\ImageMagick\ImageMagick-7.0.8-Q16>magick.exe -size 480x320 -depth 8 bgra:snapshot.bin snap.bmp
and now I get back the correct colors

So to sum up the global solution :
//Global variables
static File fsSnapFile;
static bool bSnapshot;
//Snap function
bool snapshot()
{
fsSnapFile = SPIFFS.open("/snapshot.bin", "w");
if (!fsSnapFile) {
return false;
}
bSnapshot = true;
lv_obj_invalidate(lv_scr_act());
lv_refr_now(lv_disp_get_default()); /* Will call our disp_drv.disp_flush function */
bSnapshot = false;
fsSnapFile.close();
return true;
}
/* Display flushing procedure*/
void esp_lv_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
uint16_t c;
tft_screen.startWrite(); /* Start new TFT transaction */
tft_screen.setAddrWindow(area->x1, area->y1, (area->x2 - area->x1 + 1), (area->y2 - area->y1 + 1)); /* set the working window */
for (int y = area->y1; y <= area->y2; y++) {
for (int x = area->x1; x <= area->x2; x++) {
c = color_p->full;
tft_screen.writeColor(c, 1);
if(bSnapshot) {
uint32_t data = lv_color_to32(*color_p);
fsSnapFile.write((const uint8_t *)(&data), sizeof(uint32_t));
}
color_p++;
}
}
tft.endWrite(); /* terminate TFT transaction */
lv_disp_flush_ready(disp); /* tell lvgl that flushing is done */
}
then for conversion (magick.exe is the Windows equivalent in ImageMagick for convert due to some name conflict)
C:\ImageMagick\ImageMagick-7.0.8-Q16>magick.exe -size 480x320 -depth 8 bgra:snapshot.bin snap.bmp
Thank you for your advices 
Glad to hear that you made it work!
I’ve marked your last post as solution.
1 Like
Thank you - sorry I missed this forum feature, I will remember next time