Merge pull request #424 from kwagyeman/kwabena/drawing_binary_mathop_fixes

Various drawing, binary, and mathop fixes
This commit is contained in:
Ibrahim Abd Elkader 2019-01-06 17:53:49 +02:00 committed by GitHub
commit 1412a2d234
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 593 additions and 184 deletions

View File

@ -0,0 +1,31 @@
# Keypoints Drawing
#
# This example shows off drawing keypoints on the OpenMV Cam. Usually you call draw_keypoints()
# on a keypoints object but you can also call it on a list of 3-value tuples...
import sensor, image, time, pyb
sensor.reset()
sensor.set_pixformat(sensor.RGB565) # or GRAYSCALE...
sensor.set_framesize(sensor.QVGA) # or QQVGA...
sensor.skip_frames(time = 2000)
clock = time.clock()
while(True):
clock.tick()
img = sensor.snapshot()
for i in range(20):
x = (pyb.rng() % (2*img.width())) - (img.width()//2)
y = (pyb.rng() % (2*img.height())) - (img.height()//2)
rot = pyb.rng() % 360
r = (pyb.rng() % 127) + 128
g = (pyb.rng() % 127) + 128
b = (pyb.rng() % 127) + 128
# This method draws a keypoints object or a list of (x, y, rot) tuples...
img.draw_keypoints([(x, y, rot)], color = (r, g, b), size = 20, thickness = 2, fill = False)
print(clock.fps())

View File

@ -0,0 +1,21 @@
# Gamma Correction
#
# This example shows off gamma correction to make the image brighter. The gamma
# correction method can also fix contrast and brightness too.
import sensor, image, time
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)
clock = time.clock()
while(True):
clock.tick()
# Gamma, contrast, and brightness correction are applied to each color channel. The
# values are scaled to the range per color channel per image type...
img = sensor.snapshot().gamma_corr(gamma = 0.5, contrast = 1.0, brightness = 0.0)
print(clock.fps())

View File

@ -0,0 +1,19 @@
# Negative Example
#
# This example shows off negating the image. This is not a particularly
# useful method but it can come in handy once in a while.
import sensor, image, time
sensor.reset() # Initialize the camera sensor.
sensor.set_pixformat(sensor.RGB565) # or sensor.GRAYSCALE
sensor.set_framesize(sensor.QVGA) # or sensor.QQVGA (or others)
sensor.skip_frames(time = 2000) # Let new settings take affect.
clock = time.clock() # Tracks FPS.
while(True):
clock.tick() # Track elapsed milliseconds between snapshots().
img = sensor.snapshot().negate()
print(clock.fps()) # Note: Your OpenMV Cam runs about half as fast while
# connected to your computer. The FPS should increase once disconnected.

View File

@ -0,0 +1,33 @@
# Vertical Flip - Horizontal Mirror - Transpose
#
# This example shows off how to vertically flip, horizontally mirror, or
# transpose an image. Note that:
#
# vflip=False, hmirror=False, transpose=False -> 0 degree rotation
# vflip=True, hmirror=False, transpose=True -> 90 degree rotation
# vflip=True, hmirror=True, transpose=False -> 180 degree rotation
# vflip=False, hmirror=True, transpose=True -> 270 degree rotation
import sensor, image, time, pyb
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)
clock = time.clock()
mills = pyb.millis()
counter = 0
while(True):
clock.tick()
img = sensor.snapshot().replace(vflip=(counter//2)%2,
hmirror=(counter//4)%2,
transpose=(counter//8)%2)
if (pyb.millis() > (mills + 1000)):
mills = pyb.millis()
counter += 1
print(clock.fps())

View File

@ -8,137 +8,49 @@
#ifdef IMLIB_ENABLE_BINARY_OPS
void imlib_binary(image_t *out, image_t *img, list_t *thresholds, bool invert, bool zero, image_t *mask)
{
image_t bmp;
bmp.w = img->w;
bmp.h = img->h;
bmp.bpp = IMAGE_BPP_BINARY;
bmp.data = fb_alloc0(image_size(&bmp));
for (list_lnk_t *it = iterator_start_from_head(thresholds); it; it = iterator_next(it)) {
color_thresholds_list_lnk_data_t lnk_data;
iterator_get(thresholds, it, &lnk_data);
switch(img->bpp) {
case IMAGE_BPP_BINARY: {
if (!zero) {
for (int y = 0, yy = img->h; y < yy; y++) {
uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y);
uint32_t *out_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(out, y);
for (int x = 0, xx = img->w; x < xx; x++) {
if (mask && (!image_get_mask_pixel(mask, x, y))) continue;
IMAGE_PUT_BINARY_PIXEL_FAST(out_row_ptr, x,
COLOR_THRESHOLD_BINARY(IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x), &lnk_data, invert));
}
}
} else {
for (int y = 0, yy = img->h; y < yy; y++) {
uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y);
uint32_t *out_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(out, y);
for (int x = 0, xx = img->w; x < xx; x++) {
if (mask && (!image_get_mask_pixel(mask, x, y))) continue;
if (COLOR_THRESHOLD_BINARY(IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x), &lnk_data, invert)) {
IMAGE_CLEAR_BINARY_PIXEL_FAST(out_row_ptr, x);
}
for (int y = 0, yy = img->h; y < yy; y++) {
uint32_t *old_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y);
uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y);
for (int x = 0, xx = img->w; x < xx; x++) {
if (COLOR_THRESHOLD_BINARY(IMAGE_GET_BINARY_PIXEL_FAST(old_row_ptr, x), &lnk_data, invert)) {
IMAGE_SET_BINARY_PIXEL_FAST(bmp_row_ptr, x);
}
}
}
break;
}
case IMAGE_BPP_GRAYSCALE: {
if (out->bpp == IMAGE_BPP_BINARY) {
if (!zero) {
for (int y = 0, yy = img->h; y < yy; y++) {
uint8_t *row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y);
uint32_t *out_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(out, y);
for (int x = 0, xx = img->w; x < xx; x++) {
if (mask && (!image_get_mask_pixel(mask, x, y))) continue;
IMAGE_PUT_BINARY_PIXEL_FAST(out_row_ptr, x,
COLOR_THRESHOLD_GRAYSCALE(IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x), &lnk_data, invert)
? COLOR_BINARY_MAX : COLOR_BINARY_MIN);
}
}
} else {
for (int y = 0, yy = img->h; y < yy; y++) {
uint8_t *row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y);
uint32_t *out_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(out, y);
for (int x = 0, xx = img->w; x < xx; x++) {
if (mask && (!image_get_mask_pixel(mask, x, y))) continue;
if (COLOR_THRESHOLD_GRAYSCALE(IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x), &lnk_data, invert)) {
IMAGE_PUT_BINARY_PIXEL_FAST(out_row_ptr, x, COLOR_BINARY_MIN);
}
}
}
}
} else {
if (!zero) {
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 (mask && (!image_get_mask_pixel(mask, x, y))) continue;
IMAGE_PUT_GRAYSCALE_PIXEL_FAST(row_ptr, x,
COLOR_THRESHOLD_GRAYSCALE(IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x), &lnk_data, invert)
? COLOR_GRAYSCALE_BINARY_MAX : COLOR_GRAYSCALE_BINARY_MIN);
}
}
} else {
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 (mask && (!image_get_mask_pixel(mask, x, y))) continue;
if (COLOR_THRESHOLD_GRAYSCALE(IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x), &lnk_data, invert)) {
IMAGE_PUT_GRAYSCALE_PIXEL_FAST(row_ptr, x, COLOR_GRAYSCALE_BINARY_MIN);
}
}
for (int y = 0, yy = img->h; y < yy; y++) {
uint8_t *old_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y);
uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y);
for (int x = 0, xx = img->w; x < xx; x++) {
if (COLOR_THRESHOLD_GRAYSCALE(IMAGE_GET_GRAYSCALE_PIXEL_FAST(old_row_ptr, x), &lnk_data, invert)) {
IMAGE_SET_BINARY_PIXEL_FAST(bmp_row_ptr, x);
}
}
}
break;
}
case IMAGE_BPP_RGB565: {
if (out->bpp == IMAGE_BPP_BINARY) {
if (!zero) {
for (int y = 0, yy = img->h; y < yy; y++) {
uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y);
uint32_t *out_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(out, y);
for (int x = 0, xx = img->w; x < xx; x++) {
if (mask && (!image_get_mask_pixel(mask, x, y))) continue;
IMAGE_PUT_BINARY_PIXEL_FAST(out_row_ptr, x,
COLOR_THRESHOLD_RGB565(IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x), &lnk_data, invert)
? COLOR_BINARY_MAX : COLOR_BINARY_MIN);
}
}
} else {
for (int y = 0, yy = img->h; y < yy; y++) {
uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y);
uint32_t *out_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(out, y);
for (int x = 0, xx = img->w; x < xx; x++) {
if (mask && (!image_get_mask_pixel(mask, x, y))) continue;
if (COLOR_THRESHOLD_RGB565(IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x), &lnk_data, invert)) {
IMAGE_PUT_BINARY_PIXEL_FAST(out_row_ptr, x, COLOR_BINARY_MIN);
}
}
for (int y = 0, yy = img->h; y < yy; y++) {
uint16_t *old_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y);
uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y);
for (int x = 0, xx = img->w; x < xx; x++) {
if (COLOR_THRESHOLD_RGB565(IMAGE_GET_RGB565_PIXEL_FAST(old_row_ptr, x), &lnk_data, invert)) {
IMAGE_SET_BINARY_PIXEL_FAST(bmp_row_ptr, x);
}
}
break;
} else {
if (!zero) {
for (int y = 0, yy = img->h; y < yy; y++) {
uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y);
uint16_t *out_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(out, y);
for (int x = 0, xx = img->w; x < xx; x++) {
if (mask && (!image_get_mask_pixel(mask, x, y))) continue;
IMAGE_PUT_RGB565_PIXEL_FAST(out_row_ptr, x,
COLOR_THRESHOLD_RGB565(IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x), &lnk_data, invert)
? COLOR_RGB565_BINARY_MAX : COLOR_RGB565_BINARY_MIN);
}
}
} else {
for (int y = 0, yy = img->h; y < yy; y++) {
uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y);
uint16_t *out_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(out, y);
for (int x = 0, xx = img->w; x < xx; x++) {
if (mask && (!image_get_mask_pixel(mask, x, y))) continue;
if (COLOR_THRESHOLD_RGB565(IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x), &lnk_data, invert)) {
IMAGE_PUT_RGB565_PIXEL_FAST(out_row_ptr, x, COLOR_RGB565_BINARY_MIN);
}
}
}
}
break;
}
break;
}
@ -147,6 +59,154 @@ void imlib_binary(image_t *out, image_t *img, list_t *thresholds, bool invert, b
}
}
}
switch(img->bpp) {
case IMAGE_BPP_BINARY: {
if (!zero) {
for (int y = 0, yy = img->h; y < yy; y++) {
uint32_t *old_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y);
uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y);
uint32_t *out_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(out, y);
for (int x = 0, xx = img->w; x < xx; x++) {
int pixel = ((!mask) || image_get_mask_pixel(mask, x, y))
? IMAGE_GET_BINARY_PIXEL_FAST(bmp_row_ptr, x)
: IMAGE_GET_BINARY_PIXEL_FAST(old_row_ptr, x);
IMAGE_PUT_BINARY_PIXEL_FAST(out_row_ptr, x, pixel);
}
}
} else {
for (int y = 0, yy = img->h; y < yy; y++) {
uint32_t *old_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y);
uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y);
uint32_t *out_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(out, y);
for (int x = 0, xx = img->w; x < xx; x++) {
int pixel = IMAGE_GET_BINARY_PIXEL_FAST(old_row_ptr, x);
if (((!mask) || image_get_mask_pixel(mask, x, y))
&& IMAGE_GET_BINARY_PIXEL_FAST(bmp_row_ptr, x)) pixel = 0;
IMAGE_PUT_BINARY_PIXEL_FAST(out_row_ptr, x, pixel);
}
}
}
break;
}
case IMAGE_BPP_GRAYSCALE: {
if (out->bpp == IMAGE_BPP_BINARY) {
if (!zero) {
for (int y = 0, yy = img->h; y < yy; y++) {
uint8_t *old_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y);
uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y);
uint32_t *out_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(out, y);
for (int x = 0, xx = img->w; x < xx; x++) {
int pixel = ((!mask) || image_get_mask_pixel(mask, x, y))
? IMAGE_GET_BINARY_PIXEL_FAST(bmp_row_ptr, x)
: COLOR_GRAYSCALE_TO_BINARY(IMAGE_GET_GRAYSCALE_PIXEL_FAST(old_row_ptr, x));
IMAGE_PUT_BINARY_PIXEL_FAST(out_row_ptr, x, pixel);
}
}
} else {
for (int y = 0, yy = img->h; y < yy; y++) {
uint8_t *old_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y);
uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y);
uint32_t *out_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(out, y);
for (int x = 0, xx = img->w; x < xx; x++) {
int pixel = COLOR_GRAYSCALE_TO_BINARY(IMAGE_GET_GRAYSCALE_PIXEL_FAST(old_row_ptr, x));
if (((!mask) || image_get_mask_pixel(mask, x, y))
&& IMAGE_GET_BINARY_PIXEL_FAST(bmp_row_ptr, x)) pixel = 0;
IMAGE_PUT_BINARY_PIXEL_FAST(out_row_ptr, x, pixel);
}
}
}
} else {
if (!zero) {
for (int y = 0, yy = img->h; y < yy; y++) {
uint8_t *old_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y);
uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y);
uint8_t *out_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(out, y);
for (int x = 0, xx = img->w; x < xx; x++) {
int pixel = ((!mask) || image_get_mask_pixel(mask, x, y))
? COLOR_BINARY_TO_GRAYSCALE(IMAGE_GET_BINARY_PIXEL_FAST(bmp_row_ptr, x))
: IMAGE_GET_GRAYSCALE_PIXEL_FAST(old_row_ptr, x);
IMAGE_PUT_GRAYSCALE_PIXEL_FAST(out_row_ptr, x, pixel);
}
}
} else {
for (int y = 0, yy = img->h; y < yy; y++) {
uint8_t *old_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y);
uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y);
uint8_t *out_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(out, y);
for (int x = 0, xx = img->w; x < xx; x++) {
int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(old_row_ptr, x);
if (((!mask) || image_get_mask_pixel(mask, x, y))
&& IMAGE_GET_BINARY_PIXEL_FAST(bmp_row_ptr, x)) pixel = 0;
IMAGE_PUT_GRAYSCALE_PIXEL_FAST(out_row_ptr, x, pixel);
}
}
}
}
break;
}
case IMAGE_BPP_RGB565: {
if (out->bpp == IMAGE_BPP_BINARY) {
if (!zero) {
for (int y = 0, yy = img->h; y < yy; y++) {
uint16_t *old_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y);
uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y);
uint32_t *out_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(out, y);
for (int x = 0, xx = img->w; x < xx; x++) {
int pixel = ((!mask) || image_get_mask_pixel(mask, x, y))
? IMAGE_GET_BINARY_PIXEL_FAST(bmp_row_ptr, x)
: COLOR_RGB565_TO_BINARY(IMAGE_GET_RGB565_PIXEL_FAST(old_row_ptr, x));
IMAGE_PUT_BINARY_PIXEL_FAST(out_row_ptr, x, pixel);
}
}
} else {
for (int y = 0, yy = img->h; y < yy; y++) {
uint16_t *old_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y);
uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y);
uint32_t *out_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(out, y);
for (int x = 0, xx = img->w; x < xx; x++) {
int pixel = COLOR_RGB565_TO_BINARY(IMAGE_GET_RGB565_PIXEL_FAST(old_row_ptr, x));
if (((!mask) || image_get_mask_pixel(mask, x, y))
&& IMAGE_GET_BINARY_PIXEL_FAST(bmp_row_ptr, x)) pixel = 0;
IMAGE_PUT_BINARY_PIXEL_FAST(out_row_ptr, x, pixel);
}
}
}
} else {
if (!zero) {
for (int y = 0, yy = img->h; y < yy; y++) {
uint16_t *old_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y);
uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y);
uint16_t *out_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(out, y);
for (int x = 0, xx = img->w; x < xx; x++) {
int pixel = ((!mask) || image_get_mask_pixel(mask, x, y))
? COLOR_BINARY_TO_RGB565(IMAGE_GET_BINARY_PIXEL_FAST(bmp_row_ptr, x))
: IMAGE_GET_RGB565_PIXEL_FAST(old_row_ptr, x);
IMAGE_PUT_RGB565_PIXEL_FAST(out_row_ptr, x, pixel);
}
}
} else {
for (int y = 0, yy = img->h; y < yy; y++) {
uint16_t *old_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y);
uint32_t *bmp_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&bmp, y);
uint16_t *out_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(out, y);
for (int x = 0, xx = img->w; x < xx; x++) {
int pixel = IMAGE_GET_RGB565_PIXEL_FAST(old_row_ptr, x);
if (((!mask) || image_get_mask_pixel(mask, x, y))
&& IMAGE_GET_BINARY_PIXEL_FAST(bmp_row_ptr, x)) pixel = 0;
IMAGE_PUT_RGB565_PIXEL_FAST(out_row_ptr, x, pixel);
}
}
}
}
break;
}
default: {
break;
}
}
fb_free();
}
void imlib_invert(image_t *img)

View File

@ -179,8 +179,8 @@ static void scratch_draw_pixel(image_t *img, int x0, int y0, int dx, int dy, flo
// https://scratch.mit.edu/projects/50039326/
static void scratch_draw_line(image_t *img, int x0, int y0, int dx, int dy0, int dy1, float shear_dx, float shear_dy, int c)
{
imlib_draw_line(img, x0 + dx, y0 + dy0 + fast_floorf((dx * shear_dy) / shear_dx),
x0 + dx, y0 + dy1 + fast_floorf((dx * shear_dy) / shear_dx), c, 1);
int y = y0 + fast_floorf((dx * shear_dy) / shear_dx);
yLine(img, x0 + dx, y + dy0, y + dy1, c);
}
// https://scratch.mit.edu/projects/50039326/
@ -268,7 +268,7 @@ void imlib_draw_ellipse(image_t *img, int cx, int cy, int rx, int ry, int rotati
scratch_draw_rotated_ellipse(img, cx, cy, rx * 2, ry * 2, rotation, fill, c, thickness);
}
void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int c, int 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)
{
const int anchor = x_off;
@ -280,17 +280,17 @@ 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 += (font[0].h * scale) + y_spacing; // newline height == space height
y_off += fast_roundf(font[0].h * scale) + y_spacing; // newline height == space height
continue;
}
if ((ch < ' ') || (ch > '~')) { // handle unknown characters
imlib_draw_rectangle(img,
x_off + ((scale * 3) / 2),
y_off + ((scale * 3) / 2),
(font[0].w * scale) - (((scale * 3) / 2) * 2),
(font[0].h * scale) - (((scale * 3) / 2) * 2),
c, scale, false);
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;
}
@ -303,7 +303,7 @@ void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int
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 -= x * scale;
x_off -= fast_roundf(x * scale);
exit = true;
break;
}
@ -313,16 +313,16 @@ void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int
}
}
for (int y = 0, yy = g->h * scale; y < yy; y++) {
for (int x = 0, xx = g->w * scale; x < xx; x++) {
if (g->data[y / scale] & (1 << (g->w - 1 - (x / scale)))) {
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);
}
}
}
if (mono_space) {
x_off += (g->w * scale) + x_spacing;
x_off += fast_roundf(g->w * scale) + x_spacing;
} else {
// Find the last pixel set and offset to that.
bool exit = false;
@ -330,7 +330,7 @@ void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int
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 += ((x + 2) * scale) + x_spacing;
x_off += fast_roundf((x + 2) * scale) + x_spacing;
exit = true;
break;
}
@ -339,7 +339,7 @@ void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int
if (exit) break;
}
if (!exit) x_off += scale * 3; // space char
if (!exit) x_off += fast_roundf(scale * 3); // space char
}
}
}
@ -401,9 +401,9 @@ static int safe_map_pixel(image_t *dst, image_t *src, int pixel)
}
}
void imlib_draw_image(image_t *img, image_t *other, int x_off, int y_off, float x_scale, float y_scale, image_t *mask)
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)
{
float over_xscale = IM_DIV(1.0, x_scale), over_yscale = IM_DIV(1.0f, y_scale);
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);
@ -412,7 +412,9 @@ void imlib_draw_image(image_t *img, image_t *other, int x_off, int y_off, float
int other_x = fast_roundf(x * over_xscale);
if ((!mask) || image_get_mask_pixel(mask, other_x, other_y)) {
imlib_set_pixel(img, x_off + x, y_off + y, safe_map_pixel(img, other, imlib_get_pixel(other, other_x, other_y)));
int pixel = safe_map_pixel(img, other, imlib_get_pixel(other, other_x, other_y));
imlib_set_pixel(img, x_off + x, y_off + y, (alpha == 1) ? pixel :
(pixel * alpha) + (imlib_get_pixel(img, x_off + x, y_off + y) * beta));
}
}
}

View File

@ -189,3 +189,10 @@ float fast_log(float x)
{
return 0.69314718f * fast_log2 (x);
}
float fast_powf(float a, float b)
{
union { float d; int x; } u = { a };
u.x = (int)((b * (u.x - 1064866805)) + 1064866805);
return u.d;
}

View File

@ -20,6 +20,7 @@ float fast_cbrtf(float d);
float fast_fabsf(float d);
float fast_log(float x);
float fast_log2(float x);
float fast_powf(float a, float b);
extern const float cos_table[360];
extern const float sin_table[360];
#endif // __FMATH_H__

View File

@ -361,7 +361,7 @@ extern const int8_t yuv_table[196608];
})
#define COLOR_BINARY_TO_GRAYSCALE(pixel) ((pixel) * COLOR_GRAYSCALE_MAX)
#define COLOR_BINARY_TO_RGB565(pixel) COLOR_YUV_TO_RGB565((pixel) * 127, 0, 0)
#define COLOR_BINARY_TO_RGB565(pixel) COLOR_YUV_TO_RGB565((pixel) ? 127 : -128, 0, 0)
#define COLOR_RGB565_TO_BINARY(pixel) (COLOR_RGB565_TO_Y(pixel) > (((COLOR_Y_MAX - COLOR_Y_MIN) / 2) + COLOR_Y_MIN))
#define COLOR_RGB565_TO_GRAYSCALE(pixel) (COLOR_RGB565_TO_Y(pixel) + 128)
#define COLOR_GRAYSCALE_TO_BINARY(pixel) ((pixel) > (((COLOR_GRAYSCALE_MAX - COLOR_GRAYSCALE_MIN) / 2) + COLOR_GRAYSCALE_MIN))
@ -1275,8 +1275,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, int scale, int x_spacing, int y_spacing, bool mono_space);
void imlib_draw_image(image_t *img, image_t *other, int x_off, int y_off, float x_scale, float y_scale, image_t *mask);
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_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,
int c, bool invert, bool clear_background, image_t *mask);
@ -1296,12 +1296,13 @@ void imlib_close(image_t *img, int ksize, int threshold, image_t *mask);
void imlib_top_hat(image_t *img, int ksize, int threshold, image_t *mask);
void imlib_black_hat(image_t *img, int ksize, int threshold, image_t *mask);
// Math Functions
void imlib_gamma_corr(image_t *img, float gamma, float scale, float offset);
void imlib_negate(image_t *img);
void imlib_replace(image_t *img, const char *path, image_t *other, int scalar, bool hmirror, bool vflip, image_t *mask);
void imlib_replace(image_t *img, const char *path, image_t *other, int scalar, bool hmirror, bool vflip, bool transpose, image_t *mask);
void imlib_add(image_t *img, const char *path, image_t *other, int scalar, image_t *mask);
void imlib_sub(image_t *img, const char *path, image_t *other, int scalar, bool reverse, image_t *mask);
void imlib_mul(image_t *img, const char *path, image_t *other, int scalar, bool invert, image_t *mask);
void imlib_div(image_t *img, const char *path, image_t *other, int scalar, bool invert, image_t *mask);
void imlib_div(image_t *img, const char *path, image_t *other, int scalar, bool invert, bool mod, image_t *mask);
void imlib_min(image_t *img, const char *path, image_t *other, int scalar, image_t *mask);
void imlib_max(image_t *img, const char *path, image_t *other, int scalar, image_t *mask);
void imlib_difference(image_t *img, const char *path, image_t *other, int scalar, image_t *mask);

View File

@ -6,6 +6,102 @@
#include "imlib.h"
#ifdef IMLIB_ENABLE_MATH_OPS
void imlib_gamma_corr(image_t *img, float gamma, float contrast, float brightness)
{
gamma = IM_DIV(1.0, gamma);
switch(img->bpp) {
case IMAGE_BPP_BINARY: {
float pScale = COLOR_BINARY_MAX - COLOR_BINARY_MIN;
float pDiv = 1 / pScale;
int *p_lut = fb_alloc((COLOR_BINARY_MAX - COLOR_BINARY_MIN + 1) * sizeof(int));
for (int i = COLOR_BINARY_MIN; i <= COLOR_BINARY_MAX; i++) {
int p = ((fast_powf(i * pDiv, gamma) * contrast) + brightness) * pScale;
p_lut[i] = IM_MIN(IM_MAX(p , COLOR_BINARY_MIN), COLOR_BINARY_MAX);
}
for (int y = 0, yy = img->h; y < yy; y++) {
uint32_t *data = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y);
for (int x = 0, xx = img->w; x < xx; x++) {
int dataPixel = IMAGE_GET_BINARY_PIXEL_FAST(data, x);
int p = p_lut[dataPixel];
IMAGE_PUT_BINARY_PIXEL_FAST(data, x, p);
}
}
fb_free();
break;
}
case IMAGE_BPP_GRAYSCALE: {
float pScale = COLOR_GRAYSCALE_MAX - COLOR_GRAYSCALE_MIN;
float pDiv = 1 / pScale;
int *p_lut = fb_alloc((COLOR_GRAYSCALE_MAX - COLOR_GRAYSCALE_MIN + 1) * sizeof(int));
for (int i = COLOR_GRAYSCALE_MIN; i <= COLOR_GRAYSCALE_MAX; i++) {
int p = ((fast_powf(i * pDiv, gamma) * contrast) + brightness) * pScale;
p_lut[i] = IM_MIN(IM_MAX(p , COLOR_GRAYSCALE_MIN), COLOR_GRAYSCALE_MAX);
}
for (int y = 0, yy = img->h; y < yy; y++) {
uint8_t *data = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y);
for (int x = 0, xx = img->w; x < xx; x++) {
int dataPixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(data, x);
int p = p_lut[dataPixel];
IMAGE_PUT_GRAYSCALE_PIXEL_FAST(data, x, p);
}
}
fb_free();
break;
}
case IMAGE_BPP_RGB565: {
float rScale = COLOR_R5_MAX - COLOR_R5_MIN;
float gScale = COLOR_G6_MAX - COLOR_G6_MIN;
float bScale = COLOR_B5_MAX - COLOR_B5_MIN;
float rDiv = 1 / rScale;
float gDiv = 1 / gScale;
float bDiv = 1 / bScale;
int *r_lut = fb_alloc((COLOR_R5_MAX - COLOR_R5_MIN + 1) * sizeof(int));
int *g_lut = fb_alloc((COLOR_G6_MAX - COLOR_G6_MIN + 1) * sizeof(int));
int *b_lut = fb_alloc((COLOR_B5_MAX - COLOR_B5_MIN + 1) * sizeof(int));
for (int i = COLOR_R5_MIN; i <= COLOR_R5_MAX; i++) {
int r = ((fast_powf(i * rDiv, gamma) * contrast) + brightness) * rScale;
r_lut[i] = IM_MIN(IM_MAX(r , COLOR_R5_MIN), COLOR_R5_MAX);
}
for (int i = COLOR_G6_MIN; i <= COLOR_G6_MAX; i++) {
int g = ((fast_powf(i * gDiv, gamma) * contrast) + brightness) * gScale;
g_lut[i] = IM_MIN(IM_MAX(g , COLOR_G6_MIN), COLOR_G6_MAX);
}
for (int i = COLOR_B5_MIN; i <= COLOR_B5_MAX; i++) {
int b = ((fast_powf(i * bDiv, gamma) * contrast) + brightness) * bScale;
b_lut[i] = IM_MIN(IM_MAX(b , COLOR_B5_MIN), COLOR_B5_MAX);
}
for (int y = 0, yy = img->h; y < yy; y++) {
uint16_t *data = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y);
for (int x = 0, xx = img->w; x < xx; x++) {
int dataPixel = IMAGE_GET_RGB565_PIXEL_FAST(data, x);
int r = r_lut[COLOR_RGB565_TO_R5(dataPixel)];
int g = g_lut[COLOR_RGB565_TO_G6(dataPixel)];
int b = b_lut[COLOR_RGB565_TO_B5(dataPixel)];
IMAGE_PUT_RGB565_PIXEL_FAST(data, x, COLOR_R5_G6_B5_TO_RGB565(r, g, b));
}
}
fb_free();
fb_free();
fb_free();
break;
}
default: {
break;
}
}
}
void imlib_negate(image_t *img)
{
switch(img->bpp) {
@ -51,7 +147,7 @@ void imlib_negate(image_t *img)
}
typedef struct imlib_replace_line_op_state {
bool hmirror, vflip;
bool hmirror, vflip, transpose;
image_t *mask;
} imlib_replace_line_op_state_t;
@ -59,44 +155,52 @@ static void imlib_replace_line_op(image_t *img, int line, void *other, void *dat
{
bool hmirror = ((imlib_replace_line_op_state_t *) data)->hmirror;
bool vflip = ((imlib_replace_line_op_state_t *) data)->vflip;
bool transpose = ((imlib_replace_line_op_state_t *) data)->transpose;
image_t *mask = ((imlib_replace_line_op_state_t *) data)->mask;
image_t target;
memcpy(&target, img, sizeof(image_t));
if (transpose) {
int w = target.w;
int h = target.h;
target.w = h;
target.h = w;
}
switch(img->bpp) {
case IMAGE_BPP_BINARY: {
int v_line = vflip ? (img->h - line - 1) : line;
uint32_t *data = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, v_line);
for (int i = 0, j = img->w; i < j; i++) {
int h_i = hmirror ? (img->w - i - 1) : i;
if ((!mask) || image_get_mask_pixel(mask, h_i, v_line)) {
int pixel = IMAGE_GET_BINARY_PIXEL_FAST(((uint32_t *) other), h_i);
IMAGE_PUT_BINARY_PIXEL_FAST(data, i, pixel);
IMAGE_PUT_BINARY_PIXEL(&target, transpose ? v_line : i, transpose ? i : v_line, pixel);
}
}
break;
}
case IMAGE_BPP_GRAYSCALE: {
int v_line = vflip ? (img->h - line - 1) : line;
uint8_t *data = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, v_line);
for (int i = 0, j = img->w; i < j; i++) {
int h_i = hmirror ? (img->w - i - 1) : i;
if ((!mask) || image_get_mask_pixel(mask, h_i, v_line)) {
int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(((uint8_t *) other), h_i);
IMAGE_PUT_GRAYSCALE_PIXEL_FAST(data, i, pixel);
IMAGE_PUT_GRAYSCALE_PIXEL(&target, transpose ? v_line : i, transpose ? i : v_line, pixel);
}
}
break;
}
case IMAGE_BPP_RGB565: {
int v_line = vflip ? (img->h - line - 1) : line;
uint16_t *data = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, v_line);
for (int i = 0, j = img->w; i < j; i++) {
int h_i = hmirror ? (img->w - i - 1) : i;
if ((!mask) || image_get_mask_pixel(mask, h_i, v_line)) {
int pixel = IMAGE_GET_RGB565_PIXEL_FAST(((uint16_t *) other), h_i);
IMAGE_PUT_RGB565_PIXEL_FAST(data, i, pixel);
IMAGE_PUT_RGB565_PIXEL(&target, transpose ? v_line : i, transpose ? i : v_line, pixel);
}
}
break;
@ -107,13 +211,35 @@ static void imlib_replace_line_op(image_t *img, int line, void *other, void *dat
}
}
void imlib_replace(image_t *img, const char *path, image_t *other, int scalar, bool hmirror, bool vflip, image_t *mask)
void imlib_replace(image_t *img, const char *path, image_t *other, int scalar, bool hmirror, bool vflip, bool transpose, image_t *mask)
{
bool in_place = img == other;
image_t temp;
if (in_place) {
memcpy(&temp, other, sizeof(image_t));
temp.data = fb_alloc(image_size(&temp));
memcpy(temp.data, other->data, image_size(&temp));
other = &temp;
}
imlib_replace_line_op_state_t state;
state.hmirror = hmirror;
state.vflip = vflip;
state.mask = mask;
state.transpose = transpose;
imlib_image_operation(img, path, other, scalar, imlib_replace_line_op, &state);
if (in_place) {
fb_free();
}
if (transpose) {
int w = img->w;
int h = img->h;
img->w = h;
img->h = w;
}
}
static void imlib_add_line_op(image_t *img, int line, void *other, void *data, bool vflipped)
@ -334,13 +460,14 @@ void imlib_mul(image_t *img, const char *path, image_t *other, int scalar, bool
}
typedef struct imlib_div_line_op_state {
bool invert;
bool invert, mod;
image_t *mask;
} imlib_div_line_op_state_t;
static void imlib_div_line_op(image_t *img, int line, void *other, void *data, bool vflipped)
{
bool invert = ((imlib_div_line_op_state_t *) data)->invert;
bool mod = ((imlib_div_line_op_state_t *) data)->mod;
image_t *mask = ((imlib_div_line_op_state_t *) data)->mask;
switch(img->bpp) {
@ -351,7 +478,9 @@ static void imlib_div_line_op(image_t *img, int line, void *other, void *data, b
if ((!mask) || image_get_mask_pixel(mask, i, line)) {
int dataPixel = IMAGE_GET_BINARY_PIXEL_FAST(data, i);
int otherPixel = IMAGE_GET_BINARY_PIXEL_FAST(((uint32_t *) other), i);
int p = IM_DIV((invert?otherPixel:dataPixel) * pScale, (invert?dataPixel:otherPixel));
int p = mod
? IM_MOD((invert?otherPixel:dataPixel) * pScale, (invert?dataPixel:otherPixel))
: IM_DIV((invert?otherPixel:dataPixel) * pScale, (invert?dataPixel:otherPixel));
p = IM_MIN(p, COLOR_BINARY_MAX);
IMAGE_PUT_BINARY_PIXEL_FAST(data, i, p);
}
@ -365,7 +494,9 @@ static void imlib_div_line_op(image_t *img, int line, void *other, void *data, b
if ((!mask) || image_get_mask_pixel(mask, i, line)) {
int dataPixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(data, i);
int otherPixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(((uint8_t *) other), i);
int p = IM_DIV((invert?otherPixel:dataPixel) * pScale, (invert?dataPixel:otherPixel));
int p = mod
? IM_MOD((invert?otherPixel:dataPixel) * pScale, (invert?dataPixel:otherPixel))
: IM_DIV((invert?otherPixel:dataPixel) * pScale, (invert?dataPixel:otherPixel));
p = IM_MIN(p, COLOR_GRAYSCALE_MAX);
IMAGE_PUT_GRAYSCALE_PIXEL_FAST(data, i, p);
}
@ -387,9 +518,15 @@ static void imlib_div_line_op(image_t *img, int line, void *other, void *data, b
int oR = COLOR_RGB565_TO_R5(otherPixel);
int oG = COLOR_RGB565_TO_G6(otherPixel);
int oB = COLOR_RGB565_TO_B5(otherPixel);
int r = IM_DIV((invert?oR:dR) * rScale, (invert?dR:oR));
int g = IM_DIV((invert?oG:dG) * gScale, (invert?dG:oG));
int b = IM_DIV((invert?oB:dB) * bScale, (invert?dB:oB));
int r = mod
? IM_MOD((invert?oR:dR) * rScale, (invert?dR:oR))
: IM_DIV((invert?oR:dR) * rScale, (invert?dR:oR));
int g = mod
? IM_MOD((invert?oG:dG) * gScale, (invert?dG:oG))
: IM_DIV((invert?oG:dG) * gScale, (invert?dG:oG));
int b = mod
? IM_MOD((invert?oB:dB) * bScale, (invert?dB:oB))
: IM_DIV((invert?oB:dB) * bScale, (invert?dB:oB));
r = IM_MIN(r, COLOR_R5_MAX);
g = IM_MIN(g, COLOR_G6_MAX);
b = IM_MIN(b, COLOR_B5_MAX);
@ -404,10 +541,11 @@ static void imlib_div_line_op(image_t *img, int line, void *other, void *data, b
}
}
void imlib_div(image_t *img, const char *path, image_t *other, int scalar, bool invert, image_t *mask)
void imlib_div(image_t *img, const char *path, image_t *other, int scalar, bool invert, bool mod, image_t *mask)
{
imlib_div_line_op_state_t state;
state.invert = invert;
state.mod = mod;
state.mask = mask;
imlib_image_operation(img, path, other, scalar, imlib_div_line_op, &state);
}

View File

@ -1346,8 +1346,9 @@ STATIC mp_obj_t py_image_draw_string(uint n_args, const mp_obj_t *args, mp_map_t
int arg_c =
py_helper_keyword_color(arg_img, n_args, args, offset + 0, kw_args, -1); // White.
int arg_scale =
py_helper_keyword_int(n_args, args, offset + 1, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_scale), 1);
float arg_scale =
py_helper_keyword_float(n_args, args, offset + 1, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_scale), 1.0);
PY_ASSERT_TRUE_MSG(0 < arg_scale, "Error: 0 < scale!");
int arg_x_spacing =
py_helper_keyword_int(n_args, args, offset + 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_x_spacing), 0);
int arg_y_spacing =
@ -1441,10 +1442,13 @@ STATIC mp_obj_t py_image_draw_image(uint n_args, const mp_obj_t *args, mp_map_t
float arg_y_scale =
py_helper_keyword_float(n_args, args, offset + 1, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_y_scale), 1.0f);
PY_ASSERT_TRUE_MSG((0.0f <= arg_y_scale), "Error: 0.0 <= y_scale!");
float arg_alpha =
py_helper_keyword_int(n_args, args, offset + 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_alpha), 256) / 256.0f;
PY_ASSERT_TRUE_MSG((0 <= arg_alpha) && (arg_alpha <= 1), "Error: 0 <= alpha <= 256!");
image_t *arg_msk =
py_helper_keyword_to_image_mutable_mask(n_args, args, offset + 2, kw_args);
py_helper_keyword_to_image_mutable_mask(n_args, args, offset + 3, kw_args);
imlib_draw_image(arg_img, arg_other, arg_cx, arg_cy, arg_x_scale, arg_y_scale, arg_msk);
imlib_draw_image(arg_img, arg_other, arg_cx, arg_cy, arg_x_scale, arg_y_scale, arg_alpha, arg_msk);
return args[0];
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_draw_image_obj, 3, py_image_draw_image);
@ -1452,7 +1456,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_draw_image_obj, 3, py_image_draw_imag
STATIC mp_obj_t py_image_draw_keypoints(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]);
py_kp_obj_t *kpts_obj = py_kpts_obj(args[1]);
int arg_c =
py_helper_keyword_color(arg_img, n_args, args, 2, kw_args, -1); // White.
@ -1463,14 +1466,33 @@ STATIC mp_obj_t py_image_draw_keypoints(uint n_args, const mp_obj_t *args, mp_ma
bool arg_fill =
py_helper_keyword_int(n_args, args, 5, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_fill), false);
for (int i = 0, ii = array_length(kpts_obj->kpts); i < ii; i++) {
kp_t *kp = array_at(kpts_obj->kpts, i);
int cx = kp->x;
int cy = kp->y;
int si = sin_table[kp->angle] * arg_s;
int co = cos_table[kp->angle] * arg_s;
imlib_draw_line(arg_img, cx, cy, cx + co, cy + si, arg_c, arg_thickness);
imlib_draw_circle(arg_img, cx, cy, (arg_s - 2) / 2, arg_c, arg_thickness, arg_fill);
if (MP_OBJ_IS_TYPE(args[1], &mp_type_tuple) || MP_OBJ_IS_TYPE(args[1], &mp_type_list)) {
size_t len;
mp_obj_t *items;
mp_obj_get_array(args[1], &len, &items);
for (size_t i = 0; i < len; i++) {
mp_obj_t *tuple;
mp_obj_get_array_fixed_n(items[i], 3, &tuple);
int cx = mp_obj_get_int(tuple[0]);
int cy = mp_obj_get_int(tuple[1]);
int angle = mp_obj_get_int(tuple[2]) % 360;
int si = sin_table[angle] * arg_s;
int co = cos_table[angle] * arg_s;
imlib_draw_line(arg_img, cx, cy, cx + co, cy + si, arg_c, arg_thickness);
imlib_draw_circle(arg_img, cx, cy, (arg_s - 2) / 2, arg_c, arg_thickness, arg_fill);
}
} else {
py_kp_obj_t *kpts_obj = py_kpts_obj(args[1]);
for (int i = 0, ii = array_length(kpts_obj->kpts); i < ii; i++) {
kp_t *kp = array_at(kpts_obj->kpts, i);
int cx = kp->x;
int cy = kp->y;
int angle = kp->angle % 360;
int si = sin_table[angle] * arg_s;
int co = cos_table[angle] * arg_s;
imlib_draw_line(arg_img, cx, cy, cx + co, cy + si, arg_c, arg_thickness);
imlib_draw_circle(arg_img, cx, cy, (arg_s - 2) / 2, arg_c, arg_thickness, arg_fill);
}
}
return args[0];
@ -1538,8 +1560,23 @@ STATIC mp_obj_t py_image_binary(uint n_args, const mp_obj_t *args, mp_map_t *kw_
bool arg_copy =
py_helper_keyword_int(n_args, args, 6, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_copy), false);
PY_ASSERT_TRUE_MSG((!arg_to_bitmap) || arg_copy,
"Can't convert to bitmap in place!");
if (arg_to_bitmap && (!arg_copy)) {
switch(arg_img->bpp) {
case IMAGE_BPP_GRAYSCALE: {
PY_ASSERT_TRUE_MSG((arg_img->w >= (sizeof(uint32_t)/sizeof(uint8_t))),
"Can't convert to bitmap in place!");
break;
}
case IMAGE_BPP_RGB565: {
PY_ASSERT_TRUE_MSG((arg_img->w >= (sizeof(uint32_t)/sizeof(uint16_t))),
"Can't convert to bitmap in place!");
break;
}
default: {
break;
}
}
}
image_t out;
out.w = arg_img->w;
@ -1550,9 +1587,10 @@ STATIC mp_obj_t py_image_binary(uint n_args, const mp_obj_t *args, mp_map_t *kw_
fb_alloc_mark();
imlib_binary(&out, arg_img, &arg_thresholds, arg_invert, arg_zero, arg_msk);
fb_alloc_free_till_mark();
list_free(&arg_thresholds);
if ((!arg_copy) && (MAIN_FB()->pixels == out.data)) {
if (arg_to_bitmap && (!arg_copy) && (MAIN_FB()->pixels == out.data)) {
MAIN_FB()->bpp = out.bpp;
}
@ -1562,9 +1600,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_binary_obj, 2, py_image_binary);
STATIC mp_obj_t py_image_invert(mp_obj_t img_obj)
{
fb_alloc_mark();
imlib_invert(py_helper_arg_to_image_mutable(img_obj));
fb_alloc_free_till_mark();
return img_obj;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_invert_obj, py_image_invert);
@ -1823,11 +1859,27 @@ STATIC mp_obj_t py_image_black_hat(uint n_args, const mp_obj_t *args, mp_map_t *
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_black_hat_obj, 2, py_image_black_hat);
STATIC mp_obj_t py_image_gamma_corr(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]);
float arg_gamma =
py_helper_keyword_float(n_args, args, 1, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_gamma), 1.0f);
float arg_contrast =
py_helper_keyword_float(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_contrast), 1.0f);
float arg_brightness =
py_helper_keyword_float(n_args, args, 3, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_brightness), 0.0f);
fb_alloc_mark();
imlib_gamma_corr(arg_img, arg_gamma, arg_contrast, arg_brightness);
fb_alloc_free_till_mark();
return args[0];
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_gamma_corr_obj, 1, py_image_gamma_corr);
STATIC mp_obj_t py_image_negate(mp_obj_t img_obj)
{
fb_alloc_mark();
imlib_negate(py_helper_arg_to_image_mutable(img_obj));
fb_alloc_free_till_mark();
return img_obj;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_negate_obj, py_image_negate);
@ -1840,26 +1892,50 @@ STATIC mp_obj_t py_image_replace(uint n_args, const mp_obj_t *args, mp_map_t *kw
py_helper_keyword_int(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_hmirror), false);
bool arg_vflip =
py_helper_keyword_int(n_args, args, 3, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_vflip), false);
bool arg_transpose =
py_helper_keyword_int(n_args, args, 4, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_transpose), false);
image_t *arg_msk =
py_helper_keyword_to_image_mutable_mask(n_args, args, 4, kw_args);
py_helper_keyword_to_image_mutable_mask(n_args, args, 5, kw_args);
if (arg_transpose) {
size_t size0 = image_size(arg_img);
int w = arg_img->w;
int h = arg_img->h;
arg_img->w = h;
arg_img->h = w;
size_t size1 = image_size(arg_img);
arg_img->w = w;
arg_img->h = h;
PY_ASSERT_TRUE_MSG(size1 <= size0,
"Unable to transpose the image because it would grow in size!");
}
fb_alloc_mark();
if (MP_OBJ_IS_STR(args[1])) {
imlib_replace(arg_img, mp_obj_str_get_str(args[1]), NULL, 0, arg_hmirror, arg_vflip, arg_msk);
} else if (MP_OBJ_IS_TYPE(args[1], &py_image_type)) {
imlib_replace(arg_img, NULL, py_helper_arg_to_image_mutable(args[1]), 0, arg_hmirror, arg_vflip, arg_msk);
mp_obj_t arg_1 = (n_args > 1) ? args[1] : args[0];
if (MP_OBJ_IS_STR(arg_1)) {
imlib_replace(arg_img, mp_obj_str_get_str(arg_1), NULL, 0,
arg_hmirror, arg_vflip, arg_transpose, arg_msk);
} else if (MP_OBJ_IS_TYPE(arg_1, &py_image_type)) {
imlib_replace(arg_img, NULL, py_helper_arg_to_image_mutable(arg_1), 0,
arg_hmirror, arg_vflip, arg_transpose, arg_msk);
} else {
imlib_replace(arg_img, NULL, NULL,
py_helper_keyword_color(arg_img, n_args, args, 1, NULL, 0),
arg_hmirror, arg_vflip, arg_msk);
arg_hmirror, arg_vflip, arg_transpose, arg_msk);
}
fb_alloc_free_till_mark();
if (MAIN_FB()->pixels == arg_img->data) {
MAIN_FB()->w = arg_img->w;
MAIN_FB()->h = arg_img->h;
}
return args[0];
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_replace_obj, 2, py_image_replace);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_replace_obj, 1, py_image_replace);
STATIC mp_obj_t py_image_add(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
@ -1946,19 +2022,23 @@ STATIC mp_obj_t py_image_div(uint n_args, const mp_obj_t *args, mp_map_t *kw_arg
py_helper_arg_to_image_mutable(args[0]);
bool arg_invert =
py_helper_keyword_int(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_invert), false);
bool arg_mod =
py_helper_keyword_int(n_args, args, 3, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_mod), false);
image_t *arg_msk =
py_helper_keyword_to_image_mutable_mask(n_args, args, 3, kw_args);
py_helper_keyword_to_image_mutable_mask(n_args, args, 4, kw_args);
fb_alloc_mark();
if (MP_OBJ_IS_STR(args[1])) {
imlib_div(arg_img, mp_obj_str_get_str(args[1]), NULL, 0, arg_invert, arg_msk);
imlib_div(arg_img, mp_obj_str_get_str(args[1]), NULL, 0,
arg_invert, arg_mod, arg_msk);
} else if (MP_OBJ_IS_TYPE(args[1], &py_image_type)) {
imlib_div(arg_img, NULL, py_helper_arg_to_image_mutable(args[1]), 0, arg_invert, arg_msk);
imlib_div(arg_img, NULL, py_helper_arg_to_image_mutable(args[1]), 0,
arg_invert, arg_mod, arg_msk);
} else {
imlib_div(arg_img, NULL, NULL,
py_helper_keyword_color(arg_img, n_args, args, 1, NULL, 0),
arg_invert, arg_msk);
arg_invert, arg_mod, arg_msk);
}
fb_alloc_free_till_mark();
@ -5349,8 +5429,11 @@ static const mp_rom_map_elem_t locals_dict_table[] = {
{MP_ROM_QSTR(MP_QSTR_top_hat), MP_ROM_PTR(&py_image_top_hat_obj)},
{MP_ROM_QSTR(MP_QSTR_black_hat), MP_ROM_PTR(&py_image_black_hat_obj)},
/* Math Methods */
{MP_ROM_QSTR(MP_QSTR_gamma_corr), MP_ROM_PTR(&py_image_gamma_corr_obj)},
{MP_ROM_QSTR(MP_QSTR_negate), MP_ROM_PTR(&py_image_negate_obj)},
{MP_ROM_QSTR(MP_QSTR_assign), MP_ROM_PTR(&py_image_replace_obj)},
{MP_ROM_QSTR(MP_QSTR_replace), MP_ROM_PTR(&py_image_replace_obj)},
{MP_ROM_QSTR(MP_QSTR_set), MP_ROM_PTR(&py_image_replace_obj)},
{MP_ROM_QSTR(MP_QSTR_add), MP_ROM_PTR(&py_image_add_obj)},
{MP_ROM_QSTR(MP_QSTR_sub), MP_ROM_PTR(&py_image_sub_obj)},
{MP_ROM_QSTR(MP_QSTR_mul), MP_ROM_PTR(&py_image_mul_obj)},
@ -5363,7 +5446,9 @@ static const mp_rom_map_elem_t locals_dict_table[] = {
{MP_ROM_QSTR(MP_QSTR_top_hat), MP_ROM_PTR(&py_func_unavailable_obj)},
{MP_ROM_QSTR(MP_QSTR_black_hat), MP_ROM_PTR(&py_func_unavailable_obj)},
{MP_ROM_QSTR(MP_QSTR_negate), MP_ROM_PTR(&py_func_unavailable_obj)},
{MP_ROM_QSTR(MP_QSTR_assign), MP_ROM_PTR(&py_func_unavailable_obj)},
{MP_ROM_QSTR(MP_QSTR_replace), MP_ROM_PTR(&py_func_unavailable_obj)},
{MP_ROM_QSTR(MP_QSTR_set), MP_ROM_PTR(&py_func_unavailable_obj)},
{MP_ROM_QSTR(MP_QSTR_add), MP_ROM_PTR(&py_func_unavailable_obj)},
{MP_ROM_QSTR(MP_QSTR_sub), MP_ROM_PTR(&py_func_unavailable_obj)},
{MP_ROM_QSTR(MP_QSTR_mul), MP_ROM_PTR(&py_func_unavailable_obj)},

View File

@ -429,6 +429,7 @@ Q(draw_arrow)
Q(draw_image)
Q(x_scale)
Q(y_scale)
Q(alpha)
Q(mask)
// Draw Keypoints
@ -518,13 +519,22 @@ Q(black_hat)
// duplicate Q(threshold)
// duplicate Q(mask)
// Gamma Correct
Q(gamma_corr)
Q(gamma)
Q(contrast)
Q(brightness)
// Negate
Q(negate)
// Replace
// Assign/Replace/Set
Q(assign)
Q(replace)
Q(set)
Q(hmirror)
Q(vflip)
Q(transpose)
// duplicate Q(mask)
// Add Op
@ -544,6 +554,7 @@ Q(mul)
// Div Op
Q(div)
// duplicate Q(invert)
Q(mod)
// duplicate Q(mask)
// Min
@ -560,7 +571,7 @@ Q(difference)
// Blend
Q(blend)
Q(alpha)
// duplicate Q(alpha)
// duplicate Q(mask)
// Histogram Equalization