From f066f0b8d8d9d47aabab7b81880632dd4dd58bb7 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 11 Aug 2020 10:09:31 +0200 Subject: [PATCH] fix overflow in large image transformations --- CHANGELOG.md | 1 + src/lv_draw/lv_img_buf.c | 24 ++++++++++++++++-------- src/lv_draw/lv_img_buf.h | 10 ++++++---- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 874bce62d..8e4b928be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - Fix setting local style property multiple times - Add missing background drawing and radius handling to image button - Allow adding extra label to list buttons +- Fix overflow in large image transformations ## v7.3.0 (04.08.2020) diff --git a/src/lv_draw/lv_img_buf.c b/src/lv_draw/lv_img_buf.c index 741ad0439..5ddf40577 100644 --- a/src/lv_draw/lv_img_buf.c +++ b/src/lv_draw/lv_img_buf.c @@ -435,6 +435,10 @@ void _lv_img_buf_transform_init(lv_img_transform_dsc_t * dsc) dsc->tmp.sinma = (s1 * (10 - angle_rem) + s2 * angle_rem) / 10; dsc->tmp.cosma = (c1 * (10 - angle_rem) + c2 * angle_rem) / 10; + /*Use smaller value to avoid overflow*/ + dsc->tmp.sinma = dsc->tmp.sinma >> (LV_TRIGO_SHIFT - _LV_TRANSFORM_TRIGO_SHIFT); + dsc->tmp.cosma = dsc->tmp.cosma >> (LV_TRIGO_SHIFT - _LV_TRANSFORM_TRIGO_SHIFT); + dsc->tmp.chroma_keyed = lv_img_cf_is_chroma_keyed(dsc->cfg.cf) ? 1 : 0; dsc->tmp.has_alpha = lv_img_cf_has_alpha(dsc->cfg.cf) ? 1 : 0; if(dsc->cfg.cf == LV_IMG_CF_TRUE_COLOR || dsc->cfg.cf == LV_IMG_CF_TRUE_COLOR_ALPHA || @@ -493,6 +497,10 @@ void _lv_img_buf_get_transformed_area(lv_area_t * res, lv_coord_t w, lv_coord_t int32_t sinma = (s1 * (10 - angle_rem) + s2 * angle_rem) / 10; int32_t cosma = (c1 * (10 - angle_rem) + c2 * angle_rem) / 10; + /*Use smaller value to avoid overflow*/ + sinma = sinma >> (LV_TRIGO_SHIFT - _LV_TRANSFORM_TRIGO_SHIFT); + cosma = cosma >> (LV_TRIGO_SHIFT - _LV_TRANSFORM_TRIGO_SHIFT); + lv_point_t lt; lv_point_t rt; lv_point_t lb; @@ -509,23 +517,23 @@ void _lv_img_buf_get_transformed_area(lv_area_t * res, lv_coord_t w, lv_coord_t xt = a.x1; yt = a.y1; - lt.x = ((cosma * xt - sinma * yt) >> LV_TRIGO_SHIFT) + pivot->x; - lt.y = ((sinma * xt + cosma * yt) >> LV_TRIGO_SHIFT) + pivot->y; + lt.x = ((cosma * xt - sinma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->x; + lt.y = ((sinma * xt + cosma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->y; xt = a.x2; yt = a.y1; - rt.x = ((cosma * xt - sinma * yt) >> LV_TRIGO_SHIFT) + pivot->x; - rt.y = ((sinma * xt + cosma * yt) >> LV_TRIGO_SHIFT) + pivot->y; + rt.x = ((cosma * xt - sinma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->x; + rt.y = ((sinma * xt + cosma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->y; xt = a.x1; yt = a.y2; - lb.x = ((cosma * xt - sinma * yt) >> LV_TRIGO_SHIFT) + pivot->x; - lb.y = ((sinma * xt + cosma * yt) >> LV_TRIGO_SHIFT) + pivot->y; + lb.x = ((cosma * xt - sinma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->x; + lb.y = ((sinma * xt + cosma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->y; xt = a.x2; yt = a.y2; - rb.x = ((cosma * xt - sinma * yt) >> LV_TRIGO_SHIFT) + pivot->x; - rb.y = ((sinma * xt + cosma * yt) >> LV_TRIGO_SHIFT) + pivot->y; + rb.x = ((cosma * xt - sinma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->x; + rb.y = ((sinma * xt + cosma * yt) >> _LV_TRANSFORM_TRIGO_SHIFT) + pivot->y; res->x1 = LV_MATH_MIN4(lb.x, lt.x, rb.x, rt.x); res->x2 = LV_MATH_MAX4(lb.x, lt.x, rb.x, rt.x); diff --git a/src/lv_draw/lv_img_buf.h b/src/lv_draw/lv_img_buf.h index afde70c55..d0d3991fc 100644 --- a/src/lv_draw/lv_img_buf.h +++ b/src/lv_draw/lv_img_buf.h @@ -48,6 +48,8 @@ extern "C" { #define LV_IMG_ZOOM_NONE 256 +#define _LV_TRANSFORM_TRIGO_SHIFT 10 + /********************** * TYPEDEFS **********************/ @@ -301,8 +303,8 @@ static inline bool _lv_img_buf_transform(lv_img_transform_dsc_t * dsc, lv_coord_ 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; + xs = ((dsc->tmp.cosma * xt - dsc->tmp.sinma * yt) >> (_LV_TRANSFORM_TRIGO_SHIFT - 8)) + dsc->tmp.pivot_x_256; + ys = ((dsc->tmp.sinma * xt + dsc->tmp.cosma * yt) >> (_LV_TRANSFORM_TRIGO_SHIFT - 8)) + dsc->tmp.pivot_y_256; } else if(dsc->cfg.angle == 0) { xt *= dsc->tmp.zoom_inv; @@ -313,8 +315,8 @@ static inline bool _lv_img_buf_transform(lv_img_transform_dsc_t * dsc, lv_coord_ 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; + xs = ((dsc->tmp.cosma * xt - dsc->tmp.sinma * yt) >> (_LV_TRANSFORM_TRIGO_SHIFT)) + dsc->tmp.pivot_x_256; + ys = ((dsc->tmp.sinma * xt + dsc->tmp.cosma * yt) >> (_LV_TRANSFORM_TRIGO_SHIFT)) + dsc->tmp.pivot_y_256; } /*Get the integer part of the source pixel*/