How to implement this feature in LVGL with background-filter: blur(60px) in CSS

Hi @jianjunxia,

I am sorry for my late reply, I really am a little overloaded with work right now. I apologise for not knowing about this previously but I have just seen something in the LVGL documentation which I wasn’t aware of but may potentially be a good way forward for you.

I would take a look at the canvas object in the documentation:

Canvas (lv_canvas) — LVGL documentation (latest)
Canvas (lv_canvas) — LVGL documentation (version 7)

On a quick scan it looks like it might be possible to put your background image on a canvas, then use the canvas_blur_xxx() functions on an area of the image and then place your rectangle over the canvas and make it transparent to achieve something close to your goal.

If these functions are not suitable you could perhaps think about adding an API along the lines of canvas_blur_gaus() or canvas_blur_ver_hor() in the same template as the current canvas_blur_xxx() functions using the code in the link from my previous post maybe?

It might be worth a bit of experimentation. It looks like @kisvegabor(I see he asked you to move this request from Github) may be making a comment at some point also he will obviously have a much better idea of how best to implement your ideas.

I hope this is also helpful.

Kind Regards,

Pete

Hi @pete-pjb Thank you for taking the time out of your busy schedule to reply to me!
I know the canvas in lvgl before,but I’m not sure if it can achieve the effect of background-filter:blur in CSS.
I’ve got some ideas on your previous suggestion and I’m trying to implement them.

My idea is this: get the image elements after obj in lvgl and perform fast Gaussian filtering.
However, I’m not quite sure how to get the image element behind each obj, I’m still thinking about this.

From the example you gave, I also found that Gaussian filtering of a picture is actually taking out the data behind the picture, performing fast Gaussian filtering calculations, and then combining the data into a new picture. So I think this method should also work for obj in lvgl

Stupid suggestion, but do you have any moving parts on the screen or dynamic background images? If not, then as an alternative and for more efficiency I’d add the blur to the background image (like literally bake it into the image with Gimp/Photoshop) and make the buttons transparent (except for the borders).

In my app I just want to blur my rectangle obj, don’t want to blur my background image obj

hi, @pete-pjb I used the canvas function of lvgl to make an approximate effect, such as the picture on my right, but the blurring effect of the upper and lower areas still looks poor, why is this?

This my code:

    lv_obj_t *canvas = lv_canvas_create(obj, NULL);
    static lv_color_t canvas_buf[LV_IMG_BUF_SIZE_TRUE_COLOR_ALPHA(LV_HOR_RES_MAX, LV_VER_RES_MAX)];
    lv_canvas_set_buffer(canvas, canvas_buf, LV_HOR_RES_MAX, LV_VER_RES_MAX, LV_IMG_CF_TRUE_COLOR_ALPHA);

    lv_draw_img_dsc_t img_dsc;
    lv_draw_img_dsc_init(&img_dsc);
    lv_canvas_draw_img(canvas, 0, 0, PNG_BLUR_1, &img_dsc);
    
    
    g_blur->rectangle = lv_obj_create(canvas, NULL);
    lv_style_init(&g_blur->rectangle_style);
    lv_style_set_bg_color(&g_blur->rectangle_style, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xff,0xff,0xff));
    lv_style_set_radius(&g_blur->rectangle_style, LV_STATE_DEFAULT, 16);
    lv_style_set_bg_opa(&g_blur->rectangle_style, LV_STATE_DEFAULT, LV_OPA_30 / 2);

    lv_obj_set_size(g_blur->rectangle, 208, 145);
    lv_obj_align(g_blur->rectangle, NULL, LV_ALIGN_IN_TOP_LEFT, 24, 311);
    lv_obj_add_style(g_blur->rectangle, LV_OBJ_PART_MAIN, &g_blur->rectangle_style);

    lv_area_t area = {24, 311, 24 + 208, 311 + 145};

    //! Blur needs to be set vertically and horizontally together
    lv_canvas_blur_hor(canvas, &area, 60);
    lv_canvas_blur_ver(canvas, &area, 60);

    lv_canvas_blur_hor(canvas, &area, 60);
    lv_canvas_blur_ver(canvas, &area, 60);

    lv_canvas_blur_hor(canvas, &area, 60);
    lv_canvas_blur_ver(canvas, &area, 60);

Hi @jianjunxia,

It looks like you are making progress…

I am not sure I understand:

Can you expand on what you mean by this please? What is not meeting your expectations?

Kind Regards,

Pete

The picture you see, the left is the effect achieved by Gaussian blur, the entire blur effect looks uniform, but the right is the blur of LVGL, the upper and lower areas in the red box look a bit transparent, and the blur in the middle area looks Not even enough

@pete-pjb lv_canvas_blur_hor and lv_canvas_blur_ver
Just simple box filtering, the effect does not look good enough

Hi @jianjunxia,

I understand now…

I will take a quick look to see if I can do anything to help. If I can do something fairly quickly I will post a link to a fork of the LVGL repository back here.

I’ll will let you know.

Kind Regards,

Pete

Hi, @pete-pjb
Looking forward to your help, I have been troubled by this problem for a long time!

I started to work on an automatic “widget snapshot” feature. With this any widgets (with all its children) can be “snapshot-ed”. Once it’s an image you can do any image transformations on them, e.g. zoom or rotation. It’s still in an early stage but somehow maybe it can help to achieve the blurring effect as well.

Note that lv_snapshot already exists in LVGL and even it (maybe with some modifications) can help.

E.g. if lv_snapshot could take a snapshot about a region of the widget it could be blurred manually and that image could be used as a parent of other widgets.

An other option could be this:

  1. Set disp_drv->full_refresh = 1
  2. Create a transparent container where you need the blur
  3. In the LV_EVENT_DRAW_MAIN event of that container get the current draw buffer and blur it where required.

To get draw buffer in a draw event handler:

if(code == LV_EVENT_DRAW_MAIN) {
    lv_obj_t * obj = lv_event_get_target(e);
    lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e);
    lv_color_t * buf = draw_ctx->buf;
   
    /*Blur buf on the obj->coords area*/    

}

I looked into the internal implementations of lv_canvas_blur_hor and lv_canvas_blur_ver, they seem to be just simple box filtering, so the blurring effect is not ideal. Can I add a lv_canvas_blur_xxxx function to expect a Gaussian blur effect?
For example is the method of fast Gaussian blur in this link used here?

@kisvegabor
I looked into the internal implementations of lv_canvas_blur_hor and lv_canvas_blur_ver, they seem to be just simple box filtering, so the blurring effect is not ideal. Can I add a lv_canvas_blur_xxxx function to expect a Gaussian blur effect?
For example is the method of fast Gaussian blur in this link used here?

You can just run lv_canvas_blur_hor and lv_canvas_blur_ver 2 or 3 times. The resource you have linked also suggests that for fast Gaussian blur:

@kisvegabor when i run lv_canvas_blur_hor and lv_canvas_blur_ver 3 times,It does not achieve the effect of Gaussian blur,

The picture you see, the left is the effect achieved by Gaussian blur, the entire blur effect looks uniform, but the right is the blur of LVGL, the upper and lower areas in the red box look a bit transparent, and the blur in the middle area looks Not even enough


this is my code:

It’s trade off, bu you are free to use you own functions to blur the canvas.

@kisvegabor
I see what you mean, I would like to know what materials did you refer to in implementing lv_canvas_blur_hor and lv_canvas_blur_ver? What is its specific principle? I would like to know these, this will help me to port the algorithm of fast Gaussian blur

Hi @jianjunxia,

Can you please post your background image file so I may experiment with it?

Cheers,

Pete

demo

@pete-pjb ok thanks!