From 42c5794a05923527186d5c28bf2e9e75a9c2fb88 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 12 May 2020 13:56:40 +0200 Subject: [PATCH] optimize image zoom --- src/lv_draw/lv_draw_img.c | 6 +-- src/lv_draw/lv_img_buf.c | 96 ++++----------------------------------- src/lv_draw/lv_img_buf.h | 86 ++++++++++++++++++++++++++++++++++- 3 files changed, 97 insertions(+), 91 deletions(-) diff --git a/src/lv_draw/lv_draw_img.c b/src/lv_draw/lv_draw_img.c index 0380eecaf..0baf2a9a5 100644 --- a/src/lv_draw/lv_draw_img.c +++ b/src/lv_draw/lv_draw_img.c @@ -496,10 +496,12 @@ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const int32_t x; int32_t y; + int32_t rot_y = disp_area->y1 + draw_area.y1 - map_area->y1; for(y = 0; y < draw_area_h; y++) { map_px = map_buf_tmp; uint32_t px_i_start = px_i; + int32_t rot_x = disp_area->x1 + draw_area.x1 - map_area->x1; for(x = 0; x < draw_area_w; x++, map_px += px_size_byte, px_i++) { if(transform == false) { @@ -532,9 +534,7 @@ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const else { /*Transform*/ bool ret; - int32_t rot_x = x + (disp_area->x1 + draw_area.x1) - map_area->x1; - int32_t rot_y = y + (disp_area->y1 + draw_area.y1) - map_area->y1; - ret = lv_img_buf_transform(&trans_dsc, rot_x, rot_y); + ret = lv_img_buf_transform(&trans_dsc, rot_x + x, rot_y + y); if(ret == false) { mask_buf[px_i] = LV_OPA_TRANSP; continue; diff --git a/src/lv_draw/lv_img_buf.c b/src/lv_draw/lv_img_buf.c index 14a2de1b3..e44cbb89c 100644 --- a/src/lv_draw/lv_img_buf.c +++ b/src/lv_draw/lv_img_buf.c @@ -25,7 +25,6 @@ /********************** * STATIC PROTOTYPES **********************/ -static inline bool transform_anti_alias(lv_img_transform_dsc_t * dsc); /********************** * STATIC VARIABLES @@ -456,88 +455,6 @@ void lv_img_buf_transform_init(lv_img_transform_dsc_t * dsc) dsc->res.color = dsc->cfg.color; } -/** - * Get which color and opa would come to a pixel if it were rotated - * @param dsc a descriptor initialized by `lv_img_buf_rotate_init` - * @param x the coordinate which color and opa should be get - * @param y the coordinate which color and opa should be get - * @return true: there is valid pixel on these x/y coordinates; false: the rotated pixel was out of the image - * @note the result is written back to `dsc->res_color` and `dsc->res_opa` - */ -bool lv_img_buf_transform(lv_img_transform_dsc_t * dsc, lv_coord_t x, lv_coord_t y) -{ - const uint8_t * src_u8 = dsc->cfg.src; - - /*Get the target point relative coordinates to the pivot*/ - int32_t xt = x - dsc->cfg.pivot_x; - int32_t yt = y - dsc->cfg.pivot_y; - - int32_t xs; - int32_t ys; - if(dsc->cfg.zoom == LV_IMG_ZOOM_NONE) { - /*Get the source pixel from the upscaled image*/ - xs = ((dsc->tmp.cosma * xt - dsc->tmp.sinma * yt) >> (LV_TRIGO_SHIFT - 8)) + dsc->tmp.pivot_x_256; - ys = ((dsc->tmp.sinma * xt + dsc->tmp.cosma * yt) >> (LV_TRIGO_SHIFT - 8)) + dsc->tmp.pivot_y_256; - } - else { - xt *= dsc->tmp.zoom_inv; - yt *= dsc->tmp.zoom_inv; - xs = ((dsc->tmp.cosma * xt - dsc->tmp.sinma * yt) >> (LV_TRIGO_SHIFT)) + dsc->tmp.pivot_x_256; - ys = ((dsc->tmp.sinma * xt + dsc->tmp.cosma * yt) >> (LV_TRIGO_SHIFT)) + dsc->tmp.pivot_y_256; - } - - /*Get the integer part of the source pixel*/ - int xs_int = xs >> 8; - int ys_int = ys >> 8; - - if(xs_int >= dsc->cfg.src_w) return false; - else if(xs_int < 0) return false; - - if(ys_int >= dsc->cfg.src_h) return false; - else if(ys_int < 0) return false; - - uint8_t px_size; - uint32_t pxi; - if(dsc->tmp.native_color) { - if(dsc->tmp.has_alpha == 0) { - px_size = LV_COLOR_SIZE >> 3; - - pxi = dsc->cfg.src_w * ys_int * px_size + xs_int * px_size; - lv_memcpy_small(&dsc->res.color, &src_u8[pxi], px_size); - } - else { - px_size = LV_IMG_PX_SIZE_ALPHA_BYTE; - pxi = dsc->cfg.src_w * ys_int * px_size + xs_int * px_size; - lv_memcpy_small(&dsc->res.color, &src_u8[pxi], px_size - 1); - dsc->res.opa = src_u8[pxi + px_size - 1]; - } - } - else { - pxi = 0; /*unused*/ - px_size = 0; /*unused*/ - dsc->res.color = lv_img_buf_get_px_color(&dsc->tmp.img_dsc, xs_int, ys_int, dsc->cfg.color); - dsc->res.opa = lv_img_buf_get_px_alpha(&dsc->tmp.img_dsc, xs_int, ys_int); - } - - if(dsc->tmp.chroma_keyed) { - lv_color_t ct = LV_COLOR_TRANSP; - if(dsc->res.color.full == ct.full) return false; - } - - if(dsc->cfg.antialias == false) return true; - - dsc->tmp.xs = xs; - dsc->tmp.ys = ys; - dsc->tmp.xs_int = xs_int; - dsc->tmp.ys_int = ys_int; - dsc->tmp.pxi = pxi; - dsc->tmp.px_size = px_size; - - bool ret; - ret = transform_anti_alias(dsc); - - return ret; -} /** * Get the area of a rectangle if its rotated and scaled @@ -606,10 +523,11 @@ void lv_img_buf_get_transformed_area(lv_area_t * res, lv_coord_t w, lv_coord_t h } -/********************** - * STATIC FUNCTIONS - **********************/ -static inline bool transform_anti_alias(lv_img_transform_dsc_t * dsc) +/** + * Continue transformation by taking the neighbors into account + * @param dsc pointer to the transformation descriptor + */ +bool _lv_img_buf_transform_anti_alias(lv_img_transform_dsc_t * dsc) { const uint8_t * src_u8 = dsc->cfg.src; @@ -724,3 +642,7 @@ static inline bool transform_anti_alias(lv_img_transform_dsc_t * dsc) return true; } +/********************** + * STATIC FUNCTIONS + **********************/ + diff --git a/src/lv_draw/lv_img_buf.h b/src/lv_draw/lv_img_buf.h index 66717e575..7666e2097 100644 --- a/src/lv_draw/lv_img_buf.h +++ b/src/lv_draw/lv_img_buf.h @@ -258,6 +258,12 @@ uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf); */ void lv_img_buf_transform_init(lv_img_transform_dsc_t * dsc); +/** + * Continue transformation by taking the neighbors into account + * @param dsc pointer to the transformation descriptor + */ +bool _lv_img_buf_transform_anti_alias(lv_img_transform_dsc_t * dsc); + /** * Get which color and opa would come to a pixel if it were rotated * @param dsc a descriptor initialized by `lv_img_buf_rotate_init` @@ -266,7 +272,85 @@ void lv_img_buf_transform_init(lv_img_transform_dsc_t * dsc); * @return true: there is valid pixel on these x/y coordinates; false: the rotated pixel was out of the image * @note the result is written back to `dsc->res_color` and `dsc->res_opa` */ -bool lv_img_buf_transform(lv_img_transform_dsc_t * dsc, lv_coord_t x, lv_coord_t y); +static inline bool lv_img_buf_transform(lv_img_transform_dsc_t * dsc, lv_coord_t x, lv_coord_t y) +{ + const uint8_t * src_u8 = dsc->cfg.src; + + /*Get the target point relative coordinates to the pivot*/ + int32_t xt = x - dsc->cfg.pivot_x; + int32_t yt = y - dsc->cfg.pivot_y; + + int32_t xs; + int32_t ys; + if(dsc->cfg.zoom == LV_IMG_ZOOM_NONE) { + /*Get the source pixel from the upscaled image*/ + xs = ((dsc->tmp.cosma * xt - dsc->tmp.sinma * yt) >> (LV_TRIGO_SHIFT - 8)) + dsc->tmp.pivot_x_256; + ys = ((dsc->tmp.sinma * xt + dsc->tmp.cosma * yt) >> (LV_TRIGO_SHIFT - 8)) + dsc->tmp.pivot_y_256; + } + else if(dsc->cfg.angle == 0) { + xt *= dsc->tmp.zoom_inv; + yt *= dsc->tmp.zoom_inv; + xs = xt + dsc->tmp.pivot_x_256; + ys = yt + dsc->tmp.pivot_y_256; + } else { + xt *= dsc->tmp.zoom_inv; + yt *= dsc->tmp.zoom_inv; + xs = ((dsc->tmp.cosma * xt - dsc->tmp.sinma * yt) >> (LV_TRIGO_SHIFT)) + dsc->tmp.pivot_x_256; + ys = ((dsc->tmp.sinma * xt + dsc->tmp.cosma * yt) >> (LV_TRIGO_SHIFT)) + dsc->tmp.pivot_y_256; + } + + /*Get the integer part of the source pixel*/ + int32_t xs_int = xs >> 8; + int32_t ys_int = ys >> 8; + + if(xs_int >= dsc->cfg.src_w) return false; + else if(xs_int < 0) return false; + + if(ys_int >= dsc->cfg.src_h) return false; + else if(ys_int < 0) return false; + + uint8_t px_size; + uint32_t pxi; + if(dsc->tmp.native_color) { + if(dsc->tmp.has_alpha == 0) { + px_size = LV_COLOR_SIZE >> 3; + + pxi = dsc->cfg.src_w * ys_int * px_size + xs_int * px_size; + lv_memcpy_small(&dsc->res.color, &src_u8[pxi], px_size); + } + else { + px_size = LV_IMG_PX_SIZE_ALPHA_BYTE; + pxi = dsc->cfg.src_w * ys_int * px_size + xs_int * px_size; + lv_memcpy_small(&dsc->res.color, &src_u8[pxi], px_size - 1); + dsc->res.opa = src_u8[pxi + px_size - 1]; + } + } + else { + pxi = 0; /*unused*/ + px_size = 0; /*unused*/ + dsc->res.color = lv_img_buf_get_px_color(&dsc->tmp.img_dsc, xs_int, ys_int, dsc->cfg.color); + dsc->res.opa = lv_img_buf_get_px_alpha(&dsc->tmp.img_dsc, xs_int, ys_int); + } + + if(dsc->tmp.chroma_keyed) { + lv_color_t ct = LV_COLOR_TRANSP; + if(dsc->res.color.full == ct.full) return false; + } + + if(dsc->cfg.antialias == false) return true; + + dsc->tmp.xs = xs; + dsc->tmp.ys = ys; + dsc->tmp.xs_int = xs_int; + dsc->tmp.ys_int = ys_int; + dsc->tmp.pxi = pxi; + dsc->tmp.px_size = px_size; + + bool ret; + ret = _lv_img_buf_transform_anti_alias(dsc); + + return ret; +} /** * Get the area of a rectangle if its rotated and scaled