make pixelbuf handle floats and iterables

This commit is contained in:
Roy Hooper 2020-08-07 18:42:06 -04:00
parent 354edd9431
commit e73dba21d2
3 changed files with 52 additions and 29 deletions

View File

@ -40,6 +40,10 @@
#include "shared-module/_pixelbuf/PixelBuf.h" #include "shared-module/_pixelbuf/PixelBuf.h"
#include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-bindings/digitalio/DigitalInOut.h"
#ifdef CIRCUITPY_ULAB
#include "extmod/ulab/code/ndarray.h"
#endif
extern const int32_t colorwheel(float pos); extern const int32_t colorwheel(float pos);
static void parse_byteorder(mp_obj_t byteorder_obj, pixelbuf_byteorder_details_t* parsed); static void parse_byteorder(mp_obj_t byteorder_obj, pixelbuf_byteorder_details_t* parsed);
@ -326,27 +330,15 @@ STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp
} else { // Set } else { // Set
#if MICROPY_PY_ARRAY_SLICE_ASSIGN #if MICROPY_PY_ARRAY_SLICE_ASSIGN
if (!(MP_OBJ_IS_TYPE(value, &mp_type_list) || MP_OBJ_IS_TYPE(value, &mp_type_tuple))) { size_t num_items = mp_obj_get_int(mp_obj_len(value));
mp_raise_ValueError(translate("tuple/list required on RHS"));
if (num_items != slice_len && num_items != (slice_len * common_hal__pixelbuf_pixelbuf_get_bpp(self_in))) {
mp_raise_ValueError_varg(translate("Unmatched number of items on RHS (expected %d or %d, got %d)."),
slice_len, slice_len * common_hal__pixelbuf_pixelbuf_get_bpp(self_in),
num_items);
} }
mp_obj_t *src_objs; common_hal__pixelbuf_pixelbuf_set_pixels(self_in, slice.start, slice.step, slice_len, value, num_items != slice_len);
size_t num_items;
if (MP_OBJ_IS_TYPE(value, &mp_type_list)) {
mp_obj_list_t *t = MP_OBJ_TO_PTR(value);
num_items = t->len;
src_objs = t->items;
} else {
mp_obj_tuple_t *l = MP_OBJ_TO_PTR(value);
num_items = l->len;
src_objs = l->items;
}
if (num_items != slice_len) {
mp_raise_ValueError_varg(translate("Unmatched number of items on RHS (expected %d, got %d)."),
slice_len, num_items);
}
common_hal__pixelbuf_pixelbuf_set_pixels(self_in, slice.start, slice.step, slice_len, src_objs);
return mp_const_none; return mp_const_none;
#else #else
return MP_OBJ_NULL; // op not supported return MP_OBJ_NULL; // op not supported

View File

@ -47,6 +47,6 @@ void common_hal__pixelbuf_pixelbuf_fill(mp_obj_t self, mp_obj_t item);
void common_hal__pixelbuf_pixelbuf_show(mp_obj_t self); void common_hal__pixelbuf_pixelbuf_show(mp_obj_t self);
mp_obj_t common_hal__pixelbuf_pixelbuf_get_pixel(mp_obj_t self, size_t index); mp_obj_t common_hal__pixelbuf_pixelbuf_get_pixel(mp_obj_t self, size_t index);
void common_hal__pixelbuf_pixelbuf_set_pixel(mp_obj_t self, size_t index, mp_obj_t item); void common_hal__pixelbuf_pixelbuf_set_pixel(mp_obj_t self, size_t index, mp_obj_t item);
void common_hal__pixelbuf_pixelbuf_set_pixels(mp_obj_t self_in, size_t start, mp_int_t step, size_t slice_len, mp_obj_t* values); void common_hal__pixelbuf_pixelbuf_set_pixels(mp_obj_t self_in, size_t start, mp_int_t step, size_t slice_len, mp_obj_t* values, bool flattened);
#endif // CP_SHARED_BINDINGS_PIXELBUF_PIXELBUF_H #endif // CP_SHARED_BINDINGS_PIXELBUF_PIXELBUF_H

View File

@ -132,6 +132,18 @@ void common_hal__pixelbuf_pixelbuf_set_brightness(mp_obj_t self_in, mp_float_t b
} }
} }
uint8_t _pixelbuf_get_as_uint8(mp_obj_t obj) {
if (MP_OBJ_IS_SMALL_INT(obj)) {
return MP_OBJ_SMALL_INT_VALUE(obj);
} else if (MP_OBJ_IS_INT(obj)) {
return mp_obj_get_int_truncated(obj);
} else if (mp_obj_is_float(obj)) {
return (uint8_t)mp_obj_get_float(obj);
}
mp_raise_TypeError_varg(
translate("can't convert %q to %q"), mp_obj_get_type_qstr(obj), MP_QSTR_int);
}
void _pixelbuf_parse_color(pixelbuf_pixelbuf_obj_t* self, mp_obj_t color, uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* w) { void _pixelbuf_parse_color(pixelbuf_pixelbuf_obj_t* self, mp_obj_t color, uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* w) {
pixelbuf_byteorder_details_t *byteorder = &self->byteorder; pixelbuf_byteorder_details_t *byteorder = &self->byteorder;
// w is shared between white in NeoPixels and brightness in dotstars (so that DotStars can have // w is shared between white in NeoPixels and brightness in dotstars (so that DotStars can have
@ -142,8 +154,8 @@ void _pixelbuf_parse_color(pixelbuf_pixelbuf_obj_t* self, mp_obj_t color, uint8_
*w = 0; *w = 0;
} }
if (MP_OBJ_IS_INT(color)) { if (MP_OBJ_IS_INT(color) || mp_obj_is_float(color)) {
mp_int_t value = mp_obj_get_int_truncated(color); mp_int_t value = MP_OBJ_IS_INT(color) ? mp_obj_get_int_truncated(color) : mp_obj_get_float(color);
*r = value >> 16 & 0xff; *r = value >> 16 & 0xff;
*g = (value >> 8) & 0xff; *g = (value >> 8) & 0xff;
*b = value & 0xff; *b = value & 0xff;
@ -155,9 +167,9 @@ void _pixelbuf_parse_color(pixelbuf_pixelbuf_obj_t* self, mp_obj_t color, uint8_
mp_raise_ValueError_varg(translate("Expected tuple of length %d, got %d"), byteorder->bpp, len); mp_raise_ValueError_varg(translate("Expected tuple of length %d, got %d"), byteorder->bpp, len);
} }
*r = mp_obj_get_int_truncated(items[PIXEL_R]); *r = _pixelbuf_get_as_uint8(items[PIXEL_R]);
*g = mp_obj_get_int_truncated(items[PIXEL_G]); *g = _pixelbuf_get_as_uint8(items[PIXEL_G]);
*b = mp_obj_get_int_truncated(items[PIXEL_B]); *b = _pixelbuf_get_as_uint8(items[PIXEL_B]);
if (len > 3) { if (len > 3) {
if (mp_obj_is_float(items[PIXEL_W])) { if (mp_obj_is_float(items[PIXEL_W])) {
*w = 255 * mp_obj_get_float(items[PIXEL_W]); *w = 255 * mp_obj_get_float(items[PIXEL_W]);
@ -218,17 +230,36 @@ void _pixelbuf_set_pixel(pixelbuf_pixelbuf_obj_t* self, size_t index, mp_obj_t v
_pixelbuf_set_pixel_color(self, index, r, g, b, w); _pixelbuf_set_pixel_color(self, index, r, g, b, w);
} }
void common_hal__pixelbuf_pixelbuf_set_pixels(mp_obj_t self_in, size_t start, mp_int_t step, size_t slice_len, mp_obj_t* values) { void common_hal__pixelbuf_pixelbuf_set_pixels(mp_obj_t self_in, size_t start, mp_int_t step, size_t slice_len, mp_obj_t* values, bool flattened) {
pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in); pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in);
for (size_t i = 0; i < slice_len; i++) { mp_obj_iter_buf_t iter_buf;
_pixelbuf_set_pixel(self, start, values[i]); mp_obj_t iterable = mp_getiter(values, &iter_buf);
start+=step; mp_obj_t item;
size_t i = 0;
mp_obj_tuple_t *tuple;
uint bpp = self->bytes_per_pixel;
if (flattened) {
tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(bpp, NULL));
}
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
if (flattened) {
tuple->items[i % bpp] = item;
if (++i % bpp == 0) {
_pixelbuf_set_pixel(self, start, tuple);
start+=step;
}
} else {
_pixelbuf_set_pixel(self, start, item);
start+=step;
}
} }
if (self->auto_write) { if (self->auto_write) {
common_hal__pixelbuf_pixelbuf_show(self_in); common_hal__pixelbuf_pixelbuf_show(self_in);
} }
} }
void common_hal__pixelbuf_pixelbuf_set_pixel(mp_obj_t self_in, size_t index, mp_obj_t value) { void common_hal__pixelbuf_pixelbuf_set_pixel(mp_obj_t self_in, size_t index, mp_obj_t value) {
pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in); pixelbuf_pixelbuf_obj_t* self = native_pixelbuf(self_in);
_pixelbuf_set_pixel(self, index, value); _pixelbuf_set_pixel(self, index, value);