Merge pull request #4549 from jepler/writable-bitmaps
displayio.Bitmap: Allow modification though the buffer protocol
This commit is contained in:
commit
e962b24da1
@ -397,8 +397,7 @@ STATIC mp_obj_t bitmaptools_arrayblit(size_t n_args, const mp_obj_t *pos_args, m
|
||||
{ MP_QSTR_x2, MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_y2, MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_skip_index, MP_ARG_OBJ, {.u_obj = mp_const_none } },
|
||||
}
|
||||
;
|
||||
};
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
*/
|
||||
|
||||
#include "shared-bindings/displayio/Bitmap.h"
|
||||
#include "shared-module/displayio/Bitmap.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
@ -43,8 +44,13 @@
|
||||
//| 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.numpy.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`.
|
||||
//| A Bitmap can be treated as a buffer, allowing its content to be
|
||||
//| viewed and modified using e.g., with ``ulab.numpy.frombuffer``,
|
||||
//| but the `displayio.Bitmap.dirty` method must be used to inform
|
||||
//| displayio when a bitmap was modified through the buffer interface.
|
||||
//|
|
||||
//| `bitmaptools.arrayblit` can also be useful to omve data efficiently
|
||||
//| into a Bitmap.
|
||||
//| """
|
||||
//|
|
||||
//| def __init__(self, width: int, height: int, value_count: int) -> None:
|
||||
@ -299,11 +305,57 @@ STATIC mp_obj_t displayio_bitmap_obj_fill(mp_obj_t self_in, mp_obj_t value_obj)
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(displayio_bitmap_fill_obj, displayio_bitmap_obj_fill);
|
||||
|
||||
//| def dirty(self, x1: int=0, y1: int=0, x2: int=-1, y2:int = -1) -> None:
|
||||
//| """Inform displayio of bitmap updates done via the buffer
|
||||
//| protocol.
|
||||
//|
|
||||
//| :param int x1: Minimum x-value for rectangular bounding box to be considered as modified
|
||||
//| :param int y1: Minimum y-value for rectangular bounding box to be considered as modified
|
||||
//| :param int x2: Maximum x-value (exclusive) for rectangular bounding box to be considered as modified
|
||||
//| :param int y2: Maximum y-value (exclusive) for rectangular bounding box to be considered as modified
|
||||
//|
|
||||
//| If x1 or y1 are not specified, they are taken as 0. If x2 or y2
|
||||
//| are not specified, or are given as -1, they are taken as the width
|
||||
//| and height of the image. Thus, calling dirty() with the
|
||||
//| default arguments treats the whole bitmap as modified.
|
||||
//|
|
||||
//| When a bitmap is modified through the buffer protocol, the
|
||||
//| display will not be properly updated unless the bitmap is
|
||||
//| notified of the "dirty rectangle" that encloses all modified
|
||||
//| pixels."""
|
||||
//| ...
|
||||
//|
|
||||
STATIC mp_obj_t displayio_bitmap_obj_dirty(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
displayio_bitmap_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
enum { ARG_x1, ARG_y1, ARG_x2, ARG_y2 };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_x1, MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_y1, MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_x2, MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_y2, MP_ARG_INT, {.u_int = -1} },
|
||||
};
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
displayio_area_t dirty_area = {
|
||||
.x1 = args[ARG_x1].u_int,
|
||||
.y1 = args[ARG_y1].u_int,
|
||||
.x2 = args[ARG_x2].u_int == -1 ? self->width : args[ARG_x2].u_int,
|
||||
.y2 = args[ARG_y2].u_int == -1 ? self->height : args[ARG_y2].u_int,
|
||||
};
|
||||
|
||||
displayio_bitmap_set_dirty_area(self, &dirty_area);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(displayio_bitmap_dirty_obj, 0, displayio_bitmap_obj_dirty);
|
||||
|
||||
STATIC const mp_rom_map_elem_t displayio_bitmap_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&displayio_bitmap_height_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&displayio_bitmap_width_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_blit), MP_ROM_PTR(&displayio_bitmap_blit_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_fill), MP_ROM_PTR(&displayio_bitmap_fill_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_dirty), MP_ROM_PTR(&displayio_bitmap_dirty_obj) },
|
||||
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(displayio_bitmap_locals_dict, displayio_bitmap_locals_dict_table);
|
||||
|
@ -236,7 +236,7 @@ void common_hal_displayio_bitmap_fill(displayio_bitmap_t *self, uint32_t value)
|
||||
}
|
||||
|
||||
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) {
|
||||
if ((flags & MP_BUFFER_WRITE) && self->read_only) {
|
||||
return 1;
|
||||
}
|
||||
bufinfo->len = self->stride * self->height * sizeof(size_t);
|
||||
|
Loading…
x
Reference in New Issue
Block a user