diff --git a/shared-bindings/displayio/Bitmap.c b/shared-bindings/displayio/Bitmap.c index f906be2f97fc1..ebe2946091910 100644 --- a/shared-bindings/displayio/Bitmap.c +++ b/shared-bindings/displayio/Bitmap.c @@ -37,7 +37,15 @@ #include "supervisor/shared/translate.h" //| class Bitmap: -//| """Stores values of a certain size in a 2D array""" +//| """Stores values of a certain size in a 2D array +//| +//| Bitmaps can be treated as read-only buffers. If the number of bits in a pixel is 8, 16, or 32; and the number of bytes +//| per row is a multiple of 4, then the resulting memoryview will correspond directly with the bitmap's contents. Otherwise, +//| the bitmap data is packed into the memoryview with unspecified padding. +//| +//| A read-only buffer can be used e.g., with `ulab.frombuffer` to efficiently create an array with the same content as a Bitmap; +//| to move data efficiently from ulab back into a Bitmap, use `bitmaptools.arrayblit`. +//| """ //| //| def __init__(self, width: int, height: int, value_count: int) -> None: //| """Create a Bitmap object with the given fixed size. Each pixel stores a value that is used to @@ -300,10 +308,17 @@ STATIC const mp_rom_map_elem_t displayio_bitmap_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(displayio_bitmap_locals_dict, displayio_bitmap_locals_dict_table); +// (the get_buffer protocol returns 0 for success, 1 for failure) +STATIC mp_int_t bitmap_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { + displayio_bitmap_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_displayio_bitmap_get_buffer(self, bufinfo, flags); +} + const mp_obj_type_t displayio_bitmap_type = { { &mp_type_type }, .name = MP_QSTR_Bitmap, .make_new = displayio_bitmap_make_new, .subscr = bitmap_subscr, .locals_dict = (mp_obj_dict_t *)&displayio_bitmap_locals_dict, + .buffer_p = { .get_buffer = bitmap_get_buffer }, }; diff --git a/shared-bindings/displayio/Bitmap.h b/shared-bindings/displayio/Bitmap.h index 1f74c31fc5347..458047510a8ba 100644 --- a/shared-bindings/displayio/Bitmap.h +++ b/shared-bindings/displayio/Bitmap.h @@ -45,5 +45,6 @@ void common_hal_displayio_bitmap_blit(displayio_bitmap_t *self, int16_t x, int16 uint32_t skip_index, bool skip_index_none); uint32_t common_hal_displayio_bitmap_get_pixel(displayio_bitmap_t *bitmap, int16_t x, int16_t y); void common_hal_displayio_bitmap_fill(displayio_bitmap_t *bitmap, uint32_t value); +int common_hal_displayio_bitmap_get_buffer(displayio_bitmap_t *self, mp_buffer_info_t *bufinfo, mp_uint_t flags); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO_BITMAP_H diff --git a/shared-module/displayio/Bitmap.c b/shared-module/displayio/Bitmap.c index f03ade84b12bb..5da196d9fbebf 100644 --- a/shared-module/displayio/Bitmap.c +++ b/shared-module/displayio/Bitmap.c @@ -271,3 +271,23 @@ void common_hal_displayio_bitmap_fill(displayio_bitmap_t *self, uint32_t value) self->data[i] = word; } } + +int common_hal_displayio_bitmap_get_buffer(displayio_bitmap_t *self, mp_buffer_info_t *bufinfo, mp_uint_t flags) { + if (flags & MP_BUFFER_WRITE) { + return 1; + } + bufinfo->len = self->stride * self->height * sizeof(size_t); + bufinfo->buf = self->data; + switch (self->bits_per_value) { + case 32: + bufinfo->typecode = 'I'; + break; + case 16: + bufinfo->typecode = 'H'; + break; + default: + bufinfo->typecode = 'B'; + break; + } + return 0; +}