Snapshot
Snapshot provides API to take snapshot image for LVGL object together with its children. The image will look exactly like the object on display.
Usage
Simply call API lv_snapshot_take()
to generate the image descriptor
which can be set as image object src using lv_image_set_src()
.
Note, only following color formats are supported for now: - LV_COLOR_FORMAT_RGB565 - LV_COLOR_FORMAT_RGB888 - LV_COLOR_FORMAT_XRGB8888 - LV_COLOR_FORMAT_ARGB8888
Free the Image
The memory lv_snapshot_take()
uses are dynamically allocated using
lv_malloc()
. Use API lv_snapshot_free()
to free the memory it
takes. This will firstly free memory the image data takes, then the
image descriptor.
Take caution to free the snapshot but not delete the image object. Before free the memory, be sure to firstly unlink it from image object, using lv_image_set_src(NULL) and lv_cache_invalidate(lv_cache_find(src, LV_CACHE_SRC_TYPE_PTR, 0, 0));.
Below code snippet explains usage of this API.
void update_snapshot(lv_obj_t * obj, lv_obj_t * img_snapshot)
{
lv_image_dsc_t* snapshot = (void*)lv_image_get_src(img_snapshot);
if(snapshot) {
lv_snapshot_free(snapshot);
}
snapshot = lv_snapshot_take(obj, LV_COLOR_FORMAT_ARGB8888);
lv_image_set_src(img_snapshot, snapshot);
}
Use Existing Buffer
If the snapshot needs update now and then, or simply caller provides memory, use API
lv_result_t lv_snapshot_take_to_buf(lv_obj_t * obj, lv_color_format_t cf, lv_image_dsc_t * dsc, void * buf, uint32_t buff_size);
for this case. It's caller's responsibility to alloc/free the memory.
If snapshot is generated successfully, the image descriptor is updated
and image data will be stored to provided buf
.
Note that snapshot may fail if provided buffer is not enough, which may
happen when object size changes. It's recommended to use API
lv_snapshot_buf_size_needed()
to check the needed buffer size in byte
firstly and resize the buffer accordingly.
Example
Simple snapshot example
C code
View on GitHub#include "../../lv_examples.h"
#if LV_USE_SNAPSHOT && LV_BUILD_EXAMPLES
static void event_cb(lv_event_t * e)
{
lv_obj_t * snapshot_obj = lv_event_get_user_data(e);
lv_obj_t * img = lv_event_get_target(e);
if(snapshot_obj) {
lv_image_dsc_t * snapshot = (void *)lv_image_get_src(snapshot_obj);
if(snapshot) {
lv_snapshot_free(snapshot);
}
/*Update the snapshot, we know parent of object is the container.*/
snapshot = lv_snapshot_take(img->parent, LV_COLOR_FORMAT_ARGB8888);
if(snapshot == NULL)
return;
lv_image_set_src(snapshot_obj, snapshot);
}
}
void lv_example_snapshot_1(void)
{
LV_IMAGE_DECLARE(img_star);
lv_obj_t * root = lv_screen_active();
lv_obj_set_style_bg_color(root, lv_palette_main(LV_PALETTE_LIGHT_BLUE), 0);
/*Create an image object to show snapshot*/
lv_obj_t * snapshot_obj = lv_image_create(root);
lv_obj_set_style_bg_color(snapshot_obj, lv_palette_main(LV_PALETTE_PURPLE), 0);
lv_obj_set_style_bg_opa(snapshot_obj, LV_OPA_100, 0);
lv_image_set_zoom(snapshot_obj, 128);
lv_image_set_rotation(snapshot_obj, 300);
/*Create the container and its children*/
lv_obj_t * container = lv_obj_create(root);
lv_obj_center(container);
lv_obj_set_size(container, 180, 180);
lv_obj_set_flex_flow(container, LV_FLEX_FLOW_ROW_WRAP);
lv_obj_set_flex_align(container, LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_set_style_radius(container, 50, 0);
lv_obj_t * img;
int i;
for(i = 0; i < 4; i++) {
img = lv_image_create(container);
lv_image_set_src(img, &img_star);
lv_obj_set_style_bg_color(img, lv_color_black(), 0);
lv_obj_set_style_bg_opa(img, LV_OPA_COVER, 0);
// lv_obj_set_style_transform_scale(img, 400, LV_STATE_PRESSED);
lv_obj_add_flag(img, LV_OBJ_FLAG_CLICKABLE);
lv_obj_add_event(img, event_cb, LV_EVENT_PRESSED, snapshot_obj);
lv_obj_add_event(img, event_cb, LV_EVENT_RELEASED, snapshot_obj);
}
}
#endif
import gc
import lvgl as lv
# Measure memory usage
gc.enable()
gc.collect()
mem_free = gc.mem_free()
label = lv.label(lv.screen_active())
label.align(lv.ALIGN.BOTTOM_MID, 0, -10)
label.set_text(" memory free:" + str(mem_free/1024) + " kB")
# Create an image from the png file
try:
with open('../../assets/img_star.png','rb') as f:
png_data = f.read()
except:
print("Could not find star.png")
sys.exit()
image_star = lv.image_dsc_t({
'data_size': len(png_data),
'data': png_data
})
def event_cb(e, snapshot_obj):
image = e.get_target_obj()
if snapshot_obj:
# no need to free the old source for snapshot_obj, gc will free it for us.
# take a new snapshot, overwrite the old one
dsc = lv.snapshot_take(image.get_parent(), lv.COLOR_FORMAT.NATIVE_ALPHA)
snapshot_obj.set_src(dsc)
gc.collect()
mem_used = mem_free - gc.mem_free()
label.set_text("memory used:" + str(mem_used/1024) + " kB")
root = lv.screen_active()
root.set_style_bg_color(lv.palette_main(lv.PALETTE.LIGHT_BLUE), 0)
# Create an image object to show snapshot
snapshot_obj = lv.image(root)
snapshot_obj.set_style_bg_color(lv.palette_main(lv.PALETTE.PURPLE), 0)
snapshot_obj.set_style_bg_opa(lv.OPA.COVER, 0)
snapshot_obj.set_scale(128)
# Create the container and its children
container = lv.obj(root)
container.align(lv.ALIGN.CENTER, 0, 0)
container.set_size(180, 180)
container.set_flex_flow(lv.FLEX_FLOW.ROW_WRAP)
container.set_flex_align(lv.FLEX_ALIGN.SPACE_EVENLY, lv.FLEX_ALIGN.CENTER, lv.FLEX_ALIGN.CENTER)
container.set_style_radius(50, 0)
for i in range(4):
image = lv.image(container)
image.set_src(image_star)
image.set_style_bg_color(lv.palette_main(lv.PALETTE.GREY), 0)
image.set_style_bg_opa(lv.OPA.COVER, 0)
image.set_style_transform_scale(400, lv.STATE.PRESSED)
image.add_flag(image.FLAG.CLICKABLE)
image.add_event(lambda e: event_cb(e, snapshot_obj), lv.EVENT.PRESSED, None)
image.add_event(lambda e: event_cb(e, snapshot_obj), lv.EVENT.RELEASED, None)