modules/py_image: Optimize invert and negate.

This commit is contained in:
Kwabena W. Agyeman 2024-02-10 11:33:27 -08:00
parent 8f4cb0725b
commit 84cca7c6ca
4 changed files with 26 additions and 75 deletions

View File

@ -224,28 +224,41 @@ void imlib_binary(image_t *out, image_t *img, list_t *thresholds, bool invert, b
}
void imlib_invert(image_t *img) {
uint32_t n = image_size(img);
uint32_t *p32 = (uint32_t *) img->data;
switch (img->pixfmt) {
case PIXFORMAT_BINARY: {
for (uint32_t *start = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, 0),
*end = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, img->h);
start < end; start++) {
*start = ~*start;
for (; n >= 4; n -= 4, p32++) {
*p32 = ~*p32;
}
break;
}
case PIXFORMAT_GRAYSCALE: {
for (uint8_t *start = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, 0),
*end = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, img->h);
start < end; start++) {
*start = ~*start;
#if (__ARM_ARCH > 6)
for (; n >= 4; n -= 4, p32++) {
*p32 = ~*p32;
}
#endif
uint8_t *p8 = (uint8_t *) p32;
for (; n >= 1; n -= 1, p8++) {
*p8 = ~*p8;
}
break;
}
case PIXFORMAT_RGB565: {
for (uint16_t *start = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, 0),
*end = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, img->h);
start < end; start++) {
*start = ~*start;
#if (__ARM_ARCH > 6)
for (; n >= 4; n -= 4, p32++) {
*p32 = ~*p32;
}
#endif
uint16_t *p16 = (uint16_t *) p32;
for (; n >= 2; n -= 2, p16++) {
*p16 = ~*p16;
}
break;
}

View File

@ -1375,7 +1375,6 @@ 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_negate(image_t *img);
void imlib_replace(image_t *img,
const char *path,
image_t *other,

View File

@ -11,61 +11,6 @@
#include "imlib.h"
#ifdef IMLIB_ENABLE_MATH_OPS
void imlib_negate(image_t *img) {
switch (img->pixfmt) {
case PIXFORMAT_BINARY: {
for (int y = 0, yy = img->h; y < yy; y++) {
uint32_t *data = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y);
int x = 0, xx = img->w;
uint32_t *s = data;
for (; x < xx - 31; x += 32) {
// do it faster with bit access
s[0] = ~s[0]; // invert 32 bits (pixels) in one shot
s++;
}
for (; x < xx; x++) {
int dataPixel = IMAGE_GET_BINARY_PIXEL_FAST(data, x);
int p = (COLOR_BINARY_MAX - COLOR_BINARY_MIN) - dataPixel;
IMAGE_PUT_BINARY_PIXEL_FAST(data, x, p);
}
}
break;
}
case PIXFORMAT_GRAYSCALE: {
for (int y = 0, yy = img->h; y < yy; y++) {
uint8_t *data = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y);
int x = 0, xx = img->w;
uint32_t a, b, *s = (uint32_t *) data;
for (; x < xx - 7; x += 8) {
// process a pair of 4 pixels at a time
a = s[0]; b = s[1]; // read 8 pixels
s[0] = ~a; s[1] = ~b;
s += 2;
}
for (; x < xx; x++) {
int dataPixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(data, x);
int p = (COLOR_GRAYSCALE_MAX - COLOR_GRAYSCALE_MIN) - dataPixel;
IMAGE_PUT_GRAYSCALE_PIXEL_FAST(data, x, p);
}
}
break;
}
case PIXFORMAT_RGB565: {
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);
IMAGE_PUT_RGB565_PIXEL_FAST(data, x, ~dataPixel);
}
}
break;
}
default: {
break;
}
}
}
typedef struct imlib_replace_line_op_state {
bool hmirror, vflip, transpose;
image_t *mask;

View File

@ -2186,12 +2186,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_close_obj, 2, py_image_close);
// Math Methods
///////////////
STATIC mp_obj_t py_image_negate(mp_obj_t img_obj) {
imlib_negate(py_helper_arg_to_image(img_obj, ARG_IMAGE_MUTABLE));
return img_obj;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_negate_obj, py_image_negate);
STATIC mp_obj_t py_image_replace(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
image_t *arg_img =
py_helper_arg_to_image(args[0], ARG_IMAGE_MUTABLE);
@ -6558,7 +6552,7 @@ static const mp_rom_map_elem_t locals_dict_table[] = {
#endif
#ifdef IMLIB_ENABLE_MATH_OPS
/* Math Methods */
{MP_ROM_QSTR(MP_QSTR_negate), MP_ROM_PTR(&py_image_negate_obj)},
{MP_ROM_QSTR(MP_QSTR_negate), MP_ROM_PTR(&py_image_invert_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)},