Add transpose support to replace and aliases

Now you can rotate and image by 0, 90, 180, 270 degrees along with
vertical flip and horizontal mirror. This method works in place or out
of place.
This commit is contained in:
Kwabena W. Agyeman 2019-01-02 01:35:34 -05:00
parent 563642a174
commit dbe7bf0591
4 changed files with 72 additions and 14 deletions

View File

@ -1298,7 +1298,7 @@ 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);

View File

@ -147,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;
@ -155,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;
@ -203,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)

View File

@ -1852,23 +1852,44 @@ 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);
imlib_replace(arg_img, mp_obj_str_get_str(args[1]), NULL, 0,
arg_hmirror, arg_vflip, arg_transpose, 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);
imlib_replace(arg_img, NULL, py_helper_arg_to_image_mutable(args[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);
@ -5363,7 +5384,9 @@ static const mp_rom_map_elem_t locals_dict_table[] = {
/* 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)},
@ -5376,7 +5399,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

@ -527,10 +527,13 @@ 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