From 9133b23a37649cc53568f8208c2493348441d700 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 14 Mar 2021 13:27:28 -0500 Subject: 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-module/bitmaptools/__init__.c | 90 ++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) (limited to 'shared-module/bitmaptools') diff --git a/shared-module/bitmaptools/__init__.c b/shared-module/bitmaptools/__init__.c index 6f168b555..a41b5007c 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); +} -- cgit v1.2.3 From 094265cb866fa60e1018bb36a4675de0169418a1 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 14 Mar 2021 15:36:20 -0500 Subject: bitmaptools.readinto: Fix diagnostics on atmel-samd builds --- shared-module/bitmaptools/__init__.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'shared-module/bitmaptools') diff --git a/shared-module/bitmaptools/__init__.c b/shared-module/bitmaptools/__init__.c index a41b5007c..199707651 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: -- cgit v1.2.3 From 542fb58673954be992e274b065425e4de2aea178 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Mon, 15 Mar 2021 20:19:45 -0500 Subject: 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(-) (limited to 'shared-module/bitmaptools') diff --git a/shared-bindings/bitmaptools/__init__.c b/shared-bindings/bitmaptools/__init__.c index 2780680d0..5de85156a 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 50ad7f526..bb89cd732 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 199707651..e18b8b177 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); } } -- cgit v1.2.3 From 97b6664201de2530c9b92957a5e8d2a68524fa7e Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 16 Mar 2021 12:20:09 -0500 Subject: 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(-) (limited to 'shared-module/bitmaptools') diff --git a/shared-bindings/bitmaptools/__init__.c b/shared-bindings/bitmaptools/__init__.c index 5de85156a..0edbe135d 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 bb89cd732..6b80f98f5 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 e18b8b177..4e0d72452 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); -- cgit v1.2.3