Merge pull request #451 from kwagyeman/kwabena/improve_drawing_stuff

Improve drawing functions
This commit is contained in:
Ibrahim Abd Elkader 2019-02-17 18:07:57 +02:00 committed by GitHub
commit 112a3daaa4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 389 additions and 120 deletions

View File

@ -20,7 +20,7 @@ while(True):
y = (pyb.rng() % (2*img.height())) - (img.height()//2)
radius_x = pyb.rng() % (max(img.height(), img.width())//2)
radius_y = pyb.rng() % (max(img.height(), img.width())//2)
rot = pyb.rng() % 45 # Avoid large rotation angles with fill on...
rot = pyb.rng()
r = (pyb.rng() % 127) + 128
g = (pyb.rng() % 127) + 128
@ -29,7 +29,7 @@ while(True):
# If the first argument is a scaler then this method expects
# to see x, y, radius x, and radius y.
# Otherwise, it expects a (x,y,radius_x,radius_y) tuple.
img.draw_ellipse(x, y, radius_x, radius_y, \
rotation = rot, color = (r, g, b), thickness = 2, fill = False)
img.draw_ellipse(x, y, radius_x, radius_y, rot,
color = (r, g, b), thickness = 2, fill = False)
print(clock.fps())

View File

@ -24,6 +24,10 @@ while(True):
# If the first argument is a scaler then this method expects
# to see x, y, and text. Otherwise, it expects a (x,y,text) tuple.
img.draw_string(x, y, "Hello World!", color = (r, g, b), scale = 2, mono_space = False)
# Character and string rotation can be done at 0, 90, 180, 270, and etc. degrees.
img.draw_string(x, y, "Hello World!", color = (r, g, b), scale = 2, mono_space = False,
char_rotation = 0, char_hmirror = False, char_vflip = False,
string_rotation = 0, string_hmirror = False, string_vflip = False)
print(clock.fps())

View File

@ -248,11 +248,28 @@ static void scratch_draw_sheared_ellipse(image_t *img, int x0, int y0, int width
static void scratch_draw_rotated_ellipse(image_t *img, int x, int y, int x_axis, int y_axis, int rotation, bool filled, int c, int thickness)
{
if ((x_axis > 0) && (y_axis > 0)) {
if ((x_axis == y_axis) || ((rotation % 180) == 0)) {
if ((x_axis == y_axis) || (rotation == 0)) {
scratch_draw_sheared_ellipse(img, x, y, x_axis / 2, y_axis / 2, filled, 1, 0, c, thickness);
} else if ((rotation % 180) == 90) {
} else if (rotation == 90) {
scratch_draw_sheared_ellipse(img, x, y, y_axis / 2, x_axis / 2, filled, 1, 0, c, thickness);
} else {
// Avoid rotations above 90.
if (rotation > 90) {
rotation -= 90;
int temp = x_axis;
x_axis = y_axis;
y_axis = temp;
}
// Avoid rotations above 45.
if (rotation > 45) {
rotation -= 90;
int temp = x_axis;
x_axis = y_axis;
y_axis = temp;
}
float theta = fast_atanf(IM_DIV(y_axis, x_axis) * (-tanf(IM_DEG2RAD(rotation))));
float shear_dx = (x_axis * cosf(theta) * cosf(IM_DEG2RAD(rotation))) - (y_axis * sinf(theta) * sinf(IM_DEG2RAD(rotation)));
float shear_dy = (x_axis * cosf(theta) * sinf(IM_DEG2RAD(rotation))) + (y_axis * sinf(theta) * cosf(IM_DEG2RAD(rotation)));
@ -265,11 +282,33 @@ static void scratch_draw_rotated_ellipse(image_t *img, int x, int y, int x_axis,
void imlib_draw_ellipse(image_t *img, int cx, int cy, int rx, int ry, int rotation, int c, int thickness, bool fill)
{
scratch_draw_rotated_ellipse(img, cx, cy, rx * 2, ry * 2, rotation, fill, c, thickness);
int r = rotation % 180;
if (r < 0) r += 180;
scratch_draw_rotated_ellipse(img, cx, cy, rx * 2, ry * 2, r, fill, c, thickness);
}
void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int c, float scale, int x_spacing, int y_spacing, bool mono_space)
// char rotation == 0, 90, 180, 360, etc.
// string rotation == 0, 90, 180, 360, etc.
void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int c, float scale, int x_spacing, int y_spacing, bool mono_space,
int char_rotation, bool char_hmirror, bool char_vflip, int string_rotation, bool string_hmirror, bool string_vflip)
{
char_rotation %= 360;
if (char_rotation < 0) char_rotation += 360;
char_rotation = (char_rotation / 90) * 90;
string_rotation %= 360;
if (string_rotation < 0) string_rotation += 360;
string_rotation = (string_rotation / 90) * 90;
bool char_swap_w_h = (char_rotation == 90) || (char_rotation == 270);
bool char_upsidedown = (char_rotation == 180) || (char_rotation == 270);
if (string_hmirror) x_off -= fast_floorf(font[0].w * scale) - 1;
if (string_vflip) y_off -= fast_floorf(font[0].h * scale) - 1;
int org_x_off = x_off;
int org_y_off = y_off;
const int anchor = x_off;
for(char ch, last = '\0'; (ch = *str); str++, last = ch) {
@ -280,17 +319,11 @@ void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int
if ((ch == '\n') || (ch == '\r')) { // handle '\n' or '\r' strings
x_off = anchor;
y_off += fast_roundf(font[0].h * scale) + y_spacing; // newline height == space height
y_off += (string_vflip ? -1 : +1) * (fast_floorf((char_swap_w_h ? font[0].w : font[0].h) * scale) + y_spacing); // newline height == space height
continue;
}
if ((ch < ' ') || (ch > '~')) { // handle unknown characters
imlib_draw_rectangle(img,
x_off + (fast_roundf(scale * 3) / 2),
y_off + (fast_roundf(scale * 3) / 2),
fast_roundf(font[0].w * scale) - ((fast_roundf(scale * 3) / 2) * 2),
fast_roundf(font[0].h * scale) - ((fast_roundf(scale * 3) / 2) * 2),
c, fast_roundf(scale), false);
continue;
}
@ -300,46 +333,81 @@ void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int
// Find the first pixel set and offset to that.
bool exit = false;
for (int x = 0, xx = g->w; x < xx; x++) {
for (int y = 0, yy = g->h; y < yy; y++) {
if (g->data[y] & (1 << (g->w - 1 - x))) {
x_off -= fast_roundf(x * scale);
exit = true;
break;
if (!char_swap_w_h) {
for (int x = 0, xx = g->w; x < xx; x++) {
for (int y = 0, yy = g->h; y < yy; y++) {
if (g->data[(char_upsidedown ^ char_vflip) ? (g->h - 1 - y) : y] &
(1 << ((char_upsidedown ^ char_hmirror ^ string_hmirror) ? x : (g->w - 1 - x)))) {
x_off += (string_hmirror ? +1 : -1) * fast_floorf(x * scale);
exit = true;
break;
}
}
}
if (exit) break;
if (exit) break;
}
} else {
for (int y = g->h - 1; y >= 0; y--) {
for (int x = 0, xx = g->w; x < xx; x++) {
if (g->data[(char_upsidedown ^ char_vflip) ? (g->h - 1 - y) : y] &
(1 << ((char_upsidedown ^ char_hmirror ^ string_hmirror) ? x : (g->w - 1 - x)))) {
x_off += (string_hmirror ? +1 : -1) * fast_floorf((g->h - 1 - y) * scale);
exit = true;
break;
}
}
if (exit) break;
}
}
}
for (int y = 0, yy = fast_roundf(g->h * scale); y < yy; y++) {
for (int x = 0, xx = fast_roundf(g->w * scale); x < xx; x++) {
if (g->data[fast_roundf(y / scale)] & (1 << (g->w - 1 - fast_roundf(x / scale)))) {
imlib_set_pixel(img, (x_off + x), (y_off + y), c);
for (int y = 0, yy = fast_floorf(g->h * scale); y < yy; y++) {
for (int x = 0, xx = fast_floorf(g->w * scale); x < xx; x++) {
if (g->data[fast_floorf(y / scale)] & (1 << (g->w - 1 - fast_floorf(x / scale)))) {
int16_t x_tmp = x_off + (char_hmirror ? (xx - x - 1) : x), y_tmp = y_off + (char_vflip ? (yy - y - 1) : y);
point_rotate(x_tmp, y_tmp, IM_DEG2RAD(char_rotation), x_off + (xx / 2), y_off + (yy / 2), &x_tmp, &y_tmp);
point_rotate(x_tmp, y_tmp, IM_DEG2RAD(string_rotation), org_x_off, org_y_off, &x_tmp, &y_tmp);
imlib_set_pixel(img, x_tmp, y_tmp, c);
}
}
}
if (mono_space) {
x_off += fast_roundf(g->w * scale) + x_spacing;
x_off += (string_hmirror ? -1 : +1) * (fast_floorf((char_swap_w_h ? g->h : g->w) * scale) + x_spacing);
} else {
// Find the last pixel set and offset to that.
bool exit = false;
for (int x = g->w - 1; x >= 0; x--) {
for (int y = g->h - 1; y >= 0; y--) {
if (g->data[y] & (1 << (g->w - 1 - x))) {
x_off += fast_roundf((x + 2) * scale) + x_spacing;
exit = true;
break;
if (!char_swap_w_h) {
for (int x = g->w - 1; x >= 0; x--) {
for (int y = g->h - 1; y >= 0; y--) {
if (g->data[(char_upsidedown ^ char_vflip) ? (g->h - 1 - y) : y] &
(1 << ((char_upsidedown ^ char_hmirror ^ string_hmirror) ? x : (g->w - 1 - x)))) {
x_off += (string_hmirror ? -1 : +1) * (fast_floorf((x + 2) * scale) + x_spacing);
exit = true;
break;
}
}
}
if (exit) break;
if (exit) break;
}
} else {
for (int y = 0, yy = g->h; y < yy; y++) {
for (int x = g->w - 1; x >= 0; x--) {
if (g->data[(char_upsidedown ^ char_vflip) ? (g->h - 1 - y) : y] &
(1 << ((char_upsidedown ^ char_hmirror ^ string_hmirror) ? x : (g->w - 1 - x)))) {
x_off += (string_hmirror ? -1 : +1) * (fast_floorf(((g->h - 1 - y) + 2) * scale) + x_spacing);
exit = true;
break;
}
}
if (exit) break;
}
}
if (!exit) x_off += fast_roundf(scale * 3); // space char
if (!exit) x_off += (string_hmirror ? -1 : +1) * fast_floorf(scale * 3); // space char
}
}
}
@ -405,11 +473,11 @@ void imlib_draw_image(image_t *img, image_t *other, int x_off, int y_off, float
{
float over_xscale = IM_DIV(1.0, x_scale), over_yscale = IM_DIV(1.0f, y_scale), beta = 1 - alpha;
for (int y = 0, yy = fast_roundf(other->h * y_scale); y < yy; y++) {
int other_y = fast_roundf(y * over_yscale);
for (int y = 0, yy = fast_floorf(other->h * y_scale); y < yy; y++) {
int other_y = fast_floorf(y * over_yscale);
for (int x = 0, xx = fast_roundf(other->w * x_scale); x < xx; x++) {
int other_x = fast_roundf(x * over_xscale);
for (int x = 0, xx = fast_floorf(other->w * x_scale); x < xx; x++) {
int other_x = fast_floorf(x * over_xscale);
if ((!mask) || image_get_mask_pixel(mask, other_x, other_y)) {
int pixel = safe_map_pixel(img, other, imlib_get_pixel(other, other_x, other_y));
@ -446,22 +514,22 @@ void imlib_flood_fill(image_t *img, int x, int y,
switch(img->bpp) {
case IMAGE_BPP_BINARY: {
color_seed_threshold = fast_roundf(seed_threshold * COLOR_BINARY_MAX);
color_floating_threshold = fast_roundf(floating_threshold * COLOR_BINARY_MAX);
color_seed_threshold = fast_floorf(seed_threshold * COLOR_BINARY_MAX);
color_floating_threshold = fast_floorf(floating_threshold * COLOR_BINARY_MAX);
break;
}
case IMAGE_BPP_GRAYSCALE: {
color_seed_threshold = fast_roundf(seed_threshold * COLOR_GRAYSCALE_MAX);
color_floating_threshold = fast_roundf(floating_threshold * COLOR_GRAYSCALE_MAX);
color_seed_threshold = fast_floorf(seed_threshold * COLOR_GRAYSCALE_MAX);
color_floating_threshold = fast_floorf(floating_threshold * COLOR_GRAYSCALE_MAX);
break;
}
case IMAGE_BPP_RGB565: {
color_seed_threshold = COLOR_R5_G6_B5_TO_RGB565(fast_roundf(seed_threshold * COLOR_R5_MAX),
fast_roundf(seed_threshold * COLOR_G6_MAX),
fast_roundf(seed_threshold * COLOR_B5_MAX));
color_floating_threshold = COLOR_R5_G6_B5_TO_RGB565(fast_roundf(floating_threshold * COLOR_R5_MAX),
fast_roundf(floating_threshold * COLOR_G6_MAX),
fast_roundf(floating_threshold * COLOR_B5_MAX));
color_seed_threshold = COLOR_R5_G6_B5_TO_RGB565(fast_floorf(seed_threshold * COLOR_R5_MAX),
fast_floorf(seed_threshold * COLOR_G6_MAX),
fast_floorf(seed_threshold * COLOR_B5_MAX));
color_floating_threshold = COLOR_R5_G6_B5_TO_RGB565(fast_floorf(floating_threshold * COLOR_R5_MAX),
fast_floorf(floating_threshold * COLOR_G6_MAX),
fast_floorf(floating_threshold * COLOR_B5_MAX));
break;
}
default: {

View File

@ -32,7 +32,7 @@ void imlib_histeq(image_t *img, image_t *mask)
if (mask && (!image_get_mask_pixel(mask, x, y))) continue;
int pixel = IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x);
IMAGE_PUT_BINARY_PIXEL_FAST(row_ptr, x,
fast_roundf((s * hist[pixel - COLOR_BINARY_MIN]) + COLOR_BINARY_MIN));
fast_floorf((s * hist[pixel - COLOR_BINARY_MIN]) + COLOR_BINARY_MIN));
}
}
@ -62,7 +62,7 @@ void imlib_histeq(image_t *img, image_t *mask)
if (mask && (!image_get_mask_pixel(mask, x, y))) continue;
int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x);
IMAGE_PUT_GRAYSCALE_PIXEL_FAST(row_ptr, x,
fast_roundf((s * hist[pixel - COLOR_GRAYSCALE_MIN]) + COLOR_GRAYSCALE_MIN));
fast_floorf((s * hist[pixel - COLOR_GRAYSCALE_MIN]) + COLOR_GRAYSCALE_MIN));
}
}
@ -92,7 +92,7 @@ void imlib_histeq(image_t *img, image_t *mask)
if (mask && (!image_get_mask_pixel(mask, x, y))) continue;
int pixel = IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x);
IMAGE_PUT_RGB565_PIXEL_FAST(row_ptr, x,
imlib_yuv_to_rgb(fast_roundf(s * hist[COLOR_RGB565_TO_Y(pixel) - COLOR_Y_MIN]),
imlib_yuv_to_rgb(fast_floorf(s * hist[COLOR_RGB565_TO_Y(pixel) - COLOR_Y_MIN]),
COLOR_RGB565_TO_U(pixel),
COLOR_RGB565_TO_V(pixel)));
}
@ -149,7 +149,7 @@ void imlib_mean_filter(image_t *img, const int ksize, bool threshold, int offset
}
}
int pixel = fast_roundf(acc * over_n);
int pixel = fast_floorf(acc * over_n);
if (threshold) {
if (((pixel - offset) < IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x)) ^ invert) {
@ -204,7 +204,7 @@ void imlib_mean_filter(image_t *img, const int ksize, bool threshold, int offset
}
}
int pixel = fast_roundf(acc * over_n);
int pixel = fast_floorf(acc * over_n);
if (threshold) {
if (((pixel - offset) < IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x)) ^ invert) {
@ -262,9 +262,9 @@ void imlib_mean_filter(image_t *img, const int ksize, bool threshold, int offset
}
}
int pixel = COLOR_R5_G6_B5_TO_RGB565(fast_roundf(r_acc * over_n),
fast_roundf(g_acc * over_n),
fast_roundf(b_acc * over_n));
int pixel = COLOR_R5_G6_B5_TO_RGB565(fast_floorf(r_acc * over_n),
fast_floorf(g_acc * over_n),
fast_floorf(b_acc * over_n));
if (threshold) {
if (((COLOR_RGB565_TO_Y(pixel) - offset) < COLOR_RGB565_TO_Y(IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x))) ^ invert) {
@ -310,7 +310,7 @@ void imlib_median_filter(image_t *img, const int ksize, float percentile, bool t
buf.h = brows;
buf.bpp = img->bpp;
int n = ((ksize*2)+1)*((ksize*2)+1), int_percentile = fast_roundf(percentile * (n - 1));
int n = ((ksize*2)+1)*((ksize*2)+1), int_percentile = fast_floorf(percentile * (n - 1));
switch(img->bpp) {
case IMAGE_BPP_BINARY: {
@ -782,7 +782,7 @@ void imlib_midpoint_filter(image_t *img, const int ksize, float bias, bool thres
}
}
int pixel = fast_roundf((min*min_bias)+(max*max_bias));
int pixel = fast_floorf((min*min_bias)+(max*max_bias));
if (threshold) {
if (((pixel - offset) < IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x)) ^ invert) {
@ -839,7 +839,7 @@ void imlib_midpoint_filter(image_t *img, const int ksize, float bias, bool thres
}
}
int pixel = fast_roundf((min*min_bias)+(max*max_bias));
int pixel = fast_floorf((min*min_bias)+(max*max_bias));
if (threshold) {
if (((pixel - offset) < IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x)) ^ invert) {
@ -905,9 +905,9 @@ void imlib_midpoint_filter(image_t *img, const int ksize, float bias, bool thres
}
}
int pixel = COLOR_R5_G6_B5_TO_RGB565(fast_roundf((r_min*min_bias)+(r_max*max_bias)),
fast_roundf((g_min*min_bias)+(g_max*max_bias)),
fast_roundf((b_min*min_bias)+(b_max*max_bias)));
int pixel = COLOR_R5_G6_B5_TO_RGB565(fast_floorf((r_min*min_bias)+(r_max*max_bias)),
fast_floorf((g_min*min_bias)+(g_max*max_bias)),
fast_floorf((b_min*min_bias)+(b_max*max_bias)));
if (threshold) {
if (((COLOR_RGB565_TO_Y(pixel) - offset) < COLOR_RGB565_TO_Y(IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x))) ^ invert) {
@ -980,7 +980,7 @@ void imlib_morph(image_t *img, const int ksize, const int *krn, const float m, c
}
}
int pixel = IM_MAX(IM_MIN(fast_roundf(acc * m) + b, COLOR_BINARY_MAX), COLOR_BINARY_MIN);
int pixel = IM_MAX(IM_MIN(fast_floorf(acc * m) + b, COLOR_BINARY_MAX), COLOR_BINARY_MIN);
if (threshold) {
if (((pixel - offset) < IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x)) ^ invert) {
@ -1035,7 +1035,7 @@ void imlib_morph(image_t *img, const int ksize, const int *krn, const float m, c
}
}
int pixel = IM_MAX(IM_MIN(fast_roundf(acc * m) + b, COLOR_GRAYSCALE_MAX), COLOR_GRAYSCALE_MIN);
int pixel = IM_MAX(IM_MIN(fast_floorf(acc * m) + b, COLOR_GRAYSCALE_MAX), COLOR_GRAYSCALE_MIN);
if (threshold) {
if (((pixel - offset) < IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x)) ^ invert) {
@ -1093,9 +1093,9 @@ void imlib_morph(image_t *img, const int ksize, const int *krn, const float m, c
}
}
int pixel = COLOR_R5_G6_B5_TO_RGB565(IM_MAX(IM_MIN(fast_roundf(r_acc * m) + b, COLOR_R5_MAX), COLOR_R5_MIN),
IM_MAX(IM_MIN(fast_roundf(g_acc * m) + b, COLOR_G6_MAX), COLOR_G6_MIN),
IM_MAX(IM_MIN(fast_roundf(b_acc * m) + b, COLOR_B5_MAX), COLOR_B5_MIN));
int pixel = COLOR_R5_G6_B5_TO_RGB565(IM_MAX(IM_MIN(fast_floorf(r_acc * m) + b, COLOR_R5_MAX), COLOR_R5_MIN),
IM_MAX(IM_MIN(fast_floorf(g_acc * m) + b, COLOR_G6_MAX), COLOR_G6_MIN),
IM_MAX(IM_MIN(fast_floorf(b_acc * m) + b, COLOR_B5_MAX), COLOR_B5_MIN));
if (threshold) {
if (((COLOR_RGB565_TO_Y(pixel) - offset) < COLOR_RGB565_TO_Y(IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x))) ^ invert) {
@ -1196,7 +1196,7 @@ void imlib_bilateral_filter(image_t *img, const int ksize, float color_sigma, fl
}
}
int pixel = fast_roundf(IM_MIN(IM_DIV(i_acc, w_acc), COLOR_BINARY_MAX));
int pixel = fast_floorf(IM_MIN(IM_DIV(i_acc, w_acc), COLOR_BINARY_MAX));
if (threshold) {
if (((pixel - offset) < IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x)) ^ invert) {
@ -1273,7 +1273,7 @@ void imlib_bilateral_filter(image_t *img, const int ksize, float color_sigma, fl
}
}
int pixel = fast_roundf(IM_MIN(IM_DIV(i_acc, w_acc), COLOR_GRAYSCALE_MAX));
int pixel = fast_floorf(IM_MIN(IM_DIV(i_acc, w_acc), COLOR_GRAYSCALE_MAX));
if (threshold) {
if (((pixel - offset) < IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x)) ^ invert) {
@ -1377,9 +1377,9 @@ void imlib_bilateral_filter(image_t *img, const int ksize, float color_sigma, fl
}
}
int pixel = COLOR_R5_G6_B5_TO_RGB565(fast_roundf(IM_MIN(IM_DIV(r_i_acc, r_w_acc), COLOR_R5_MAX)),
fast_roundf(IM_MIN(IM_DIV(g_i_acc, g_w_acc), COLOR_G6_MAX)),
fast_roundf(IM_MIN(IM_DIV(b_i_acc, b_w_acc), COLOR_B5_MAX)));
int pixel = COLOR_R5_G6_B5_TO_RGB565(fast_floorf(IM_MIN(IM_DIV(r_i_acc, r_w_acc), COLOR_R5_MAX)),
fast_floorf(IM_MIN(IM_DIV(g_i_acc, g_w_acc), COLOR_G6_MAX)),
fast_floorf(IM_MIN(IM_DIV(b_i_acc, b_w_acc), COLOR_B5_MAX)));
if (threshold) {
if (((COLOR_RGB565_TO_Y(pixel) - offset) < COLOR_RGB565_TO_Y(IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x))) ^ invert) {
@ -1527,22 +1527,22 @@ void imlib_cartoon_filter(image_t *img, float seed_threshold, float floating_thr
switch(img->bpp) {
case IMAGE_BPP_BINARY: {
color_seed_threshold = fast_roundf(seed_threshold * COLOR_BINARY_MAX);
color_floating_threshold = fast_roundf(floating_threshold * COLOR_BINARY_MAX);
color_seed_threshold = fast_floorf(seed_threshold * COLOR_BINARY_MAX);
color_floating_threshold = fast_floorf(floating_threshold * COLOR_BINARY_MAX);
break;
}
case IMAGE_BPP_GRAYSCALE: {
color_seed_threshold = fast_roundf(seed_threshold * COLOR_GRAYSCALE_MAX);
color_floating_threshold = fast_roundf(floating_threshold * COLOR_GRAYSCALE_MAX);
color_seed_threshold = fast_floorf(seed_threshold * COLOR_GRAYSCALE_MAX);
color_floating_threshold = fast_floorf(floating_threshold * COLOR_GRAYSCALE_MAX);
break;
}
case IMAGE_BPP_RGB565: {
color_seed_threshold = COLOR_R5_G6_B5_TO_RGB565(fast_roundf(seed_threshold * COLOR_R5_MAX),
fast_roundf(seed_threshold * COLOR_G6_MAX),
fast_roundf(seed_threshold * COLOR_B5_MAX));
color_floating_threshold = COLOR_R5_G6_B5_TO_RGB565(fast_roundf(floating_threshold * COLOR_R5_MAX),
fast_roundf(floating_threshold * COLOR_G6_MAX),
fast_roundf(floating_threshold * COLOR_B5_MAX));
color_seed_threshold = COLOR_R5_G6_B5_TO_RGB565(fast_floorf(seed_threshold * COLOR_R5_MAX),
fast_floorf(seed_threshold * COLOR_G6_MAX),
fast_floorf(seed_threshold * COLOR_B5_MAX));
color_floating_threshold = COLOR_R5_G6_B5_TO_RGB565(fast_floorf(floating_threshold * COLOR_R5_MAX),
fast_floorf(floating_threshold * COLOR_G6_MAX),
fast_floorf(floating_threshold * COLOR_B5_MAX));
break;
}
default: {

View File

@ -314,7 +314,7 @@ int8_t imlib_rgb565_to_l(uint16_t pixel)
y = (y>0.008856f) ? fast_cbrtf(y) : ((y * 7.787037f) + 0.137931f);
return fast_roundf(116 * y) - 16;
return fast_floorf(116 * y) - 16;
}
int8_t imlib_rgb565_to_a(uint16_t pixel)
@ -329,7 +329,7 @@ int8_t imlib_rgb565_to_a(uint16_t pixel)
x = (x>0.008856f) ? fast_cbrtf(x) : ((x * 7.787037f) + 0.137931f);
y = (y>0.008856f) ? fast_cbrtf(y) : ((y * 7.787037f) + 0.137931f);
return fast_roundf(500 * (x-y));
return fast_floorf(500 * (x-y));
}
int8_t imlib_rgb565_to_b(uint16_t pixel)
@ -344,7 +344,7 @@ int8_t imlib_rgb565_to_b(uint16_t pixel)
y = (y>0.008856f) ? fast_cbrtf(y) : ((y * 7.787037f) + 0.137931f);
z = (z>0.008856f) ? fast_cbrtf(z) : ((z * 7.787037f) + 0.137931f);
return fast_roundf(200 * (y-z));
return fast_floorf(200 * (y-z));
}
int8_t imlib_rgb565_to_y(uint16_t pixel)
@ -394,9 +394,9 @@ uint16_t imlib_lab_to_rgb(uint8_t l, int8_t a, int8_t b)
g_lin = (g_lin>0.0031308f) ? ((1.055f*powf(g_lin, 0.416666f))-0.055f) : (g_lin*12.92f);
b_lin = (b_lin>0.0031308f) ? ((1.055f*powf(b_lin, 0.416666f))-0.055f) : (b_lin*12.92f);
uint32_t red = IM_MAX(IM_MIN(fast_roundf(r_lin * COLOR_R8_MAX), COLOR_R8_MAX), COLOR_R8_MIN);
uint32_t green = IM_MAX(IM_MIN(fast_roundf(g_lin * COLOR_G8_MAX), COLOR_G8_MAX), COLOR_G8_MIN);
uint32_t blue = IM_MAX(IM_MIN(fast_roundf(b_lin * COLOR_B8_MAX), COLOR_B8_MAX), COLOR_B8_MIN);
uint32_t red = IM_MAX(IM_MIN(fast_floorf(r_lin * COLOR_R8_MAX), COLOR_R8_MAX), COLOR_R8_MIN);
uint32_t green = IM_MAX(IM_MIN(fast_floorf(g_lin * COLOR_G8_MAX), COLOR_G8_MAX), COLOR_G8_MIN);
uint32_t blue = IM_MAX(IM_MIN(fast_floorf(b_lin * COLOR_B8_MAX), COLOR_B8_MAX), COLOR_B8_MIN);
return COLOR_R8_G8_B8_TO_RGB565(red, green, blue);
}
@ -755,6 +755,48 @@ void imlib_save_image(image_t *img, const char *path, rectangle_t *roi, int qual
////////////////////////////////////////////////////////////////////////////////
void imlib_zero(image_t *img, image_t *mask, bool invert)
{
switch(img->bpp) {
case IMAGE_BPP_BINARY: {
for (int y = 0, yy = img->h; y < yy; y++) {
uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y);
for (int x = 0, xx = img->w; x < xx; x++) {
if (image_get_mask_pixel(mask, x, y) ^ invert) {
IMAGE_PUT_BINARY_PIXEL_FAST(row_ptr, x, 0);
}
}
}
break;
}
case IMAGE_BPP_GRAYSCALE: {
for (int y = 0, yy = img->h; y < yy; y++) {
uint8_t *row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y);
for (int x = 0, xx = img->w; x < xx; x++) {
if (image_get_mask_pixel(mask, x, y) ^ invert) {
IMAGE_PUT_GRAYSCALE_PIXEL_FAST(row_ptr, x, 0);
}
}
}
break;
}
case IMAGE_BPP_RGB565: {
for (int y = 0, yy = img->h; y < yy; y++) {
uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y);
for (int x = 0, xx = img->w; x < xx; x++) {
if (image_get_mask_pixel(mask, x, y) ^ invert) {
IMAGE_PUT_RGB565_PIXEL_FAST(row_ptr, x, 0);
}
}
}
break;
}
default: {
break;
}
}
}
// A simple algorithm for correcting lens distortion.
// See http://www.tannerhelland.com/4743/simple-algorithm-correcting-lens-distortion/
void imlib_lens_corr(image_t *img, float strength, float zoom)
@ -784,8 +826,8 @@ void imlib_lens_corr(image_t *img, float strength, float zoom)
float r = lens_corr_radius * fast_sqrtf(newX2 + newY2);
float theta = (r < 0.0000001f) ? 1.0f : (fast_atanf(r) / r);
int sourceX = halfWidth + fast_roundf(theta * zoomedX);
int sourceY = halfHeight + fast_roundf(theta * zoomedY);
int sourceX = halfWidth + fast_floorf(theta * zoomedX);
int sourceY = halfHeight + fast_floorf(theta * zoomedY);
if ((0 <= sourceX) && (sourceX < img->w) && (0 <= sourceY) && (sourceY < img->h)) {
uint32_t *ptr = tmp + (((img->w + UINT32_T_MASK) >> UINT32_T_SHIFT) * sourceY);
@ -817,8 +859,8 @@ void imlib_lens_corr(image_t *img, float strength, float zoom)
float r = lens_corr_radius * fast_sqrtf(newX2 + newY2);
float theta = (r < 0.0000001f) ? 1.0f : (fast_atanf(r) / r);
int sourceX = halfWidth + fast_roundf(theta * zoomedX);
int sourceY = halfHeight + fast_roundf(theta * zoomedY);
int sourceX = halfWidth + fast_floorf(theta * zoomedX);
int sourceY = halfHeight + fast_floorf(theta * zoomedY);
if ((0 <= sourceX) && (sourceX < img->w) && (0 <= sourceY) && (sourceY < img->h)) {
uint8_t *ptr = tmp + (img->w * sourceY);
@ -850,8 +892,8 @@ void imlib_lens_corr(image_t *img, float strength, float zoom)
float r = lens_corr_radius * fast_sqrtf(newX2 + newY2);
float theta = (r < 0.0000001f) ? 1.0f : (fast_atanf(r) / r);
int sourceX = halfWidth + fast_roundf(theta * zoomedX);
int sourceY = halfHeight + fast_roundf(theta * zoomedY);
int sourceX = halfWidth + fast_floorf(theta * zoomedX);
int sourceY = halfHeight + fast_floorf(theta * zoomedY);
if ((0 <= sourceX) && (sourceX < img->w) && (0 <= sourceY) && (sourceY < img->h)) {
uint16_t *ptr = tmp + (img->w * sourceY);

View File

@ -1251,6 +1251,7 @@ void imlib_edge_canny(image_t *src, rectangle_t *roi, int low_thresh, int high_t
void imlib_find_hog(image_t *src, rectangle_t *roi, int cell_size);
// Helper Functions
void imlib_zero(image_t *img, image_t *mask, bool invert);
void imlib_flood_fill_int(image_t *out, image_t *img, int x, int y,
int seed_threshold, int floating_threshold,
flood_fill_call_back_t cb, void *data);
@ -1261,7 +1262,8 @@ void imlib_draw_line(image_t *img, int x0, int y0, int x1, int y1, int c, int th
void imlib_draw_rectangle(image_t *img, int rx, int ry, int rw, int rh, int c, int thickness, bool fill);
void imlib_draw_circle(image_t *img, int cx, int cy, int r, int c, int thickness, bool fill);
void imlib_draw_ellipse(image_t *img, int cx, int cy, int rx, int ry, int rotation, int c, int thickness, bool fill);
void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int c, float scale, int x_spacing, int y_spacing, bool mono_space);
void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int c, float scale, int x_spacing, int y_spacing, bool mono_space,
int char_rotation, bool char_hmirror, bool char_vflip, int string_rotation, bool string_hmirror, bool string_hflip);
void imlib_draw_image(image_t *img, image_t *other, int x_off, int y_off, float x_scale, float y_scale, float alpha, image_t *mask);
void imlib_flood_fill(image_t *img, int x, int y,
float seed_threshold, float floating_threshold,

View File

@ -1430,9 +1430,9 @@ static mp_obj_t py_image_copy_int(uint n_args, const mp_obj_t *args, mp_map_t *k
}
image_t image;
image.w = fast_roundf(roi.w * arg_x_scale);
image.w = fast_floorf(roi.w * arg_x_scale);
PY_ASSERT_TRUE_MSG(image.w >= 1, "Output image width is 0!");
image.h = fast_roundf(roi.h * arg_y_scale);
image.h = fast_floorf(roi.h * arg_y_scale);
PY_ASSERT_TRUE_MSG(image.h >= 1, "Output image height is 0!");
image.bpp = arg_img->bpp;
image.data = NULL;
@ -1478,33 +1478,33 @@ static mp_obj_t py_image_copy_int(uint n_args, const mp_obj_t *args, mp_map_t *k
switch(arg_img->bpp) {
case IMAGE_BPP_BINARY: {
for (int y = 0, yy = image.h; y < yy; y++) {
uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(arg_img, fast_roundf(y * over_yscale) + roi.y);
uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(arg_img, fast_floorf(y * over_yscale) + roi.y);
uint32_t *row_ptr_2 = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&image, y);
for (int x = 0, xx = image.w; x < xx; x++) {
IMAGE_PUT_BINARY_PIXEL_FAST(row_ptr_2, x,
IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, fast_roundf(x * over_xscale) + roi.x));
IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, fast_floorf(x * over_xscale) + roi.x));
}
}
break;
}
case IMAGE_BPP_GRAYSCALE: {
for (int y = 0, yy = image.h; y < yy; y++) {
uint8_t *row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(arg_img, fast_roundf(y * over_yscale) + roi.y);
uint8_t *row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(arg_img, fast_floorf(y * over_yscale) + roi.y);
uint8_t *row_ptr_2 = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&image, y);
for (int x = 0, xx = image.w; x < xx; x++) {
IMAGE_PUT_GRAYSCALE_PIXEL_FAST(row_ptr_2, x,
IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, fast_roundf(x * over_xscale) + roi.x));
IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, fast_floorf(x * over_xscale) + roi.x));
}
}
break;
}
case IMAGE_BPP_RGB565: {
for (int y = 0, yy = image.h; y < yy; y++) {
uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(arg_img, fast_roundf(y * over_yscale) + roi.y);
uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(arg_img, fast_floorf(y * over_yscale) + roi.y);
uint16_t *row_ptr_2 = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&image, y);
for (int x = 0, xx = image.w; x < xx; x++) {
IMAGE_PUT_RGB565_PIXEL_FAST(row_ptr_2, x,
IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, fast_roundf(x * over_xscale) + roi.x));
IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, fast_floorf(x * over_xscale) + roi.x));
}
}
break;
@ -1578,13 +1578,22 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_save_obj, 2, py_image_save);
// Drawing Methods
//////////////////
STATIC mp_obj_t py_image_clear(mp_obj_t img_obj)
STATIC mp_obj_t py_image_clear(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
image_t *arg_img = py_helper_arg_to_image_mutable_bayer(img_obj);
memset(arg_img->data, 0, image_size(arg_img));
return img_obj;
image_t *arg_img = py_helper_arg_to_image_mutable_bayer(args[0]);
image_t *arg_msk =
py_helper_keyword_to_image_mutable_mask(n_args, args, 1, kw_args);
if (!arg_msk) {
memset(arg_img->data, 0, image_size(arg_img));
} else {
imlib_zero(arg_img, arg_msk, false);
}
return args[0];
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_clear_obj, py_image_clear);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_clear_obj, 1, py_image_clear);
STATIC mp_obj_t py_image_draw_line(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
@ -1657,14 +1666,13 @@ STATIC mp_obj_t py_image_draw_ellipse(uint n_args, const mp_obj_t *args, mp_map_
image_t *arg_img = py_helper_arg_to_image_mutable(args[0]);
const mp_obj_t *arg_vec;
uint offset = py_helper_consume_array(n_args, args, 1, 4, &arg_vec);
uint offset = py_helper_consume_array(n_args, args, 1, 5, &arg_vec);
int arg_cx = mp_obj_get_int(arg_vec[0]);
int arg_cy = mp_obj_get_int(arg_vec[1]);
int arg_rx = mp_obj_get_int(arg_vec[2]);
int arg_ry = mp_obj_get_int(arg_vec[3]);
int arg_r = mp_obj_get_int(arg_vec[4]);
int arg_rotation =
py_helper_keyword_int(n_args, args, offset + 0, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_rotation), 0);
int arg_c =
py_helper_keyword_color(arg_img, n_args, args, offset + 1, kw_args, -1); // White.
int arg_thickness =
@ -1672,7 +1680,7 @@ STATIC mp_obj_t py_image_draw_ellipse(uint n_args, const mp_obj_t *args, mp_map_
bool arg_fill =
py_helper_keyword_int(n_args, args, offset + 3, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_fill), false);
imlib_draw_ellipse(arg_img, arg_cx, arg_cy, arg_rx, arg_ry, arg_rotation, arg_c, arg_thickness, arg_fill);
imlib_draw_ellipse(arg_img, arg_cx, arg_cy, arg_rx, arg_ry, arg_r, arg_c, arg_thickness, arg_fill);
return args[0];
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_draw_ellipse_obj, 2, py_image_draw_ellipse);
@ -1698,10 +1706,23 @@ STATIC mp_obj_t py_image_draw_string(uint n_args, const mp_obj_t *args, mp_map_t
py_helper_keyword_int(n_args, args, offset + 3, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_y_spacing), 0);
bool arg_mono_space =
py_helper_keyword_int(n_args, args, offset + 4, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_mono_space), true);
int arg_char_rotation =
py_helper_keyword_int(n_args, args, offset + 5, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_char_rotation), 0);
int arg_char_hmirror =
py_helper_keyword_int(n_args, args, offset + 6, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_char_hmirror), false);
int arg_char_vflip =
py_helper_keyword_int(n_args, args, offset + 7, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_char_vflip), false);
int arg_string_rotation =
py_helper_keyword_int(n_args, args, offset + 8, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_string_rotation), 0);
int arg_string_hmirror =
py_helper_keyword_int(n_args, args, offset + 9, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_string_hmirror), false);
int arg_string_vflip =
py_helper_keyword_int(n_args, args, offset + 10, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_string_vflip), false);
imlib_draw_string(arg_img, arg_x_off, arg_y_off, arg_str,
arg_c, arg_scale, arg_x_spacing, arg_y_spacing,
arg_mono_space);
arg_c, arg_scale, arg_x_spacing, arg_y_spacing, arg_mono_space,
arg_char_rotation, arg_char_hmirror, arg_char_vflip,
arg_string_rotation, arg_string_hmirror, arg_string_vflip);
return args[0];
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_draw_string_obj, 2, py_image_draw_string);
@ -1892,6 +1913,120 @@ STATIC mp_obj_t py_image_draw_keypoints(uint n_args, const mp_obj_t *args, mp_ma
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_draw_keypoints_obj, 2, py_image_draw_keypoints);
STATIC mp_obj_t py_image_mask_rectangle(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
image_t *arg_img = py_helper_arg_to_image_mutable(args[0]);
int arg_rx;
int arg_ry;
int arg_rw;
int arg_rh;
if (n_args > 1) {
const mp_obj_t *arg_vec;
py_helper_consume_array(n_args, args, 1, 4, &arg_vec);
arg_rx = mp_obj_get_int(arg_vec[0]);
arg_ry = mp_obj_get_int(arg_vec[1]);
arg_rw = mp_obj_get_int(arg_vec[2]);
arg_rh = mp_obj_get_int(arg_vec[3]);
} else {
arg_rx = arg_img->w / 4;
arg_ry = arg_img->h / 4;
arg_rw = arg_img->w / 2;
arg_rh = arg_img->h / 2;
}
fb_alloc_mark();
image_t temp;
temp.w = arg_img->w;
temp.h = arg_img->h;
temp.bpp = IMAGE_BPP_BINARY;
temp.data = fb_alloc0(image_size(&temp));
imlib_draw_rectangle(&temp, arg_rx, arg_ry, arg_rw, arg_rh, -1, 0, true);
imlib_zero(arg_img, &temp, true);
fb_free();
fb_alloc_free_till_mark();
return args[0];
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_mask_rectangle_obj, 1, py_image_mask_rectangle);
STATIC mp_obj_t py_image_mask_circle(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
image_t *arg_img = py_helper_arg_to_image_mutable(args[0]);
int arg_cx;
int arg_cy;
int arg_cr;
if (n_args > 1) {
const mp_obj_t *arg_vec;
py_helper_consume_array(n_args, args, 1, 3, &arg_vec);
arg_cx = mp_obj_get_int(arg_vec[0]);
arg_cy = mp_obj_get_int(arg_vec[1]);
arg_cr = mp_obj_get_int(arg_vec[2]);
} else {
arg_cx = arg_img->w / 2;
arg_cy = arg_img->h / 2;
arg_cr = IM_MIN(arg_img->w, arg_img->h) / 2;
}
fb_alloc_mark();
image_t temp;
temp.w = arg_img->w;
temp.h = arg_img->h;
temp.bpp = IMAGE_BPP_BINARY;
temp.data = fb_alloc0(image_size(&temp));
imlib_draw_circle(&temp, arg_cx, arg_cy, arg_cr, -1, 0, true);
imlib_zero(arg_img, &temp, true);
fb_free();
fb_alloc_free_till_mark();
return args[0];
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_mask_circle_obj, 1, py_image_mask_circle);
STATIC mp_obj_t py_image_mask_ellipse(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
image_t *arg_img = py_helper_arg_to_image_mutable(args[0]);
int arg_cx;
int arg_cy;
int arg_rx;
int arg_ry;
int arg_r;
if (n_args > 1) {
const mp_obj_t *arg_vec;
py_helper_consume_array(n_args, args, 1, 5, &arg_vec);
arg_cx = mp_obj_get_int(arg_vec[0]);
arg_cy = mp_obj_get_int(arg_vec[1]);
arg_rx = mp_obj_get_int(arg_vec[2]);
arg_ry = mp_obj_get_int(arg_vec[3]);
arg_r = mp_obj_get_int(arg_vec[4]);
} else {
arg_cx = arg_img->w / 2;
arg_cy = arg_img->h / 2;
arg_rx = arg_img->w / 2;
arg_ry = arg_img->h / 2;
arg_r = 0;
}
fb_alloc_mark();
image_t temp;
temp.w = arg_img->w;
temp.h = arg_img->h;
temp.bpp = IMAGE_BPP_BINARY;
temp.data = fb_alloc0(image_size(&temp));
imlib_draw_ellipse(&temp, arg_cx, arg_cy, arg_rx, arg_ry, arg_r, -1, 0, true);
imlib_zero(arg_img, &temp, true);
fb_free();
fb_alloc_free_till_mark();
return args[0];
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_mask_ellipse_obj, 1, py_image_mask_ellipse);
#ifdef IMLIB_ENABLE_FLOOD_FILL
STATIC mp_obj_t py_image_flood_fill(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
@ -6215,6 +6350,9 @@ static const mp_rom_map_elem_t locals_dict_table[] = {
{MP_ROM_QSTR(MP_QSTR_flood_fill), MP_ROM_PTR(&py_func_unavailable_obj)},
#endif
{MP_ROM_QSTR(MP_QSTR_draw_keypoints), MP_ROM_PTR(&py_image_draw_keypoints_obj)},
{MP_ROM_QSTR(MP_QSTR_mask_rectangle), MP_ROM_PTR(&py_image_mask_rectangle_obj)},
{MP_ROM_QSTR(MP_QSTR_mask_circle), MP_ROM_PTR(&py_image_mask_circle_obj)},
{MP_ROM_QSTR(MP_QSTR_mask_ellipse), MP_ROM_PTR(&py_image_mask_ellipse_obj)},
/* Binary Methods */
#ifdef IMLIB_ENABLE_BINARY_OPS
{MP_ROM_QSTR(MP_QSTR_binary), MP_ROM_PTR(&py_image_binary_obj)},

View File

@ -431,6 +431,7 @@ Q(save)
// Clear
Q(clear)
Q(mask)
// Draw Line
Q(draw_line)
@ -451,7 +452,6 @@ Q(draw_circle)
// Draw Ellipse
Q(draw_ellipse)
Q(rotation)
// duplicate Q(color)
// duplicate Q(thickness)
// duplicate Q(fill)
@ -463,6 +463,12 @@ Q(draw_string)
Q(x_spacing)
Q(y_spacing)
Q(mono_space)
Q(char_rotation)
Q(char_hmirror)
Q(char_vflip)
Q(string_rotation)
Q(string_hmirror)
Q(string_vflip)
// Draw Cross
Q(draw_cross)
@ -488,7 +494,7 @@ Q(draw_image)
// duplicate Q(x_scale)
// duplicate Q(y_scale)
Q(alpha)
Q(mask)
// duplicate Q(mask)
// Draw Keypoints
Q(draw_keypoints)
@ -506,6 +512,15 @@ Q(invert)
Q(clear_background)
// duplicate Q(mask)
// Mask Rectangle
Q(mask_rectangle)
// Mask Circle
Q(mask_circle)
// Mask Ellipse
Q(mask_ellipse)
// Binary
Q(binary)
// duplicate Q(invert)
@ -882,7 +897,7 @@ Q(cx)
Q(cxf)
Q(cy)
Q(cyf)
// duplicate Q(rotation)
Q(rotation)
Q(rotation_deg)
Q(rotation_rad)
Q(code)