Function 'lv_canvas_copy_buf' dosen't work as expected when drawing with indexed color

Description

sorry about my poor english, it’s not my native language.
im trying to fast draw rectangles on a 300*720 canvas, TRUE COLOR works great but it costs 800+K RAM which is too much, LV_IMG_CF_INDEXED_8BIT costs lesser RAM but i cant get correct display when using ‘lv_canvas_copy_buf’, and to draw pixels one by one is too slow for me.

What MCU/Processor/Board and compiler are you using?

stm32f407zgt6

What LVGL version are you using?

v8 (download from rt-thread env)

What do you want to achieve?

What have you tried so far?

i’ve searched on google and documentation about this function but it seems that few people use it. I print out the buffer to see how it storage color data, and i discovered the buffer[0] to buffer[31] (first 64 bytes) are regular(like some parameters of this widget), but in ‘lv_canvas_copy_buf’, the memcpy starts from 0 if u set x=0 and y=0. Also ‘px_size’ are set to zero when using LV_IMG_CF_INDEXED_4BIT and below(so only LV_IMG_CF_INDEXED_8BIT or higher can use this function?). I’m curious about what correct ‘color format’ should be, or is there a faster way for indexed color to draw?

Code to reproduce

static void tetris_init_board(lv_obj_t *parent, uint8_t max_x, uint8_t max_y, lv_color_t bg_color)
{
tetris_canvas = lv_canvas_create(parent);
    lv_canvas_set_buffer(tetris_canvas, canvas_buffer, WIDTH, HEIGHT, LV_IMG_CF_INDEXED_8BIT);
    chr_key[0].full = 0;
    lv_canvas_set_palette(tetris_canvas, chr_key[0].full, lv_color_white());
    chr_key[1].full = 1;
    lv_canvas_set_palette(tetris_canvas, chr_key[1].full, lv_color_black());
    for (uint8_t i = 2; i < 16; i++)
    {
        chr_key[i].full = i;
        lv_canvas_set_palette(tetris_canvas, chr_key[i].full, lv_palette_main((lv_palette_t)chr_key[i].full));
  }
 tetris_draw_block(NULL, 0, 0, chr_key[4]);
}
static void tetris_draw_block(lv_obj_t *parent, uint8_t x, uint8_t y, lv_color_t color)
{
    uint32_t i, j;

    static uint8_t buf_to_copy[30][30];
    for (i = x; i < x + 30; i++)
    {
        for (j = y; j < y + 30; j++)
        {
            if (i == x || i == x + 29 || j == y || j == y + 29)
            {
                buf_to_copy[i][j] = 1;
            }
            else
            {
                buf_to_copy[i][j] = color.full;
            }
        }
    }
    lv_canvas_copy_buf(tetris_canvas, buf_to_copy, y, x, 30, 30);
uint32_t cnt = 0;
    for (i = x; i < x + 30; i++)
    {
        //cnt = HEIGHT * i;
        for (j = y; j < y + 30; j++)
        {
            rt_kprintf("%04X ", canvas_buffer[cnt++]);
        }
        rt_kprintf("\n");
    }
}

Screenshot and/or video

correct output of buffer (using lv_canvas_set_px)

wrong output (start from 0 and format is incorrect)

thank you for your time!!

detail of function

canvas buffer initalize

#define WIDTH 300
#define HEIGHT 720
static lv_color_t canvas_buffer[LV_CANVAS_BUF_SIZE_INDEXED_8BIT(WIDTH, HEIGHT)] __attribute__((at(0x68000000)));

@kisvegabor @embeddedt :sob:

made a little change in function, and add ‘lv_obj_invalidate’(orignal function can’t do real time display), parameter ‘to_copy’ is (lv_color_t)color.full
everything working good right now.

Thanks for investigating it. If you have some time could you send a PR?