8000 Merge pull request #5145 from FoamyGuy/bitmaptools_paint_fill · mscreations/circuitpython@7587a52 · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7587a52

Browse files
authored
Merge pull request adafruit#5145 from FoamyGuy/bitmaptools_paint_fill
Bitmaptools boundary_fill
2 parents fa9a98d + 80c7a15 commit 7587a52

File tree

6 files changed

+217
-1
lines changed

6 files changed

+217
-1
lines changed

locale/circuitpython.pot

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2575,6 +2575,10 @@ msgstr ""
25752575
msgid "axis too long"
25762576
msgstr ""
25772577

2578+
#: shared-bindings/bitmaptools/__init__.c
2579+
msgid "background value out of range of target"
2580+
msgstr ""
2581+
25782582
#: py/builtinevex.c
25792583
msgid "bad compile mode"
25802584
msgstr ""
@@ -3926,6 +3930,7 @@ msgstr ""
39263930
#: ports/esp32s2/boards/gravitech_cucumber_rs/mpconfigboard.h
39273931
#: ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
39283932
#: ports/esp32s2/boards/microdev_micro_s2/mpconfigboard.h
3933+
#: ports/esp32s2/boards/morpheans_morphesp-240/mpconfigboard.h
39293934
#: ports/esp32s2/boards/muselab_nanoesp32_s2_wroom/mpconfigboard.h
39303935
#: ports/esp32s2/boards/muselab_nanoesp32_s2_wrover/mpconfigboard.h
39313936
#: ports/esp32s2/boards/targett_module_clip_wroom/mpconfigboard.h
@@ -4367,6 +4372,10 @@ msgstr ""
43674372
msgid "value must fit in %d byte(s)"
43684373
msgstr ""
43694374

4375+
#: shared-bindings/bitmaptools/__init__.c
4376+
msgid "value out of range of target"
4377+
msgstr ""
4378+
43704379
#: shared-bindings/displayio/Bitmap.c
43714380
msgid "value_count must be > 0"
43724381
msgstr ""

ports/stm/boards/pyb_nano_v2/mpconfigboard.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ CIRCUITPY_AUDIOPWMIO = 0
1919
CIRCUITPY_KEYPAD = 0
2020
CIRCUITPY_MIDI = 0
2121
CIRCUITPY_MSGPACK = 0
22+
CIRCUITPY_BITMAPTOOLS = 0

ports/stm/boards/stm32f411ve_discovery/mpconfigboard.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ CIRCUITPY_AUDIOPWMIO = 0
1818
CIRCUITPY_KEYPAD = 0
1919
CIRCUITPY_MIDI = 0
2020
CIRCUITPY_MSGPACK = 0
21+
CIRCUITPY_BITMAPTOOLS = 0

shared-bindings/bitmaptools/__init__.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,68 @@ STATIC mp_obj_t bitmaptools_obj_fill_region(size_t n_args, const mp_obj_t *pos_a
296296
}
297297

298298
MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_fill_region_obj, 0, bitmaptools_obj_fill_region);
299+
//|
300+
//| def boundary_fill(
301+
//| dest_bitmap: displayio.Bitmap,
302+
//| x: int, y: int,
303+
//| fill_color_value: int, replaced_color_value: int) -> None:
304+
//| """Draws the color value into the destination bitmap enclosed
305+
//| area of pixels of the background_value color. Like "Paint Bucket"
306+
//| fill tool.
307+
//|
308+
//| :param bitmap dest_bitmap: Destination bitmap that will be written into
309+
//| :param int x: x-pixel position of the first pixel to check and fill if needed
310+
//| :param int y: y-pixel position of the first pixel to check and fill if needed
311+
//| :param int fill_color_value: Bitmap palette index that will be written into the
312+
//| enclosed area in the destination bitmap
313+
//| :param int replaced_color_value: Bitmap palette index that will filled with the
314+
//| value color in the enclosed area in the destination bitmap"""
315+
//| ...
316+
//|
317+
STATIC mp_obj_t bitmaptools_obj_boundary_fill(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
318+
enum {ARG_dest_bitmap, ARG_x, ARG_y, ARG_fill_color_value, ARG_replaced_color_value};
319+
320+
static const mp_arg_t allowed_args[] = {
321+
{MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ},
322+
{MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT},
323+
{MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT},
324+
{MP_QSTR_fill_color_value, MP_ARG_REQUIRED | MP_ARG_INT},
325+
{MP_QSTR_replaced_color_value, MP_ARG_INT, {.u_int = INT_MAX} },
326+
};
327+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
328+
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
329+
330+
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
331+
332+
uint32_t fill_color_value, color_depth;
333+
fill_color_value = args[ARG_fill_color_value].u_int;
334+
color_depth = (1 << destination->bits_per_value);
335+
if (color_depth <= fill_color_value) {
336+
mp_raise_ValueError(translate("value out of range of target"));
337+
}
338+
339+
uint32_t replaced_color_value;
340+
replaced_color_value = args[ARG_replaced_color_value].u_int;
341+
if (replaced_color_value != INT_MAX && color_depth <= replaced_color_value) {
342+
mp_raise_ValueError(translate("background value out of range of target"));
343+
}
344+
345+
int16_t x = args[ARG_x].u_int;
346+
int16_t y = args[ARG_y].u_int;
347+
348+
if (x < 0 || x >= destination->width) {
349+
mp_raise_ValueError(translate("out of range of target"));
350+
}
351+
if (y < 0 || y >= destination->height) {
352+
mp_raise_ValueError(translate("out of range of target"));
353+
}
354+
355+
common_hal_bitmaptools_boundary_fill(destination, x, y, fill_color_value, replaced_color_value);
356+
357+
return mp_const_none;
358+
}
359+
360+
MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_boundary_fill_obj, 0, bitmaptools_obj_boundary_fill);
299361
// requires all 6 arguments
300362

301363
//|
@@ -520,6 +582,7 @@ STATIC const mp_rom_map_elem_t bitmaptools_module_globals_table[] = {
520582
{ MP_ROM_QSTR(MP_QSTR_rotozoom), MP_ROM_PTR(&bitmaptools_rotozoom_obj) },
521583
{ MP_ROM_QSTR(MP_QSTR_arrayblit), MP_ROM_PTR(&bitmaptools_arrayblit_obj) },
522584
{ MP_ROM_QSTR(MP_QSTR_fill_region), MP_ROM_PTR(&bitmaptools_fill_region_obj) },
585+
{ MP_ROM_QSTR(MP_QSTR_boundary_fill), MP_ROM_PTR(&bitmaptools_boundary_fill_obj) },
523586
{ MP_ROM_QSTR(MP_QSTR_draw_line), MP_ROM_PTR(&bitmaptools_draw_line_obj) },
524587
};
525588
STATIC MP_DEFINE_CONST_DICT(bitmaptools_module_globals, bitmaptools_module_globals_table);

shared-bindings/bitmaptools/__init__.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ void common_hal_bitmaptools_fill_region(displayio_bitmap_t *destination,
4646
int16_t x2, int16_t y2,
4747
uint32_t value);
4848

49+
void common_hal_bitmaptools_boundary_fill(displayio_bitmap_t *destination,
50+
int16_t x, int16_t y,
51+
uint32_t fill_color_value, uint32_t replaced_color_value);
52+
4953
void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination,
5054
int16_t x0, int16_t y0,
5155
int16_t x1, int16_t y1,

shared-module/bitmaptools/__init__.c

Lines changed: 139 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
* THE SOFTWARE.
2525
*/
2626

27-
2827
#include "shared-bindings/bitmaptools/__init__.h"
2928
#include "shared-bindings/displayio/Bitmap.h"
3029
#include "shared-module/displayio/Bitmap.h"
@@ -252,6 +251,145 @@ void common_hal_bitmaptools_fill_region(displayio_bitmap_t *destination,
252251
}
253252
}
254253

254+
void common_hal_bitmaptools_boundary_fill(displayio_bitmap_t *destination,
255+
int16_t x, int16_t y,
256+
uint32_t fill_color_value, uint32_t replaced_color_value) {
257+
258+
if (fill_color_value == replaced_color_value) {
259+
// There is nothing to do
260+
return;
261+
}
262+
263+
uint32_t current_point_color_value;
264+
265+
// the list of points that we'll check
266+
mp_obj_t fill_area = mp_obj_new_list(0, NULL);
267+
268+
// first point is the one user passed in
269+
mp_obj_t point[] = { mp_obj_new_int(x), mp_obj_new_int(y) };
270+
mp_obj_list_append(
271+
fill_area,
272+
mp_obj_new_tuple(2, point)
273+
);
274+
275+
int16_t minx = x;
276+
int16_t miny = y;
277+
int16_t maxx = x;
278+
int16_t maxy = y;
279+
280+
if (replaced_color_value == INT_MAX) {
281+
current_point_color_value = common_hal_displayio_bitmap_get_pixel(
282+
destination,
283+
mp_obj_get_int(point[0]),
284+
mp_obj_get_int(point[1]));
285+
replaced_color_value = (uint32_t)current_point_color_value;
286+
}
287+
288+
mp_obj_t *fill_points;
289+
size_t list_length = 0;
290+
mp_obj_list_get(fill_area, &list_length, &fill_points);
291+
292+
mp_obj_t current_point;
293+
294+
size_t tuple_len = 0;
295+
mp_obj_t *tuple_items;
296+
297+
int cur_x, cur_y;
298+
299+
// while there are still points to check
300+
while (list_length > 0) {
301+
mp_obj_list_get(fill_area, &list_length, &fill_points);
302+
current_point = mp_obj_list_pop(fill_area, 0);
303+
mp_obj_tuple_get(current_point, &tuple_len, &tuple_items);
304+
current_point_color_value = common_hal_displayio_bitmap_get_pixel(
305+
destination,
306+
mp_obj_get_int(tuple_items[0]),
307+
mp_obj_get_int(tuple_items[1]));
308+
309+
// if the current point is not background color ignore it
310+
if (current_point_color_value != replaced_color_value) {
311+
mp_obj_list_get(fill_area, &list_length, &fill_points);
312+
continue;
313+
}
314+
315+
cur_x = mp_obj_int_get_checked(tuple_items[0]);
316+
cur_y = mp_obj_int_get_checked(tuple_items[1]);
317+
318+
if (cur_x < minx) {
319+
minx = (int16_t)cur_x;
320+
}
321+
if (cur_x > maxx) {
322+
maxx = (int16_t)cur_x;
323+
}
324+
if (cur_y < miny) {
325+
miny = (int16_t)cur_y;
326+
}
327+
if (cur_y > maxy) {
328+
maxy = (int16_t)cur_y;
329+
}
330+
331+
// fill the current point with fill color
332+
displayio_bitmap_write_pixel(
333+
destination,
334+
mp_obj_get_int(tuple_items[0]),
335+
mp_obj_get_int(tuple_items[1]),
336+
fill_color_value);
337+
338+
// add all 4 surrounding points to the list to check
339+
340+
// ignore points outside of the bitmap
341+
if (mp_obj_int_get_checked(tuple_items[1]) - 1 >= 0) {
342+
mp_obj_t above_point[] = {
343+
tuple_items[0],
344+
MP_OBJ_NEW_SMALL_INT(mp_obj_int_get_checked(tuple_items[1]) - 1)
345+
};
346+
mp_obj_list_append(
347+
fill_area,
348+
mp_obj_new_tuple(2, above_point));
349+
}
350+
351+
// ignore points outside of the bitmap
352+
if (mp_obj_int_get_checked(tuple_items[0]) - 1 >= 0) {
353+
mp_obj_t left_point[] = {
354+
MP_OBJ_NEW_SMALL_INT(mp_obj_int_get_checked(tuple_items[0]) - 1),
355+
tuple_items[1]
356+
};
357+
mp_obj_list_append(
358+
fill_area,
359+
mp_obj_new_tuple(2, left_point));
360+
}
361+
362+
// ignore points outside of the bitmap
363+
if (mp_obj_int_get_checked(tuple_items[0]) + 1 < destination->width) {
364+
mp_obj_t right_point[] = {
365+
MP_OBJ_NEW_SMALL_INT(mp_obj_int_get_checked(tuple_items[0]) + 1),
366+
tuple_items[1]
367+
};
368+
mp_obj_list_append(
369+
fill_area,
370+
mp_obj_new_tuple(2, right_point));
371+
}
372+
373+
// ignore points outside of the bitmap
374+
if (mp_obj_int_get_checked(tuple_items[1]) + 1 < destination->height) {
375+
mp_obj_t below_point[] = {
376+
tuple_items[0],
377+
MP_OBJ_NEW_SMALL_INT(mp_obj_int_get_checked(tuple_items[1]) + 1)
378+
};
379+
mp_obj_list_append(
380+
fill_area,
381+
mp_obj_new_tuple(2, below_point));
382+
}
383+
384+
mp_obj_list_get(fill_area, &list_length, &fill_points);
385+
}
386+
387+
// set dirty the area so displayio will draw
388+
displayio_area_t area = { minx, miny, maxx + 1, maxy + 1};
389+
displayio_bitmap_set_dirty_area(destination, &area);
390+
391+
}
392+
255393
void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination,
256394
int16_t x0, int16_t y0,
257395
int16_t x1, int16_t y1,

0 commit comments

Comments
 (0)
0