Snapshot

Snapshot provides API to take snapshot image for LVGL Widget together with its children. The image will look exactly like the Widget on display.

Usage

Simply call API lv_snapshot_take() to generate the image descriptor which can be set as image Widget src using lv_image_set_src().

Note, only following color formats are supported for now:

Free the Image

The memory lv_snapshot_take() uses are dynamically allocated using lv_draw_buf_create(). Use API lv_draw_buf_destroy() to free the memory it takes. This will firstly free memory the image data takes, then the image descriptor.

The snapshot image which is the draw buffer returned by lv_snapshot_take() normally won't be added to cache because it can be drawn directly. So you don't need to invalidate cache by lv_image_cache_drop() before destroy the draw buffer.

Below code snippet explains usage of this API.

void update_snapshot(lv_obj_t * widget, lv_obj_t * img_snapshot)
{
    lv_draw_buf_t* snapshot = (void*)lv_image_get_src(img_snapshot);
    if(snapshot) {
        lv_draw_buf_destroy(snapshot);
    }
    snapshot = lv_snapshot_take(widget, 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_draw_buf(lv_obj_t * widget, lv_color_format_t cf, lv_draw_buf_t * draw_buf); for this case. It's caller's responsibility to create and destroy the draw buffer.

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 Widget size changes. It's recommended to use API lv_snapshot_reshape_draw_buf() to prepare the buffer firstly and if it fails, destroy the existing draw buffer and call lv_snapshot_take directly.

Example

Simple snapshot example

#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_draw_buf_t * snapshot = (lv_draw_buf_t *)lv_image_get_src(snapshot_obj);
        if(snapshot) {
            lv_draw_buf_destroy(snapshot);
        }

        /*Update the snapshot, we know parent of object is the container.*/
        snapshot = lv_snapshot_take(lv_obj_get_parent(img), 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_scale(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_cb(img, event_cb, LV_EVENT_PRESSED, snapshot_obj);
        lv_obj_add_event_cb(img, event_cb, LV_EVENT_RELEASED, snapshot_obj);
    }
}

#endif

API

lv_snapshot.h