From cbe780de14411826de08d0754b7bde939566be12 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Mon, 4 Nov 2019 08:47:49 +0100 Subject: [PATCH] img rotate fixes --- src/lv_draw/lv_draw_img.c | 112 +++++++++++++++++++++----------------- src/lv_draw/lv_img_buf.c | 4 +- 2 files changed, 66 insertions(+), 50 deletions(-) diff --git a/src/lv_draw/lv_draw_img.c b/src/lv_draw/lv_draw_img.c index 71b8cb531..dd19247ae 100644 --- a/src/lv_draw/lv_draw_img.c +++ b/src/lv_draw/lv_draw_img.c @@ -191,52 +191,6 @@ lv_img_src_t lv_img_src_get_type(const void * src) static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mask, const void * src, const lv_style_t * style, uint16_t angle, lv_opa_t opa_scale) { - lv_area_t map_area_rot; - lv_area_copy(&map_area_rot, coords); - if(angle) { - /*Get the exact area which is required to show the rotated image*/ - lv_coord_t pivot_x = lv_area_get_width(coords) / 2 + coords->x1; - lv_coord_t pivot_y = lv_area_get_height(coords) / 2 + coords->y1; - - lv_area_t norm; - norm.x1 = + coords->x1 - pivot_x; - norm.y1 = + coords->y1 - pivot_y; - norm.x2 = + coords->x2 - pivot_x; - norm.y2 = + coords->y2 - pivot_y; - - int16_t sinma = lv_trigo_sin(-angle); - int16_t cosma = lv_trigo_sin(-angle + 90); - - lv_point_t lt; - lv_point_t rt; - lv_point_t lb; - lv_point_t rb; - lt.x = ((cosma * norm.x1 - sinma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_x; - lt.y = ((sinma * norm.x1 + cosma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_y; - - rt.x = ((cosma * norm.x2 - sinma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_x; - rt.y = ((sinma * norm.x2 + cosma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_y; - - lb.x = ((cosma * norm.x1 - sinma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_x; - lb.y = ((sinma * norm.x1 + cosma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_y; - - rb.x = ((cosma * norm.x2 - sinma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_x; - rb.y = ((sinma * norm.x2 + cosma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_y; - - map_area_rot.x1 = LV_MATH_MIN(LV_MATH_MIN(LV_MATH_MIN(lb.x, lt.x), rb.x), rt.x); - map_area_rot.x2 = LV_MATH_MAX(LV_MATH_MAX(LV_MATH_MAX(lb.x, lt.x), rb.x), rt.x); - map_area_rot.y1 = LV_MATH_MIN(LV_MATH_MIN(LV_MATH_MIN(lb.y, lt.y), rb.y), rt.y); - map_area_rot.y2 = LV_MATH_MAX(LV_MATH_MAX(LV_MATH_MAX(lb.y, lt.y), rb.y), rt.y); - } - - lv_area_t mask_com; /*Common area of mask and coords*/ - bool union_ok; - union_ok = lv_area_intersect(&mask_com, mask, &map_area_rot); - if(union_ok == false) { - return LV_RES_OK; /*Out of mask. There is nothing to draw so the image is drawn - successfully.*/ - } - lv_opa_t opa = opa_scale == LV_OPA_COVER ? style->image.opa : (uint16_t)((uint16_t)style->image.opa * opa_scale) >> 8; @@ -249,16 +203,70 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas if(cdsc->dec_dsc.error_msg != NULL) { LV_LOG_WARN("Image draw error"); - lv_draw_rect(coords, &mask_com, &lv_style_plain, LV_OPA_COVER); - lv_draw_label(coords, &mask_com, &lv_style_plain, LV_OPA_COVER, cdsc->dec_dsc.error_msg, LV_TXT_FLAG_NONE, NULL, NULL, NULL); + lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER); + lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, cdsc->dec_dsc.error_msg, LV_TXT_FLAG_NONE, NULL, NULL, NULL); } /* The decoder open could open the image and gave the entire uncompressed image. * Just draw it!*/ else if(cdsc->dec_dsc.img_data) { + lv_area_t map_area_rot; + lv_area_copy(&map_area_rot, coords); + if(angle) { + /*Get the exact area which is required to show the rotated image*/ + lv_coord_t pivot_x = lv_area_get_width(coords) / 2 + coords->x1; + lv_coord_t pivot_y = lv_area_get_height(coords) / 2 + coords->y1; + + lv_area_t norm; + norm.x1 = + coords->x1 - pivot_x; + norm.y1 = + coords->y1 - pivot_y; + norm.x2 = + coords->x2 - pivot_x; + norm.y2 = + coords->y2 - pivot_y; + + int16_t sinma = lv_trigo_sin(-angle); + int16_t cosma = lv_trigo_sin(-angle + 90); + + lv_point_t lt; + lv_point_t rt; + lv_point_t lb; + lv_point_t rb; + lt.x = ((cosma * norm.x1 - sinma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_x; + lt.y = ((sinma * norm.x1 + cosma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_y; + + rt.x = ((cosma * norm.x2 - sinma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_x; + rt.y = ((sinma * norm.x2 + cosma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_y; + + lb.x = ((cosma * norm.x1 - sinma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_x; + lb.y = ((sinma * norm.x1 + cosma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_y; + + rb.x = ((cosma * norm.x2 - sinma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_x; + rb.y = ((sinma * norm.x2 + cosma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_y; + + map_area_rot.x1 = LV_MATH_MIN(LV_MATH_MIN(LV_MATH_MIN(lb.x, lt.x), rb.x), rt.x); + map_area_rot.x2 = LV_MATH_MAX(LV_MATH_MAX(LV_MATH_MAX(lb.x, lt.x), rb.x), rt.x); + map_area_rot.y1 = LV_MATH_MIN(LV_MATH_MIN(LV_MATH_MIN(lb.y, lt.y), rb.y), rt.y); + map_area_rot.y2 = LV_MATH_MAX(LV_MATH_MAX(LV_MATH_MAX(lb.y, lt.y), rb.y), rt.y); + } + + lv_area_t mask_com; /*Common area of mask and coords*/ + bool union_ok; + union_ok = lv_area_intersect(&mask_com, mask, &map_area_rot); + if(union_ok == false) { + return LV_RES_OK; /*Out of mask. There is nothing to draw so the image is drawn + successfully.*/ + } + lv_draw_map(coords, &mask_com, cdsc->dec_dsc.img_data, opa, chroma_keyed, alpha_byte, style, angle); } /* The whole uncompressed image is not available. Try to read it line-by-line*/ else { + lv_area_t mask_com; /*Common area of mask and coords*/ + bool union_ok; + union_ok = lv_area_intersect(&mask_com, mask, coords); + if(union_ok == false) { + return LV_RES_OK; /*Out of mask. There is nothing to draw so the image is drawn + successfully.*/ + } + lv_coord_t width = lv_area_get_width(&mask_com); uint8_t * buf = lv_draw_buf_get(lv_area_get_width(&mask_com) * LV_IMG_PX_SIZE_ALPHA_BYTE); /*+1 because of the possible alpha byte*/ @@ -271,6 +279,10 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas lv_coord_t row; lv_res_t read_res; for(row = mask_com.y1; row <= mask_com.y2; row++) { + lv_area_t mask_line; + union_ok = lv_area_intersect(&mask_line, mask, &line); + if(union_ok == false) continue; + read_res = lv_img_decoder_read_line(&cdsc->dec_dsc, x, y, width, buf); if(read_res != LV_RES_OK) { lv_img_decoder_close(&cdsc->dec_dsc); @@ -278,7 +290,9 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas lv_draw_buf_release(buf); return LV_RES_INV; } - lv_draw_map(&line, &mask_com, buf, opa, chroma_keyed, alpha_byte, style, 0); + + + lv_draw_map(&line, &mask_line, buf, opa, chroma_keyed, alpha_byte, style, 0); line.y1++; line.y2++; y++; diff --git a/src/lv_draw/lv_img_buf.c b/src/lv_draw/lv_img_buf.c index fdde8922f..0ada27708 100644 --- a/src/lv_draw/lv_img_buf.c +++ b/src/lv_draw/lv_img_buf.c @@ -7,7 +7,9 @@ * INCLUDES *********************/ #include +#include #include "lv_img_buf.h" +#include "lv_draw_img.h" #include "../lv_misc/lv_math.h" #include "../lv_misc/lv_log.h" @@ -459,7 +461,7 @@ bool lv_img_buf_get_px_rotated(lv_img_rotate_dsc_t * dsc, lv_coord_t x, lv_coord if(dsc->native_color) { memcpy(&c_dest_yn, &src_u8[px - px_size * dsc->src_w], sizeof(lv_color_t)); - if(dsc->has_alpha) opa_dest_yn = src_u8[px - px_size * dsc->src_w - 1]; + if(dsc->has_alpha) opa_dest_yn = src_u8[px - px_size * dsc->src_w + px_size- 1]; } else { c_dest_yn = lv_img_buf_get_px_color(&dsc->img_dsc, yn, y, dsc->color); if(dsc->has_alpha) opa_dest_yn = lv_img_buf_get_px_alpha(&dsc->img_dsc, yn, y);