[ Request ] in function `lv_canvas_set_buffer(...)` support LV_IMG_CF_TRUE_COLOR_ALPHA for drawing too

When I create color’s buffer by LV_CANVAS_BUF_SIZE_TRUE_COLOR_ALPHA(...)
and set the color’s buffer to the canvas’s obj by lv_canvas_set_buffer(...) with LV_IMG_CF_TRUE_COLOR_ALPHA type.

But when draw anything by the canvas’s api.
It can’t display correctly.

Wish the canvas’s api support for LV_IMG_CF_TRUE_COLOR_ALPHA type too,
and support lv_canvas_set_alpha(...) and lv_canvas_get_alpha(...)
( like lv_canvas_set_px(...) and lv_canvas_get_px(...) )

Thank you.

It’s really not supported now, but it’s on the road map.

Unfortunately, I can’t say an exact date but most probably it will be added in v7.0.

1 Like

At the current version (6.0.2),

If I wish to create manual alpha-buffer 8 bit for a canvas, such as

  lv_color1_t *alpha8_buf = (lv_color1_t*) lv_mem_alloc(LV_CANVAS_BUF_SIZE_ALPHA_8BIT(240,240));
  lv_obj_t* canvas_alpha8 = lv_canvas_create(lv_scr_act(), NULL);
    lv_canvas_set_buffer(canvas_alpha8, alpha8_buf, 240,240, LV_IMG_CF_ALPHA_8BIT );

Can this version use lv_canvas_fill_bg(...) or lv_canvas_draw....() (any canvas draw-api)
for using in this canvas?

Or any suggest for using alpha in the canvas temperaly between version 7.0 will come.
Thank you.

OK, I’ve just found disp.driver.set_px_cb in any canvas’ draw-api can
can use for manual drawing or alpha-masking
for canvas’ LV_IMG_CF_TRUE_COLOR_ALPHA type.

Thank you.

Great!

Unfortunately, this way you can’t use LittlevGL high level drawing API (e.g. anti-aliased rounded button with border and gradient) but you can really use for some simple drawings.

Thank you for the suggestion.

I add some additional code to lv_canvas.c
for a canvas can support drawing for LV_IMG_CF_TRUE_COLOR_ALPHA canvas-buffer.
such as lv_canvas_draw_rect(...) , lv_canvas_draw_text(...),
lv_canvas_draw_line(...) , lv_canvas_draw_polygon(...).

Do you mind to give any suggestion about the following code?

What do you want to achieve?

lv_canvas_draw_rect(...) can use for LV_IMG_CF_TRUE_COLOR_ALPHA too

Code to reproduce

(in lv_canvas.c with additional code)

void lv_canvas_draw_rect(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord_t w, lv_coord_t h,
                         const lv_style_t * style)
{
    lv_img_dsc_t * dsc = lv_canvas_get_img(canvas);

    /* Create a dummy display to fool the lv_draw function.
     * It will think it draws to real screen. */
    lv_area_t mask;
    mask.x1 = 0;
    mask.x2 = dsc->header.w - 1;
    mask.y1 = 0;
    mask.y2 = dsc->header.h - 1;

    lv_area_t coords;
    coords.x1 = x;
    coords.y1 = y;
    coords.x2 = x + w - 1;
    coords.y2 = y + h - 1;

    lv_disp_t disp;
    memset(&disp, 0, sizeof(lv_disp_t));

    lv_disp_buf_t disp_buf;
    lv_disp_buf_init(&disp_buf, (void *)dsc->data, NULL, dsc->header.w * dsc->header.h);
    lv_area_copy(&disp_buf.area, &mask);

    lv_disp_drv_init(&disp.driver);

    disp.driver.buffer  = &disp_buf;
    disp.driver.hor_res = dsc->header.w;
    disp.driver.ver_res = dsc->header.h;

    //---------------------------------------------------------------------------
    // link to  manual set_px_cb if canvas's buffer is LV_IMG_CF_TRUE_COLOR_ALPHA type
    if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA)
        disp.driver.set_px_cb = lv_canvas_truecolor_alpha_set_px_cb;
    //---------------------------------------------------------------------------

#if LV_ANTIALIAS
    /*Disable anti-aliasing if drawing with transparent color to chroma keyed canvas*/
    lv_color_t ctransp = LV_COLOR_TRANSP;
    if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED &&
        style->body.main_color.full == ctransp.full &&
        style->body.grad_color.full == ctransp.full)
    {
        disp.driver.antialiasing = 0;
    }
#endif

    lv_disp_t * refr_ori = lv_refr_get_disp_refreshing();
    lv_refr_set_disp_refreshing(&disp);

    lv_draw_rect(&coords, &mask, style, LV_OPA_COVER);

    lv_refr_set_disp_refreshing(refr_ori);
}

and add manual lv_canvas_truecolor_alpha_set_px_cb(..) like this.

static void lv_canvas_truecolor_alpha_set_px_cb(struct _disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
                      lv_color_t color, lv_opa_t opa)
{
// at now support for color-depth 16 bit
#if LV_COLOR_DEPTH == 16
    uint16_t* buf_color = (uint16_t*) &buf[ (x + y*buf_w)*3];
    if(opa == LV_OPA_COVER) {
        *buf_color = color.full;
    }else{
        lv_color_t bg_tmp; bg_tmp.full = *buf_color;
        lv_color_t opa_tmp = lv_color_mix(color, bg_tmp, opa);
        *buf_color = opa_tmp.full;
    }
#endif
}
1 Like

Excellent idea. I was also considering the option. Probably I’ll end up with set_px callback too.

Because of your great-job lvgl, the core is very well-defined.

Thank you.

1 Like