When I use a 480X272 image as background, why the lvgl will use fill_normal to draw a 480X272 background, and then use map_fill to draw 480X272 image.
background = lv_img_create(lv_scr_act());
lv_img_set_src(background, &g_bg);
lv_obj_set_size(background, LV_HOR_RES, LV_VER_RES);
I don’t want to draw 480*272 background, because my image is the same as the screen.
@kisvegabor Can you tell me how to optimazition it?
What is the color format of the image? If it’s TRUE_COLOR_ALPHA
LVGL assumes that the image might have transparent pixels so it can’t convert the area.
If it’s TRUE_COLOR
LVGL should see the image as “top object”.
Can you send a photo about the UI?
Happy new year, @kisvegabor, I’m glad to get your reply.
I decode jpg file, and set data to the ‘lv_img_dsc_t’. The cf value is LV_IMG_CF_TRUE_COLOR:
img_dst->header.w = result.pixel_x;
img_dst->header.h = result.pixel_y;
img_dst->data_size = img_dst->header.w*img_dst->header.h*2;
img_dst->header.always_zero = 0;
img_dst->header.cf = LV_IMG_CF_TRUE_COLOR;
Happy new year
It’s strange. It seems you are using a quite old LVGL version. Exactly which one?
My code likes this, the version of LVGL is V8.3.3:
lv_obj_t *background = NULL;
background = lv_img_create(lv_scr_act());
lv_img_set_src(background, &g_bg);
lv_obj_set_size(background, LV_HOR_RES, LV_VER_RES);
lv_obj_set_scrollbar_mode(background, LV_SCROLLBAR_MODE_OFF);
lv_obj_add_style(background, &img_style, 0);
It’s a pretty recent version. What is in img_style
?
The img_style is like this:
lv_style_init(&img_style);
lv_style_set_border_width(&img_style, 0);
lv_style_set_pad_all(&img_style, 0);
@kisvegabor I try it on the newest code with below code, also will use fill_normal to draw background first. you can try it to see the question.
git clone --recurse-submodules https://github.com/lvgl/lv_sim_visual_studio.git
It seems good. I’d like to try it out but I need
- the image
- the display resolution
- the exact LVGL commit your using
I directly use the image of the lv_demo_widgets, my code is below:
- change the display to 154X154:
@@ -38,8 +38,8 @@ bool single_display_mode_initialization()
if (!lv_win32_init(
GetModuleHandleW(NULL),
SW_SHOW,
- 800,
- 480,
+ 154,
+ 154,
LoadIconW(GetModuleHandleW(NULL), MAKEINTRESOURCE(IDI_LVGL))))
{
- close LV_USE_PERF_MONITOR and LV_USE_MEM_MONITOR
#define LV_USE_PERF_MONITOR 0
#define LV_USE_MEM_MONITOR 0
-
void lv_demo_widgets(void)
{
+ lv_obj_t *g_close_label;
+#if 1
+ g_close_label;
+
+ LV_IMG_DECLARE(img_demo_widgets_avatar);
+ lv_obj_t * avatar = lv_img_create(lv_scr_act());
+ lv_obj_set_size(avatar, LV_HOR_RES, LV_VER_RES);
+ lv_img_set_src(avatar, &img_demo_widgets_avatar);
+#else
if(LV_HOR_RES <= 320) disp_size = DISP_SMALL;
else if(LV_HOR_RES < 720) disp_size = DISP_MEDIUM;
else disp_size = DISP_LARGE;
@@ -194,6 +203,7 @@ void lv_demo_widgets(void)
shop_create(t3);
color_changer_create(tv);
+#endif
}
Now I add below code in here, can resolve my question:
+static int _check_child_is_cover_parent(lv_obj_t * obj)
+{
+ lv_obj_t *child;
+ lv_opa_t child_opa;
+ lv_area_t *child_coords;
+
+ lv_opa_t parent_opa;
+ lv_area_t *parent_coords;
+ int ret = 0;
+ int child_cnt;
+ int i = 0;
+
+ do{
+ parent_opa = lv_obj_get_style_opa(obj, 0);
+ parent_coords = &(obj->coords);
+
+ if(parent_opa < LV_OPA_MAX)
+ {
+ break;
+ }
+
+ if(LV_VER_RES != lv_area_get_height(parent_coords)
+ || LV_HOR_RES != lv_area_get_width(parent_coords))
+ {
+ break;
+ }
+
+ child_cnt = lv_obj_get_child_cnt(obj);
+ for(i = 0; i < child_cnt; i++) {
+ child = obj->spec_attr->children[i];
+ child_opa = lv_obj_get_style_opa(child, 0);
+ child_coords = &(child->coords);
+
+ if(child_opa >= parent_opa
+ && child_coords->x1 <= parent_coords->x1
+ && child_coords->y1 <= parent_coords->y1
+ && child_coords->x2 >= parent_coords->x2
+ && child_coords->y2 >= parent_coords->y2)
+ {
+ ret = 1;
+ break;
+ }
+ }
+ }while(0);
+
+ return ret;
+}
+
void lv_obj_redraw(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj)
{
const lv_area_t * clip_area_ori = draw_ctx->clip_area;
lv_area_t clip_coords_for_obj;
/*Truncate the clip area to `obj size + ext size` area*/
lv_area_t obj_coords_ext;
lv_obj_get_coords(obj, &obj_coords_ext);
@@ -140,12 +189,17 @@ void lv_obj_redraw(lv_draw_ctx_t * draw_ctx, lv_obj_t * obj)
/*If the object is visible on the current clip area OR has overflow visible draw it.
*With overflow visible drawing should happen to apply the masks which might affect children */
bool should_draw = com_clip_res || lv_obj_has_flag(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE);
+
+ if(_check_child_is_cover_parent(obj))
+ should_draw = 0;
+
if(should_draw) {
draw_ctx->clip_area = &clip_coords_for_obj;
lv_refr_get_top_obj should find which the top most object from where the drawing should start. IF the image is screen sized than it should work well.
Note that img_demo_widgets_avatar
has LV_IMG_CF_TRUE_COLOR_ALPHA
color format, so LVGL assumes that it might have transparent pixels. therefore it can be a good “top object”.
I change the img_demo_widgets_avatar to another jpeg, and convert LV_IMG_CF_TRUE_COLOR on lvgl website, also fill_normal will draw first.
It’s easy to try on your demo, you will see what I say.
git clone --recurse-submodules https://github.com/lvgl/lv_sim_visual_studio.git
I’m on Linux and a little bit hard to test on Windows.
Can you debug what happens in lv_refr_get_top_obj
and why LVGL thinks the image is not a good top object?