From 9133b23a37649cc53568f8208c2493348441d700 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 14 Mar 2021 13:27:28 -0500 Subject: [PATCH 01/12] bitmaptools: Add readinto When reading uncompressed bitmap data directly, readinto can work much more quickly than a Python-coded loop. On a Raspberry Pi Pico, I benchmarked a modified version of adafruit_bitmap_font's pcf reader which uses readinto instead of the existing code. My test font was a 72-point file created from Arial. This decreased the time to load all the ASCII glyphs from 4.9 seconds to just 0.44 seconds. While this attempts to support many pixel configurations (1/2/4/8/16/24/32 bpp; swapped words and pixels) only the single combination used by PCF fonts was tested. --- shared-bindings/bitmaptools/__init__.c | 76 ++++++++++++++++++++++ shared-bindings/bitmaptools/__init__.h | 4 ++ shared-module/bitmaptools/__init__.c | 90 ++++++++++++++++++++++++++ 3 files changed, 170 insertions(+) diff --git a/shared-bindings/bitmaptools/__init__.c b/shared-bindings/bitmaptools/__init__.c index 118564ff85702..0e655d5bfb08a 100644 --- a/shared-bindings/bitmaptools/__init__.c +++ b/shared-bindings/bitmaptools/__init__.c @@ -357,7 +357,83 @@ STATIC mp_obj_t bitmaptools_obj_draw_line(size_t n_args, const mp_obj_t *pos_arg MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_line_obj, 0, bitmaptools_obj_draw_line); // requires all 6 arguments +//| def readinto(bitmap: displayio.Bitmap, file: typing.BinaryIO, bits_per_pixel: int, element_size: int = 1, reverse_pixels_in_element: bool = False, swap_bytes_in_element: bool = False): +//| """Read from a binary file into a bitmap +//| The file must be positioned so that it consists of ``bitmap.height`` rows of pixel data, where each row is the smallest multiple of ``element_size`` bytes that can hold ``bitmap.width`` pixels. +//| +//| The bytes in an element can be optionally swapped, and the pixels in an element can be reversed. +//| +//| This function doesn't parse image headers, but is useful to speed up loading of uncompressed image formats such as PCF glyph data. +//| +//| :param displayio.Bitmap bitmap: A writable bitmap +//| :param typing.BinaryIO file: A file opened in binary mode +//| :param int bits_per_pixel: Number of bits per pixel. Values 1, 2, 4, 8, 16, 24, and 32 are supported; +//| :param int element_size: Number of bytes per element. Values of 1, 2, and 4 are supported, except that 24 ``bits_per_pixel`` requires 1 byte per element. +//| :param bool reverse_pixels_in_element: If set, the first pixel in a word is taken from the Most Signficant Bits; otherwise, it is taken from the Least Significant Bits. +//| :param bool swap_bytes_in_element: If the ``element_size`` is not 1, then reverse the byte order of each element read. +//| """ +//| ... +//| + +STATIC mp_obj_t bitmaptools_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_bitmap, ARG_file, ARG_bits_per_pixel, ARG_element_size, ARG_reverse_pixels_in_element, ARG_swap_bytes_in_element }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_file, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_bits_per_pixel, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_element_size, MP_ARG_INT, { .u_int = 1 } }, + { MP_QSTR_reverse_pixels_in_element, MP_ARG_BOOL, { .u_bool = false } }, + { MP_QSTR_swap_bytes_in_element, MP_ARG_BOOL, { .u_bool = false } }, + }; + + 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); + + if (!MP_OBJ_IS_TYPE(args[ARG_bitmap].u_obj, &displayio_bitmap_type)) { + mp_raise_TypeError(NULL); + } + displayio_bitmap_t *bitmap = MP_OBJ_TO_PTR(args[ARG_bitmap].u_obj); + + if (!MP_OBJ_IS_TYPE(args[ARG_file].u_obj, &mp_type_fileio)) { + mp_raise_TypeError(NULL); + } + pyb_file_obj_t* file = MP_OBJ_TO_PTR(args[ARG_file].u_obj); + + int element_size = args[ARG_element_size].u_int; + if (element_size != 1 && element_size != 2 && element_size != 4) { + mp_raise_ValueError_varg(translate("invalid element_size %d, must be, 1, 2, or 4"), element_size); + } + + int bits_per_pixel = args[ARG_bits_per_pixel].u_int; + switch (bits_per_pixel) { + case 24: + if (element_size != 1) { + mp_raise_ValueError_varg(translate("invalid element size %d for bits_per_pixel %d\n"), element_size, bits_per_pixel); + } + break; + case 1: + case 2: + case 4: + case 8: + case 16: + case 32: + break; + default: + mp_raise_ValueError_varg(translate("invalid bits_per_pixel %d, must be, 1, 4, 8, 16, 24, or 32"), bits_per_pixel); + } + + bool reverse_pixels_in_element = args[ARG_reverse_pixels_in_element].u_bool; + bool swap_bytes_in_element = args[ARG_swap_bytes_in_element].u_bool; + + common_hal_bitmaptools_readinto(bitmap, file, element_size, bits_per_pixel, reverse_pixels_in_element, swap_bytes_in_element); + + return mp_const_none; +} + +MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_readinto_obj, 0, bitmaptools_readinto); + STATIC const mp_rom_map_elem_t bitmaptools_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&bitmaptools_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_rotozoom), MP_ROM_PTR(&bitmaptools_rotozoom_obj) }, { MP_ROM_QSTR(MP_QSTR_fill_region), MP_ROM_PTR(&bitmaptools_fill_region_obj) }, { MP_ROM_QSTR(MP_QSTR_draw_line), MP_ROM_PTR(&bitmaptools_draw_line_obj) }, diff --git a/shared-bindings/bitmaptools/__init__.h b/shared-bindings/bitmaptools/__init__.h index 1ab6e412939ca..50ad7f526446c 100644 --- a/shared-bindings/bitmaptools/__init__.h +++ b/shared-bindings/bitmaptools/__init__.h @@ -27,7 +27,9 @@ #ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BITMAPTOOLS__INIT__H #define MICROPY_INCLUDED_SHARED_BINDINGS_BITMAPTOOLS__INIT__H +#include "shared-module/displayio/Bitmap.h" #include "py/obj.h" +#include "extmod/vfs_fat.h" void common_hal_bitmaptools_rotozoom(displayio_bitmap_t *self, int16_t ox, int16_t oy, int16_t dest_clip0_x, int16_t dest_clip0_y, @@ -49,4 +51,6 @@ void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination, int16_t x1, int16_t y1, uint32_t value); +void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, pyb_file_obj_t* file, int element_size, int bits_per_pixel, bool reverse_pixels_in_word, bool swap_bytes); + #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BITMAPTOOLS__INIT__H diff --git a/shared-module/bitmaptools/__init__.c b/shared-module/bitmaptools/__init__.c index 6f168b5552871..a41b5007c2ea4 100644 --- a/shared-module/bitmaptools/__init__.c +++ b/shared-module/bitmaptools/__init__.c @@ -25,10 +25,12 @@ */ +#include "shared-bindings/bitmaptools/__init__.h" #include "shared-bindings/displayio/Bitmap.h" #include "shared-module/displayio/Bitmap.h" #include "py/runtime.h" +#include "py/mperrno.h" #include "math.h" #include "stdlib.h" @@ -336,3 +338,91 @@ void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination, } } } + +void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, pyb_file_obj_t* file, int element_size, int bits_per_pixel, bool reverse_pixels_in_element, bool swap_bytes) { + if (self->read_only) { + mp_raise_RuntimeError(translate("Read-only object")); + } + + size_t elements_per_row = (self->width * bits_per_pixel + element_size * 8 - 1) / (element_size * 8); + size_t rowsize = element_size * elements_per_row; + size_t rowsize_in_u32 = (rowsize + sizeof(uint32_t) - 1) / sizeof(uint32_t); + size_t rowsize_in_u16 = (rowsize + sizeof(uint16_t) - 1) / sizeof(uint16_t); + for(int y=0; yheight; y++) { + uint32_t rowdata32[rowsize_in_u32]; + uint16_t *rowdata16 = (uint16_t*)rowdata32; + uint8_t *rowdata8 = (uint8_t*)rowdata32; + + UINT bytes_read = 0; + if (f_read(&file->fp, rowdata32, rowsize, &bytes_read) != FR_OK || bytes_read != rowsize) { + mp_raise_OSError(MP_EIO); + } + + if (swap_bytes) { + switch(element_size) { + case 2: + { + for(int i=0; i< rowsize_in_u16; i++) { + rowdata16[i] = __builtin_bswap16(rowdata16[i]); + } + } + break; + case 4: + for(int i=0; i< rowsize_in_u32; i++) { + rowdata32[i] = __builtin_bswap32(rowdata32[i]); + } + default: + break; + } + } + + for(int x=0; xwidth; x++) { + int value = 0; + switch(bits_per_pixel) { + case 1: + { + int byte_offset = x / 8; + int bit_offset = reverse_pixels_in_element ? (7 - x % 8) : x % 8; + + value = (rowdata8[byte_offset] >> bit_offset) & 1; + break; + } + case 2: + { + int byte_offset = x / 4; + int bit_offset = 2 * (reverse_pixels_in_element ? (3 - x % 4) : x % 4); + + value = (rowdata8[byte_offset] >> bit_offset) & 3; + break; + } + case 4: + { + int byte_offset = x / 2; + int bit_offset = 4 * (reverse_pixels_in_element ? (1 - x % 2) : x % 2); + + value = (rowdata8[byte_offset] >> bit_offset) & 7; + break; + } + case 8: + value = rowdata8[x]; + break; + + case 16: + value = rowdata16[x]; + break; + + case 24: + value = (rowdata8[x * 3] << 16) | (rowdata8[x * 3 + 1] << 8) | (rowdata8[x * 3 + 2] << 8); + break; + + case 32: + value = rowdata32[x]; + break; + } + + displayio_bitmap_write_pixel(self, x, y, value); + } + } + + displayio_bitmap_set_dirty_area(self, 0, 0, self->width, self->height); +} From 6e9a44bbfdeeebde8fb553b86dac3b15c3ab8318 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 14 Mar 2021 15:03:00 -0500 Subject: [PATCH 02/12] make translate --- locale/circuitpython.pot | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 2f15d70b12254..7aaf1bfabbce1 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -73,6 +73,7 @@ msgstr "" #: extmod/moductypes.c ports/atmel-samd/common-hal/pulseio/PulseIn.c #: ports/cxd56/common-hal/pulseio/PulseIn.c #: ports/nrf/common-hal/pulseio/PulseIn.c +#: ports/raspberrypi/common-hal/pulseio/PulseIn.c #: ports/stm/common-hal/pulseio/PulseIn.c py/obj.c py/objstr.c #: py/objstrunicode.c msgid "%q index out of range" @@ -962,6 +963,7 @@ msgstr "" #: ports/cxd56/common-hal/pulseio/PulseIn.c #: ports/esp32s2/common-hal/pulseio/PulseIn.c #: ports/nrf/common-hal/pulseio/PulseIn.c +#: ports/raspberrypi/common-hal/pulseio/PulseIn.c #: ports/stm/common-hal/pulseio/PulseIn.c #, c-format msgid "Failed to allocate RX buffer of %d bytes" @@ -1247,7 +1249,7 @@ msgstr "" msgid "Invalid format chunk size" msgstr "" -#: ports/esp32s2/common-hal/pwmio/PWMOut.c +#: ports/esp32s2/common-hal/busio/I2C.c ports/esp32s2/common-hal/pwmio/PWMOut.c msgid "Invalid frequency" msgstr "" @@ -2291,7 +2293,7 @@ msgstr "" msgid "Unsupported format" msgstr "" -#: py/moduerrno.c +#: ports/raspberrypi/common-hal/pulseio/PulseOut.c py/moduerrno.c msgid "Unsupported operation" msgstr "" @@ -3206,6 +3208,11 @@ msgstr "" msgid "invalid arguments" msgstr "" +#: shared-bindings/bitmaptools/__init__.c +#, c-format +msgid "invalid bits_per_pixel %d, must be, 1, 4, 8, 16, 24, or 32" +msgstr "" + #: extmod/modussl_axtls.c msgid "invalid cert" msgstr "" @@ -3214,6 +3221,16 @@ msgstr "" msgid "invalid dupterm index" msgstr "" +#: shared-bindings/bitmaptools/__init__.c +#, c-format +msgid "invalid element size %d for bits_per_pixel %d\n" +msgstr "" + +#: shared-bindings/bitmaptools/__init__.c +#, c-format +msgid "invalid element_size %d, must be, 1, 2, or 4" +msgstr "" + #: extmod/modframebuf.c msgid "invalid format" msgstr "" @@ -3699,6 +3716,7 @@ msgstr "" #: ports/atmel-samd/common-hal/pulseio/PulseIn.c #: ports/cxd56/common-hal/pulseio/PulseIn.c #: ports/nrf/common-hal/pulseio/PulseIn.c +#: ports/raspberrypi/common-hal/pulseio/PulseIn.c #: ports/stm/common-hal/pulseio/PulseIn.c py/objdict.c py/objlist.c py/objset.c #: shared-bindings/ps2io/Ps2.c msgid "pop from empty %q" @@ -3724,6 +3742,8 @@ msgstr "" #: ports/esp32s2/boards/espressif_kaluga_1/mpconfigboard.h #: ports/esp32s2/boards/espressif_saola_1_wroom/mpconfigboard.h #: ports/esp32s2/boards/espressif_saola_1_wrover/mpconfigboard.h +#: ports/esp32s2/boards/franzininho_wifi_wroom/mpconfigboard.h +#: ports/esp32s2/boards/franzininho_wifi_wrover/mpconfigboard.h #: ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h #: ports/esp32s2/boards/microdev_micro_s2/mpconfigboard.h #: ports/esp32s2/boards/muselab_nanoesp32_s2/mpconfigboard.h From 094265cb866fa60e1018bb36a4675de0169418a1 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 14 Mar 2021 15:36:20 -0500 Subject: [PATCH 03/12] bitmaptools.readinto: Fix diagnostics on atmel-samd builds --- shared-module/bitmaptools/__init__.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/shared-module/bitmaptools/__init__.c b/shared-module/bitmaptools/__init__.c index a41b5007c2ea4..1997076514f23 100644 --- a/shared-module/bitmaptools/__init__.c +++ b/shared-module/bitmaptools/__init__.c @@ -361,14 +361,12 @@ void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, pyb_file_obj_t* f if (swap_bytes) { switch(element_size) { case 2: - { - for(int i=0; i< rowsize_in_u16; i++) { - rowdata16[i] = __builtin_bswap16(rowdata16[i]); - } + for(size_t i=0; i< rowsize_in_u16; i++) { + rowdata16[i] = __builtin_bswap16(rowdata16[i]); } break; case 4: - for(int i=0; i< rowsize_in_u32; i++) { + for(size_t i=0; i< rowsize_in_u32; i++) { rowdata32[i] = __builtin_bswap32(rowdata32[i]); } default: From 651f54b4ccc7b35aa17f3e1498043aaea96a690f Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 14 Mar 2021 15:47:15 -0500 Subject: [PATCH 04/12] fix docs --- shared-bindings/bitmaptools/__init__.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-bindings/bitmaptools/__init__.c b/shared-bindings/bitmaptools/__init__.c index 0e655d5bfb08a..2780680d004b9 100644 --- a/shared-bindings/bitmaptools/__init__.c +++ b/shared-bindings/bitmaptools/__init__.c @@ -357,7 +357,7 @@ STATIC mp_obj_t bitmaptools_obj_draw_line(size_t n_args, const mp_obj_t *pos_arg MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_line_obj, 0, bitmaptools_obj_draw_line); // requires all 6 arguments -//| def readinto(bitmap: displayio.Bitmap, file: typing.BinaryIO, bits_per_pixel: int, element_size: int = 1, reverse_pixels_in_element: bool = False, swap_bytes_in_element: bool = False): +//| def readinto(bitmap: displayio.Bitmap, file: typing.BinaryIO, bits_per_pixel: int, element_size: int = 1, reverse_pixels_in_element: bool = False, swap_bytes_in_element: bool = False) -> None: //| """Read from a binary file into a bitmap //| The file must be positioned so that it consists of ``bitmap.height`` rows of pixel data, where each row is the smallest multiple of ``element_size`` bytes that can hold ``bitmap.width`` pixels. //| From b33d77bfe86d2ae5ef86ab0153a55e903cd1134b Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 14 Mar 2021 20:08:09 -0500 Subject: [PATCH 05/12] disable bitmaptools on over-full board --- .../atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk b/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk index 2f4db69b45258..29774db742c27 100755 --- a/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk @@ -15,6 +15,7 @@ CIRCUITPY_AUDIOBUSIO = 0 # No DAC on SAMR21G CIRCUITPY_AUDIOIO = 0 CIRCUITPY_BITBANGIO = 0 +CIRCUITPY_BITMAPTOOLS = 0 CIRCUITPY_COUNTIO = 0 CIRCUITPY_RTC = 0 CIRCUITPY_FREQUENCYIO = 0 From 542fb58673954be992e274b065425e4de2aea178 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 15 Mar 2021 20:19:45 -0500 Subject: [PATCH 06/12] add arrayblit --- shared-bindings/bitmaptools/__init__.c | 81 ++++++++++++++++++++++++++ shared-bindings/bitmaptools/__init__.h | 1 + shared-module/bitmaptools/__init__.c | 32 +++++++++- 3 files changed, 113 insertions(+), 1 deletion(-) diff --git a/shared-bindings/bitmaptools/__init__.c b/shared-bindings/bitmaptools/__init__.c index 2780680d004b9..5de85156a1c1e 100644 --- a/shared-bindings/bitmaptools/__init__.c +++ b/shared-bindings/bitmaptools/__init__.c @@ -29,6 +29,7 @@ #include +#include "py/binary.h" #include "py/obj.h" #include "py/runtime.h" @@ -357,6 +358,85 @@ STATIC mp_obj_t bitmaptools_obj_draw_line(size_t n_args, const mp_obj_t *pos_arg MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_line_obj, 0, bitmaptools_obj_draw_line); // requires all 6 arguments +//| def arrayblit(bitmap: display.Bitmap, data: ReadableBuffer, x1: int=0, y1: int=0, x2: Optional[int]=None, y2: Optional[int]=None, skip_index:Optional[int]=None) -> None: +//| """Inserts pixels from ``data`` into the rectangle of width×height pixels with the upper left corner at ``(x,y)`` +//| +//| The values from ``data`` are taken modulo the number of color values +//| avalable in the destintaion bitmap. +//| +//| 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. +//| +//| The coordinates affected by the blit are ``x1 <= x < x2`` and ``y1 < +//| y < y2``. +//| +//| ``data`` must contain at least as many elements as required. If it +//| contains excess elements, they are ignored. +//| +//| The blit takes place by rows, so the first elements of ``data`` go +//| to the first row, the next elements to the next row, and so on. +//| +//| :param displayio.Bitmap bitmap: A writable bitmap +//| :param ReadableBuffer data: Buffer containing the source pixel values +//| :param int x1: The left corner of the area to blit into (inclusive) +//| :param int y1: The top corner of the area to blit into (inclusive) +//| :param int x2: The right of the area to blit into (exclusive) +//| :param int y2: The bottom corner of the area to blit into (exclusive) +//| :param int skip_index: Bitmap palette index in the source that will not be copied, +//| set to None to copy all pixels""" +//| """ +//| ... +//| +STATIC mp_obj_t bitmaptools_arrayblit(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_bitmap, ARG_data, ARG_x1, ARG_y1, ARG_x2, ARG_y2, ARG_skip_index }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { 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_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); + + if (!MP_OBJ_IS_TYPE(args[ARG_bitmap].u_obj, &displayio_bitmap_type)) { + mp_raise_TypeError(NULL); + } + displayio_bitmap_t *bitmap = MP_OBJ_TO_PTR(args[ARG_bitmap].u_obj); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_data].u_obj, &bufinfo, MP_BUFFER_READ); + + int x1 = args[ARG_x1].u_int; + int y1 = args[ARG_y1].u_int; + int x2 = args[ARG_x2].u_int == -1 ? bitmap->width : args[ARG_x2].u_int; + int y2 = args[ARG_y2].u_int == -1 ? bitmap->height : args[ARG_y2].u_int; + + if ((x1 < 0) || (y1 < 0) || (x1 > x2) || (y1 > y2) || (x2 > bitmap->width) || (y2 > bitmap->height)) { + mp_raise_IndexError(translate("pixel coordinates out of bounds")); + } + + size_t output_element_count = (x2-x1) * (y2-y1); + size_t element_size = mp_binary_get_size('@', bufinfo.typecode, NULL); + size_t input_element_count = bufinfo.len / element_size; + + bool skip_specified = args[ARG_skip_index].u_obj != mp_const_none; + uint32_t skip_index = skip_specified ? mp_obj_get_int(args[ARG_skip_index].u_obj) : 0; + if (input_element_count < output_element_count) { + mp_raise_IndexError(translate("index out of range")); + } + + common_hal_bitmaptools_arrayblit(bitmap, bufinfo.buf, element_size, x1, y1, x2, y2, skip_specified, skip_index); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_arrayblit_obj, 0, bitmaptools_arrayblit); + + //| def readinto(bitmap: displayio.Bitmap, file: typing.BinaryIO, bits_per_pixel: int, element_size: int = 1, reverse_pixels_in_element: bool = False, swap_bytes_in_element: bool = False) -> None: //| """Read from a binary file into a bitmap //| The file must be positioned so that it consists of ``bitmap.height`` rows of pixel data, where each row is the smallest multiple of ``element_size`` bytes that can hold ``bitmap.width`` pixels. @@ -435,6 +515,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_readinto_obj, 0, bitmaptools_readinto); STATIC const mp_rom_map_elem_t bitmaptools_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&bitmaptools_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_rotozoom), MP_ROM_PTR(&bitmaptools_rotozoom_obj) }, + { MP_ROM_QSTR(MP_QSTR_arrayblit), MP_ROM_PTR(&bitmaptools_arrayblit_obj) }, { MP_ROM_QSTR(MP_QSTR_fill_region), MP_ROM_PTR(&bitmaptools_fill_region_obj) }, { MP_ROM_QSTR(MP_QSTR_draw_line), MP_ROM_PTR(&bitmaptools_draw_line_obj) }, }; diff --git a/shared-bindings/bitmaptools/__init__.h b/shared-bindings/bitmaptools/__init__.h index 50ad7f526446c..bb89cd7321da1 100644 --- a/shared-bindings/bitmaptools/__init__.h +++ b/shared-bindings/bitmaptools/__init__.h @@ -52,5 +52,6 @@ void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination, uint32_t value); void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, pyb_file_obj_t* file, int element_size, int bits_per_pixel, bool reverse_pixels_in_word, bool swap_bytes); +void common_hal_bitmaptools_arrayblit(displayio_bitmap_t *self, void *data, int element_size, int x1, int y1, int x2, int y2, bool skip_specified, uint32_t skip_index); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BITMAPTOOLS__INIT__H diff --git a/shared-module/bitmaptools/__init__.c b/shared-module/bitmaptools/__init__.c index 1997076514f23..e18b8b177974d 100644 --- a/shared-module/bitmaptools/__init__.c +++ b/shared-module/bitmaptools/__init__.c @@ -339,7 +339,37 @@ void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination, } } +void common_hal_bitmaptools_arrayblit(displayio_bitmap_t *self, void *data, int element_size, int x1, int y1, int x2, int y2, bool skip_specified, uint32_t skip_value) { + uint32_t mask = (1 << common_hal_displayio_bitmap_get_bits_per_value(self)) - 1; + + for (int y=y1; yread_only) { mp_raise_RuntimeError(translate("Read-only object")); } @@ -418,7 +448,7 @@ void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, pyb_file_obj_t* f break; } - displayio_bitmap_write_pixel(self, x, y, value); + displayio_bitmap_write_pixel(self, x, y, value & mask); } } From 97b6664201de2530c9b92957a5e8d2a68524fa7e Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 16 Mar 2021 12:20:09 -0500 Subject: [PATCH 07/12] re-format with uncrustify --- shared-bindings/bitmaptools/__init__.c | 86 ++++----- shared-bindings/bitmaptools/__init__.h | 30 +-- shared-module/bitmaptools/__init__.c | 247 ++++++++++++++----------- 3 files changed, 198 insertions(+), 165 deletions(-) diff --git a/shared-bindings/bitmaptools/__init__.c b/shared-bindings/bitmaptools/__init__.c index 5de85156a1c1e..0edbe135d51c6 100644 --- a/shared-bindings/bitmaptools/__init__.c +++ b/shared-bindings/bitmaptools/__init__.c @@ -38,7 +38,7 @@ STATIC int16_t validate_point(mp_obj_t point, int16_t default_value) { // Checks if point is None and returns default_value, otherwise decodes integer value - if ( point == mp_const_none ) { + if (point == mp_const_none) { return default_value; } return mp_obj_get_int(point); @@ -47,13 +47,13 @@ STATIC int16_t validate_point(mp_obj_t point, int16_t default_value) { STATIC void extract_tuple(mp_obj_t xy_tuple, int16_t *x, int16_t *y, int16_t x_default, int16_t y_default) { // Helper function for rotozoom // Extract x,y values from a tuple or default if None - if ( xy_tuple == mp_const_none ) { + if (xy_tuple == mp_const_none) { *x = x_default; *y = y_default; - } else if ( !MP_OBJ_IS_OBJ(xy_tuple) ) { + } else if (!MP_OBJ_IS_OBJ(xy_tuple)) { mp_raise_ValueError(translate("clip point must be (x,y) tuple")); } else { - mp_obj_t* items; + mp_obj_t *items; mp_obj_get_array_fixed_n(xy_tuple, 2, &items); *x = mp_obj_get_int(items[0]); *y = mp_obj_get_int(items[1]); @@ -61,7 +61,7 @@ STATIC void extract_tuple(mp_obj_t xy_tuple, int16_t *x, int16_t *y, int16_t x_d } STATIC void validate_clip_region(displayio_bitmap_t *bitmap, mp_obj_t clip0_tuple, int16_t *clip0_x, int16_t *clip0_y, - mp_obj_t clip1_tuple, int16_t *clip1_x, int16_t *clip1_y) { + mp_obj_t clip1_tuple, int16_t *clip1_x, int16_t *clip1_y) { // Helper function for rotozoom // 1. Extract the clip x,y points from the two clip tuples // 2. Rearrange values such that clip0_ < clip1_ @@ -71,12 +71,12 @@ STATIC void validate_clip_region(displayio_bitmap_t *bitmap, mp_obj_t clip0_tupl extract_tuple(clip1_tuple, clip1_x, clip1_y, bitmap->width, bitmap->height); // Ensure the value for clip0 is less than clip1 (for both x and y) - if ( *clip0_x > *clip1_x ) { + if (*clip0_x > *clip1_x) { int16_t temp_value = *clip0_x; // swap values *clip0_x = *clip1_x; *clip1_x = temp_value; } - if ( *clip0_y > *clip1_y ) { + if (*clip0_y > *clip1_y) { int16_t temp_value = *clip0_y; // swap values *clip0_y = *clip1_y; *clip1_y = temp_value; @@ -144,11 +144,11 @@ STATIC void validate_clip_region(displayio_bitmap_t *bitmap, mp_obj_t clip0_tupl //| set to None to copy all pixels""" //| ... //| -STATIC mp_obj_t bitmaptools_obj_rotozoom(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ +STATIC mp_obj_t bitmaptools_obj_rotozoom(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum {ARG_dest_bitmap, ARG_source_bitmap, - ARG_ox, ARG_oy, ARG_dest_clip0, ARG_dest_clip1, - ARG_px, ARG_py, ARG_source_clip0, ARG_source_clip1, - ARG_angle, ARG_scale, ARG_skip_index}; + ARG_ox, ARG_oy, ARG_dest_clip0, ARG_dest_clip1, + ARG_px, ARG_py, ARG_source_clip0, ARG_source_clip1, + ARG_angle, ARG_scale, ARG_skip_index}; static const mp_arg_t allowed_args[] = { {MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ}, @@ -166,7 +166,7 @@ STATIC mp_obj_t bitmaptools_obj_rotozoom(size_t n_args, const mp_obj_t *pos_args {MP_QSTR_angle, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, // None convert to 0.0 {MP_QSTR_scale, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, // None convert to 1.0 - {MP_QSTR_skip_index, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj=mp_const_none} }, + {MP_QSTR_skip_index, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -183,35 +183,35 @@ STATIC mp_obj_t bitmaptools_obj_rotozoom(size_t n_args, const mp_obj_t *pos_args // Confirm the destination location target (ox,oy); if None, default to bitmap midpoint int16_t ox, oy; - ox = validate_point(args[ARG_ox].u_obj, destination->width / 2); + ox = validate_point(args[ARG_ox].u_obj, destination->width / 2); oy = validate_point(args[ARG_oy].u_obj, destination->height / 2); // Confirm the source location target (px,py); if None, default to bitmap midpoint int16_t px, py; - px = validate_point(args[ARG_px].u_obj, source->width / 2); + px = validate_point(args[ARG_px].u_obj, source->width / 2); py = validate_point(args[ARG_py].u_obj, source->height / 2); // Validate the clipping regions for the destination bitmap int16_t dest_clip0_x, dest_clip0_y, dest_clip1_x, dest_clip1_y; validate_clip_region(destination, args[ARG_dest_clip0].u_obj, &dest_clip0_x, &dest_clip0_y, - args[ARG_dest_clip1].u_obj, &dest_clip1_x, &dest_clip1_y); + args[ARG_dest_clip1].u_obj, &dest_clip1_x, &dest_clip1_y); // Validate the clipping regions for the source bitmap int16_t source_clip0_x, source_clip0_y, source_clip1_x, source_clip1_y; validate_clip_region(source, args[ARG_source_clip0].u_obj, &source_clip0_x, &source_clip0_y, - args[ARG_source_clip1].u_obj, &source_clip1_x, &source_clip1_y); + args[ARG_source_clip1].u_obj, &source_clip1_x, &source_clip1_y); // Confirm the angle value - float angle=0.0; - if ( args[ARG_angle].u_obj != mp_const_none ) { + float angle = 0.0; + if (args[ARG_angle].u_obj != mp_const_none) { angle = mp_obj_get_float(args[ARG_angle].u_obj); } // Confirm the scale value - float scale=1.0; - if ( args[ARG_scale].u_obj != mp_const_none ) { + float scale = 1.0; + if (args[ARG_scale].u_obj != mp_const_none) { scale = mp_obj_get_float(args[ARG_scale].u_obj); } if (scale < 0) { // ensure scale >= 0 @@ -220,7 +220,7 @@ STATIC mp_obj_t bitmaptools_obj_rotozoom(size_t n_args, const mp_obj_t *pos_args uint32_t skip_index; bool skip_index_none; // Flag whether input skip_value was None - if (args[ARG_skip_index].u_obj == mp_const_none ) { + if (args[ARG_skip_index].u_obj == mp_const_none) { skip_index = 0; skip_index_none = true; } else { @@ -229,14 +229,14 @@ STATIC mp_obj_t bitmaptools_obj_rotozoom(size_t n_args, const mp_obj_t *pos_args } common_hal_bitmaptools_rotozoom(destination, ox, oy, - dest_clip0_x, dest_clip0_y, - dest_clip1_x, dest_clip1_y, - source, px, py, - source_clip0_x, source_clip0_y, - source_clip1_x, source_clip1_y, - angle, - scale, - skip_index, skip_index_none); + dest_clip0_x, dest_clip0_y, + dest_clip1_x, dest_clip1_y, + source, px, py, + source_clip0_x, source_clip0_y, + source_clip1_x, source_clip1_y, + angle, + scale, + skip_index, skip_index_none); return mp_const_none; } @@ -262,7 +262,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_rotozoom_obj, 0, bitmaptools_obj_rotozoom //| fill region in the destination bitmap""" //| ... //| -STATIC mp_obj_t bitmaptools_obj_fill_region(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ +STATIC mp_obj_t bitmaptools_obj_fill_region(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum {ARG_dest_bitmap, ARG_x1, ARG_y1, ARG_x2, ARG_y2, ARG_value}; static const mp_arg_t allowed_args[] = { @@ -282,8 +282,8 @@ STATIC mp_obj_t bitmaptools_obj_fill_region(size_t n_args, const mp_obj_t *pos_a value = args[ARG_value].u_int; color_depth = (1 << destination->bits_per_value); if (color_depth <= value) { - mp_raise_ValueError(translate("out of range of target")); - } + mp_raise_ValueError(translate("out of range of target")); + } int16_t x1 = args[ARG_x1].u_int; int16_t y1 = args[ARG_y1].u_int; @@ -315,7 +315,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_fill_region_obj, 0, bitmaptools_obj_fill_ //| line in the destination bitmap""" //| ... //| -STATIC mp_obj_t bitmaptools_obj_draw_line(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ +STATIC mp_obj_t bitmaptools_obj_draw_line(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum {ARG_dest_bitmap, ARG_x1, ARG_y1, ARG_x2, ARG_y2, ARG_value}; static const mp_arg_t allowed_args[] = { @@ -335,8 +335,8 @@ STATIC mp_obj_t bitmaptools_obj_draw_line(size_t n_args, const mp_obj_t *pos_arg value = args[ARG_value].u_int; color_depth = (1 << destination->bits_per_value); if (color_depth <= value) { - mp_raise_ValueError(translate("out of range of target")); - } + mp_raise_ValueError(translate("out of range of target")); + } int16_t x1 = args[ARG_x1].u_int; int16_t y1 = args[ARG_y1].u_int; @@ -344,9 +344,9 @@ STATIC mp_obj_t bitmaptools_obj_draw_line(size_t n_args, const mp_obj_t *pos_arg int16_t y2 = args[ARG_y2].u_int; // verify points are within the bitmap boundary (inclusive) - if ( (x1 < 0) || (x2 < 0) || (y1 < 0) || (y2 < 0) || - (x1 >= destination->width) || (x2 >= destination->width) || - (y1 >= destination->height) || (y2 >= destination->height) ) { + if ((x1 < 0) || (x2 < 0) || (y1 < 0) || (y2 < 0) || + (x1 >= destination->width) || (x2 >= destination->width) || + (y1 >= destination->height) || (y2 >= destination->height)) { mp_raise_ValueError(translate("out of range of target")); } @@ -399,7 +399,7 @@ STATIC mp_obj_t bitmaptools_arrayblit(size_t n_args, const mp_obj_t *pos_args, m { 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); @@ -420,7 +420,7 @@ STATIC mp_obj_t bitmaptools_arrayblit(size_t n_args, const mp_obj_t *pos_args, m mp_raise_IndexError(translate("pixel coordinates out of bounds")); } - size_t output_element_count = (x2-x1) * (y2-y1); + size_t output_element_count = (x2 - x1) * (y2 - y1); size_t element_size = mp_binary_get_size('@', bufinfo.typecode, NULL); size_t input_element_count = bufinfo.len / element_size; @@ -477,11 +477,11 @@ STATIC mp_obj_t bitmaptools_readinto(size_t n_args, const mp_obj_t *pos_args, mp if (!MP_OBJ_IS_TYPE(args[ARG_file].u_obj, &mp_type_fileio)) { mp_raise_TypeError(NULL); } - pyb_file_obj_t* file = MP_OBJ_TO_PTR(args[ARG_file].u_obj); + pyb_file_obj_t *file = MP_OBJ_TO_PTR(args[ARG_file].u_obj); int element_size = args[ARG_element_size].u_int; if (element_size != 1 && element_size != 2 && element_size != 4) { - mp_raise_ValueError_varg(translate("invalid element_size %d, must be, 1, 2, or 4"), element_size); + mp_raise_ValueError_varg(translate("invalid element_size %d, must be, 1, 2, or 4"), element_size); } int bits_per_pixel = args[ARG_bits_per_pixel].u_int; @@ -523,5 +523,5 @@ STATIC MP_DEFINE_CONST_DICT(bitmaptools_module_globals, bitmaptools_module_globa const mp_obj_module_t bitmaptools_module = { .base = {&mp_type_module }, - .globals = (mp_obj_dict_t*)&bitmaptools_module_globals, + .globals = (mp_obj_dict_t *)&bitmaptools_module_globals, }; diff --git a/shared-bindings/bitmaptools/__init__.h b/shared-bindings/bitmaptools/__init__.h index bb89cd7321da1..6b80f98f539ba 100644 --- a/shared-bindings/bitmaptools/__init__.h +++ b/shared-bindings/bitmaptools/__init__.h @@ -32,26 +32,26 @@ #include "extmod/vfs_fat.h" void common_hal_bitmaptools_rotozoom(displayio_bitmap_t *self, int16_t ox, int16_t oy, - int16_t dest_clip0_x, int16_t dest_clip0_y, - int16_t dest_clip1_x, int16_t dest_clip1_y, - displayio_bitmap_t *source, int16_t px, int16_t py, - int16_t source_clip0_x, int16_t source_clip0_y, - int16_t source_clip1_x, int16_t source_clip1_y, - float angle, - float scale, - uint32_t skip_index, bool skip_index_none); + int16_t dest_clip0_x, int16_t dest_clip0_y, + int16_t dest_clip1_x, int16_t dest_clip1_y, + displayio_bitmap_t *source, int16_t px, int16_t py, + int16_t source_clip0_x, int16_t source_clip0_y, + int16_t source_clip1_x, int16_t source_clip1_y, + float angle, + float scale, + uint32_t skip_index, bool skip_index_none); void common_hal_bitmaptools_fill_region(displayio_bitmap_t *destination, - int16_t x1, int16_t y1, - int16_t x2, int16_t y2, - uint32_t value); + int16_t x1, int16_t y1, + int16_t x2, int16_t y2, + uint32_t value); void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination, - int16_t x0, int16_t y0, - int16_t x1, int16_t y1, - uint32_t value); + int16_t x0, int16_t y0, + int16_t x1, int16_t y1, + uint32_t value); -void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, pyb_file_obj_t* file, int element_size, int bits_per_pixel, bool reverse_pixels_in_word, bool swap_bytes); +void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, pyb_file_obj_t *file, int element_size, int bits_per_pixel, bool reverse_pixels_in_word, bool swap_bytes); void common_hal_bitmaptools_arrayblit(displayio_bitmap_t *self, void *data, int element_size, int x1, int y1, int x2, int y2, bool skip_specified, uint32_t skip_index); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BITMAPTOOLS__INIT__H diff --git a/shared-module/bitmaptools/__init__.c b/shared-module/bitmaptools/__init__.c index e18b8b177974d..4e0d72452dbbe 100644 --- a/shared-module/bitmaptools/__init__.c +++ b/shared-module/bitmaptools/__init__.c @@ -36,14 +36,14 @@ #include "stdlib.h" void common_hal_bitmaptools_rotozoom(displayio_bitmap_t *self, int16_t ox, int16_t oy, - int16_t dest_clip0_x, int16_t dest_clip0_y, - int16_t dest_clip1_x, int16_t dest_clip1_y, - displayio_bitmap_t *source, int16_t px, int16_t py, - int16_t source_clip0_x, int16_t source_clip0_y, - int16_t source_clip1_x, int16_t source_clip1_y, - float angle, - float scale, - uint32_t skip_index, bool skip_index_none) { + int16_t dest_clip0_x, int16_t dest_clip0_y, + int16_t dest_clip1_x, int16_t dest_clip1_y, + displayio_bitmap_t *source, int16_t px, int16_t py, + int16_t source_clip0_x, int16_t source_clip0_y, + int16_t source_clip1_x, int16_t source_clip1_y, + float angle, + float scale, + uint32_t skip_index, bool skip_index_none) { // Copies region from source to the destination bitmap, including rotation, // scaling and clipping of either the source or destination regions @@ -115,37 +115,77 @@ void common_hal_bitmaptools_rotozoom(displayio_bitmap_t *self, int16_t ox, int16 will be on the destination to get a bounding box for scanning */ dx = -cosAngle * px * scale + sinAngle * py * scale + ox; dy = -sinAngle * px * scale - cosAngle * py * scale + oy; - if(dx < minx) minx = (int16_t)dx; - if(dx > maxx) maxx = (int16_t)dx; - if(dy < miny) miny = (int16_t)dy; - if(dy > maxy) maxy = (int16_t)dy; + if (dx < minx) { + minx = (int16_t)dx; + } + if (dx > maxx) { + maxx = (int16_t)dx; + } + if (dy < miny) { + miny = (int16_t)dy; + } + if (dy > maxy) { + maxy = (int16_t)dy; + } dx = cosAngle * (source->width - px) * scale + sinAngle * py * scale + ox; dy = sinAngle * (source->width - px) * scale - cosAngle * py * scale + oy; - if(dx < minx) minx = (int16_t)dx; - if(dx > maxx) maxx = (int16_t)dx; - if(dy < miny) miny = (int16_t)dy; - if(dy > maxy) maxy = (int16_t)dy; + if (dx < minx) { + minx = (int16_t)dx; + } + if (dx > maxx) { + maxx = (int16_t)dx; + } + if (dy < miny) { + miny = (int16_t)dy; + } + if (dy > maxy) { + maxy = (int16_t)dy; + } dx = cosAngle * (source->width - px) * scale - sinAngle * (source->height - py) * scale + ox; dy = sinAngle * (source->width - px) * scale + cosAngle * (source->height - py) * scale + oy; - if(dx < minx) minx = (int16_t)dx; - if(dx > maxx) maxx = (int16_t)dx; - if(dy < miny) miny = (int16_t)dy; - if(dy > maxy) maxy = (int16_t)dy; + if (dx < minx) { + minx = (int16_t)dx; + } + if (dx > maxx) { + maxx = (int16_t)dx; + } + if (dy < miny) { + miny = (int16_t)dy; + } + if (dy > maxy) { + maxy = (int16_t)dy; + } dx = -cosAngle * px * scale - sinAngle * (source->height - py) * scale + ox; dy = -sinAngle * px * scale + cosAngle * (source->height - py) * scale + oy; - if(dx < minx) minx = (int16_t)dx; - if(dx > maxx) maxx = (int16_t)dx; - if(dy < miny) miny = (int16_t)dy; - if(dy > maxy) maxy = (int16_t)dy; + if (dx < minx) { + minx = (int16_t)dx; + } + if (dx > maxx) { + maxx = (int16_t)dx; + } + if (dy < miny) { + miny = (int16_t)dy; + } + if (dy > maxy) { + maxy = (int16_t)dy; + } /* Clipping */ - if(minx < dest_clip0_x) minx = dest_clip0_x; - if(maxx > dest_clip1_x - 1) maxx = dest_clip1_x - 1; - if(miny < dest_clip0_y) miny = dest_clip0_y; - if(maxy > dest_clip1_y - 1) maxy = dest_clip1_y - 1; + if (minx < dest_clip0_x) { + minx = dest_clip0_x; + } + if (maxx > dest_clip1_x - 1) { + maxx = dest_clip1_x - 1; + } + if (miny < dest_clip0_y) { + miny = dest_clip0_y; + } + if (maxy > dest_clip1_y - 1) { + maxy = dest_clip1_y - 1; + } float dvCol = cosAngle / scale; float duCol = sinAngle / scale; @@ -159,13 +199,13 @@ void common_hal_bitmaptools_rotozoom(displayio_bitmap_t *self, int16_t ox, int16 float rowu = startu + miny * duCol; float rowv = startv + miny * dvCol; - for(y = miny; y <= maxy; y++) { + for (y = miny; y <= maxy; y++) { float u = rowu + minx * duRow; float v = rowv + minx * dvRow; - for(x = minx; x <= maxx; x++) { - if(u >= source_clip0_x && u < source_clip1_x && v >= source_clip0_y && v < source_clip1_y) { + for (x = minx; x <= maxx; x++) { + if (u >= source_clip0_x && u < source_clip1_x && v >= source_clip0_y && v < source_clip1_y) { uint32_t c = common_hal_displayio_bitmap_get_pixel(source, u, v); - if( (skip_index_none) || (c != skip_index) ) { + if ((skip_index_none) || (c != skip_index)) { common_hal_displayio_bitmap_set_pixel(self, x, y, c); } } @@ -189,9 +229,9 @@ int16_t constrain(int16_t input, int16_t min, int16_t max) { } void common_hal_bitmaptools_fill_region(displayio_bitmap_t *destination, - int16_t x1, int16_t y1, - int16_t x2, int16_t y2, - uint32_t value) { + int16_t x1, int16_t y1, + int16_t x2, int16_t y2, + uint32_t value) { // writes the value (a bitmap color index) into a bitmap in the specified rectangular region // // input checks should ensure that x1 < x2 and y1 < y2 and are within the bitmap region @@ -202,14 +242,14 @@ void common_hal_bitmaptools_fill_region(displayio_bitmap_t *destination, // Ensure x1 < x2 and y1 < y2 if (x1 > x2) { - int16_t temp=x2; - x2=x1; - x1=temp; + int16_t temp = x2; + x2 = x1; + x1 = temp; } if (y1 > y2) { - int16_t temp=y2; - y2=y1; - y1=temp; + int16_t temp = y2; + y2 = y1; + y1 = temp; } // constrain to bitmap dimensions @@ -223,16 +263,16 @@ void common_hal_bitmaptools_fill_region(displayio_bitmap_t *destination, int16_t x, y; for (x = x1; x < x2; x++) { - for (y = y1; y < y2; y++ ) { + for (y = y1; y < y2; y++) { displayio_bitmap_write_pixel(destination, x, y, value); } } } void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination, - int16_t x0, int16_t y0, - int16_t x1, int16_t y1, - uint32_t value) { + int16_t x0, int16_t y0, + int16_t x1, int16_t y1, + uint32_t value) { if (destination->read_only) { mp_raise_RuntimeError(translate("Read-only object")); @@ -277,8 +317,7 @@ void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination, for (y = y0; y < (y1 + 1); y++) { // write a horizontal line displayio_bitmap_write_pixel(destination, x0, y, value); } - } - else if (y0 == y1) { // horizontal line + } else if (y0 == y1) { // horizontal line if (x0 > x1) { // ensure y1 > y0 temp = x0; x0 = x1; @@ -287,12 +326,11 @@ void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination, for (x = x0; x < (x1 + 1); x++) { // write a horizontal line displayio_bitmap_write_pixel(destination, x, y0, value); } - } - else { + } else { bool steep; - steep = ( abs(y1 - y0) > abs(x1 - x0) ); + steep = (abs(y1 - y0) > abs(x1 - x0)); - if ( steep ) { // flip x0<->y0 and x1<->y1 + if (steep) { // flip x0<->y0 and x1<->y1 temp = x0; x0 = y0; y0 = temp; @@ -318,16 +356,14 @@ void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination, if (y0 < y1) { ystep = 1; - } - else { + } else { ystep = -1; } for (x = x0; x < (x1 + 1); x++) { if (steep) { displayio_bitmap_write_pixel(destination, y0, x, value); - } - else { + } else { displayio_bitmap_write_pixel(destination, x, y0, value); } err -= dy; @@ -342,23 +378,23 @@ void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination, void common_hal_bitmaptools_arrayblit(displayio_bitmap_t *self, void *data, int element_size, int x1, int y1, int x2, int y2, bool skip_specified, uint32_t skip_value) { uint32_t mask = (1 << common_hal_displayio_bitmap_get_bits_per_value(self)) - 1; - for (int y=y1; yread_only) { @@ -378,10 +414,10 @@ void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, pyb_file_obj_t* f size_t rowsize = element_size * elements_per_row; size_t rowsize_in_u32 = (rowsize + sizeof(uint32_t) - 1) / sizeof(uint32_t); size_t rowsize_in_u16 = (rowsize + sizeof(uint16_t) - 1) / sizeof(uint16_t); - for(int y=0; yheight; y++) { + for (int y = 0; y < self->height; y++) { uint32_t rowdata32[rowsize_in_u32]; - uint16_t *rowdata16 = (uint16_t*)rowdata32; - uint8_t *rowdata8 = (uint8_t*)rowdata32; + uint16_t *rowdata16 = (uint16_t *)rowdata32; + uint8_t *rowdata8 = (uint8_t *)rowdata32; UINT bytes_read = 0; if (f_read(&file->fp, rowdata32, rowsize, &bytes_read) != FR_OK || bytes_read != rowsize) { @@ -389,63 +425,60 @@ void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, pyb_file_obj_t* f } if (swap_bytes) { - switch(element_size) { - case 2: - for(size_t i=0; i< rowsize_in_u16; i++) { - rowdata16[i] = __builtin_bswap16(rowdata16[i]); - } - break; - case 4: - for(size_t i=0; i< rowsize_in_u32; i++) { - rowdata32[i] = __builtin_bswap32(rowdata32[i]); - } - default: - break; + switch (element_size) { + case 2: + for (size_t i = 0; i < rowsize_in_u16; i++) { + rowdata16[i] = __builtin_bswap16(rowdata16[i]); + } + break; + case 4: + for (size_t i = 0; i < rowsize_in_u32; i++) { + rowdata32[i] = __builtin_bswap32(rowdata32[i]); + } + default: + break; } } - for(int x=0; xwidth; x++) { + for (int x = 0; x < self->width; x++) { int value = 0; - switch(bits_per_pixel) { - case 1: - { + switch (bits_per_pixel) { + case 1: { int byte_offset = x / 8; int bit_offset = reverse_pixels_in_element ? (7 - x % 8) : x % 8; value = (rowdata8[byte_offset] >> bit_offset) & 1; break; } - case 2: - { + case 2: { int byte_offset = x / 4; int bit_offset = 2 * (reverse_pixels_in_element ? (3 - x % 4) : x % 4); value = (rowdata8[byte_offset] >> bit_offset) & 3; break; } - case 4: - { + case 4: { int byte_offset = x / 2; int bit_offset = 4 * (reverse_pixels_in_element ? (1 - x % 2) : x % 2); value = (rowdata8[byte_offset] >> bit_offset) & 7; break; } - case 8: - value = rowdata8[x]; - break; + case 8: + value = rowdata8[x]; + break; - case 16: - value = rowdata16[x]; - break; + case 16: + value = rowdata16[x]; + break; - case 24: - value = (rowdata8[x * 3] << 16) | (rowdata8[x * 3 + 1] << 8) | (rowdata8[x * 3 + 2] << 8); - break; + case 24: + value = (rowdata8[x * 3] << 16) | (rowdata8[x * 3 + 1] << 8) | (rowdata8[x * 3 + 2] << 8); + break; - case 32: - value = rowdata32[x]; - break; + case 32: + value = rowdata32[x]; + break; } displayio_bitmap_write_pixel(self, x, y, value & mask); From e1dd396de7fc489bb5b4fa8d08f36ab6480063dc Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 16 Mar 2021 13:37:04 -0500 Subject: [PATCH 08/12] fix stub docs --- shared-bindings/bitmaptools/__init__.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared-bindings/bitmaptools/__init__.c b/shared-bindings/bitmaptools/__init__.c index 0edbe135d51c6..ae1787439ff4f 100644 --- a/shared-bindings/bitmaptools/__init__.c +++ b/shared-bindings/bitmaptools/__init__.c @@ -358,7 +358,7 @@ STATIC mp_obj_t bitmaptools_obj_draw_line(size_t n_args, const mp_obj_t *pos_arg MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_line_obj, 0, bitmaptools_obj_draw_line); // requires all 6 arguments -//| def arrayblit(bitmap: display.Bitmap, data: ReadableBuffer, x1: int=0, y1: int=0, x2: Optional[int]=None, y2: Optional[int]=None, skip_index:Optional[int]=None) -> None: +//| def arrayblit(bitmap: displayio.Bitmap, data: ReadableBuffer, x1: int=0, y1: int=0, x2: Optional[int]=None, y2: Optional[int]=None, skip_index:Optional[int]=None) -> None: //| """Inserts pixels from ``data`` into the rectangle of width×height pixels with the upper left corner at ``(x,y)`` //| //| The values from ``data`` are taken modulo the number of color values @@ -384,7 +384,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_line_obj, 0, bitmaptools_obj_draw_li //| :param int x2: The right of the area to blit into (exclusive) //| :param int y2: The bottom corner of the area to blit into (exclusive) //| :param int skip_index: Bitmap palette index in the source that will not be copied, -//| set to None to copy all pixels""" +//| set to None to copy all pixels //| """ //| ... //| From df2d08366afa14f52e537d267bd4f75032865f2a Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 16 Mar 2021 13:37:19 -0500 Subject: [PATCH 09/12] make translate --- locale/circuitpython.pot | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 53c8ed2cec266..bc084219f67e1 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -2851,6 +2851,10 @@ msgstr "" msgid "differentiation order out of range" msgstr "" +#: extmod/ulab/code/linalg/linalg.c +msgid "dimensions do not match" +msgstr "" + #: py/modmath.c py/objfloat.c py/objint_longlong.c py/objint_mpz.c py/runtime.c #: shared-bindings/math/__init__.c msgid "division by zero" @@ -3357,10 +3361,6 @@ msgstr "" msgid "math domain error" msgstr "" -#: extmod/ulab/code/linalg/linalg.c -msgid "matrix dimensions do not match" -msgstr "" - #: extmod/ulab/code/linalg/linalg.c msgid "matrix is not positive definite" msgstr "" @@ -4175,10 +4175,6 @@ msgstr "" msgid "value_count must be > 0" msgstr "" -#: extmod/ulab/code/linalg/linalg.c -msgid "vectors must have same lengths" -msgstr "" - #: ports/esp32s2/common-hal/alarm/pin/__init__.c msgid "wakeup conflict" msgstr "" From 5810004bc9b4e50d6e21abf361d280d4046a5ca5 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 16 Mar 2021 19:01:38 -0500 Subject: [PATCH 10/12] fix doc error --- shared-bindings/bitmaptools/__init__.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/shared-bindings/bitmaptools/__init__.c b/shared-bindings/bitmaptools/__init__.c index ae1787439ff4f..7d89ec252cd0e 100644 --- a/shared-bindings/bitmaptools/__init__.c +++ b/shared-bindings/bitmaptools/__init__.c @@ -368,8 +368,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_line_obj, 0, bitmaptools_obj_draw_li //| are not specified, or are given as -1, they are taken as the width //| and height of the image. //| -//| The coordinates affected by the blit are ``x1 <= x < x2`` and ``y1 < -//| y < y2``. +//| The coordinates affected by the blit are ``x1 <= x < x2`` and ``y1 <= y < y2``. //| //| ``data`` must contain at least as many elements as required. If it //| contains excess elements, they are ignored. From 94fa8e8a606352ad3eb7c5986e62d9850ceeb865 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 16 Mar 2021 19:04:21 -0500 Subject: [PATCH 11/12] disable bitmaptools on small board --- ports/atmel-samd/boards/cp_sapling_m0_spiflash/mpconfigboard.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/atmel-samd/boards/cp_sapling_m0_spiflash/mpconfigboard.mk b/ports/atmel-samd/boards/cp_sapling_m0_spiflash/mpconfigboard.mk index 48b22b394e02d..1a1bf8cc79b11 100644 --- a/ports/atmel-samd/boards/cp_sapling_m0_spiflash/mpconfigboard.mk +++ b/ports/atmel-samd/boards/cp_sapling_m0_spiflash/mpconfigboard.mk @@ -14,6 +14,7 @@ EXTERNAL_FLASH_DEVICES = AT25DF081A CIRCUITPY_AUDIOIO = 0 CIRCUITPY_AUDIOBUSIO = 0 CIRCUITPY_BITBANGIO = 0 +CIRCUITPY_BITMAPTOOLS = 0 CIRCUITPY_COUNTIO = 0 CIRCUITPY_FREQUENCYIO = 0 CIRCUITPY_I2CPERIPHERAL = 0 From 074ba1daff2c188d1aef278833982016da49f403 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 16 Mar 2021 19:05:06 -0500 Subject: [PATCH 12/12] more doc fixes --- shared-bindings/bitmaptools/__init__.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-bindings/bitmaptools/__init__.c b/shared-bindings/bitmaptools/__init__.c index 7d89ec252cd0e..bdd4d3e676d06 100644 --- a/shared-bindings/bitmaptools/__init__.c +++ b/shared-bindings/bitmaptools/__init__.c @@ -362,7 +362,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_line_obj, 0, bitmaptools_obj_draw_li //| """Inserts pixels from ``data`` into the rectangle of width×height pixels with the upper left corner at ``(x,y)`` //| //| The values from ``data`` are taken modulo the number of color values -//| avalable in the destintaion bitmap. +//| avalable in the destination bitmap. //| //| 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