Skip to content
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

Adding circle bitmaptools #7782

Merged
merged 13 commits into from
Apr 1, 2023
23 changes: 9 additions & 14 deletions locale/circuitpython.pot
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ msgid "%q in %q must be of type %q, not %q"
msgstr ""

#: ports/espressif/common-hal/espulp/ULP.c
#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
#: shared-bindings/digitalio/DigitalInOut.c
#: shared-bindings/microcontroller/Pin.c
Expand Down Expand Up @@ -1217,13 +1218,15 @@ msgstr ""
msgid "Interrupt error."
msgstr ""

#: ports/mimxrt10xx/common-hal/audiobusio/__init__.c
#: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c py/argcheck.c
#: shared-bindings/digitalio/DigitalInOut.c
#: shared-bindings/displayio/EPaperDisplay.c
msgid "Invalid %q"
msgstr ""

#: ports/atmel-samd/common-hal/microcontroller/Pin.c
#: ports/mimxrt10xx/common-hal/microcontroller/Pin.c
#: shared-bindings/microcontroller/Pin.c
msgid "Invalid %q pin"
msgstr ""
Expand Down Expand Up @@ -3827,11 +3830,7 @@ msgstr ""
msgid "out must be a float dense array"
msgstr ""

#: shared-bindings/displayio/Bitmap.c
msgid "out of range of source"
msgstr ""

#: shared-bindings/bitmaptools/__init__.c shared-bindings/displayio/Bitmap.c
#: shared-bindings/bitmaptools/__init__.c
msgid "out of range of target"
msgstr ""

Expand All @@ -3856,14 +3855,10 @@ msgstr ""
msgid "parameters must be registers in sequence r0 to r3"
msgstr ""

#: shared-bindings/bitmaptools/__init__.c shared-bindings/displayio/Bitmap.c
#: shared-bindings/bitmaptools/__init__.c
msgid "pixel coordinates out of bounds"
msgstr ""

#: shared-bindings/displayio/Bitmap.c
msgid "pixel value requires too many bits"
msgstr ""

#: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c
msgid "pixel_shader must be displayio.Palette or displayio.ColorConverter"
msgstr ""
Expand Down Expand Up @@ -3905,6 +3900,10 @@ msgstr ""
msgid "queue overflow"
msgstr ""

#: shared-bindings/bitmaptools/__init__.c
msgid "radius must be greater than zero"
msgstr ""

#: py/parse.c
msgid "raw f-strings are not supported"
msgstr ""
Expand Down Expand Up @@ -4276,10 +4275,6 @@ msgstr ""
msgid "value out of range of target"
msgstr ""

#: shared-bindings/displayio/Bitmap.c
msgid "value_count must be > 0"
msgstr ""

#: ports/espressif/common-hal/watchdog/WatchDogTimer.c
msgid "watchdog not initialized"
msgstr ""
Expand Down
86 changes: 86 additions & 0 deletions shared-bindings/bitmaptools/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -868,7 +868,92 @@ STATIC mp_obj_t bitmaptools_dither(size_t n_args, const mp_obj_t *pos_args, mp_m
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_dither_obj, 0, bitmaptools_dither);
// requires all 5 arguments

//| def draw_circle(
//| dest_bitmap: displayio.Bitmap, x: int, y: int, radius: int, value: int
//| ) -> None:
//| """Draws a circle into a bitmap specified using a center (x0,y0) and radius r.
//|
//| :param bitmap dest_bitmap: Destination bitmap that will be written into
//| :param int x: x-pixel position of the circle's center
//| :param int y: y-pixel position of the circle's center
//| :param int radius: circle's radius
//| :param int value: Bitmap palette index that will be written into the
//| circle in the destination bitmap
//|
//| .. code-block:: Python
//|
//| import board
//| import displayio
//| import bitmaptools
//|
//| display = board.DISPLAY
//| main_group = displayio.Group()
//| display.root_group = main_group
//|
//| palette = displayio.Palette(2)
//| palette[0] = 0xffffff
//| palette[1] = 0x440044
//|
//| bmp = displayio.Bitmap(128,128, 2)
//| bmp.fill(0)
//|
//| bitmaptools.circle(64,64, 32, 1)
//|
//| tilegrid = displayio.TileGrid(bitmap=bmp, pixel_shader=palette)
//| main_group.append(tilegrid)
//|
//| while True:
//| pass
//|
//| """
//|
//| ...
//|
STATIC mp_obj_t bitmaptools_obj_draw_circle(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum {ARG_dest_bitmap, ARG_x, ARG_y, ARG_radius, ARG_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_radius, MP_ARG_REQUIRED | MP_ARG_INT},
{MP_QSTR_value, MP_ARG_REQUIRED | MP_ARG_INT},
};
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(args[ARG_dest_bitmap].u_obj); // the destination bitmap

uint32_t value, color_depth;
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"));
}


int16_t x = args[ARG_x].u_int;
int16_t y = args[ARG_y].u_int;
int16_t radius = args[ARG_radius].u_int;

if (x < 0 || x >= destination->width) {
mp_raise_ValueError(translate("out of range of target"));
jposada202020 marked this conversation as resolved.
Show resolved Hide resolved
}
if (y < 0 || y >= destination->height) {
mp_raise_ValueError(translate("out of range of target"));
jposada202020 marked this conversation as resolved.
Show resolved Hide resolved
}
if (radius < 0) {
mp_raise_ValueError(translate("radius must be greater than zero"));
jposada202020 marked this conversation as resolved.
Show resolved Hide resolved
}

common_hal_bitmaptools_draw_circle(destination, x, y, radius, value);

return mp_const_none;
}

MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_circle_obj, 0, bitmaptools_obj_draw_circle);

STATIC const mp_rom_map_elem_t bitmaptools_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bitmaptools) },
Expand All @@ -880,6 +965,7 @@ STATIC const mp_rom_map_elem_t bitmaptools_module_globals_table[] = {
{ 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_polygon), MP_ROM_PTR(&bitmaptools_draw_polygon_obj) },
{ MP_ROM_QSTR(MP_QSTR_draw_circle), MP_ROM_PTR(&bitmaptools_draw_circle_obj) },
{ MP_ROM_QSTR(MP_QSTR_dither), MP_ROM_PTR(&bitmaptools_dither_obj) },
{ MP_ROM_QSTR(MP_QSTR_DitherAlgorithm), MP_ROM_PTR(&bitmaptools_dither_algorithm_type) },
};
Expand Down
5 changes: 5 additions & 0 deletions shared-bindings/bitmaptools/__init__.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination,
int16_t x1, int16_t y1,
uint32_t value);

void common_hal_bitmaptools_draw_circle(displayio_bitmap_t *destination,
int16_t x, int16_t y,
int16_t radius,
uint32_t value);

void common_hal_bitmaptools_draw_polygon(displayio_bitmap_t *destination, void *xs, void *ys, size_t points_len, int point_size, uint32_t value, bool close);
void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, mp_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);
Expand Down
66 changes: 65 additions & 1 deletion shared-module/bitmaptools/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Kevin Matocha
* Copyright (c) 2021 Kevin Matocha, Jose David Montoya
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -40,6 +40,9 @@
#include <stdio.h>
#include <string.h>

#define BITMAP_DEBUG(...) (void)0
// #define BITMAP_DEBUG(...) mp_printf(&mp_plat_print, __VA_ARGS__)

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,
Expand Down Expand Up @@ -918,3 +921,64 @@ void common_hal_bitmaptools_alphablend(displayio_bitmap_t *dest, displayio_bitma
}
}
}

STATIC void draw_circle(displayio_bitmap_t *destination,
int16_t x, int16_t y,
int16_t radius, uint32_t value) {

int16_t d, yb;

mp_arg_validate_int_range(x, SHRT_MIN, SHRT_MAX, MP_QSTR_x);
mp_arg_validate_int_range(y, SHRT_MIN, SHRT_MAX, MP_QSTR_y);

x = MIN(x, destination->width);
x = MAX(0, x);
y = MIN(y, destination->height);
y = MAX(0, y);

BITMAP_DEBUG("x, y, radius (%4d, %4d, %4d)\n", x, y, radius);

yb = radius;
d = 3 - 2 * radius;

// Bresenham's circle algorithm
for (int xb = 0; xb <= yb; xb++) {
displayio_bitmap_write_pixel(destination, xb + x, yb + y, value);
displayio_bitmap_write_pixel(destination, -xb + x, -yb + y, value);
displayio_bitmap_write_pixel(destination, -xb + x, yb + y, value);
displayio_bitmap_write_pixel(destination, xb + x, -yb + y, value);
displayio_bitmap_write_pixel(destination, yb + x, xb + y, value);
displayio_bitmap_write_pixel(destination, -yb + x, xb + y, value);
displayio_bitmap_write_pixel(destination, -yb + x, -xb + y, value);
displayio_bitmap_write_pixel(destination, yb + x, -xb + y, value);
if (d <= 0) {
d = d + (4 * xb) + 6;
} else {
d = d + 4 * (xb - yb) + 10;
yb = yb - 1;
}
}
}

void common_hal_bitmaptools_draw_circle(displayio_bitmap_t *destination,
int16_t x, int16_t y,
int16_t radius,
uint32_t value) {


// update the dirty area
int16_t xbb0, xbb1, ybb0, ybb1;

xbb0 = x - radius;
xbb1 = x + radius;
ybb0 = y - radius;
ybb1 = y + radius;

displayio_area_t area = { xbb0, ybb0, xbb1, ybb1, NULL };
displayio_area_t bitmap_area = { 0, 0, destination->width, destination->height, NULL };
displayio_area_compute_overlap(&area, &bitmap_area, &area);

displayio_bitmap_set_dirty_area(destination, &area);

draw_circle(destination, x, y, radius, value);
}