How to change single pixels in a monochrome Canvas


I need to display icons in my GUI. I am using a monochrome display and already have said icon codified as C arrays (1 byte = 8 pixels on one line). I guess it would be pointless to convert them as images for lvgl as they would require at least 8 times more RAM.
I think (but I am not sure) the best way to display those icons is by using a canvas object. I have thus far failed at changing single pixels on a canvas: everything remains constantly black.

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

For now I’m working on the SDL simulator.

What do you want to achieve?

Changing single pixels on a canvas

What have you tried so far?

Using the lv_canvas_set_px function

Code to reproduce

    lv_theme_t *th = lv_theme_mono_init(0, NULL);
    static lv_color_t cbuf[LV_CANVAS_BUF_SIZE_INDEXED_1BIT(48,48)];
    lv_obj_t *canvas = lv_canvas_create(lv_scr_act(), NULL);
    lv_canvas_set_buffer(canvas, cbuf, 48, 48, LV_IMG_CF_INDEXED_1BIT);
    lv_obj_align(canvas, NULL, LV_ALIGN_CENTER, 0, 0);

    for(int i = 0; i < 48; i++) {
        for (int j = 0; j < 48; j++) {
            lv_color_t px;
            px.full = j % 2;
            lv_canvas_set_px(canvas, i, j, px);

Screenshot and/or video

I would expect the canvas to display a grid of full/empty pixels, but it ends up being entirely black.

I currently have issues getting the Indexed 1bit canvas to work correctly. I have been looking into it but perhaps those with better knowledge than me can figure it out. (Note that it doesn’t work for me in both my hardware or the simulator).

If you are using the simulator try changing the type to LV_IMG_CF_TRUE_COLOR and use LV_CANVAS_BUF_SIZE_TRUE_COLOR(48,48) for your buffer sizing. Does this configuration work for you? If so then I suspect we have a bug in the 1bit indexed that needs to be root caused.

When you set your canvas by LV_IMG_CF_INDEXED_1BIT,
you must set your 2 colors to the canvas’ palette-color by

lv_canvas_set_palette(canvas, 0, LV_COLOR_BLACK);
lv_canvas_set_palette(canvas, 1, LV_COLOR_WHITE);

and must create 2 colors by

lv_color_t black; black.full = 0;
lv_color_t white; white.full = 1;

and when you want to set_pixel for the canvas, using by

lv_canvas_set_px(canvas, i, j, white);


lv_canvas_set_px(canvas, i, j, black);

By the ways, at now LV_IMG_CF_INDEXED_1BIT can use only
lv_canvas_set_px(...) api, it can’t use any ‘lv_canvas_draw_xxxxx(…)’ api.

That’s it. While reading the docs that part slipped. Thanks!

Where you able to successfully get your canvas to display after adding the indexed colors?

Yes, immediately.

Can you tell me what your settings are for LV_HOR_RES_MAX, LV_VER_RES_MAX, and LV_COLOR_DEPTH? Thanks.

I’m using a 128x128 pixel wide SDL window with a color depth of 1 pixel