Merge pull request #4376 from kmatch98/displayio_bitmap
add fill_region and draw_line to bitmap_tools
This commit is contained in:
commit
b413535ee1
@ -3643,7 +3643,7 @@ msgstr ""
|
||||
msgid "out of range of source"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/displayio/Bitmap.c
|
||||
#: shared-bindings/bitmaptools/__init__.c shared-bindings/displayio/Bitmap.c
|
||||
msgid "out of range of target"
|
||||
msgstr ""
|
||||
|
||||
|
@ -243,13 +243,127 @@ STATIC mp_obj_t bitmaptools_obj_rotozoom(size_t n_args, const mp_obj_t *pos_args
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_rotozoom_obj, 0, bitmaptools_obj_rotozoom);
|
||||
// requires at least 2 arguments (destination bitmap and source bitmap)
|
||||
|
||||
//|
|
||||
//| def fill_region(
|
||||
//| dest_bitmap: displayio.Bitmap,
|
||||
//| x1: int, y1: int,
|
||||
//| x2: int, y2: int,
|
||||
//| value: int) -> None:
|
||||
//| """Draws the color value into the destination bitmap within the
|
||||
//| rectangular region bounded by (x1,y1) and (x2,y2), exclusive.
|
||||
//|
|
||||
//| :param bitmap dest_bitmap: Destination bitmap that will be written into
|
||||
//| :param int x1: x-pixel position of the first corner of the rectangular fill region
|
||||
//| :param int y1: y-pixel position of the first corner of the rectangular fill region
|
||||
//| :param int x2: x-pixel position of the second corner of the rectangular fill region (exclusive)
|
||||
//| :param int y2: y-pixel position of the second corner of the rectangular fill region (exclusive)
|
||||
//| :param int value: Bitmap palette index that will be written into the rectangular
|
||||
//| 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){
|
||||
enum {ARG_dest_bitmap, ARG_x1, ARG_y1, ARG_x2, ARG_y2, ARG_value};
|
||||
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ},
|
||||
{MP_QSTR_x1, MP_ARG_REQUIRED | MP_ARG_INT},
|
||||
{MP_QSTR_y1, MP_ARG_REQUIRED | MP_ARG_INT},
|
||||
{MP_QSTR_x2, MP_ARG_REQUIRED | MP_ARG_INT},
|
||||
{MP_QSTR_y2, 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 x1 = args[ARG_x1].u_int;
|
||||
int16_t y1 = args[ARG_y1].u_int;
|
||||
int16_t x2 = args[ARG_x2].u_int;
|
||||
int16_t y2 = args[ARG_y2].u_int;
|
||||
|
||||
common_hal_bitmaptools_fill_region(destination, x1, y1, x2, y2, value);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_fill_region_obj, 0, bitmaptools_obj_fill_region);
|
||||
// requires all 6 arguments
|
||||
|
||||
//|
|
||||
//| def draw_line(
|
||||
//| dest_bitmap: displayio.Bitmap,
|
||||
//| x1: int, y1: int,
|
||||
//| x2: int, y2: int,
|
||||
//| value: int) -> None:
|
||||
//| """Draws a line into a bitmap specified two endpoints (x1,y1) and (x2,y2).
|
||||
//|
|
||||
//| :param bitmap dest_bitmap: Destination bitmap that will be written into
|
||||
//| :param int x1: x-pixel position of the line's first endpoint
|
||||
//| :param int y1: y-pixel position of the line's first endpoint
|
||||
//| :param int x2: x-pixel position of the line's second endpoint
|
||||
//| :param int y2: y-pixel position of the line's second endpoint
|
||||
//| :param int value: Bitmap palette index that will be written into the
|
||||
//| 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){
|
||||
enum {ARG_dest_bitmap, ARG_x1, ARG_y1, ARG_x2, ARG_y2, ARG_value};
|
||||
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ},
|
||||
{MP_QSTR_x1, MP_ARG_REQUIRED | MP_ARG_INT},
|
||||
{MP_QSTR_y1, MP_ARG_REQUIRED | MP_ARG_INT},
|
||||
{MP_QSTR_x2, MP_ARG_REQUIRED | MP_ARG_INT},
|
||||
{MP_QSTR_y2, 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 x1 = args[ARG_x1].u_int;
|
||||
int16_t y1 = args[ARG_y1].u_int;
|
||||
int16_t x2 = args[ARG_x2].u_int;
|
||||
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) ) {
|
||||
mp_raise_ValueError(translate("out of range of target"));
|
||||
}
|
||||
|
||||
common_hal_bitmaptools_draw_line(destination, x1, y1, x2, y2, value);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_line_obj, 0, bitmaptools_obj_draw_line);
|
||||
// requires all 6 arguments
|
||||
|
||||
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_fill_region), MP_ROM_PTR(&bitmaptools_fill_region_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);
|
||||
|
||||
|
||||
const mp_obj_module_t bitmaptools_module = {
|
||||
.base = {&mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&bitmaptools_module_globals,
|
||||
|
@ -39,4 +39,14 @@ void common_hal_bitmaptools_rotozoom(displayio_bitmap_t *self, int16_t ox, int16
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BITMAPTOOLS__INIT__H
|
||||
|
@ -26,10 +26,12 @@
|
||||
|
||||
|
||||
#include "shared-bindings/displayio/Bitmap.h"
|
||||
#include "shared-module/displayio/Bitmap.h"
|
||||
|
||||
#include "py/runtime.h"
|
||||
|
||||
#include "math.h"
|
||||
#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,
|
||||
@ -172,3 +174,165 @@ void common_hal_bitmaptools_rotozoom(displayio_bitmap_t *self, int16_t ox, int16
|
||||
rowv += dvCol;
|
||||
}
|
||||
}
|
||||
|
||||
int16_t constrain(int16_t input, int16_t min, int16_t max) {
|
||||
// constrain the input between the min and max values
|
||||
if (input < min) {
|
||||
return min;
|
||||
}
|
||||
if (input > max) {
|
||||
return max;
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
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) {
|
||||
// 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
|
||||
|
||||
if (destination->read_only) {
|
||||
mp_raise_RuntimeError(translate("Read-only object"));
|
||||
}
|
||||
|
||||
// Ensure x1 < x2 and y1 < y2
|
||||
if (x1 > x2) {
|
||||
int16_t temp=x2;
|
||||
x2=x1;
|
||||
x1=temp;
|
||||
}
|
||||
if (y1 > y2) {
|
||||
int16_t temp=y2;
|
||||
y2=y1;
|
||||
y1=temp;
|
||||
}
|
||||
|
||||
// constrain to bitmap dimensions
|
||||
x1 = constrain(x1, 0, destination->width);
|
||||
x2 = constrain(x2, 0, destination->width);
|
||||
y1 = constrain(y1, 0, destination->height);
|
||||
y2 = constrain(y2, 0, destination->height);
|
||||
|
||||
// update the dirty rectangle
|
||||
displayio_bitmap_set_dirty_area(destination, x1, y1, x2, y2);
|
||||
|
||||
int16_t x, y;
|
||||
for (x = x1; x < x2; x++) {
|
||||
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) {
|
||||
|
||||
if (destination->read_only) {
|
||||
mp_raise_RuntimeError(translate("Read-only object"));
|
||||
}
|
||||
|
||||
//
|
||||
// adapted from Adafruit_CircuitPython_Display_Shapes.Polygon._line
|
||||
//
|
||||
|
||||
// update the dirty rectangle
|
||||
int16_t xbb0, xbb1, ybb0, ybb1;
|
||||
if (x0 < x1) {
|
||||
xbb0 = x0;
|
||||
xbb1 = x1 + 1;
|
||||
} else {
|
||||
xbb0 = x1;
|
||||
xbb1 = x0 + 1;
|
||||
}
|
||||
if (y0 < y1) {
|
||||
ybb0 = y0;
|
||||
ybb1 = y1 + 1;
|
||||
} else {
|
||||
ybb0 = y1;
|
||||
ybb1 = y0 + 1;
|
||||
}
|
||||
|
||||
xbb0 = constrain(xbb0, 0, destination->width);
|
||||
xbb1 = constrain(xbb1, 0, destination->width);
|
||||
ybb0 = constrain(ybb0, 0, destination->height);
|
||||
ybb1 = constrain(ybb1, 0, destination->height);
|
||||
|
||||
displayio_bitmap_set_dirty_area(destination, xbb0, ybb0, xbb1, ybb1);
|
||||
|
||||
int16_t temp, x, y;
|
||||
|
||||
if (x0 == x1) { // vertical line
|
||||
if (y0 > y1) { // ensure y1 > y0
|
||||
temp = y0;
|
||||
y0 = y1;
|
||||
y1 = temp;
|
||||
}
|
||||
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
|
||||
if (x0 > x1) { // ensure y1 > y0
|
||||
temp = x0;
|
||||
x0 = x1;
|
||||
x1 = temp;
|
||||
}
|
||||
for (x = x0; x < (x1 + 1); x++) { // write a horizontal line
|
||||
displayio_bitmap_write_pixel(destination, x, y0, value);
|
||||
}
|
||||
}
|
||||
else {
|
||||
bool steep;
|
||||
steep = ( abs(y1 - y0) > abs(x1 - x0) );
|
||||
|
||||
if ( steep ) { // flip x0<->y0 and x1<->y1
|
||||
temp = x0;
|
||||
x0 = y0;
|
||||
y0 = temp;
|
||||
temp = x1;
|
||||
x1 = y1;
|
||||
y1 = temp;
|
||||
}
|
||||
|
||||
if (x0 > x1) { // flip x0<->x1 and y0<->y1
|
||||
temp = x0;
|
||||
x0 = x1;
|
||||
x1 = temp;
|
||||
temp = y0;
|
||||
y0 = y1;
|
||||
y1 = temp;
|
||||
}
|
||||
|
||||
int16_t dx, dy, ystep;
|
||||
dx = x1 - x0;
|
||||
dy = abs(y1 - y0);
|
||||
|
||||
float err = dx / 2;
|
||||
|
||||
if (y0 < y1) {
|
||||
ystep = 1;
|
||||
}
|
||||
else {
|
||||
ystep = -1;
|
||||
}
|
||||
|
||||
for (x = x0; x < (x1 + 1); x++) {
|
||||
if (steep) {
|
||||
displayio_bitmap_write_pixel(destination, y0, x, value);
|
||||
}
|
||||
else {
|
||||
displayio_bitmap_write_pixel(destination, x, y0, value);
|
||||
}
|
||||
err -= dy;
|
||||
if (err < 0) {
|
||||
y0 += ystep;
|
||||
err += dx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,5 +49,7 @@ typedef struct {
|
||||
|
||||
void displayio_bitmap_finish_refresh(displayio_bitmap_t *self);
|
||||
displayio_area_t* displayio_bitmap_get_refresh_areas(displayio_bitmap_t *self, displayio_area_t* tail);
|
||||
void displayio_bitmap_set_dirty_area(displayio_bitmap_t *self, int16_t x1, int16_t y1, int16_t x2, int16_t y2);
|
||||
void displayio_bitmap_write_pixel(displayio_bitmap_t *self, int16_t x, int16_t y, uint32_t value);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_BITMAP_H
|
||||
|
Loading…
Reference in New Issue
Block a user