100ask
August 28, 2023, 7:04am
1
Video: https://youtu.be/zR_niKRp0sI
Introduction
lv_100ask_screenshot is a screenshot tool based on LVGL.
lv_100ask_screenshot features:
Save LVGL screen objects (full screen) as image files: lv_scr_act(),layer_sys(),layer_top()
Capture and save the specified LVGL object and its children as an image file
Supported save as: BMP, PNG, JPG
more todo…
lv_100ask_screenshot
is very simple to use, and the subsequent custom expansion functions are also very convenient, so stay tuned for more functions.
Usage
Refer to the example in lv_lib_100ask/test/lv_100ask_screenshot_test .
Get lv_100ask_screenshot
Try lv_100ask_screenshot
You can try lv_100ask_screenshot functionality through these two files, please feel free to use them.
The path for saving images is “D:/” and cannot be modified:
2 Likes
Very nice! I’m sure it will be useful for many people!
100ask
August 29, 2023, 1:48am
3
Thank you! I hope so too!
Hey, this looks generally useful, but after quickly trying out I’d prefer to be able to get a single actual screenshot of full display output for an actual real screenshot, is there a simple way of doing this without hooking flush_cb? As snapshot only seems to be able to get a layer at a time, but I want all visible layers in capture.
100ask
April 23, 2024, 2:30am
5
Hi
lv_100ask_screenshot based on snapshot .
If you want to obtain all the screenshots, the best way I can think of at the moment is to process them in flush_cb.
I actually now made a small modified copy of snapshot functions that takes a display object and renders scr/top/sys layers to do the job for now, this appears at a quick test to get me the result I wanted whilst allowing rendering in RGB8888 despite using 16bit RGB output.
100ask
April 23, 2024, 6:15am
7
Sounds great! Looking forward to your sharing of code and upgrading snapshot .
Sure, it’s pretty much just a quick hack, and I didn’t check if the output size is necessarily correct, as it worked as expected in my situation:
lv_result_t lv_screenshot_take_to_draw_buf(lv_display_t * disp, lv_color_format_t cf, lv_draw_buf_t * draw_buf)
{
LV_ASSERT_NULL(disp);
LV_ASSERT_NULL(draw_buf);
lv_result_t res;
switch(cf) {
case LV_COLOR_FORMAT_RGB565:
case LV_COLOR_FORMAT_RGB888:
case LV_COLOR_FORMAT_XRGB8888:
case LV_COLOR_FORMAT_ARGB8888:
break;
default:
LV_LOG_WARN("Not supported color format");
return LV_RESULT_INVALID;
}
res = lv_snapshot_reshape_draw_buf(disp->act_scr, draw_buf);
if(res != LV_RESULT_OK) return res;
/* clear draw buffer*/
lv_draw_buf_clear(draw_buf, NULL);
lv_area_t snapshot_area;
int32_t w = draw_buf->header.w;
int32_t h = draw_buf->header.h;
int32_t ext_size = _lv_obj_get_ext_draw_size(disp->act_scr);
lv_obj_get_coords(disp->act_scr, &snapshot_area);
lv_area_increase(&snapshot_area, ext_size, ext_size);
lv_layer_t layer;
lv_memzero(&layer, sizeof(layer));
layer.draw_buf = draw_buf;
layer.buf_area.x1 = snapshot_area.x1;
layer.buf_area.y1 = snapshot_area.y1;
layer.buf_area.x2 = snapshot_area.x1 + w - 1;
layer.buf_area.y2 = snapshot_area.y1 + h - 1;
layer.color_format = cf;
layer._clip_area = snapshot_area;
lv_display_t * disp_old = _lv_refr_get_disp_refreshing();
lv_display_t * disp_new = disp;//lv_obj_get_display(obj);
lv_layer_t * layer_old = disp_new->layer_head;
disp_new->layer_head = &layer;
_lv_refr_set_disp_refreshing(disp_new);
lv_obj_redraw(&layer, disp_new->bottom_layer);
lv_obj_redraw(&layer, disp_new->act_scr);
lv_obj_redraw(&layer, disp_new->top_layer);
lv_obj_redraw(&layer, disp_new->sys_layer);
while(layer.draw_task_head) {
lv_draw_dispatch_wait_for_request();
lv_draw_dispatch_layer(NULL, &layer);
}
disp_new->layer_head = layer_old;
_lv_refr_set_disp_refreshing(disp_old);
return LV_RESULT_OK;
}
lv_draw_buf_t * lv_screenshot_take(lv_display_t * disp, lv_color_format_t cf)
{
LV_ASSERT_NULL(disp);
lv_draw_buf_t * draw_buf = lv_snapshot_create_draw_buf(disp->act_scr, cf);
if(draw_buf == NULL) return NULL;
if(lv_screenshot_take_to_draw_buf(disp, cf, draw_buf) != LV_RESULT_OK) {
lv_draw_buf_destroy(draw_buf);
return NULL;
}
return draw_buf;
}
1 Like
Can be ported to embedded systems?
I have STM32H757 that supports LvGL and SD-Card.
Embedded RAM scarce systems will definitely be a challenge due to it allocating a full frame buffer to capture into, I think they such would have to be captured via a flush_cb hook with a hook to write out partial frame writes out to sd card.
My board has enough ram to store the entire buffer (externally).