Merge pull request #5145 from FoamyGuy/bitmaptools_paint_fill
Bitmaptools boundary_fill
This commit is contained in:
commit
7587a521cb
@ -2575,6 +2575,10 @@ msgstr ""
|
|||||||
msgid "axis too long"
|
msgid "axis too long"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: shared-bindings/bitmaptools/__init__.c
|
||||||
|
msgid "background value out of range of target"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: py/builtinevex.c
|
#: py/builtinevex.c
|
||||||
msgid "bad compile mode"
|
msgid "bad compile mode"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -3926,6 +3930,7 @@ msgstr ""
|
|||||||
#: ports/esp32s2/boards/gravitech_cucumber_rs/mpconfigboard.h
|
#: ports/esp32s2/boards/gravitech_cucumber_rs/mpconfigboard.h
|
||||||
#: ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
|
#: ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
|
||||||
#: ports/esp32s2/boards/microdev_micro_s2/mpconfigboard.h
|
#: ports/esp32s2/boards/microdev_micro_s2/mpconfigboard.h
|
||||||
|
#: ports/esp32s2/boards/morpheans_morphesp-240/mpconfigboard.h
|
||||||
#: ports/esp32s2/boards/muselab_nanoesp32_s2_wroom/mpconfigboard.h
|
#: ports/esp32s2/boards/muselab_nanoesp32_s2_wroom/mpconfigboard.h
|
||||||
#: ports/esp32s2/boards/muselab_nanoesp32_s2_wrover/mpconfigboard.h
|
#: ports/esp32s2/boards/muselab_nanoesp32_s2_wrover/mpconfigboard.h
|
||||||
#: ports/esp32s2/boards/targett_module_clip_wroom/mpconfigboard.h
|
#: ports/esp32s2/boards/targett_module_clip_wroom/mpconfigboard.h
|
||||||
@ -4367,6 +4372,10 @@ msgstr ""
|
|||||||
msgid "value must fit in %d byte(s)"
|
msgid "value must fit in %d byte(s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: shared-bindings/bitmaptools/__init__.c
|
||||||
|
msgid "value out of range of target"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: shared-bindings/displayio/Bitmap.c
|
#: shared-bindings/displayio/Bitmap.c
|
||||||
msgid "value_count must be > 0"
|
msgid "value_count must be > 0"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -19,3 +19,4 @@ CIRCUITPY_AUDIOPWMIO = 0
|
|||||||
CIRCUITPY_KEYPAD = 0
|
CIRCUITPY_KEYPAD = 0
|
||||||
CIRCUITPY_MIDI = 0
|
CIRCUITPY_MIDI = 0
|
||||||
CIRCUITPY_MSGPACK = 0
|
CIRCUITPY_MSGPACK = 0
|
||||||
|
CIRCUITPY_BITMAPTOOLS = 0
|
||||||
|
@ -18,3 +18,4 @@ CIRCUITPY_AUDIOPWMIO = 0
|
|||||||
CIRCUITPY_KEYPAD = 0
|
CIRCUITPY_KEYPAD = 0
|
||||||
CIRCUITPY_MIDI = 0
|
CIRCUITPY_MIDI = 0
|
||||||
CIRCUITPY_MSGPACK = 0
|
CIRCUITPY_MSGPACK = 0
|
||||||
|
CIRCUITPY_BITMAPTOOLS = 0
|
||||||
|
@ -296,6 +296,68 @@ STATIC mp_obj_t bitmaptools_obj_fill_region(size_t n_args, const mp_obj_t *pos_a
|
|||||||
}
|
}
|
||||||
|
|
||||||
MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_fill_region_obj, 0, bitmaptools_obj_fill_region);
|
MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_fill_region_obj, 0, bitmaptools_obj_fill_region);
|
||||||
|
//|
|
||||||
|
//| def boundary_fill(
|
||||||
|
//| dest_bitmap: displayio.Bitmap,
|
||||||
|
//| x: int, y: int,
|
||||||
|
//| fill_color_value: int, replaced_color_value: int) -> None:
|
||||||
|
//| """Draws the color value into the destination bitmap enclosed
|
||||||
|
//| area of pixels of the background_value color. Like "Paint Bucket"
|
||||||
|
//| fill tool.
|
||||||
|
//|
|
||||||
|
//| :param bitmap dest_bitmap: Destination bitmap that will be written into
|
||||||
|
//| :param int x: x-pixel position of the first pixel to check and fill if needed
|
||||||
|
//| :param int y: y-pixel position of the first pixel to check and fill if needed
|
||||||
|
//| :param int fill_color_value: Bitmap palette index that will be written into the
|
||||||
|
//| enclosed area in the destination bitmap
|
||||||
|
//| :param int replaced_color_value: Bitmap palette index that will filled with the
|
||||||
|
//| value color in the enclosed area in the destination bitmap"""
|
||||||
|
//| ...
|
||||||
|
//|
|
||||||
|
STATIC mp_obj_t bitmaptools_obj_boundary_fill(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||||
|
enum {ARG_dest_bitmap, ARG_x, ARG_y, ARG_fill_color_value, ARG_replaced_color_value};
|
||||||
|
|
||||||
|
static const mp_arg_t allowed_args[] = {
|
||||||
|
{MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ},
|
||||||
|
{MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT},
|
||||||
|
{MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT},
|
||||||
|
{MP_QSTR_fill_color_value, MP_ARG_REQUIRED | MP_ARG_INT},
|
||||||
|
{MP_QSTR_replaced_color_value, MP_ARG_INT, {.u_int = INT_MAX} },
|
||||||
|
};
|
||||||
|
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);
|
||||||
|
|
||||||
|
displayio_bitmap_t *destination = MP_OBJ_TO_PTR(mp_arg_validate_type(args[ARG_dest_bitmap].u_obj, &displayio_bitmap_type, MP_QSTR_dest_bitmap)); // the destination bitmap
|
||||||
|
|
||||||
|
uint32_t fill_color_value, color_depth;
|
||||||
|
fill_color_value = args[ARG_fill_color_value].u_int;
|
||||||
|
color_depth = (1 << destination->bits_per_value);
|
||||||
|
if (color_depth <= fill_color_value) {
|
||||||
|
mp_raise_ValueError(translate("value out of range of target"));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t replaced_color_value;
|
||||||
|
replaced_color_value = args[ARG_replaced_color_value].u_int;
|
||||||
|
if (replaced_color_value != INT_MAX && color_depth <= replaced_color_value) {
|
||||||
|
mp_raise_ValueError(translate("background value out of range of target"));
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t x = args[ARG_x].u_int;
|
||||||
|
int16_t y = args[ARG_y].u_int;
|
||||||
|
|
||||||
|
if (x < 0 || x >= destination->width) {
|
||||||
|
mp_raise_ValueError(translate("out of range of target"));
|
||||||
|
}
|
||||||
|
if (y < 0 || y >= destination->height) {
|
||||||
|
mp_raise_ValueError(translate("out of range of target"));
|
||||||
|
}
|
||||||
|
|
||||||
|
common_hal_bitmaptools_boundary_fill(destination, x, y, fill_color_value, replaced_color_value);
|
||||||
|
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_boundary_fill_obj, 0, bitmaptools_obj_boundary_fill);
|
||||||
// requires all 6 arguments
|
// requires all 6 arguments
|
||||||
|
|
||||||
//|
|
//|
|
||||||
@ -520,6 +582,7 @@ STATIC const mp_rom_map_elem_t bitmaptools_module_globals_table[] = {
|
|||||||
{ MP_ROM_QSTR(MP_QSTR_rotozoom), MP_ROM_PTR(&bitmaptools_rotozoom_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_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_fill_region), MP_ROM_PTR(&bitmaptools_fill_region_obj) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_boundary_fill), MP_ROM_PTR(&bitmaptools_boundary_fill_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_draw_line), MP_ROM_PTR(&bitmaptools_draw_line_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_draw_line), MP_ROM_PTR(&bitmaptools_draw_line_obj) },
|
||||||
};
|
};
|
||||||
STATIC MP_DEFINE_CONST_DICT(bitmaptools_module_globals, bitmaptools_module_globals_table);
|
STATIC MP_DEFINE_CONST_DICT(bitmaptools_module_globals, bitmaptools_module_globals_table);
|
||||||
|
@ -46,6 +46,10 @@ void common_hal_bitmaptools_fill_region(displayio_bitmap_t *destination,
|
|||||||
int16_t x2, int16_t y2,
|
int16_t x2, int16_t y2,
|
||||||
uint32_t value);
|
uint32_t value);
|
||||||
|
|
||||||
|
void common_hal_bitmaptools_boundary_fill(displayio_bitmap_t *destination,
|
||||||
|
int16_t x, int16_t y,
|
||||||
|
uint32_t fill_color_value, uint32_t replaced_color_value);
|
||||||
|
|
||||||
void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination,
|
void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination,
|
||||||
int16_t x0, int16_t y0,
|
int16_t x0, int16_t y0,
|
||||||
int16_t x1, int16_t y1,
|
int16_t x1, int16_t y1,
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "shared-bindings/bitmaptools/__init__.h"
|
#include "shared-bindings/bitmaptools/__init__.h"
|
||||||
#include "shared-bindings/displayio/Bitmap.h"
|
#include "shared-bindings/displayio/Bitmap.h"
|
||||||
#include "shared-module/displayio/Bitmap.h"
|
#include "shared-module/displayio/Bitmap.h"
|
||||||
@ -252,6 +251,145 @@ void common_hal_bitmaptools_fill_region(displayio_bitmap_t *destination,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void common_hal_bitmaptools_boundary_fill(displayio_bitmap_t *destination,
|
||||||
|
int16_t x, int16_t y,
|
||||||
|
uint32_t fill_color_value, uint32_t replaced_color_value) {
|
||||||
|
|
||||||
|
if (fill_color_value == replaced_color_value) {
|
||||||
|
// There is nothing to do
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t current_point_color_value;
|
||||||
|
|
||||||
|
// the list of points that we'll check
|
||||||
|
mp_obj_t fill_area = mp_obj_new_list(0, NULL);
|
||||||
|
|
||||||
|
// first point is the one user passed in
|
||||||
|
mp_obj_t point[] = { mp_obj_new_int(x), mp_obj_new_int(y) };
|
||||||
|
mp_obj_list_append(
|
||||||
|
fill_area,
|
||||||
|
mp_obj_new_tuple(2, point)
|
||||||
|
);
|
||||||
|
|
||||||
|
int16_t minx = x;
|
||||||
|
int16_t miny = y;
|
||||||
|
int16_t maxx = x;
|
||||||
|
int16_t maxy = y;
|
||||||
|
|
||||||
|
if (replaced_color_value == INT_MAX) {
|
||||||
|
current_point_color_value = common_hal_displayio_bitmap_get_pixel(
|
||||||
|
destination,
|
||||||
|
mp_obj_get_int(point[0]),
|
||||||
|
mp_obj_get_int(point[1]));
|
||||||
|
replaced_color_value = (uint32_t)current_point_color_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_t *fill_points;
|
||||||
|
size_t list_length = 0;
|
||||||
|
mp_obj_list_get(fill_area, &list_length, &fill_points);
|
||||||
|
|
||||||
|
mp_obj_t current_point;
|
||||||
|
|
||||||
|
size_t tuple_len = 0;
|
||||||
|
mp_obj_t *tuple_items;
|
||||||
|
|
||||||
|
int cur_x, cur_y;
|
||||||
|
|
||||||
|
// while there are still points to check
|
||||||
|
while (list_length > 0) {
|
||||||
|
mp_obj_list_get(fill_area, &list_length, &fill_points);
|
||||||
|
current_point = mp_obj_list_pop(fill_area, 0);
|
||||||
|
mp_obj_tuple_get(current_point, &tuple_len, &tuple_items);
|
||||||
|
current_point_color_value = common_hal_displayio_bitmap_get_pixel(
|
||||||
|
destination,
|
||||||
|
mp_obj_get_int(tuple_items[0]),
|
||||||
|
mp_obj_get_int(tuple_items[1]));
|
||||||
|
|
||||||
|
// if the current point is not background color ignore it
|
||||||
|
if (current_point_color_value != replaced_color_value) {
|
||||||
|
mp_obj_list_get(fill_area, &list_length, &fill_points);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_x = mp_obj_int_get_checked(tuple_items[0]);
|
||||||
|
cur_y = mp_obj_int_get_checked(tuple_items[1]);
|
||||||
|
|
||||||
|
if (cur_x < minx) {
|
||||||
|
minx = (int16_t)cur_x;
|
||||||
|
}
|
||||||
|
if (cur_x > maxx) {
|
||||||
|
maxx = (int16_t)cur_x;
|
||||||
|
}
|
||||||
|
if (cur_y < miny) {
|
||||||
|
miny = (int16_t)cur_y;
|
||||||
|
}
|
||||||
|
if (cur_y > maxy) {
|
||||||
|
maxy = (int16_t)cur_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill the current point with fill color
|
||||||
|
displayio_bitmap_write_pixel(
|
||||||
|
destination,
|
||||||
|
mp_obj_get_int(tuple_items[0]),
|
||||||
|
mp_obj_get_int(tuple_items[1]),
|
||||||
|
fill_color_value);
|
||||||
|
|
||||||
|
// add all 4 surrounding points to the list to check
|
||||||
|
|
||||||
|
// ignore points outside of the bitmap
|
||||||
|
if (mp_obj_int_get_checked(tuple_items[1]) - 1 >= 0) {
|
||||||
|
mp_obj_t above_point[] = {
|
||||||
|
tuple_items[0],
|
||||||
|
MP_OBJ_NEW_SMALL_INT(mp_obj_int_get_checked(tuple_items[1]) - 1)
|
||||||
|
};
|
||||||
|
mp_obj_list_append(
|
||||||
|
fill_area,
|
||||||
|
mp_obj_new_tuple(2, above_point));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore points outside of the bitmap
|
||||||
|
if (mp_obj_int_get_checked(tuple_items[0]) - 1 >= 0) {
|
||||||
|
mp_obj_t left_point[] = {
|
||||||
|
MP_OBJ_NEW_SMALL_INT(mp_obj_int_get_checked(tuple_items[0]) - 1),
|
||||||
|
tuple_items[1]
|
||||||
|
};
|
||||||
|
mp_obj_list_append(
|
||||||
|
fill_area,
|
||||||
|
mp_obj_new_tuple(2, left_point));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore points outside of the bitmap
|
||||||
|
if (mp_obj_int_get_checked(tuple_items[0]) + 1 < destination->width) {
|
||||||
|
mp_obj_t right_point[] = {
|
||||||
|
MP_OBJ_NEW_SMALL_INT(mp_obj_int_get_checked(tuple_items[0]) + 1),
|
||||||
|
tuple_items[1]
|
||||||
|
};
|
||||||
|
mp_obj_list_append(
|
||||||
|
fill_area,
|
||||||
|
mp_obj_new_tuple(2, right_point));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore points outside of the bitmap
|
||||||
|
if (mp_obj_int_get_checked(tuple_items[1]) + 1 < destination->height) {
|
||||||
|
mp_obj_t below_point[] = {
|
||||||
|
tuple_items[0],
|
||||||
|
MP_OBJ_NEW_SMALL_INT(mp_obj_int_get_checked(tuple_items[1]) + 1)
|
||||||
|
};
|
||||||
|
mp_obj_list_append(
|
||||||
|
fill_area,
|
||||||
|
mp_obj_new_tuple(2, below_point));
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_obj_list_get(fill_area, &list_length, &fill_points);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set dirty the area so displayio will draw
|
||||||
|
displayio_area_t area = { minx, miny, maxx + 1, maxy + 1};
|
||||||
|
displayio_bitmap_set_dirty_area(destination, &area);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination,
|
void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination,
|
||||||
int16_t x0, int16_t y0,
|
int16_t x0, int16_t y0,
|
||||||
int16_t x1, int16_t y1,
|
int16_t x1, int16_t y1,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user