Merge pull request #4549 from jepler/writable-bitmaps

displayio.Bitmap: Allow modification though the buffer protocol
This commit is contained in:
Scott Shawcroft 2021-04-05 14:23:16 -07:00 committed by GitHub
commit e962b24da1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 5 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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);