Skip to content

Add reverse_rows to speedy bitmaptools.readinto function #4428

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Mar 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion locale/circuitpython.pot
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,7 @@ msgstr ""
#: ports/atmel-samd/common-hal/displayio/ParallelBus.c
#: ports/esp32s2/common-hal/displayio/ParallelBus.c
#: ports/nrf/common-hal/displayio/ParallelBus.c
#: ports/raspberrypi/common-hal/displayio/ParallelBus.c
#, c-format
msgid "Bus pin %d is already in use"
msgstr ""
Expand Down Expand Up @@ -1729,7 +1730,6 @@ msgid "PWM slice channel A already in use"
msgstr ""

#: ports/mimxrt10xx/common-hal/displayio/ParallelBus.c
#: ports/raspberrypi/common-hal/displayio/ParallelBus.c
#: ports/stm/common-hal/displayio/ParallelBus.c
msgid "ParallelBus not yet supported"
msgstr ""
Expand Down
39 changes: 22 additions & 17 deletions shared-bindings/bitmaptools/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
//| """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 destination bitmap.
//| The values from ``data`` are taken modulo the number of color values
//| 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
//| and height of the image.
//| 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``.
//| 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.
//| ``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.
//| 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
Expand Down Expand Up @@ -436,33 +436,37 @@ 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);


//| 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.
//| 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:
//| """Reads from a binary file into a bitmap.
//|
//| 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 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.
//| :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) {
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[] = {
{ 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_QSTR_reverse_rows, MP_ARG_BOOL, { .u_bool = false } },
};

mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
Expand Down Expand Up @@ -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 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;
}
Expand Down
2 changes: 1 addition & 1 deletion shared-bindings/bitmaptools/__init__.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ 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);
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);

#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BITMAPTOOLS__INIT__H
7 changes: 4 additions & 3 deletions shared-module/bitmaptools/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ void common_hal_bitmaptools_arrayblit(displayio_bitmap_t *self, void *data, int
}
}

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;

if (self->read_only) {
Expand All @@ -414,10 +414,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_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; y < self->height; y++) {
uint32_t rowdata32[rowsize_in_u32];
uint16_t *rowdata16 = (uint16_t *)rowdata32;
uint8_t *rowdata8 = (uint8_t *)rowdata32;
const int y_draw = reverse_rows ? (self->height) - 1 - y : y;

UINT bytes_read = 0;
if (f_read(&file->fp, rowdata32, rowsize, &bytes_read) != FR_OK || bytes_read != rowsize) {
Expand Down Expand Up @@ -480,8 +482,7 @@ void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, pyb_file_obj_t *f
value = rowdata32[x];
break;
}

displayio_bitmap_write_pixel(self, x, y, value & mask);
displayio_bitmap_write_pixel(self, x, y_draw, value & mask);
}
}

Expand Down