mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Merge pull request #1993 from kwagyeman/kwabena/add_hmirror_vflip_transpose_to_draw_image
imlib: Add hmirror, vflip, and transpose support to draw_image.
This commit is contained in:
commit
a388b0711d
@ -2765,6 +2765,13 @@ void imlib_draw_image_get_bounds(image_t *dst_img,
|
||||
int src_width_scaled = fast_floorf(fast_fabsf(x_scale) * (roi ? roi->w : src_img->w));
|
||||
int src_height_scaled = fast_floorf(fast_fabsf(y_scale) * (roi ? roi->h : src_img->h));
|
||||
|
||||
// Make sure bounds checking works when transposed.
|
||||
if (hint & IMAGE_HINT_TRANSPOSE) {
|
||||
int temp = src_width_scaled;
|
||||
src_width_scaled = src_height_scaled;
|
||||
src_height_scaled = temp;
|
||||
}
|
||||
|
||||
// Center src if hint is set.
|
||||
if (hint & IMAGE_HINT_CENTER) {
|
||||
dst_x_start -= src_width_scaled / 2;
|
||||
@ -2846,6 +2853,9 @@ void imlib_draw_image(image_t *dst_img,
|
||||
dst_delta_x = -1;
|
||||
x_scale = -x_scale;
|
||||
}
|
||||
if (hint & IMAGE_HINT_HMIRROR) {
|
||||
dst_delta_x = -dst_delta_x;
|
||||
}
|
||||
|
||||
int dst_delta_y = 1; // positive direction
|
||||
if (y_scale < 0.f) {
|
||||
@ -2853,6 +2863,9 @@ void imlib_draw_image(image_t *dst_img,
|
||||
dst_delta_y = -1;
|
||||
y_scale = -y_scale;
|
||||
}
|
||||
if (hint & IMAGE_HINT_VFLIP) {
|
||||
dst_delta_y = -dst_delta_y;
|
||||
}
|
||||
|
||||
int src_img_w = roi ? roi->w : src_img->w;
|
||||
int w_start = roi ? roi->x : 0, w_start_p_1 = w_start + 1, w_start_p_2 = w_start_p_1 + 1;
|
||||
@ -2887,6 +2900,15 @@ void imlib_draw_image(image_t *dst_img,
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure bounds checking works when transposed.
|
||||
if (hint & IMAGE_HINT_TRANSPOSE) {
|
||||
int temp = src_width_scaled;
|
||||
src_width_scaled = src_height_scaled;
|
||||
src_height_scaled = temp;
|
||||
}
|
||||
|
||||
int dst_x_start_backup = dst_x_start;
|
||||
int dst_y_start_backup = dst_y_start;
|
||||
// Center src if hint is set.
|
||||
if (hint & IMAGE_HINT_CENTER) {
|
||||
dst_x_start -= src_width_scaled / 2;
|
||||
@ -3102,6 +3124,130 @@ void imlib_draw_image(image_t *dst_img,
|
||||
src_img = &new_src_img;
|
||||
}
|
||||
|
||||
// To improve transpose performance we will split the operation up into chunks that fit in
|
||||
// onchip RAM. These chunks will then be copied to the target buffer in an efficent manner.
|
||||
// However, this doesn't work when the image is being scaled. So, we have to scale the image
|
||||
// first if that is requested.
|
||||
if (hint & IMAGE_HINT_TRANSPOSE) {
|
||||
rectangle_t t_roi = {};
|
||||
image_t t_src_img;
|
||||
t_src_img.pixfmt = src_img->pixfmt;
|
||||
|
||||
// Are we scaling?
|
||||
if ((src_x_frac != 65536) || (src_y_frac != 65536)) {
|
||||
t_src_img.w = t_roi.w = src_height_scaled; // was transposed
|
||||
t_src_img.h = t_roi.h = src_width_scaled; // was transposed
|
||||
t_src_img.data = fb_alloc(image_size(&t_src_img), FB_ALLOC_CACHE_ALIGN);
|
||||
imlib_draw_image(&t_src_img, src_img, 0, 0, x_scale, y_scale, roi,
|
||||
-1, 256, NULL, NULL,
|
||||
hint & (IMAGE_HINT_AREA | IMAGE_HINT_BILINEAR | IMAGE_HINT_BICUBIC),
|
||||
NULL, NULL, NULL);
|
||||
} else {
|
||||
memcpy(&t_roi, roi, sizeof(rectangle_t));
|
||||
t_src_img.w = src_img->w;
|
||||
t_src_img.h = src_img->h;
|
||||
t_src_img.data = src_img->data;
|
||||
}
|
||||
|
||||
uint32_t size;
|
||||
void *data = fb_alloc_all(&size, FB_ALLOC_PREFER_SPEED | FB_ALLOC_CACHE_ALIGN);
|
||||
|
||||
// line_num stores how many lines we can do at a time with on-chip RAM.
|
||||
image_t temp = {.w = t_roi.w, .h = t_roi.h, .pixfmt = t_src_img.pixfmt};
|
||||
int line_num = size / image_line_size(&temp);
|
||||
|
||||
// Work top to bottom transposing as many lines at a time in a chunk of the image.
|
||||
for (int i = t_roi.y; i < t_roi.h; i += line_num) {
|
||||
line_num = IM_MIN(line_num, (t_roi.h - i));
|
||||
|
||||
// Make an image that is a slice of the input image.
|
||||
image_t in = {.w = t_src_img.w, .h = line_num, .pixfmt = t_src_img.pixfmt};
|
||||
in.data = t_src_img.data + (image_line_size(&t_src_img) *
|
||||
((dst_delta_y < 0) ? (t_roi.h - i - 1) : i));
|
||||
|
||||
// Make an image that will hold the transposed output.
|
||||
image_t out = in;
|
||||
out.w = line_num;
|
||||
out.h = t_roi.w;
|
||||
out.data = data;
|
||||
|
||||
switch (t_src_img.pixfmt) {
|
||||
case PIXFORMAT_BINARY: {
|
||||
for (int y = 0; y < in.h; y++) {
|
||||
int y_2 = (dst_delta_y < 0) ? -y : y;
|
||||
uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR((&in), y_2);
|
||||
if (dst_delta_x < 0) {
|
||||
for (int x = 0; x < t_roi.w; x++) {
|
||||
int pixel = IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, (t_roi.x + (t_roi.w - x - 1)));
|
||||
IMAGE_PUT_BINARY_PIXEL((&out), y, x, pixel);
|
||||
}
|
||||
} else {
|
||||
for (int x = 0; x < t_roi.w; x++) {
|
||||
int pixel = IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, (t_roi.x + x));
|
||||
IMAGE_PUT_BINARY_PIXEL((&out), y, x, pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PIXFORMAT_GRAYSCALE: {
|
||||
for (int y = 0; y < in.h; y++) {
|
||||
int y_2 = (dst_delta_y < 0) ? -y : y;
|
||||
uint8_t *i_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR((&in), y_2) + t_roi.x;
|
||||
uint8_t *o_row_ptr = ((uint8_t *) out.data) + y;
|
||||
if (dst_delta_x < 0) {
|
||||
for (int x = t_roi.w - 1; x >= 0; x--, o_row_ptr += line_num) {
|
||||
*o_row_ptr = i_row_ptr[x];
|
||||
}
|
||||
} else {
|
||||
for (int x = 0; x < t_roi.w; x++, o_row_ptr += line_num) {
|
||||
*o_row_ptr = i_row_ptr[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PIXFORMAT_RGB565: {
|
||||
for (int y = 0; y < in.h; y++) {
|
||||
int y_2 = (dst_delta_y < 0) ? -y : y;
|
||||
uint16_t *i_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR((&in), y_2) + t_roi.x;
|
||||
uint16_t *o_row_ptr = ((uint16_t *) out.data) + y;
|
||||
if (dst_delta_x < 0) {
|
||||
for (int x = t_roi.w - 1; x >= 0; x--, o_row_ptr += line_num) {
|
||||
*o_row_ptr = i_row_ptr[x];
|
||||
}
|
||||
} else {
|
||||
for (int x = 0; x < t_roi.w; x++, o_row_ptr += line_num) {
|
||||
*o_row_ptr = i_row_ptr[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
imlib_draw_image(dst_img, &out, dst_x_start_backup + i, dst_y_start_backup, 1.f, 1.f, NULL,
|
||||
rgb_channel, alpha, color_palette, alpha_palette,
|
||||
hint & (IMAGE_HINT_CENTER | IMAGE_HINT_BLACK_BACKGROUND),
|
||||
callback, callback_arg, dst_row_override);
|
||||
}
|
||||
|
||||
fb_free(); // fb_alloc_all
|
||||
|
||||
if (t_src_img.data != src_img->data) {
|
||||
fb_free();
|
||||
}
|
||||
|
||||
if (&new_src_img == src_img) {
|
||||
fb_free();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
imlib_draw_row_data_t imlib_draw_row_data;
|
||||
imlib_draw_row_data.dst_img = dst_img;
|
||||
imlib_draw_row_data.src_img_pixfmt = (!src_img->is_mutable) ? new_not_mutable_pixfmt : src_img->pixfmt;
|
||||
|
||||
@ -1077,13 +1077,16 @@ typedef struct find_barcodes_list_lnk_data {
|
||||
} find_barcodes_list_lnk_data_t;
|
||||
|
||||
typedef enum image_hint {
|
||||
IMAGE_HINT_AREA = 1 << 0,
|
||||
IMAGE_HINT_BILINEAR = 1 << 1,
|
||||
IMAGE_HINT_BICUBIC = 1 << 2,
|
||||
IMAGE_HINT_CENTER = 1 << 7,
|
||||
IMAGE_HINT_EXTRACT_RGB_CHANNEL_FIRST = 1 << 8,
|
||||
IMAGE_HINT_APPLY_COLOR_PALETTE_FIRST = 1 << 9,
|
||||
IMAGE_HINT_BLACK_BACKGROUND = 1 << 31
|
||||
IMAGE_HINT_AREA = (1 << 0),
|
||||
IMAGE_HINT_BILINEAR = (1 << 1),
|
||||
IMAGE_HINT_BICUBIC = (1 << 2),
|
||||
IMAGE_HINT_HMIRROR = (1 << 4),
|
||||
IMAGE_HINT_VFLIP = (1 << 5),
|
||||
IMAGE_HINT_TRANSPOSE = (1 << 6),
|
||||
IMAGE_HINT_CENTER = (1 << 7),
|
||||
IMAGE_HINT_EXTRACT_RGB_CHANNEL_FIRST = (1 << 8),
|
||||
IMAGE_HINT_APPLY_COLOR_PALETTE_FIRST = (1 << 9),
|
||||
IMAGE_HINT_BLACK_BACKGROUND = (1 << 31)
|
||||
} image_hint_t;
|
||||
|
||||
typedef struct imlib_draw_row_data {
|
||||
|
||||
@ -7215,9 +7215,15 @@ static const mp_rom_map_elem_t globals_dict_table[] = {
|
||||
{MP_ROM_QSTR(MP_QSTR_AREA), MP_ROM_INT(IMAGE_HINT_AREA)},
|
||||
{MP_ROM_QSTR(MP_QSTR_BILINEAR), MP_ROM_INT(IMAGE_HINT_BILINEAR)},
|
||||
{MP_ROM_QSTR(MP_QSTR_BICUBIC), MP_ROM_INT(IMAGE_HINT_BICUBIC)},
|
||||
{MP_ROM_QSTR(MP_QSTR_HMIRROR), MP_ROM_INT(IMAGE_HINT_HMIRROR)},
|
||||
{MP_ROM_QSTR(MP_QSTR_VFLIP), MP_ROM_INT(IMAGE_HINT_VFLIP)},
|
||||
{MP_ROM_QSTR(MP_QSTR_TRANSPOSE), MP_ROM_INT(IMAGE_HINT_TRANSPOSE)},
|
||||
{MP_ROM_QSTR(MP_QSTR_CENTER), MP_ROM_INT(IMAGE_HINT_CENTER)},
|
||||
{MP_ROM_QSTR(MP_QSTR_EXTRACT_RGB_CHANNEL_FIRST), MP_ROM_INT(IMAGE_HINT_EXTRACT_RGB_CHANNEL_FIRST)},
|
||||
{MP_ROM_QSTR(MP_QSTR_APPLY_COLOR_PALETTE_FIRST), MP_ROM_INT(IMAGE_HINT_APPLY_COLOR_PALETTE_FIRST)},
|
||||
{MP_ROM_QSTR(MP_QSTR_ROTATE_90), MP_ROM_INT(IMAGE_HINT_VFLIP | IMAGE_HINT_TRANSPOSE)},
|
||||
{MP_ROM_QSTR(MP_QSTR_ROTATE_180), MP_ROM_INT(IMAGE_HINT_HMIRROR | IMAGE_HINT_VFLIP)},
|
||||
{MP_ROM_QSTR(MP_QSTR_ROTATE_270), MP_ROM_INT(IMAGE_HINT_HMIRROR | IMAGE_HINT_TRANSPOSE)},
|
||||
#ifdef IMLIB_FIND_TEMPLATE
|
||||
{MP_ROM_QSTR(MP_QSTR_SEARCH_EX), MP_ROM_INT(SEARCH_EX)},
|
||||
{MP_ROM_QSTR(MP_QSTR_SEARCH_DS), MP_ROM_INT(SEARCH_DS)},
|
||||
|
||||
Loading…
Reference in New Issue
Block a user