Merge pull request #4428 from kmatch98/bitmap-read-2

Add `reverse_rows` to speedy bitmaptools.readinto function
This commit is contained in:
Jeff Epler 2021-03-18 18:41:35 -05:00 committed by GitHub
commit d0125617fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 28 additions and 22 deletions

View File

@ -550,6 +550,7 @@ msgstr ""
#: ports/atmel-samd/common-hal/displayio/ParallelBus.c #: ports/atmel-samd/common-hal/displayio/ParallelBus.c
#: ports/esp32s2/common-hal/displayio/ParallelBus.c #: ports/esp32s2/common-hal/displayio/ParallelBus.c
#: ports/nrf/common-hal/displayio/ParallelBus.c #: ports/nrf/common-hal/displayio/ParallelBus.c
#: ports/raspberrypi/common-hal/displayio/ParallelBus.c
#, c-format #, c-format
msgid "Bus pin %d is already in use" msgid "Bus pin %d is already in use"
msgstr "" msgstr ""
@ -1729,7 +1730,6 @@ msgid "PWM slice channel A already in use"
msgstr "" msgstr ""
#: ports/mimxrt10xx/common-hal/displayio/ParallelBus.c #: ports/mimxrt10xx/common-hal/displayio/ParallelBus.c
#: ports/raspberrypi/common-hal/displayio/ParallelBus.c
#: ports/stm/common-hal/displayio/ParallelBus.c #: ports/stm/common-hal/displayio/ParallelBus.c
msgid "ParallelBus not yet supported" msgid "ParallelBus not yet supported"
msgstr "" msgstr ""

View File

@ -361,20 +361,20 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_line_obj, 0, bitmaptools_obj_draw_li
//| 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: //| 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)`` //| """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 //| The values from ``data`` are taken modulo the number of color values
//| avalable in the destination bitmap. //| avalable in the destination bitmap.
//| //|
//| If x1 or y1 are not specified, they are taken as 0. If x2 or y2 //| 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 //| are not specified, or are given as -1, they are taken as the width
//| and height of the image. //| 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 //| ``data`` must contain at least as many elements as required. If it
//| contains excess elements, they are ignored. //| contains excess elements, they are ignored.
//| //|
//| The blit takes place by rows, so the first elements of ``data`` go //| 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. //| to the first row, the next elements to the next row, and so on.
//| //|
//| :param displayio.Bitmap bitmap: A writable bitmap //| :param displayio.Bitmap bitmap: A writable bitmap
//| :param ReadableBuffer data: Buffer containing the source pixel values //| :param ReadableBuffer data: Buffer containing the source pixel values
@ -436,13 +436,15 @@ STATIC mp_obj_t bitmaptools_arrayblit(size_t n_args, const mp_obj_t *pos_args, m
MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_arrayblit_obj, 0, bitmaptools_arrayblit); 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: //| 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, reverse_rows: bool = False) -> None:
//| """Read from a binary file into a bitmap //| """Reads 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. //| 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.
//| //|
//| This function doesn't parse image headers, but is useful to speed up loading of uncompressed image formats such as PCF glyph data. //| The bytes in an element can be optionally swapped, and the pixels in an element can be reversed. Also, the
//| row loading direction can be reversed, which may be requires for loading certain bitmap files.
//|
//| 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 displayio.Bitmap bitmap: A writable bitmap
//| :param typing.BinaryIO file: A file opened in binary mode //| :param typing.BinaryIO file: A file opened in binary mode
@ -450,12 +452,13 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_arrayblit_obj, 0, bitmaptools_arrayblit);
//| :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 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 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. //| :param bool swap_bytes_in_element: If the ``element_size`` is not 1, then reverse the byte order of each element read.
//| :param bool reverse_rows: Reverse the direction of the row loading (required for some bitmap images).
//| """ //| """
//| ... //| ...
//| //|
STATIC mp_obj_t bitmaptools_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { 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 }; enum { ARG_bitmap, ARG_file, ARG_bits_per_pixel, ARG_element_size, ARG_reverse_pixels_in_element, ARG_swap_bytes_in_element, ARG_reverse_rows };
static const mp_arg_t allowed_args[] = { static const mp_arg_t allowed_args[] = {
{ MP_QSTR_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_file, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_file, MP_ARG_REQUIRED | MP_ARG_OBJ },
@ -463,6 +466,7 @@ STATIC mp_obj_t bitmaptools_readinto(size_t n_args, const mp_obj_t *pos_args, mp
{ MP_QSTR_element_size, MP_ARG_INT, { .u_int = 1 } }, { MP_QSTR_element_size, MP_ARG_INT, { .u_int = 1 } },
{ MP_QSTR_reverse_pixels_in_element, MP_ARG_BOOL, { .u_bool = false } }, { 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_QSTR_swap_bytes_in_element, MP_ARG_BOOL, { .u_bool = false } },
{ MP_QSTR_reverse_rows, MP_ARG_BOOL, { .u_bool = false } },
}; };
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
@ -503,8 +507,9 @@ STATIC mp_obj_t bitmaptools_readinto(size_t n_args, const mp_obj_t *pos_args, mp
bool reverse_pixels_in_element = args[ARG_reverse_pixels_in_element].u_bool; 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; bool swap_bytes_in_element = args[ARG_swap_bytes_in_element].u_bool;
bool reverse_rows = args[ARG_reverse_rows].u_bool;
common_hal_bitmaptools_readinto(bitmap, file, element_size, bits_per_pixel, reverse_pixels_in_element, swap_bytes_in_element); common_hal_bitmaptools_readinto(bitmap, file, element_size, bits_per_pixel, reverse_pixels_in_element, swap_bytes_in_element, reverse_rows);
return mp_const_none; return mp_const_none;
} }

View File

@ -51,7 +51,7 @@ void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination,
int16_t x1, int16_t y1, int16_t x1, int16_t y1,
uint32_t value); 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, bool reverse_rows);
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); 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 #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BITMAPTOOLS__INIT__H

View File

@ -404,7 +404,7 @@ void common_hal_bitmaptools_arrayblit(displayio_bitmap_t *self, void *data, int
displayio_bitmap_set_dirty_area(self, x1, y1, x2, y2); displayio_bitmap_set_dirty_area(self, x1, y1, x2, y2);
} }
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) { 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, bool reverse_rows) {
uint32_t mask = (1 << common_hal_displayio_bitmap_get_bits_per_value(self)) - 1; uint32_t mask = (1 << common_hal_displayio_bitmap_get_bits_per_value(self)) - 1;
if (self->read_only) { if (self->read_only) {
@ -415,10 +415,12 @@ 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 = element_size * elements_per_row;
size_t rowsize_in_u32 = (rowsize + sizeof(uint32_t) - 1) / sizeof(uint32_t); 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); size_t rowsize_in_u16 = (rowsize + sizeof(uint16_t) - 1) / sizeof(uint16_t);
for (int y = 0; y < self->height; y++) { for (int y = 0; y < self->height; y++) {
uint32_t rowdata32[rowsize_in_u32]; uint32_t rowdata32[rowsize_in_u32];
uint16_t *rowdata16 = (uint16_t *)rowdata32; uint16_t *rowdata16 = (uint16_t *)rowdata32;
uint8_t *rowdata8 = (uint8_t *)rowdata32; uint8_t *rowdata8 = (uint8_t *)rowdata32;
const int y_draw = reverse_rows ? (self->height) - 1 - y : y;
UINT bytes_read = 0; UINT bytes_read = 0;
if (f_read(&file->fp, rowdata32, rowsize, &bytes_read) != FR_OK || bytes_read != rowsize) { if (f_read(&file->fp, rowdata32, rowsize, &bytes_read) != FR_OK || bytes_read != rowsize) {
@ -481,8 +483,7 @@ void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, pyb_file_obj_t *f
value = rowdata32[x]; value = rowdata32[x];
break; break;
} }
displayio_bitmap_write_pixel(self, x, y_draw, value & mask);
displayio_bitmap_write_pixel(self, x, y, value & mask);
} }
} }