1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-28 07:03:00 +08:00

feat(draw_buf): distinguish between lv_image_dsc_t and lv_draw_buf_t (#5496)

Signed-off-by: Xu Xingliang <xuxingliang@xiaomi.com>
Signed-off-by: Neo Xu <neo.xu1990@gmail.com>
This commit is contained in:
Neo Xu 2024-02-18 10:52:50 +08:00 committed by GitHub
parent fa9142ef36
commit bd119043a1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 151 additions and 205 deletions

View File

@ -767,7 +767,7 @@ static void blend_mode_cb(lv_obj_t * parent)
const char * cf_txt[] = {"RGB565", "RGB888.", "XRGB8888", "ARGB8888"};
lv_color_format_t cf_values[] = {LV_COLOR_FORMAT_RGB565, LV_COLOR_FORMAT_RGB888, LV_COLOR_FORMAT_XRGB8888, LV_COLOR_FORMAT_ARGB8888};
uint8_t * cf_bufs[] = {buf_rgb565, buf_rgb888, buf_xrgb8888, buf_argb8888};
static lv_image_dsc_t image_dscs[4];
static lv_draw_buf_t image_dscs[4];
const char * mode_txt[] = {"Add.", "Sub.", "Mul."};
lv_blend_mode_t mode_values[] = {LV_BLEND_MODE_ADDITIVE, LV_BLEND_MODE_SUBTRACTIVE, LV_BLEND_MODE_MULTIPLY};
@ -787,7 +787,7 @@ static void blend_mode_cb(lv_obj_t * parent)
lv_canvas_set_buffer(canvas, cf_bufs[cf], 36, 30, cf_values[cf]);
create_blend_mode_image_buffer(canvas);
lv_img_dsc_t * img_src = lv_canvas_get_image(canvas);
lv_draw_buf_t * img_src = lv_canvas_get_draw_buf(canvas);
image_dscs[cf] = *img_src;
for(m = 0; m < 3; m++) {

1
lvgl.h
View File

@ -109,6 +109,7 @@ extern "C" {
#include "src/layouts/lv_layout.h"
#include "src/draw/lv_draw.h"
#include "src/draw/lv_draw_buf.h"
#include "src/draw/lv_draw_vector.h"
#include "src/themes/lv_theme.h"

View File

@ -172,7 +172,14 @@ lv_result_t lv_draw_buf_init(lv_draw_buf_t * draw_buf, uint32_t w, uint32_t h, l
return LV_RESULT_INVALID;
}
lv_image_header_init(&draw_buf->header, w, h, cf, stride, 0);
lv_image_header_t * header = &draw_buf->header;
header->w = w;
header->h = h;
header->cf = cf;
header->stride = stride;
header->flags = 0;
header->magic = LV_IMAGE_HEADER_MAGIC;
draw_buf->data = lv_draw_buf_align(data, cf);
draw_buf->unaligned_data = data;
draw_buf->data_size = data_size;
@ -272,8 +279,7 @@ void * lv_draw_buf_goto_xy(const lv_draw_buf_t * buf, uint32_t x, uint32_t y)
LV_ASSERT_NULL(buf);
if(buf == NULL) return NULL;
uint8_t * data = buf->data;
data += buf->header.stride * y;
uint8_t * data = buf->data + buf->header.stride * y;
if(x == 0)
return data;
@ -416,6 +422,20 @@ lv_result_t lv_draw_buf_premultiply(lv_draw_buf_t * draw_buf)
return LV_RESULT_OK;
}
void lv_draw_buf_set_palette(lv_draw_buf_t * draw_buf, uint8_t index, lv_color32_t color)
{
LV_ASSERT_NULL(draw_buf);
if(draw_buf == NULL) return;
if(!LV_COLOR_FORMAT_IS_INDEXED(draw_buf->header.cf)) {
LV_LOG_WARN("Not indexed color format");
return;
}
uint8_t * buf = (uint8_t *)draw_buf->data;
lv_memcpy(&buf[index * sizeof(color)], &color, sizeof(color));
}
/**********************
* STATIC FUNCTIONS
**********************/

View File

@ -15,7 +15,8 @@ extern "C" {
*********************/
#include "../misc/lv_area.h"
#include "../misc/lv_color.h"
#include "lv_image_buf.h"
#include "../stdlib/lv_string.h"
#include "lv_image_dsc.h"
/*********************
* DEFINES
@ -193,7 +194,7 @@ lv_draw_buf_t * lv_draw_buf_reshape(lv_draw_buf_t * draw_buf, lv_color_format_t
uint32_t stride);
/**
* Destroy a draw buf by free the actual buffer if it's marked as LV_IMAGE_FLAGS_MODIFIABLE in header.
* Destroy a draw buf by free the actual buffer if it's marked as LV_IMAGE_FLAGS_ALLOCATED in header.
* Then free the lv_draw_buf_t struct.
*/
void lv_draw_buf_destroy(lv_draw_buf_t * buf);
@ -248,7 +249,43 @@ static inline void lv_draw_buf_from_image(lv_draw_buf_t * buf, const lv_image_ds
static inline void lv_draw_buf_to_image(const lv_draw_buf_t * buf, lv_image_dsc_t * img)
{
lv_memcpy(img, buf, sizeof(lv_image_dsc_t));
lv_memcpy((void *)img, buf, sizeof(lv_image_dsc_t));
}
/**
* Set the palette color of an indexed image. Valid only for `LV_COLOR_FORMAT_I1/2/4/8`
* @param draw_buf pointer to an image descriptor
* @param index the palette color to set:
* - for `LV_COLOR_FORMAT_I1`: 0..1
* - for `LV_COLOR_FORMAT_I2`: 0..3
* - for `LV_COLOR_FORMAT_I4`: 0..15
* - for `LV_COLOR_FORMAT_I8`: 0..255
* @param color the color to set in lv_color32_t format
*/
void lv_draw_buf_set_palette(lv_draw_buf_t * draw_buf, uint8_t index, lv_color32_t color);
/**
* @deprecated Use lv_draw_buf_set_palette instead.
*/
static inline void lv_image_buf_set_palette(lv_image_dsc_t * dsc, uint8_t id, lv_color32_t c)
{
LV_LOG_WARN("Deprecated API, use lv_draw_buf_set_palette instead.");
lv_draw_buf_set_palette((lv_draw_buf_t *)dsc, id, c);
}
/**
* @deprecated Use lv_draw_buffer_create/destroy instead.
* Free the data pointer and dsc struct of an image.
*/
static inline void lv_image_buf_free(lv_image_dsc_t * dsc)
{
LV_LOG_WARN("Deprecated API, use lv_draw_buf_destroy instead.");
if(dsc != NULL) {
if(dsc->data != NULL)
lv_free((void *)dsc->data);
lv_free((void *)dsc);
}
}
/**********************

View File

@ -220,6 +220,33 @@ void _lv_draw_image_tiled_helper(lv_draw_unit_t * draw_unit, const lv_draw_image
lv_image_decoder_close(&decoder_dsc);
}
void _lv_image_buf_get_transformed_area(lv_area_t * res, int32_t w, int32_t h, int32_t angle,
uint16_t scale_x, uint16_t scale_y, const lv_point_t * pivot)
{
if(angle == 0 && scale_x == LV_SCALE_NONE && scale_y == LV_SCALE_NONE) {
res->x1 = 0;
res->y1 = 0;
res->x2 = w - 1;
res->y2 = h - 1;
return;
}
lv_point_t p[4] = {
{0, 0},
{w, 0},
{0, h},
{w, h},
};
lv_point_transform(&p[0], angle, scale_x, scale_y, pivot, true);
lv_point_transform(&p[1], angle, scale_x, scale_y, pivot, true);
lv_point_transform(&p[2], angle, scale_x, scale_y, pivot, true);
lv_point_transform(&p[3], angle, scale_x, scale_y, pivot, true);
res->x1 = LV_MIN4(p[0].x, p[1].x, p[2].x, p[3].x);
res->x2 = LV_MAX4(p[0].x, p[1].x, p[2].x, p[3].x) - 1;
res->y1 = LV_MIN4(p[0].y, p[1].y, p[2].y, p[3].y);
res->y2 = LV_MAX4(p[0].y, p[1].y, p[2].y, p[3].y) - 1;
}
/**********************
* STATIC FUNCTIONS
**********************/

View File

@ -15,7 +15,7 @@ extern "C" {
*********************/
#include "lv_draw.h"
#include "lv_image_decoder.h"
#include "lv_image_buf.h"
#include "lv_draw_buf.h"
#include "../misc/lv_style.h"
/*********************
@ -143,6 +143,19 @@ void _lv_draw_image_normal_helper(lv_draw_unit_t * draw_unit, const lv_draw_imag
void _lv_draw_image_tiled_helper(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc,
const lv_area_t * coords, lv_draw_image_core_cb draw_core_cb);
/**
* Get the area of a rectangle if its rotated and scaled
* @param res store the coordinates here
* @param w width of the rectangle to transform
* @param h height of the rectangle to transform
* @param angle angle of rotation
* @param scale_x zoom in x direction, (256 no zoom)
* @param scale_y zoom in y direction, (256 no zoom)
* @param pivot x,y pivot coordinates of rotation
*/
void _lv_image_buf_get_transformed_area(lv_area_t * res, int32_t w, int32_t h, int32_t angle,
uint16_t scale_x, uint16_t scale_y, const lv_point_t * pivot);
#ifdef __cplusplus
} /*extern "C"*/
#endif

View File

@ -1,92 +0,0 @@
/**
* @file lv_image_buf.c
*
*/
/*********************
* INCLUDES
*********************/
#include <stddef.h>
#include <string.h>
#include "lv_image_buf.h"
#include "lv_draw_image.h"
#include "../misc/lv_math.h"
#include "../misc/lv_log.h"
#include "../stdlib/lv_mem.h"
#include "../stdlib/lv_string.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_image_buf_set_palette(lv_image_dsc_t * dsc, uint8_t id, lv_color32_t c)
{
if(dsc->header.cf < LV_COLOR_FORMAT_I1 || dsc->header.cf > LV_COLOR_FORMAT_I8) {
LV_LOG_WARN("Not indexed color format");
return;
}
uint8_t * buf = (uint8_t *)dsc->data;
lv_memcpy(&buf[id * sizeof(c)], &c, sizeof(c));
}
void lv_image_buf_free(lv_image_dsc_t * dsc)
{
if(dsc != NULL) {
if(dsc->data != NULL)
lv_free((void *)dsc->data);
lv_free(dsc);
}
}
void _lv_image_buf_get_transformed_area(lv_area_t * res, int32_t w, int32_t h, int32_t angle, uint16_t scale_x,
uint16_t scale_y,
const lv_point_t * pivot)
{
if(angle == 0 && scale_x == LV_SCALE_NONE && scale_y == LV_SCALE_NONE) {
res->x1 = 0;
res->y1 = 0;
res->x2 = w - 1;
res->y2 = h - 1;
return;
}
lv_point_t p[4] = {
{0, 0},
{w, 0},
{0, h},
{w, h},
};
lv_point_transform(&p[0], angle, scale_x, scale_y, pivot, true);
lv_point_transform(&p[1], angle, scale_x, scale_y, pivot, true);
lv_point_transform(&p[2], angle, scale_x, scale_y, pivot, true);
lv_point_transform(&p[3], angle, scale_x, scale_y, pivot, true);
res->x1 = LV_MIN4(p[0].x, p[1].x, p[2].x, p[3].x);
res->x2 = LV_MAX4(p[0].x, p[1].x, p[2].x, p[3].x) - 1;
res->y1 = LV_MIN4(p[0].y, p[1].y, p[2].y, p[3].y);
res->y2 = LV_MAX4(p[0].y, p[1].y, p[2].y, p[3].y) - 1;
}
/**********************
* STATIC FUNCTIONS
**********************/

View File

@ -1,5 +1,5 @@
/**
* @file lv_image_buf.h
* @file lv_image_dsc.h
*
*/
@ -13,21 +13,17 @@ extern "C" {
/*********************
* INCLUDES
*********************/
#include <stdbool.h>
#include "../misc/lv_color.h"
#include "../misc/lv_area.h"
#include "../stdlib/lv_string.h"
#include "../lv_conf_internal.h"
/*********************
* DEFINES
*********************/
#define _LV_ZOOM_INV_UPSCALE 5
/** Magic number for lvgl image, 9 means lvgl version 9
* It must not be a valid ASCII character nor larger than 0x80. See `lv_image_src_get_type`.
*/
#define LV_IMAGE_HEADER_MAGIC (0x19)
LV_EXPORT_CONST_INT(LV_IMAGE_HEADER_MAGIC);
/**********************
* TYPEDEFS
@ -38,43 +34,38 @@ typedef enum _lv_image_flags_t {
* For RGB map of the image data, mark if it's pre-multiplied with alpha.
* For indexed image, this bit indicated palette data is pre-multiplied with alpha.
*/
LV_IMAGE_FLAGS_PREMULTIPLIED = (1 << 0),
/**
* If the image data is malloced and can be processed in place.
* In image decoder post processing, this flag means we modify it in-place.
*/
LV_IMAGE_FLAGS_MODIFIABLE = (1 << 1),
/**
* Indicating it's a vector image instead of default raster image.
* Some of the flags are not usable for vector image, like PREMULTIPLIED.
*/
LV_IMAGE_FLAGS_VECTORS = (1 << 2),
LV_IMAGE_FLAGS_PREMULTIPLIED = 0x0001,
/**
* The image data is compressed, so decoder needs to decode image firstly.
* If this flag is set, the whole image will be decompressed upon decode, and
* `get_area_cb` won't be necessary.
*/
LV_IMAGE_FLAGS_COMPRESSED = (1 << 3),
LV_IMAGE_FLAGS_COMPRESSED = 0x0008,
/*Below flags are applicable only for draw buffer header.*/
/**
* The image is allocated from heap, thus should be freed after use.
*/
LV_IMAGE_FLAGS_ALLOCATED = (1 << 4),
LV_IMAGE_FLAGS_ALLOCATED = 0x0010,
/**
* If the image data is malloced and can be processed in place.
* In image decoder post processing, this flag means we modify it in-place.
*/
LV_IMAGE_FLAGS_MODIFIABLE = 0x0020,
/**
* Flags reserved for user, lvgl won't use these bits.
*/
LV_IMAGE_FLAGS_USER1 = 0x1000,
LV_IMAGE_FLAGS_USER2 = 0x2000,
LV_IMAGE_FLAGS_USER3 = 0x4000,
LV_IMAGE_FLAGS_USER4 = 0x8000,
LV_IMAGE_FLAGS_USER5 = 0x0100,
LV_IMAGE_FLAGS_USER6 = 0x0200,
LV_IMAGE_FLAGS_USER7 = 0x0400,
LV_IMAGE_FLAGS_USER8 = 0x0800,
LV_IMAGE_FLAGS_USER1 = 0x0100,
LV_IMAGE_FLAGS_USER2 = 0x0200,
LV_IMAGE_FLAGS_USER3 = 0x0400,
LV_IMAGE_FLAGS_USER4 = 0x0800,
LV_IMAGE_FLAGS_USER5 = 0x1000,
LV_IMAGE_FLAGS_USER6 = 0x2000,
LV_IMAGE_FLAGS_USER7 = 0x4000,
LV_IMAGE_FLAGS_USER8 = 0x8000,
} lv_image_flags_t;
typedef enum {
@ -125,66 +116,20 @@ typedef union {
} lv_yuv_buf_t;
/**
* Struct to describe an image. Both decoded and raw image can share
* the same struct.
*
* Image is also identical to lv_draw_buf_t for now.
* Ideally, decoded image should be lv_draw_buf_t.
* Struct to describe a constant image resource.
* It's similar to lv_draw_buf_t, but the data is constant.
*/
typedef struct {
lv_image_header_t header; /**< A header describing the basics of the image*/
uint32_t data_size; /**< Size of the image in bytes*/
const uint8_t * data; /**< Pointer to the data of the image*/
lv_image_header_t header; /**< A header describing the basics of the image*/
uint32_t data_size; /**< Size of the image in bytes*/
const uint8_t * data; /**< Pointer to the data of the image*/
const void * reserved; /**< A reserved field to make it has same size as lv_draw_buf_t*/
} lv_image_dsc_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Set the palette color of an indexed image. Valid only for `LV_COLOR_FORMAT_I1/2/4/8`
* @param dsc pointer to an image descriptor
* @param id the palette color to set:
* - for `LV_COLOR_FORMAT_I1`: 0..1
* - for `LV_COLOR_FORMAT_I2`: 0..3
* - for `LV_COLOR_FORMAT_I4`: 0..15
* - for `LV_COLOR_FORMAT_I8`: 0..255
* @param c the color to set in lv_color32_t format
*/
void lv_image_buf_set_palette(lv_image_dsc_t * dsc, uint8_t id, lv_color32_t c);
/**
* Free an allocated image buffer
* @param dsc image buffer to free
*/
void lv_image_buf_free(lv_image_dsc_t * dsc);
/**
* Get the area of a rectangle if its rotated and scaled
* @param res store the coordinates here
* @param w width of the rectangle to transform
* @param h height of the rectangle to transform
* @param angle angle of rotation
* @param scale_x zoom in x direction, (256 no zoom)
* @param scale_y zoom in y direction, (256 no zoom)
* @param pivot x,y pivot coordinates of rotation
*/
void _lv_image_buf_get_transformed_area(lv_area_t * res, int32_t w, int32_t h, int32_t angle, uint16_t scale_x,
uint16_t scale_y,
const lv_point_t * pivot);
static inline void lv_image_header_init(lv_image_header_t * header, uint32_t w, uint32_t h, lv_color_format_t cf,
uint32_t stride, lv_image_flags_t flags)
{
LV_ASSERT(header);
lv_memzero(header, sizeof(*header));
header->w = w;
header->h = h;
header->cf = cf;
header->stride = stride;
header->flags = flags;
header->magic = LV_IMAGE_HEADER_MAGIC;
}
/**********************
* MACROS
**********************/

View File

@ -31,7 +31,7 @@ typedef struct {
lv_image_t img;
gd_GIF * gif;
lv_timer_t * timer;
lv_image_dsc_t imgdsc;
lv_draw_buf_t imgdsc;
uint32_t last_call;
} lv_gif_t;

View File

@ -67,19 +67,18 @@ lv_result_t lv_snapshot_reshape_draw_buf(lv_obj_t * obj, lv_draw_buf_t * draw_bu
lv_result_t lv_snapshot_take_to_draw_buf(lv_obj_t * obj, lv_color_format_t cf, lv_draw_buf_t * draw_buf);
/**
* Legacy API, use `lv_draw_buf_destroy` instead.
* @deprecated Use `lv_draw_buf_destroy` instead.
*
* Free the snapshot image returned by @ref lv_snapshot_take
* @param dsc the image descriptor generated by lv_snapshot_take.
*/
static inline void lv_snapshot_free(lv_image_dsc_t * dsc)
{
LV_LOG_WARN("Legacy API, use lv_draw_buf_destroy instead.");
LV_LOG_WARN("Deprecated API, use lv_draw_buf_destroy directly.");
lv_draw_buf_destroy((lv_draw_buf_t *)dsc);
}
/**
* Legacy API, use lv_snapshot_take_to_draw_buf instead.
* Take snapshot for object with its children, save image info to provided buffer.
* @param obj the object to generate snapshot.
* @param cf color format for generated image.
@ -87,13 +86,14 @@ static inline void lv_snapshot_free(lv_image_dsc_t * dsc)
* @param buf the buffer to store image data. It must meet align requirement.
* @param buf_size provided buffer size in bytes.
* @return LV_RESULT_OK on success, LV_RESULT_INVALID on error.
* @deprecated Use lv_snapshot_take_to_draw_buf instead.
*/
static inline 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 buf_size)
{
lv_draw_buf_t draw_buf;
LV_LOG_WARN("Legacy API, use lv_snapshot_take_to_draw_buf instead.");
LV_LOG_WARN("Deprecated API, use lv_snapshot_take_to_draw_buf instead.");
lv_draw_buf_init(&draw_buf, 1, 1, cf, buf_size, buf, buf_size);
lv_result_t res = lv_snapshot_take_to_draw_buf(obj, cf, &draw_buf);
if(res == LV_RESULT_OK) {

View File

@ -152,16 +152,13 @@ void lv_canvas_set_px(lv_obj_t * obj, int32_t x, int32_t y, lv_color_t color, lv
lv_obj_invalidate(obj);
}
void lv_canvas_set_palette(lv_obj_t * obj, uint8_t id, lv_color32_t c)
void lv_canvas_set_palette(lv_obj_t * obj, uint8_t index, lv_color32_t color)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_canvas_t * canvas = (lv_canvas_t *)obj;
lv_image_dsc_t dsc;
lv_draw_buf_to_image(canvas->draw_buf, &dsc);
lv_image_buf_set_palette(&dsc, id, c);
lv_draw_buf_set_palette(canvas->draw_buf, index, color);
lv_obj_invalidate(obj);
}

View File

@ -91,15 +91,15 @@ void lv_canvas_set_px(lv_obj_t * obj, int32_t x, int32_t y, lv_color_t color, lv
/**
* Set the palette color of a canvas for index format. Valid only for `LV_COLOR_FORMAT_I1/2/4/8`
* @param canvas pointer to canvas object
* @param id the palette color to set:
* @param obj pointer to canvas object
* @param index the palette color to set:
* - for `LV_COLOR_FORMAT_I1`: 0..1
* - for `LV_COLOR_FORMAT_I2`: 0..3
* - for `LV_COLOR_FORMAT_I4`: 0..15
* - for `LV_COLOR_FORMAT_I8`: 0..255
* @param c the color to set
* @param color the color to set
*/
void lv_canvas_set_palette(lv_obj_t * canvas, uint8_t id, lv_color32_t c);
void lv_canvas_set_palette(lv_obj_t * obj, uint8_t index, lv_color32_t color);
/*=====================
* Getter functions

View File

@ -204,7 +204,7 @@ void lv_textarea_set_text_selection(lv_obj_t * obj, bool en);
void lv_textarea_set_password_show_time(lv_obj_t * obj, uint32_t time);
/**
* Deprecated: use the normal text_align style property instead
* @deprecated Use the normal text_align style property instead
* Set the label's alignment.
* It sets where the label is aligned (in one line mode it can be smaller than the text area)
* and how the lines of the area align in case of multiline text area

View File

@ -3,7 +3,7 @@ $(info LVGL_PATH is set to: $(LVGL_PATH))
include ../../lvgl.mk
CSRCS += test.c
CFLAGS += -DLV_CONF_SKIP=1 -DLV_BUILD_TEST=1 -DLV_USE_DEV_VERSION -I$(LVGL_PATH)/..
CFLAGS += -Werror -DLV_CONF_SKIP=1 -DLV_BUILD_TEST=1 -DLV_USE_DEV_VERSION -I$(LVGL_PATH)/..
COBJS := $(patsubst %.c, %.o, $(CSRCS))
test_file: $(COBJS)

View File

@ -90,7 +90,7 @@ static void canvas_basic_render(uint8_t * canvas_buf, lv_color_format_t render_c
void canvas_blend_test(lv_obj_t * canvas_large, lv_draw_image_dsc_t * img_dsc, const char * name_main,
const char * name_sub, lv_color_format_t small_render_cf, uint32_t idx)
{
lv_image_dsc_t * img = (lv_image_dsc_t *)img_dsc->src;
lv_draw_buf_t * img = (lv_draw_buf_t *)img_dsc->src;
img->header.cf = small_render_cf;
img->header.stride = lv_draw_buf_width_to_stride(180, small_render_cf);
canvas_basic_render((uint8_t *)img->data, small_render_cf, name_main, name_sub);
@ -129,10 +129,8 @@ static void canvas_draw(const char * name, lv_color_format_t large_render_cf)
lv_canvas_set_buffer(canvas2, lv_draw_buf_align(canvas2_buf, large_render_cf), 768, 390, large_render_cf);
lv_canvas_fill_bg(canvas2, lv_palette_lighten(LV_PALETTE_BLUE_GREY, 2), LV_OPA_COVER);
lv_image_dsc_t img = { 0 };
img.header.w = 180;
img.header.h = 180;
img.data = lv_draw_buf_align(canvas_buf, LV_COLOR_FORMAT_ARGB8888);
lv_draw_buf_t img;
lv_draw_buf_init(&img, 180, 180, LV_COLOR_FORMAT_ARGB8888, LV_STRIDE_AUTO, canvas_buf, sizeof(canvas_buf));
lv_draw_image_dsc_t img_dsc;
lv_draw_image_dsc_init(&img_dsc);