Getting the buffer, dimensions, or format from an existing framebuf.FrameBuffer object #17266
-
I noticed that the framebuf.FrameBuffer objects don't seem to expose any of their properties, like the width, height, format, or the bytearray buffer that was used. Of course, it's not a problem if I'm just working with my own framebuffer that I initialized myself, since I can just keep those info in a variable somewhere. But the problem is that if I just receive a framebuffer object from another part of the code (maybe a library), I can't do some things because I don't know their width, height, or format, and don't have access to their buffer. So right now I am kinda stuck For context, basically what I'm trying to do is make a full RGB888 framebuffer class for my neopixel matrix. I'm doing this by basically having 3 different framebuf.GS8 framebuffers for each color channel. Now this has worked quite well on its own and is only a little bit slower than a single framebuf.RGB565 framebuffer in my use case. But the problem is that I'm struggling to implement a blit method that would allow drawing a standard framebuffer (at the very least the framebuf.RGB565 framebuffer) to this RGB888 framebuffer. Now, figuring out how to do this was already quite confusing for me, but then I hit a roadblock after realizing I couldn't directly read the buffer of the source framebuffer or even just get its width, height, or format. Also, I'm using this opportunity to ask if we'll get a native RGB888 format for framebuf? From my search, the last discussion I found seems to have stopped in 2022? Thanks guys |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 5 replies
-
I think you can subclass
If you can build MicroPython, this patch will work 👍🏼 diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c
index b718a66cc..7782186cf 100644
--- a/extmod/modframebuf.c
+++ b/extmod/modframebuf.c
@@ -56,9 +56,23 @@ typedef struct _mp_framebuf_p_t {
fill_rect_t fill_rect;
} mp_framebuf_p_t;
+
+typedef struct {
+ uint8_t bytes[3]; // RGB888: [R, G, B]
+} uint24_t;
+
+static uint24_t uint32_to_uint24(uint32_t col) {
+ uint24_t result;
+ result.bytes[2] = (col >> 16) & 0xFF; // R
+ result.bytes[1] = (col >> 8) & 0xFF; // G
+ result.bytes[0] = col & 0xFF; // B
+ return result;
+}
+
// constants for formats
#define FRAMEBUF_MVLSB (0)
#define FRAMEBUF_RGB565 (1)
+#define FRAMEBUF_RGB888 (7)
#define FRAMEBUF_GS2_HMSB (5)
#define FRAMEBUF_GS4_HMSB (2)
#define FRAMEBUF_GS8 (6)
@@ -137,6 +151,28 @@ static void rgb565_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsign
}
}
+// Functions for RGB888 format
+
+static void rgb888_setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
+ uint24_t *b = &((uint24_t *)fb->buf)[x + y * fb->stride];
+ *b = uint32_to_uint24(col);
+}
+
+static uint32_t rgb888_getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
+ uint24_t pixel = ((uint24_t *)fb->buf)[x + y * fb->stride];
+ return (pixel.bytes[2] << 16) | (pixel.bytes[1] << 8) | pixel.bytes[0];
+}
+
+static void rgb888_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint32_t col) {
+ uint24_t *b = &((uint24_t *)fb->buf)[x + y * fb->stride];
+ uint24_t rgb24_col = uint32_to_uint24(col);
+ while (h--) {
+ for (unsigned int ww = w; ww; --ww) {
+ *b++ = rgb24_col;
+ }
+ b += fb->stride - w;
+ }
+}
// Functions for GS2_HMSB format
static void gs2_hmsb_setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
@@ -234,6 +270,7 @@ static void gs8_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigned
static mp_framebuf_p_t formats[] = {
[FRAMEBUF_MVLSB] = {mvlsb_setpixel, mvlsb_getpixel, mvlsb_fill_rect},
[FRAMEBUF_RGB565] = {rgb565_setpixel, rgb565_getpixel, rgb565_fill_rect},
+ [FRAMEBUF_RGB888] = {rgb888_setpixel, rgb888_getpixel, rgb888_fill_rect},
[FRAMEBUF_GS2_HMSB] = {gs2_hmsb_setpixel, gs2_hmsb_getpixel, gs2_hmsb_fill_rect},
[FRAMEBUF_GS4_HMSB] = {gs4_hmsb_setpixel, gs4_hmsb_getpixel, gs4_hmsb_fill_rect},
[FRAMEBUF_GS8] = {gs8_setpixel, gs8_getpixel, gs8_fill_rect},
@@ -313,6 +350,9 @@ static mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size
case FRAMEBUF_RGB565:
bpp = 16;
break;
+ case FRAMEBUF_RGB888:
+ bpp = 24;
+ break;
default:
mp_raise_ValueError(MP_ERROR_TEXT("invalid format"));
}
@@ -889,6 +929,7 @@ static const mp_rom_map_elem_t framebuf_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_MVLSB), MP_ROM_INT(FRAMEBUF_MVLSB) },
{ MP_ROM_QSTR(MP_QSTR_MONO_VLSB), MP_ROM_INT(FRAMEBUF_MVLSB) },
{ MP_ROM_QSTR(MP_QSTR_RGB565), MP_ROM_INT(FRAMEBUF_RGB565) },
+ { MP_ROM_QSTR(MP_QSTR_RGB888), MP_ROM_INT(FRAMEBUF_RGB888) },
{ MP_ROM_QSTR(MP_QSTR_GS2_HMSB), MP_ROM_INT(FRAMEBUF_GS2_HMSB) },
{ MP_ROM_QSTR(MP_QSTR_GS4_HMSB), MP_ROM_INT(FRAMEBUF_GS4_HMSB) },
{ MP_ROM_QSTR(MP_QSTR_GS8), MP_ROM_INT(FRAMEBUF_GS8) },
|
Beta Was this translation helpful? Give feedback.
-
I've added an implementation for this in #17328 |
Beta Was this translation helpful? Give feedback.
-
Have you considered using a single RGB565 framebuffer and expanding the resolution to RGB888 on output? This ILI9488 driver expands from a framebuffer using 4-bit color to RGB666 at runtime using a lookup table. I do agree that RGB888 and RGB666 FrameBuffer modes would be useful. The |
Beta Was this translation helpful? Give feedback.
I've added an implementation for this in #17328