From 05da56c839e370d7d292c6cc1c9bab3e9e167b0f Mon Sep 17 00:00:00 2001 From: TridentTD Date: Sat, 2 Nov 2019 20:17:45 +0700 Subject: [PATCH 01/17] fix rounded-ending arc --- src/lv_objx/lv_arc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/lv_objx/lv_arc.c b/src/lv_objx/lv_arc.c index a95371ac6..85af1c33c 100644 --- a/src/lv_objx/lv_arc.c +++ b/src/lv_objx/lv_arc.c @@ -243,8 +243,8 @@ static lv_design_res_t lv_arc_design(lv_obj_t * arc, const lv_area_t * clip_area /*Draw circle on the ends if enabled */ if(style->line.rounded) { lv_coord_t thick_half = style->line.width / 2; - lv_coord_t cir_x = ((r - thick_half) * lv_trigo_sin(ext->angle_start) >> LV_TRIGO_SHIFT); - lv_coord_t cir_y = ((r - thick_half) * lv_trigo_sin(ext->angle_start + 90) >> LV_TRIGO_SHIFT); + lv_coord_t cir_x = ((r - thick_half + 1) * lv_trigo_sin(90 - ext->angle_start) >> LV_TRIGO_SHIFT); + lv_coord_t cir_y = ((r - thick_half + 1) * lv_trigo_sin(ext->angle_start) >> LV_TRIGO_SHIFT); lv_style_t cir_style; lv_style_copy(&cir_style, &lv_style_plain); @@ -252,18 +252,18 @@ static lv_design_res_t lv_arc_design(lv_obj_t * arc, const lv_area_t * clip_area cir_style.body.main_color = cir_style.body.grad_color; cir_style.body.radius = LV_RADIUS_CIRCLE; lv_area_t cir_area; - cir_area.x1 = cir_x + x - thick_half; - cir_area.y1 = cir_y + y - thick_half; + cir_area.x1 = cir_x + x - thick_half +1; + cir_area.y1 = cir_y + y - thick_half +1; cir_area.x2 = cir_x + x + thick_half; cir_area.y2 = cir_y + y + thick_half; lv_draw_rect(&cir_area, clip_area, &cir_style, opa_scale); - cir_x = ((r - thick_half) * lv_trigo_sin(ext->angle_end) >> LV_TRIGO_SHIFT); - cir_y = ((r - thick_half) * lv_trigo_sin(ext->angle_end + 90) >> LV_TRIGO_SHIFT); + cir_x = ((r - thick_half + 1) * lv_trigo_sin(90 - ext->angle_end) >> LV_TRIGO_SHIFT); + cir_y = ((r - thick_half + 1) * lv_trigo_sin(ext->angle_end) >> LV_TRIGO_SHIFT); - cir_area.x1 = cir_x + x - thick_half; - cir_area.y1 = cir_y + y - thick_half; + cir_area.x1 = cir_x + x - thick_half +1; + cir_area.y1 = cir_y + y - thick_half +1; cir_area.x2 = cir_x + x + thick_half; cir_area.y2 = cir_y + y + thick_half; From 9f5fc99c9b6d443dc8d5b5525c892033ea064c22 Mon Sep 17 00:00:00 2001 From: TridentTD Date: Tue, 5 Nov 2019 17:37:32 +0700 Subject: [PATCH 02/17] remove rounded-ending in lv_arc.c --- src/lv_objx/lv_arc.c | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/src/lv_objx/lv_arc.c b/src/lv_objx/lv_arc.c index 85af1c33c..88f16089c 100644 --- a/src/lv_objx/lv_arc.c +++ b/src/lv_objx/lv_arc.c @@ -239,37 +239,6 @@ static lv_design_res_t lv_arc_design(lv_obj_t * arc, const lv_area_t * clip_area lv_coord_t y = arc->coords.y1 + lv_obj_get_height(arc) / 2; lv_opa_t opa_scale = lv_obj_get_opa_scale(arc); lv_draw_arc(x, y, r, clip_area, ext->angle_start, ext->angle_end, style, opa_scale); - - /*Draw circle on the ends if enabled */ - if(style->line.rounded) { - lv_coord_t thick_half = style->line.width / 2; - lv_coord_t cir_x = ((r - thick_half + 1) * lv_trigo_sin(90 - ext->angle_start) >> LV_TRIGO_SHIFT); - lv_coord_t cir_y = ((r - thick_half + 1) * lv_trigo_sin(ext->angle_start) >> LV_TRIGO_SHIFT); - - lv_style_t cir_style; - lv_style_copy(&cir_style, &lv_style_plain); - cir_style.body.grad_color = style->line.color; - cir_style.body.main_color = cir_style.body.grad_color; - cir_style.body.radius = LV_RADIUS_CIRCLE; - lv_area_t cir_area; - cir_area.x1 = cir_x + x - thick_half +1; - cir_area.y1 = cir_y + y - thick_half +1; - cir_area.x2 = cir_x + x + thick_half; - cir_area.y2 = cir_y + y + thick_half; - - lv_draw_rect(&cir_area, clip_area, &cir_style, opa_scale); - - cir_x = ((r - thick_half + 1) * lv_trigo_sin(90 - ext->angle_end) >> LV_TRIGO_SHIFT); - cir_y = ((r - thick_half + 1) * lv_trigo_sin(ext->angle_end) >> LV_TRIGO_SHIFT); - - cir_area.x1 = cir_x + x - thick_half +1; - cir_area.y1 = cir_y + y - thick_half +1; - cir_area.x2 = cir_x + x + thick_half; - cir_area.y2 = cir_y + y + thick_half; - - lv_draw_rect(&cir_area, clip_area, &cir_style, opa_scale); - } - } /*Post draw when the children are drawn*/ else if(mode == LV_DESIGN_DRAW_POST) { From 60148c5c73acc6ce7f340840c9e202677c2211ba Mon Sep 17 00:00:00 2001 From: TridentTD Date: Tue, 5 Nov 2019 17:40:02 +0700 Subject: [PATCH 03/17] move round-ending from lv_arc.c to lv_draw_arc.c --- src/lv_draw/lv_draw_arc.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/lv_draw/lv_draw_arc.c b/src/lv_draw/lv_draw_arc.c index 7b10df6f8..3590b6ff0 100644 --- a/src/lv_draw/lv_draw_arc.c +++ b/src/lv_draw/lv_draw_arc.c @@ -69,8 +69,34 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons lv_draw_mask_remove_id(mask_angle_id); + // draw rounded-ending if(style->line.rounded) { - /*TODO*/ + circle_style.body.main_color = style->line.color; + circle_style.body.grad_color = style->line.color; + circle_style.body.opa = LV_OPA_COVER; + circle_style.body.border.width = 0; + + lv_coord_t thick_half = style->line.width / 2; + lv_coord_t cir_x = ((radius - thick_half + 1) * lv_trigo_sin(90 - start_angle) >> LV_TRIGO_SHIFT); + lv_coord_t cir_y = ((radius - thick_half + 1) * lv_trigo_sin(start_angle) >> LV_TRIGO_SHIFT); + + lv_area_t round_area; + round_area.x1 = cir_x + center_x - thick_half + 1; + round_area.y1 = cir_y + center_y - thick_half + 1; + round_area.x2 = cir_x + center_x + thick_half; + round_area.y2 = cir_y + center_y + thick_half; + + lv_draw_rect(&round_area, clip_area, &circle_style, LV_OPA_COVER); + + cir_x = ((radius - thick_half + 1) * lv_trigo_sin(90 - end_angle) >> LV_TRIGO_SHIFT); + cir_y = ((radius - thick_half + 1) * lv_trigo_sin(end_angle) >> LV_TRIGO_SHIFT); + + round_area.x1 = cir_x + center_x - thick_half + 1; + round_area.y1 = cir_y + center_y - thick_half + 1; + round_area.x2 = cir_x + center_x + thick_half; + round_area.y2 = cir_y + center_y + thick_half; + + lv_draw_rect(&round_area, clip_area, &circle_style, LV_OPA_COVER); } } From 93f5f69f7321c7c6a5dc82f0540fc79439002eab Mon Sep 17 00:00:00 2001 From: TridentTD Date: Tue, 5 Nov 2019 17:44:05 +0700 Subject: [PATCH 04/17] move rounded-ending from lv_arc.c to lv_draw.arc.c --- src/lv_draw/lv_draw_arc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_draw/lv_draw_arc.c b/src/lv_draw/lv_draw_arc.c index 3590b6ff0..010831740 100644 --- a/src/lv_draw/lv_draw_arc.c +++ b/src/lv_draw/lv_draw_arc.c @@ -8,6 +8,7 @@ *********************/ #include "lv_draw_arc.h" #include "lv_draw_mask.h" +#include "../lv_misc/lv_math.h" // LV_TRIGO_SHIFT /********************* * DEFINES @@ -69,7 +70,6 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons lv_draw_mask_remove_id(mask_angle_id); - // draw rounded-ending if(style->line.rounded) { circle_style.body.main_color = style->line.color; circle_style.body.grad_color = style->line.color; From 1e685324cfa5aeda398de15ff1747aaae8482f0c Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Thu, 7 Nov 2019 05:38:40 +0100 Subject: [PATCH 05/17] add lv_img_buf_get_px() --- src/lv_draw/lv_img_buf.c | 257 +++++++++++++++++++-------------------- src/lv_draw/lv_img_buf.h | 11 +- src/lv_objx/lv_canvas.c | 76 ++++++------ 3 files changed, 173 insertions(+), 171 deletions(-) diff --git a/src/lv_draw/lv_img_buf.c b/src/lv_draw/lv_img_buf.c index 433d1a04b..5cf84972c 100644 --- a/src/lv_draw/lv_img_buf.c +++ b/src/lv_draw/lv_img_buf.c @@ -37,6 +37,7 @@ * GLOBAL FUNCTIONS **********************/ + /** * Get the color of an image's pixel * @param dsc an image descriptor @@ -47,26 +48,8 @@ * @param safe true: check out of bounds * @return color of the point */ -lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color, bool safe) +lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color) { - if(safe) { - if(x >= dsc->header.w) { - x = dsc->header.w - 1; - LV_LOG_WARN("lv_img_buf_get_px_color: x is too large"); - } else if(x < 0) { - x = 0; - LV_LOG_WARN("lv_img_buf_get_px_color: x is < 0"); - } - - if(y >= dsc->header.h) { - y = dsc->header.h - 1; - LV_LOG_WARN("lv_img_buf_get_px_color: y is too large"); - } else if(y < 0) { - y = 0; - LV_LOG_WARN("lv_img_buf_get_px_color: y is < 0"); - } - } - lv_color_t p_color = LV_COLOR_BLACK; uint8_t * buf_u8 = (uint8_t *)dsc->data; @@ -114,7 +97,7 @@ lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t p_color.full = buf_u8[px]; } else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT || dsc->header.cf == LV_IMG_CF_ALPHA_2BIT || dsc->header.cf == LV_IMG_CF_ALPHA_4BIT || dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) { - p_color = color; + p_color = color; } return p_color; } @@ -127,26 +110,8 @@ lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t * @param safe true: check out of bounds * @return alpha value of the point */ -lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, bool safe) +lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y) { - if(safe) { - if(x >= dsc->header.w) { - x = dsc->header.w - 1; - LV_LOG_WARN("lv_img_buf_get_px_alpha: x is too large"); - } else if(x < 0) { - x = 0; - LV_LOG_WARN("lv_img_buf_get_px_alpha: x is < 0"); - } - - if(y >= dsc->header.h) { - y = dsc->header.h - 1; - LV_LOG_WARN("lv_img_buf_get_px_alpha: y is too large"); - } else if(y < 0) { - y = 0; - LV_LOG_WARN("lv_img_buf_get_px_alpha: y is < 0"); - } - } - uint8_t * buf_u8 = (uint8_t *)dsc->data; if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) { @@ -195,6 +160,118 @@ lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, return LV_OPA_COVER; } +/** + * Get the color of an image's pixel + * @param dsc an image descriptor + * @param x x coordinate of the point to get + * @param y x coordinate of the point to get + * @param color the color of the image. In case of `LV_IMG_CF_ALPHA_1/2/4/8` this color is used. + * Not used in other cases. + * @param safe true: check out of bounds + * @return color of the point + */ +void lv_img_buf_get_px(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_color_t * px_color, lv_opa_t * px_opa) +{ + uint8_t * buf_u8 = (uint8_t *)dsc->data; + + if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { + uint32_t px = dsc->header.w * y * sizeof(lv_color_t) + x * sizeof(lv_color_t); + memcpy(px_color, &buf_u8[px], sizeof(lv_color_t)); + *px_opa = LV_OPA_COVER; + } else if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) { + uint32_t px = dsc->header.w * y * LV_IMG_PX_SIZE_ALPHA_BYTE + x * LV_IMG_PX_SIZE_ALPHA_BYTE; + memcpy(px_color, &buf_u8[px], sizeof(lv_color_t)); + *px_opa = buf_u8[px + LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; +#if LV_COLOR_SIZE == 32 + p_color.ch.alpha = 0xFF; /*Only the color should be get so use a default alpha value*/ +#endif + } else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT) { + buf_u8 += 4 * 2; + uint8_t bit = x & 0x7; + x = x >> 3; + + /* Get the current pixel. + * dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned + * so the possible real width are 8, 16, 24 ...*/ + uint32_t px = ((dsc->header.w + 7) >> 3) * y + x; + px_color->full = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit); + *px_opa = LV_OPA_COVER; + } else if(dsc->header.cf == LV_IMG_CF_INDEXED_2BIT) { + buf_u8 += 4 * 4; + uint8_t bit = (x & 0x3) * 2; + x = x >> 2; + + /* Get the current pixel. + * dsc->header.w + 3 means rounding up to 4 because the lines are byte aligned + * so the possible real width are 4, 8, 12 ...*/ + uint32_t px = ((dsc->header.w + 3) >> 2) * y + x; + px_color->full = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit); + *px_opa = LV_OPA_COVER; + } else if(dsc->header.cf == LV_IMG_CF_INDEXED_4BIT) { + buf_u8 += 4 * 16; + uint8_t bit = (x & 0x1) * 4; + x = x >> 1; + + /* Get the current pixel. + * dsc->header.w + 1 means rounding up to 2 because the lines are byte aligned + * so the possible real width are 2, 4, 6 ...*/ + uint32_t px = ((dsc->header.w + 1) >> 1) * y + x; + px_color->full = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit); + *px_opa = LV_OPA_COVER; + } else if(dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) { + buf_u8 += 4 * 256; + uint32_t px = dsc->header.w * y + x; + px_color->full = buf_u8[px]; + } else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT || dsc->header.cf == LV_IMG_CF_ALPHA_2BIT || + dsc->header.cf == LV_IMG_CF_ALPHA_4BIT || dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) { + *px_color = color; + *px_opa = LV_OPA_COVER; + } else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT) { + uint8_t bit = x & 0x7; + x = x >> 3; + + /* Get the current pixel. + * dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned + * so the possible real width are 8 ,16, 24 ...*/ + uint32_t px = ((dsc->header.w + 7) >> 3) * y + x; + uint8_t tmp = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit); + *px_opa = tmp ? LV_OPA_TRANSP : LV_OPA_COVER; + *px_color = color; + } else if(dsc->header.cf == LV_IMG_CF_ALPHA_2BIT) { + const uint8_t opa_table[4] = {0, 85, 170, 255}; /*Opacity mapping with bpp = 2*/ + + uint8_t bit = (x & 0x3) * 2; + x = x >> 2; + + /* Get the current pixel. + * dsc->header.w + 4 means rounding up to 8 because the lines are byte aligned + * so the possible real width are 4 ,8, 12 ...*/ + uint32_t px = ((dsc->header.w + 3) >> 2) * y + x; + uint8_t tmp = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit); + *px_opa = opa_table[tmp]; + *px_color = color; + } else if(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT) { + const uint8_t opa_table[16] = {0, 17, 34, 51, /*Opacity mapping with bpp = 4*/ + 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255}; + + uint8_t bit = (x & 0x1) * 4; + x = x >> 1; + + /* Get the current pixel. + * dsc->header.w + 1 means rounding up to 8 because the lines are byte aligned + * so the possible real width are 2 ,4, 6 ...*/ + uint32_t px = ((dsc->header.w + 1) >> 1) * y + x; + uint8_t tmp = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit); + *px_opa = opa_table[tmp]; + *px_color = color; + } else if(dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) { + uint32_t px = dsc->header.w * y + x; + *px_opa = buf_u8[px]; + *px_color = color; + } +} + + /** * Set the color of a pixel of an image. The alpha channel won't be affected. * @param dsc pointer to an image descriptor @@ -203,26 +280,8 @@ lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, * @param c color of the point * @param safe true: check out of bounds */ -void lv_img_buf_set_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t c, bool safe) +void lv_img_buf_set_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t c) { - if(safe) { - if(x >= dsc->header.w) { - x = dsc->header.w - 1; - LV_LOG_WARN("lv_img_buf_set_px_color: x is too large"); - } else if(x < 0) { - x = 0; - LV_LOG_WARN("lv_img_buf_set_px_color: x is < 0"); - } - - if(y >= dsc->header.h) { - y = dsc->header.h - 1; - LV_LOG_WARN("lv_img_buf_set_px_color: y is too large"); - } else if(y < 0) { - y = 0; - LV_LOG_WARN("lv_img_buf_set_px_color: y is < 0"); - } - } - uint8_t * buf_u8 = (uint8_t *)dsc->data; if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { @@ -283,26 +342,8 @@ void lv_img_buf_set_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_ * @param opa the desired opacity * @param safe true: check out of bounds */ -void lv_img_buf_set_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_opa_t opa, bool safe) +void lv_img_buf_set_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_opa_t opa) { - if(safe) { - if(x >= dsc->header.w) { - x = dsc->header.w - 1; - LV_LOG_WARN("lv_img_buf_set_px_alpha: x is too large"); - } else if(x < 0) { - x = 0; - LV_LOG_WARN("lv_img_buf_set_px_alpha: x is < 0"); - } - - if(y >= dsc->header.h) { - y = dsc->header.h - 1; - LV_LOG_WARN("lv_img_buf_set_px_alpha: y is too large"); - } else if(y < 0) { - y = 0; - LV_LOG_WARN("lv_img_buf_set_px_alpha: y is < 0"); - } - } - uint8_t * buf_u8 = (uint8_t *)dsc->data; if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) { @@ -463,7 +504,7 @@ uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf) * @param color a color used for `LV_IMG_CF_INDEXED_1/2/4/8BIT` color formats */ void lv_img_buf_rotate_init(lv_img_rotate_dsc_t * dsc, int16_t angle, const void * src, lv_coord_t src_w, lv_coord_t src_h, - lv_img_cf_t cf, lv_coord_t pivot_x, lv_coord_t pivot_y, lv_color_t color) + lv_img_cf_t cf, lv_coord_t pivot_x, lv_coord_t pivot_y, lv_color_t color) { memset(dsc, 0x00, sizeof(lv_img_rotate_dsc_t)); @@ -505,12 +546,15 @@ void lv_img_buf_rotate_init(lv_img_rotate_dsc_t * dsc, int16_t angle, const void */ bool lv_img_buf_get_px_rotated(lv_img_rotate_dsc_t * dsc, lv_coord_t x, lv_coord_t y) { - const uint8_t * src_u8 = dsc->src; /*Get the target point relative coordinates to the pivot*/ int32_t xt = x - dsc->pivot_x; int32_t yt = y - dsc->pivot_y; + + // xt = xt / 2; + // yt = yt / 2; + /*Get the source pixel from the upscaled image*/ int32_t xs = ((dsc->cosma * xt - dsc->sinma * yt) >> (LV_TRIGO_SHIFT - 8)) + dsc->pivot_x_256; int32_t ys = ((dsc->sinma * xt + dsc->cosma * yt) >> (LV_TRIGO_SHIFT - 8)) + dsc->pivot_y_256; @@ -536,27 +580,7 @@ bool lv_img_buf_get_px_rotated(lv_img_rotate_dsc_t * dsc, lv_coord_t x, lv_coord lv_color_t c_dest_int; lv_opa_t opa_dest_int = 0; - uint8_t px_size; - uint32_t px; - if(dsc->native_color) { - if(dsc->has_alpha == 0) { - px_size = LV_COLOR_SIZE >> 3; - - px = dsc->src_w * ys_int * px_size + xs_int * px_size; - memcpy(&c_dest_int, &src_u8[px], px_size); - } else { - px_size = LV_IMG_PX_SIZE_ALPHA_BYTE; - px = dsc->src_w * ys_int * px_size + xs_int * px_size; - memcpy(&c_dest_int, &src_u8[px], px_size - 1); - opa_dest_int = src_u8[px + px_size - 1]; - } - } else { - px = 0; /*unused*/ - px_size = 0; /*unused*/ - c_dest_int = lv_img_buf_get_px_color(&dsc->img_dsc, xs_int, ys_int, dsc->color, false); - opa_dest_int = lv_img_buf_get_px_alpha(&dsc->img_dsc, xs_int, ys_int, false); - } - + lv_img_buf_get_px(&dsc->img_dsc, xs_int, ys_int, dsc->color, &c_dest_int, &opa_dest_int); if(dsc->chroma_keyed) { lv_color_t ct = LV_COLOR_TRANSP; @@ -579,14 +603,7 @@ bool lv_img_buf_get_px_rotated(lv_img_rotate_dsc_t * dsc, lv_coord_t x, lv_coord if(xn < 0) return false; xr = xs_fract + 0x80; - - if(dsc->native_color) { - memcpy(&c_dest_xn, &src_u8[px - px_size], sizeof(lv_color_t)); - if(dsc->has_alpha) opa_dest_xn = src_u8[px - 1]; - } else { - c_dest_xn = lv_img_buf_get_px_color(&dsc->img_dsc, xn, ys_int, dsc->color, false); - if(dsc->has_alpha) opa_dest_xn = lv_img_buf_get_px_alpha(&dsc->img_dsc, xn, ys_int, false); - } + lv_img_buf_get_px(&dsc->img_dsc, xn, ys_int, dsc->color, &c_dest_xn, &opa_dest_xn); c_x_dest = lv_color_mix(c_dest_int, c_dest_xn, xr); if(dsc->has_alpha) opa_x_dest = (opa_dest_int * xr + (opa_dest_xn * (255 - xr))) >> 8; @@ -597,13 +614,7 @@ bool lv_img_buf_get_px_rotated(lv_img_rotate_dsc_t * dsc, lv_coord_t x, lv_coord xr = (0xFF - xs_fract) + 0x80; - if(dsc->native_color) { - memcpy(&c_dest_xn, &src_u8[px + px_size], sizeof(lv_color_t)); - if(dsc->has_alpha) opa_dest_xn = src_u8[px + 2 * px_size - 1]; - } else { - c_dest_xn = lv_img_buf_get_px_color(&dsc->img_dsc, xn, ys_int, dsc->color, false); - if(dsc->has_alpha) opa_dest_xn = lv_img_buf_get_px_alpha(&dsc->img_dsc, xn, ys_int, false); - } + lv_img_buf_get_px(&dsc->img_dsc, xn, ys_int, dsc->color, &c_dest_xn, &opa_dest_xn); c_x_dest = lv_color_mix(c_dest_int, c_dest_xn, xr); if(dsc->has_alpha) opa_x_dest = (opa_dest_int * xr + (opa_dest_xn * (255 - xr))) >> 8; @@ -625,13 +636,7 @@ bool lv_img_buf_get_px_rotated(lv_img_rotate_dsc_t * dsc, lv_coord_t x, lv_coord yr = ys_fract + 0x80; - 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 + px_size- 1]; - } else { - c_dest_yn = lv_img_buf_get_px_color(&dsc->img_dsc, xs_int, yn, dsc->color, false); - if(dsc->has_alpha) opa_dest_yn = lv_img_buf_get_px_alpha(&dsc->img_dsc, xs_int, yn, false); - } + lv_img_buf_get_px(&dsc->img_dsc, xs_int, yn, dsc->color, &c_dest_yn, &opa_dest_yn); c_y_dest = lv_color_mix(c_dest_int, c_dest_yn, yr); if(dsc->has_alpha) opa_y_dest = (opa_dest_int * yr + (opa_dest_yn * (255 - yr))) >> 8; @@ -642,13 +647,7 @@ bool lv_img_buf_get_px_rotated(lv_img_rotate_dsc_t * dsc, lv_coord_t x, lv_coord yr = (0xFF - ys_fract) + 0x80; - 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 + 2 * px_size - 1]; - } else { - c_dest_yn = lv_img_buf_get_px_color(&dsc->img_dsc, xs_int, yn, dsc->color, false); - if(dsc->has_alpha) opa_dest_yn = lv_img_buf_get_px_alpha(&dsc->img_dsc, xs_int, yn, false); - } + lv_img_buf_get_px(&dsc->img_dsc, xs_int, yn, dsc->color, &c_dest_yn, &opa_dest_yn); c_y_dest = lv_color_mix(c_dest_int, c_dest_yn, yr); if(dsc->has_alpha) opa_y_dest = (opa_dest_int * yr + (opa_dest_yn * (255 - yr))) >> 8; diff --git a/src/lv_draw/lv_img_buf.h b/src/lv_draw/lv_img_buf.h index 41f33af5b..787865d14 100644 --- a/src/lv_draw/lv_img_buf.h +++ b/src/lv_draw/lv_img_buf.h @@ -173,7 +173,7 @@ lv_img_dsc_t *lv_img_buf_alloc(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf); * @param safe true: check out of bounds * @return color of the point */ -lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color, bool safe); +lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color); /** * Get the alpha value of an image's pixel @@ -183,7 +183,10 @@ lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t * @param safe true: check out of bounds * @return alpha value of the point */ -lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, bool safe); +lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y); + + +void lv_img_buf_get_px(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_color_t * px_color, lv_opa_t * px_opa); /** * Set the color of a pixel of an image. The alpha channel won't be affected. @@ -193,7 +196,7 @@ lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, * @param c color of the point * @param safe true: check out of bounds */ -void lv_img_buf_set_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t c, bool safe); +void lv_img_buf_set_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t c); /** * Set the alpha value of a pixel of an image. The color won't be affected @@ -203,7 +206,7 @@ void lv_img_buf_set_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_ * @param opa the desired opacity * @param safe true: check out of bounds */ -void lv_img_buf_set_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_opa_t opa, bool safe); +void lv_img_buf_set_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_opa_t opa); /** * Set the palette color of an indexed image. Valid only for `LV_IMG_CF_INDEXED1/2/4/8` diff --git a/src/lv_objx/lv_canvas.c b/src/lv_objx/lv_canvas.c index 50f2b7c1d..4a0e04327 100644 --- a/src/lv_objx/lv_canvas.c +++ b/src/lv_objx/lv_canvas.c @@ -159,7 +159,7 @@ void lv_canvas_set_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_color_t lv_canvas_ext_t * ext = lv_obj_get_ext_attr(canvas); - lv_img_buf_set_px_color(&ext->dsc, x, y, c, true); + lv_img_buf_set_px_color(&ext->dsc, x, y, c); lv_obj_invalidate(canvas); } @@ -218,7 +218,7 @@ lv_color_t lv_canvas_get_px(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y) if(style == NULL) style = &lv_style_scr; - return lv_img_buf_get_px_color(&ext->dsc, x, y, style->image.color, true); + return lv_img_buf_get_px_color(&ext->dsc, x, y, style->image.color); } /** @@ -333,30 +333,30 @@ void lv_canvas_rotate(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, lv_c if(x + offset_x >= 0 && x + offset_x < dest_width && y + offset_y >= 0 && y + offset_y < dest_height) { /*If the image has no alpha channel just simple set the result color on the canvas*/ if(lv_img_cf_has_alpha(img->header.cf) == false) { - lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res_color, false); + lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res_color); } else { - lv_color_t bg_color = lv_img_buf_get_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, style->image.color, false); + lv_color_t bg_color = lv_img_buf_get_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, style->image.color); /*If the canvas has no alpha but the image has mix the image's color with * canvas*/ if(lv_img_cf_has_alpha(ext_dst->dsc.header.cf) == false) { if(dsc.res_opa < LV_OPA_MAX) dsc.res_color = lv_color_mix(dsc.res_color, bg_color, dsc.res_opa); - lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res_color, false); + lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res_color); } /*Both the image and canvas has alpha channel. Some extra calculation is required*/ else { - lv_opa_t bg_opa = lv_img_buf_get_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y, false); + lv_opa_t bg_opa = lv_img_buf_get_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y); /* Pick the foreground if it's fully opaque or the Background is fully * transparent*/ if(dsc.res_opa >= LV_OPA_MAX || bg_opa <= LV_OPA_MIN) { - lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res_color, false); - lv_img_buf_set_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res_opa, false); + lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res_color); + lv_img_buf_set_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res_opa); } /*Opaque background: use simple mix*/ else if(bg_opa >= LV_OPA_MAX) { lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, - lv_color_mix(dsc.res_color, bg_color, dsc.res_opa), false); + lv_color_mix(dsc.res_color, bg_color, dsc.res_opa)); } /*Both colors have alpha. Expensive calculation need to be applied*/ else { @@ -370,8 +370,8 @@ void lv_canvas_rotate(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, lv_c lv_opa_t ratio = (uint16_t)((uint16_t)dsc.res_opa * 255) / opa_res_2; lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, - lv_color_mix(dsc.res_color, bg_color, ratio), false); - lv_img_buf_set_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y, opa_res_2, false); + lv_color_mix(dsc.res_color, bg_color, ratio)); + lv_img_buf_set_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y, opa_res_2); } } } @@ -449,8 +449,8 @@ void lv_canvas_blur_hor(lv_obj_t * canvas, const lv_area_t * area, uint16_t r) x_safe = x < 0 ? 0 : x; x_safe = x_safe > ext->dsc.header.w - 1 ? ext->dsc.header.w - 1 : x_safe; - c = lv_img_buf_get_px_color(&line_img, x_safe, 0, style->image.color, false); - if(has_alpha) opa = lv_img_buf_get_px_alpha(&line_img, x_safe, 0, false); + c = lv_img_buf_get_px_color(&line_img, x_safe, 0, style->image.color); + if(has_alpha) opa = lv_img_buf_get_px_alpha(&line_img, x_safe, 0); rsum += c.ch.red; #if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP @@ -479,14 +479,14 @@ void lv_canvas_blur_hor(lv_obj_t * canvas, const lv_area_t * area, uint16_t r) c.ch.blue = bsum / r; if(has_alpha) opa = asum / r; - lv_img_buf_set_px_color(&ext->dsc, x, y, c, false); + lv_img_buf_set_px_color(&ext->dsc, x, y, c); } - if(has_alpha) lv_img_buf_set_px_alpha(&ext->dsc, x, y, opa, false); + if(has_alpha) lv_img_buf_set_px_alpha(&ext->dsc, x, y, opa); x_safe = x - r_back; x_safe = x_safe < 0 ? 0 : x_safe; - c = lv_img_buf_get_px_color(&line_img, x_safe, 0, style->image.color, false); - if(has_alpha) opa = lv_img_buf_get_px_alpha(&line_img, x_safe, 0, false); + c = lv_img_buf_get_px_color(&line_img, x_safe, 0, style->image.color); + if(has_alpha) opa = lv_img_buf_get_px_alpha(&line_img, x_safe, 0); rsum -= c.ch.red; #if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP @@ -499,8 +499,8 @@ void lv_canvas_blur_hor(lv_obj_t * canvas, const lv_area_t * area, uint16_t r) x_safe = x + 1 + r_front; x_safe = x_safe > ext->dsc.header.w - 1 ? ext->dsc.header.w - 1 : x_safe; - c = lv_img_buf_get_px_color(&line_img, x_safe, 0, LV_COLOR_RED, false); - if(has_alpha) opa = lv_img_buf_get_px_alpha(&line_img, x_safe, 0, false); + c = lv_img_buf_get_px_color(&line_img, x_safe, 0, LV_COLOR_RED); + if(has_alpha) opa = lv_img_buf_get_px_alpha(&line_img, x_safe, 0); rsum += c.ch.red; #if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP @@ -581,11 +581,11 @@ void lv_canvas_blur_ver(lv_obj_t * canvas, const lv_area_t * area, uint16_t r) y_safe = y < 0 ? 0 : y; y_safe = y_safe > ext->dsc.header.h - 1 ? ext->dsc.header.h - 1 : y_safe; - c = lv_img_buf_get_px_color(&ext->dsc, x, y_safe, style->image.color, false); - if(has_alpha) opa = lv_img_buf_get_px_alpha(&ext->dsc, x, y_safe, false); + c = lv_img_buf_get_px_color(&ext->dsc, x, y_safe, style->image.color); + if(has_alpha) opa = lv_img_buf_get_px_alpha(&ext->dsc, x, y_safe); - lv_img_buf_set_px_color(&line_img, 0, y_safe, c, false); - if(has_alpha) lv_img_buf_set_px_alpha(&line_img, 0, y_safe, opa, false); + lv_img_buf_set_px_color(&line_img, 0, y_safe, c); + if(has_alpha) lv_img_buf_set_px_alpha(&line_img, 0, y_safe, opa); rsum += c.ch.red; #if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP @@ -613,14 +613,14 @@ void lv_canvas_blur_ver(lv_obj_t * canvas, const lv_area_t * area, uint16_t r) c.ch.blue = bsum / r; if(has_alpha) opa = asum / r; - lv_img_buf_set_px_color(&ext->dsc, x, y, c, false); + lv_img_buf_set_px_color(&ext->dsc, x, y, c); } - if(has_alpha) lv_img_buf_set_px_alpha(&ext->dsc, x, y, opa, false); + if(has_alpha) lv_img_buf_set_px_alpha(&ext->dsc, x, y, opa); y_safe = y - r_back; y_safe = y_safe < 0 ? 0 : y_safe; - c = lv_img_buf_get_px_color(&line_img, 0, y_safe, style->image.color, false); - if(has_alpha) opa = lv_img_buf_get_px_alpha(&line_img, 0, y_safe, false); + c = lv_img_buf_get_px_color(&line_img, 0, y_safe, style->image.color); + if(has_alpha) opa = lv_img_buf_get_px_alpha(&line_img, 0, y_safe); rsum -= c.ch.red; #if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP @@ -634,11 +634,11 @@ void lv_canvas_blur_ver(lv_obj_t * canvas, const lv_area_t * area, uint16_t r) y_safe = y + 1 + r_front; y_safe = y_safe > ext->dsc.header.h - 1 ? ext->dsc.header.h - 1 : y_safe; - c = lv_img_buf_get_px_color(&ext->dsc, x, y_safe, style->image.color, false); - if(has_alpha) opa = lv_img_buf_get_px_alpha(&ext->dsc, x, y_safe, false); + c = lv_img_buf_get_px_color(&ext->dsc, x, y_safe, style->image.color); + if(has_alpha) opa = lv_img_buf_get_px_alpha(&ext->dsc, x, y_safe); - lv_img_buf_set_px_color(&line_img, 0, y_safe, c, false); - if(has_alpha) lv_img_buf_set_px_alpha(&line_img, 0, y_safe, opa, false); + lv_img_buf_set_px_color(&line_img, 0, y_safe, c); + if(has_alpha) lv_img_buf_set_px_alpha(&line_img, 0, y_safe, opa); rsum += c.ch.red; #if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP @@ -671,7 +671,7 @@ void lv_canvas_fill_bg(lv_obj_t * canvas, lv_color_t color) uint32_t y; for(y = 0; y < dsc->header.h; y++) { for(x = 0; x < dsc->header.w; x++) { - lv_img_buf_set_px_color(dsc, x, y, color, false); + lv_img_buf_set_px_color(dsc, x, y, color); } } } @@ -1194,11 +1194,11 @@ static void set_px_alpha_generic(lv_img_dsc_t * d, lv_coord_t x, lv_coord_t y, l uint8_t br = lv_color_brightness(color); if(opa < LV_OPA_MAX) { - uint8_t bg = lv_img_buf_get_px_alpha(d, x, y, false); + uint8_t bg = lv_img_buf_get_px_alpha(d, x, y); br = (uint16_t)((uint16_t)br * opa + (bg * (255 - opa))) >> 8; } - lv_img_buf_set_px_alpha(d, x, y, br, false); + lv_img_buf_set_px_alpha(d, x, y, br); } @@ -1215,8 +1215,8 @@ static void set_px_true_color_alpha(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_ d.header.w = buf_w; d.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA; - lv_color_t bg_color = lv_img_buf_get_px_color(&d, x, y, LV_COLOR_BLACK, false); - lv_opa_t bg_opa = lv_img_buf_get_px_alpha(&d, x, y, false); + lv_color_t bg_color = lv_img_buf_get_px_color(&d, x, y, LV_COLOR_BLACK); + lv_opa_t bg_opa = lv_img_buf_get_px_alpha(&d, x, y); lv_opa_t res_opa; lv_color_t res_color; @@ -1224,8 +1224,8 @@ static void set_px_true_color_alpha(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_ lv_color_mix_with_alpha(bg_color, bg_opa, color, opa, &res_color, &res_opa); - lv_img_buf_set_px_alpha(&d, x, y, res_opa, false); - lv_img_buf_set_px_color(&d, x, y, res_color, false); + lv_img_buf_set_px_alpha(&d, x, y, res_opa); + lv_img_buf_set_px_color(&d, x, y, res_color); } #endif From c632c62cb9f6db3312989c7aa65a4702c1bfb385 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Thu, 7 Nov 2019 06:00:16 +0100 Subject: [PATCH 06/17] static inline lv_img_buf_get_px --- src/lv_draw/lv_img_buf.c | 110 --------------------------------------- src/lv_draw/lv_img_buf.h | 108 +++++++++++++++++++++++++++++++++++++- 2 files changed, 107 insertions(+), 111 deletions(-) diff --git a/src/lv_draw/lv_img_buf.c b/src/lv_draw/lv_img_buf.c index 5cf84972c..47accdd53 100644 --- a/src/lv_draw/lv_img_buf.c +++ b/src/lv_draw/lv_img_buf.c @@ -160,116 +160,6 @@ lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y) return LV_OPA_COVER; } -/** - * Get the color of an image's pixel - * @param dsc an image descriptor - * @param x x coordinate of the point to get - * @param y x coordinate of the point to get - * @param color the color of the image. In case of `LV_IMG_CF_ALPHA_1/2/4/8` this color is used. - * Not used in other cases. - * @param safe true: check out of bounds - * @return color of the point - */ -void lv_img_buf_get_px(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_color_t * px_color, lv_opa_t * px_opa) -{ - uint8_t * buf_u8 = (uint8_t *)dsc->data; - - if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { - uint32_t px = dsc->header.w * y * sizeof(lv_color_t) + x * sizeof(lv_color_t); - memcpy(px_color, &buf_u8[px], sizeof(lv_color_t)); - *px_opa = LV_OPA_COVER; - } else if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) { - uint32_t px = dsc->header.w * y * LV_IMG_PX_SIZE_ALPHA_BYTE + x * LV_IMG_PX_SIZE_ALPHA_BYTE; - memcpy(px_color, &buf_u8[px], sizeof(lv_color_t)); - *px_opa = buf_u8[px + LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; -#if LV_COLOR_SIZE == 32 - p_color.ch.alpha = 0xFF; /*Only the color should be get so use a default alpha value*/ -#endif - } else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT) { - buf_u8 += 4 * 2; - uint8_t bit = x & 0x7; - x = x >> 3; - - /* Get the current pixel. - * dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned - * so the possible real width are 8, 16, 24 ...*/ - uint32_t px = ((dsc->header.w + 7) >> 3) * y + x; - px_color->full = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit); - *px_opa = LV_OPA_COVER; - } else if(dsc->header.cf == LV_IMG_CF_INDEXED_2BIT) { - buf_u8 += 4 * 4; - uint8_t bit = (x & 0x3) * 2; - x = x >> 2; - - /* Get the current pixel. - * dsc->header.w + 3 means rounding up to 4 because the lines are byte aligned - * so the possible real width are 4, 8, 12 ...*/ - uint32_t px = ((dsc->header.w + 3) >> 2) * y + x; - px_color->full = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit); - *px_opa = LV_OPA_COVER; - } else if(dsc->header.cf == LV_IMG_CF_INDEXED_4BIT) { - buf_u8 += 4 * 16; - uint8_t bit = (x & 0x1) * 4; - x = x >> 1; - - /* Get the current pixel. - * dsc->header.w + 1 means rounding up to 2 because the lines are byte aligned - * so the possible real width are 2, 4, 6 ...*/ - uint32_t px = ((dsc->header.w + 1) >> 1) * y + x; - px_color->full = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit); - *px_opa = LV_OPA_COVER; - } else if(dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) { - buf_u8 += 4 * 256; - uint32_t px = dsc->header.w * y + x; - px_color->full = buf_u8[px]; - } else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT || dsc->header.cf == LV_IMG_CF_ALPHA_2BIT || - dsc->header.cf == LV_IMG_CF_ALPHA_4BIT || dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) { - *px_color = color; - *px_opa = LV_OPA_COVER; - } else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT) { - uint8_t bit = x & 0x7; - x = x >> 3; - - /* Get the current pixel. - * dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned - * so the possible real width are 8 ,16, 24 ...*/ - uint32_t px = ((dsc->header.w + 7) >> 3) * y + x; - uint8_t tmp = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit); - *px_opa = tmp ? LV_OPA_TRANSP : LV_OPA_COVER; - *px_color = color; - } else if(dsc->header.cf == LV_IMG_CF_ALPHA_2BIT) { - const uint8_t opa_table[4] = {0, 85, 170, 255}; /*Opacity mapping with bpp = 2*/ - - uint8_t bit = (x & 0x3) * 2; - x = x >> 2; - - /* Get the current pixel. - * dsc->header.w + 4 means rounding up to 8 because the lines are byte aligned - * so the possible real width are 4 ,8, 12 ...*/ - uint32_t px = ((dsc->header.w + 3) >> 2) * y + x; - uint8_t tmp = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit); - *px_opa = opa_table[tmp]; - *px_color = color; - } else if(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT) { - const uint8_t opa_table[16] = {0, 17, 34, 51, /*Opacity mapping with bpp = 4*/ - 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255}; - - uint8_t bit = (x & 0x1) * 4; - x = x >> 1; - - /* Get the current pixel. - * dsc->header.w + 1 means rounding up to 8 because the lines are byte aligned - * so the possible real width are 2 ,4, 6 ...*/ - uint32_t px = ((dsc->header.w + 1) >> 1) * y + x; - uint8_t tmp = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit); - *px_opa = opa_table[tmp]; - *px_color = color; - } else if(dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) { - uint32_t px = dsc->header.w * y + x; - *px_opa = buf_u8[px]; - *px_color = color; - } -} /** diff --git a/src/lv_draw/lv_img_buf.h b/src/lv_draw/lv_img_buf.h index 787865d14..184e29ae9 100644 --- a/src/lv_draw/lv_img_buf.h +++ b/src/lv_draw/lv_img_buf.h @@ -186,7 +186,113 @@ lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y); -void lv_img_buf_get_px(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_color_t * px_color, lv_opa_t * px_opa); + +/** + * Get the color of an image's pixel + * @param dsc an image descriptor + * @param x x coordinate of the point to get + * @param y x coordinate of the point to get + * @param color the color of the image. In case of `LV_IMG_CF_ALPHA_1/2/4/8` this color is used. + * Not used in other cases. + * @param safe true: check out of bounds + * @return color of the point + */ +static inline void lv_img_buf_get_px(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_color_t * px_color, lv_opa_t * px_opa) +{ + uint8_t * buf_u8 = (uint8_t *)dsc->data; + + if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) { + uint32_t px = dsc->header.w * y * LV_IMG_PX_SIZE_ALPHA_BYTE + x * LV_IMG_PX_SIZE_ALPHA_BYTE; + memcpy(px_color, &buf_u8[px], sizeof(lv_color_t)); + *px_opa = buf_u8[px + LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; +#if LV_COLOR_SIZE == 32 + p_color.ch.alpha = 0xFF; /*Only the color should be get so use a default alpha value*/ +#endif + } else if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { + uint32_t px = dsc->header.w * y * sizeof(lv_color_t) + x * sizeof(lv_color_t); + memcpy(px_color, &buf_u8[px], sizeof(lv_color_t)); + *px_opa = LV_OPA_COVER; + } else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT) { + buf_u8 += 4 * 2; + uint8_t bit = x & 0x7; + x = x >> 3; + + /* Get the current pixel. + * dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned + * so the possible real width are 8, 16, 24 ...*/ + uint32_t px = ((dsc->header.w + 7) >> 3) * y + x; + px_color->full = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit); + *px_opa = LV_OPA_COVER; + } else if(dsc->header.cf == LV_IMG_CF_INDEXED_2BIT) { + buf_u8 += 4 * 4; + uint8_t bit = (x & 0x3) * 2; + x = x >> 2; + + /* Get the current pixel. + * dsc->header.w + 3 means rounding up to 4 because the lines are byte aligned + * so the possible real width are 4, 8, 12 ...*/ + uint32_t px = ((dsc->header.w + 3) >> 2) * y + x; + px_color->full = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit); + *px_opa = LV_OPA_COVER; + } else if(dsc->header.cf == LV_IMG_CF_INDEXED_4BIT) { + buf_u8 += 4 * 16; + uint8_t bit = (x & 0x1) * 4; + x = x >> 1; + + /* Get the current pixel. + * dsc->header.w + 1 means rounding up to 2 because the lines are byte aligned + * so the possible real width are 2, 4, 6 ...*/ + uint32_t px = ((dsc->header.w + 1) >> 1) * y + x; + px_color->full = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit); + *px_opa = LV_OPA_COVER; + } else if(dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) { + buf_u8 += 4 * 256; + uint32_t px = dsc->header.w * y + x; + px_color->full = buf_u8[px]; + } else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT) { + uint8_t bit = x & 0x7; + x = x >> 3; + + /* Get the current pixel. + * dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned + * so the possible real width are 8 ,16, 24 ...*/ + uint32_t px = ((dsc->header.w + 7) >> 3) * y + x; + uint8_t tmp = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit); + *px_opa = tmp ? LV_OPA_TRANSP : LV_OPA_COVER; + *px_color = color; + } else if(dsc->header.cf == LV_IMG_CF_ALPHA_2BIT) { + const uint8_t opa_table[4] = {0, 85, 170, 255}; /*Opacity mapping with bpp = 2*/ + + uint8_t bit = (x & 0x3) * 2; + x = x >> 2; + + /* Get the current pixel. + * dsc->header.w + 4 means rounding up to 8 because the lines are byte aligned + * so the possible real width are 4 ,8, 12 ...*/ + uint32_t px = ((dsc->header.w + 3) >> 2) * y + x; + uint8_t tmp = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit); + *px_opa = opa_table[tmp]; + *px_color = color; + } else if(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT) { + const uint8_t opa_table[16] = {0, 17, 34, 51, /*Opacity mapping with bpp = 4*/ + 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255}; + + uint8_t bit = (x & 0x1) * 4; + x = x >> 1; + + /* Get the current pixel. + * dsc->header.w + 1 means rounding up to 8 because the lines are byte aligned + * so the possible real width are 2 ,4, 6 ...*/ + uint32_t px = ((dsc->header.w + 1) >> 1) * y + x; + uint8_t tmp = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit); + *px_opa = opa_table[tmp]; + *px_color = color; + } else if(dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) { + uint32_t px = dsc->header.w * y + x; + *px_opa = buf_u8[px]; + *px_color = color; + } +} /** * Set the color of a pixel of an image. The alpha channel won't be affected. From 49bafb1d3659b06c01ec2e299928e5765da847bd Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 8 Nov 2019 08:20:42 +0100 Subject: [PATCH 07/17] improve img rotate quality --- src/lv_draw/lv_img_buf.c | 248 +++++++++++++++++++++------------------ src/lv_draw/lv_img_buf.h | 8 ++ 2 files changed, 142 insertions(+), 114 deletions(-) diff --git a/src/lv_draw/lv_img_buf.c b/src/lv_draw/lv_img_buf.c index 433d1a04b..75a87ddc9 100644 --- a/src/lv_draw/lv_img_buf.c +++ b/src/lv_draw/lv_img_buf.c @@ -24,6 +24,7 @@ /********************** * STATIC PROTOTYPES **********************/ +static inline bool transform_anti_alias(lv_img_rotate_dsc_t * dsc); /********************** * STATIC VARIABLES @@ -483,7 +484,7 @@ void lv_img_buf_rotate_init(lv_img_rotate_dsc_t * dsc, int16_t angle, const void dsc->chroma_keyed = lv_img_cf_is_chroma_keyed(cf) ? 1 : 0; dsc->has_alpha = lv_img_cf_has_alpha(cf) ? 1 : 0; if(cf == LV_IMG_CF_TRUE_COLOR || cf == LV_IMG_CF_TRUE_COLOR_ALPHA || cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { - dsc->native_color = 1; + dsc->native_color = 0; } dsc->img_dsc.data = src; @@ -511,9 +512,23 @@ bool lv_img_buf_get_px_rotated(lv_img_rotate_dsc_t * dsc, lv_coord_t x, lv_coord int32_t xt = x - dsc->pivot_x; int32_t yt = y - dsc->pivot_y; - /*Get the source pixel from the upscaled image*/ - int32_t xs = ((dsc->cosma * xt - dsc->sinma * yt) >> (LV_TRIGO_SHIFT - 8)) + dsc->pivot_x_256; - int32_t ys = ((dsc->sinma * xt + dsc->cosma * yt) >> (LV_TRIGO_SHIFT - 8)) + dsc->pivot_y_256; + bool fast = false; + bool zoomed = false; + uint16_t zoom = 128; + uint16_t zoom_inv = (256 / zoom) * 256;; + int32_t xs; + int32_t ys; + if(!zoomed) { + /*Get the source pixel from the upscaled image*/ + xs = ((dsc->cosma * xt - dsc->sinma * yt) >> (LV_TRIGO_SHIFT - 8)) + dsc->pivot_x_256; + ys = ((dsc->sinma * xt + dsc->cosma * yt) >> (LV_TRIGO_SHIFT - 8)) + dsc->pivot_y_256; + } else { + xt *= zoom_inv; + yt *= zoom_inv; + xs = ((dsc->cosma * xt - dsc->sinma * yt) >> (LV_TRIGO_SHIFT)) + dsc->pivot_x_256; + ys = ((dsc->sinma * xt + dsc->cosma * yt) >> (LV_TRIGO_SHIFT)) + dsc->pivot_y_256; + + } /*Get the integer part of the source pixel*/ int xs_int = xs >> 8; @@ -525,144 +540,149 @@ bool lv_img_buf_get_px_rotated(lv_img_rotate_dsc_t * dsc, lv_coord_t x, lv_coord if(ys_int >= dsc->src_h) return false; else if(ys_int < 0) return false; - /*Get the fractional part of the source pixel*/ - int xs_fract = xs & 0xff; - int ys_fract = ys & 0xff; - /* If the fractional < 0x70 mix the source pixel with the left/top pixel * If the fractional > 0x90 mix the source pixel with the right/bottom pixel * In the 0x70..0x90 range use the unchanged source pixel */ - lv_color_t c_dest_int; - lv_opa_t opa_dest_int = 0; - uint8_t px_size; - uint32_t px; + uint32_t pxi; if(dsc->native_color) { if(dsc->has_alpha == 0) { px_size = LV_COLOR_SIZE >> 3; - px = dsc->src_w * ys_int * px_size + xs_int * px_size; - memcpy(&c_dest_int, &src_u8[px], px_size); + pxi = dsc->src_w * ys_int * px_size + xs_int * px_size; + memcpy(&dsc->res_color, &src_u8[pxi], px_size); } else { px_size = LV_IMG_PX_SIZE_ALPHA_BYTE; - px = dsc->src_w * ys_int * px_size + xs_int * px_size; - memcpy(&c_dest_int, &src_u8[px], px_size - 1); - opa_dest_int = src_u8[px + px_size - 1]; + pxi = dsc->src_w * ys_int * px_size + xs_int * px_size; + memcpy(&dsc->res_color, &src_u8[pxi], px_size - 1); + dsc->res_opa = src_u8[pxi + px_size - 1]; } } else { - px = 0; /*unused*/ + pxi = 0; /*unused*/ px_size = 0; /*unused*/ - c_dest_int = lv_img_buf_get_px_color(&dsc->img_dsc, xs_int, ys_int, dsc->color, false); - opa_dest_int = lv_img_buf_get_px_alpha(&dsc->img_dsc, xs_int, ys_int, false); + dsc->res_color = lv_img_buf_get_px_color(&dsc->img_dsc, xs_int, ys_int, dsc->color, false); + dsc->res_opa = lv_img_buf_get_px_alpha(&dsc->img_dsc, xs_int, ys_int, false); } if(dsc->chroma_keyed) { lv_color_t ct = LV_COLOR_TRANSP; - if(c_dest_int.full == ct.full) return false; - } - - /*Get the mixture of the original source and the neightboor pixels in both directions*/ - lv_color_t c_x_dest; - lv_color_t c_y_dest; - lv_opa_t opa_x_dest = 0; - lv_opa_t opa_y_dest = 0; - - int32_t xn; /*x neightboor*/ - lv_opa_t xr; /*x mix ratio*/ - lv_color_t c_dest_xn; - lv_opa_t opa_dest_xn = 0; - - if(xs_fract < 0x70) { - xn = xs_int - 1; - if(xn < 0) return false; - - xr = xs_fract + 0x80; - - if(dsc->native_color) { - memcpy(&c_dest_xn, &src_u8[px - px_size], sizeof(lv_color_t)); - if(dsc->has_alpha) opa_dest_xn = src_u8[px - 1]; - } else { - c_dest_xn = lv_img_buf_get_px_color(&dsc->img_dsc, xn, ys_int, dsc->color, false); - if(dsc->has_alpha) opa_dest_xn = lv_img_buf_get_px_alpha(&dsc->img_dsc, xn, ys_int, false); - } - - c_x_dest = lv_color_mix(c_dest_int, c_dest_xn, xr); - if(dsc->has_alpha) opa_x_dest = (opa_dest_int * xr + (opa_dest_xn * (255 - xr))) >> 8; - - } else if(xs_fract > 0x90) { - xn = xs_int + 1; - if(xn >= dsc->src_w) return false; - - xr = (0xFF - xs_fract) + 0x80; - - if(dsc->native_color) { - memcpy(&c_dest_xn, &src_u8[px + px_size], sizeof(lv_color_t)); - if(dsc->has_alpha) opa_dest_xn = src_u8[px + 2 * px_size - 1]; - } else { - c_dest_xn = lv_img_buf_get_px_color(&dsc->img_dsc, xn, ys_int, dsc->color, false); - if(dsc->has_alpha) opa_dest_xn = lv_img_buf_get_px_alpha(&dsc->img_dsc, xn, ys_int, false); - } - - c_x_dest = lv_color_mix(c_dest_int, c_dest_xn, xr); - if(dsc->has_alpha) opa_x_dest = (opa_dest_int * xr + (opa_dest_xn * (255 - xr))) >> 8; - - } else { - c_x_dest.full = c_dest_int.full; - opa_x_dest = opa_dest_int; + if(dsc->res_color.full == ct.full) return false; } - int32_t yn; /*x neightboor*/ - lv_opa_t yr; /*x mix ratio*/ - lv_color_t c_dest_yn; - lv_opa_t opa_dest_yn = 0; + if(fast) return true; - if(ys_fract < 0x70) { - yn = ys_int - 1; - if(yn < 0) return false; + dsc->xs = xs; + dsc->ys = ys; + dsc->xs_int = xs_int; + dsc->ys_int = ys_int; + dsc->pxi = pxi; + dsc->px_size = px_size; - yr = ys_fract + 0x80; + bool ret; - 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 + px_size- 1]; - } else { - c_dest_yn = lv_img_buf_get_px_color(&dsc->img_dsc, xs_int, yn, dsc->color, false); - if(dsc->has_alpha) opa_dest_yn = lv_img_buf_get_px_alpha(&dsc->img_dsc, xs_int, yn, false); - } + ret = transform_anti_alias(dsc); - c_y_dest = lv_color_mix(c_dest_int, c_dest_yn, yr); - if(dsc->has_alpha) opa_y_dest = (opa_dest_int * yr + (opa_dest_yn * (255 - yr))) >> 8; - - } else if(ys_fract > 0x90) { - yn = ys_int + 1; - if(yn >= dsc->src_h) return false; - - yr = (0xFF - ys_fract) + 0x80; - - 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 + 2 * px_size - 1]; - } else { - c_dest_yn = lv_img_buf_get_px_color(&dsc->img_dsc, xs_int, yn, dsc->color, false); - if(dsc->has_alpha) opa_dest_yn = lv_img_buf_get_px_alpha(&dsc->img_dsc, xs_int, yn, false); - } - - c_y_dest = lv_color_mix(c_dest_int, c_dest_yn, yr); - if(dsc->has_alpha) opa_y_dest = (opa_dest_int * yr + (opa_dest_yn * (255 - yr))) >> 8; - } else { - c_y_dest.full = c_dest_int.full; - opa_y_dest = opa_dest_int; - } - - dsc->res_color = lv_color_mix(c_x_dest, c_y_dest, LV_OPA_50); - if(dsc->has_alpha) dsc->res_opa = (opa_x_dest + opa_y_dest) >> 1; - - return true; + return ret; } /********************** * STATIC FUNCTIONS **********************/ +static inline bool transform_anti_alias(lv_img_rotate_dsc_t * dsc) +{ + const uint8_t * src_u8 = dsc->src; + + /*Get the fractional part of the source pixel*/ + int xs_fract = dsc->xs & 0xff; + int ys_fract = dsc->ys & 0xff; + int32_t xn; /*x neightboor*/ + lv_opa_t xr; /*x mix ratio*/ + + if(xs_fract < 0x70) { + xn = - 1; + if(dsc->xs_int + xn < 0) return false; + xr = xs_fract + 0x80; + } else if(xs_fract > 0x90) { + xn = 1; + if(dsc->xs_int + xn >= dsc->src_w) return false; + xr = (0xFF - xs_fract) + 0x80; + } else { + xn = 0; + xr = 0xFF; + } + + int32_t yn; /*x neightboor*/ + lv_opa_t yr; /*x mix ratio*/ + + if(ys_fract < 0x70) { + yn = - 1; + if(dsc->ys_int + yn < 0) return false; + + yr = ys_fract + 0x80; + } else if(ys_fract > 0x90) { + yn = 1; + if(dsc->ys_int + yn >= dsc->src_h) return false; + + yr = (0xFF - ys_fract) + 0x80; + } else { + yn = 0; + yr = 0xFF; + } + + + lv_color_t c00 = dsc->res_color; + lv_color_t c01; + lv_color_t c10; + lv_color_t c11; + + lv_opa_t a00 = dsc->res_opa; + lv_opa_t a10; + lv_opa_t a01; + lv_opa_t a11; + + if(dsc->native_color) { + memcpy(&c01, &src_u8[dsc->pxi + dsc->px_size * xn], sizeof(lv_color_t)); + memcpy(&c10, &src_u8[dsc->pxi + dsc->src_w * dsc->px_size * yn], sizeof(lv_color_t)); + memcpy(&c11, &src_u8[dsc->pxi + dsc->src_w * dsc->px_size * yn + dsc->px_size * xn], sizeof(lv_color_t)); + if(dsc->has_alpha) { + a10 = src_u8[dsc->pxi + dsc->px_size * xn + dsc->px_size - 1]; + a01 = src_u8[dsc->pxi + dsc->src_w * dsc->px_size * yn + dsc->px_size - 1]; + a11 = src_u8[dsc->pxi + dsc->src_w * dsc->px_size * yn + dsc->px_size * xn + dsc->px_size - 1]; + } + } else { + c01 = lv_img_buf_get_px_color(&dsc->img_dsc, dsc->xs_int + xn, dsc->ys_int, dsc->color, false); + c10 = lv_img_buf_get_px_color(&dsc->img_dsc, dsc->xs_int, dsc->ys_int + yn, dsc->color, false); + c11 = lv_img_buf_get_px_color(&dsc->img_dsc, dsc->xs_int + xn, dsc->ys_int + yn, dsc->color, false); + + if(dsc->has_alpha) { + a10 = lv_img_buf_get_px_alpha(&dsc->img_dsc, dsc->xs_int + xn, dsc->ys_int, false); + a01 = lv_img_buf_get_px_alpha(&dsc->img_dsc, dsc->xs_int, dsc->ys_int + yn, false); + a11 = lv_img_buf_get_px_alpha(&dsc->img_dsc, dsc->xs_int + xn, dsc->ys_int + yn, false); + } + + } + + lv_opa_t a0; + lv_opa_t a1; + lv_opa_t xr0 = xr; + lv_opa_t xr1 = xr; + if(dsc->has_alpha) { + a0 = (a00 * xr + (a10 * (255 - xr))) >> 8; + a1 = (a01 * xr + (a11 * (255 - xr))) >> 8; + dsc->res_opa = (a0 * yr + (a1 * (255 - yr))) >> 8; + } else { + xr0 = xr; + xr1 = xr; + dsc->res_opa = LV_OPA_COVER; + } + + lv_color_t c0 = lv_color_mix(c00, c01, xr0); + lv_color_t c1 = lv_color_mix(c10, c11, xr1); + + dsc->res_color = lv_color_mix(c0, c1, yr); + + return true; +} diff --git a/src/lv_draw/lv_img_buf.h b/src/lv_draw/lv_img_buf.h index 41f33af5b..266394c2f 100644 --- a/src/lv_draw/lv_img_buf.h +++ b/src/lv_draw/lv_img_buf.h @@ -148,6 +148,14 @@ typedef struct { uint8_t has_alpha :1; uint8_t native_color :1; + /*Runtime data*/ + lv_coord_t xs; + lv_coord_t ys; + lv_coord_t xs_int; + lv_coord_t ys_int; + uint32_t pxi; + uint8_t px_size; + }lv_img_rotate_dsc_t; /********************** From cde17104a0060cab32792f1a8d2ced63f8651bda Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 8 Nov 2019 08:21:08 +0100 Subject: [PATCH 08/17] add alpha to lv_canvas_fill_bg --- src/lv_objx/lv_canvas.c | 7 ++++--- src/lv_objx/lv_canvas.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/lv_objx/lv_canvas.c b/src/lv_objx/lv_canvas.c index 50f2b7c1d..7ca14a3da 100644 --- a/src/lv_objx/lv_canvas.c +++ b/src/lv_objx/lv_canvas.c @@ -323,8 +323,8 @@ void lv_canvas_rotate(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, lv_c lv_img_rotate_dsc_t dsc; lv_img_buf_rotate_init(&dsc, angle, img->data, img->header.w, img->header.h, img->header.cf, pivot_x, pivot_y, style->image.color); - for(x = -offset_x; x < dest_width - offset_x; x++) { - for(y = -offset_y; y < dest_height - offset_y; y++) { + for(y = -offset_y; y < dest_height - offset_y; y++) { + for(x = -offset_x; x < dest_width - offset_x; x++) { ret = lv_img_buf_get_px_rotated(&dsc, x, y); @@ -661,7 +661,7 @@ void lv_canvas_blur_ver(lv_obj_t * canvas, const lv_area_t * area, uint16_t r) * @param canvas pointer to a canvas * @param color the background color */ -void lv_canvas_fill_bg(lv_obj_t * canvas, lv_color_t color) +void lv_canvas_fill_bg(lv_obj_t * canvas, lv_color_t color, lv_opa_t opa) { LV_ASSERT_OBJ(canvas, LV_OBJX_NAME); @@ -672,6 +672,7 @@ void lv_canvas_fill_bg(lv_obj_t * canvas, lv_color_t color) for(y = 0; y < dsc->header.h; y++) { for(x = 0; x < dsc->header.w; x++) { lv_img_buf_set_px_color(dsc, x, y, color, false); + lv_img_buf_set_px_alpha(dsc, x, y, opa, false); } } } diff --git a/src/lv_objx/lv_canvas.h b/src/lv_objx/lv_canvas.h index 5a1b37577..9ef6c1a3d 100644 --- a/src/lv_objx/lv_canvas.h +++ b/src/lv_objx/lv_canvas.h @@ -188,7 +188,7 @@ void lv_canvas_blur_ver(lv_obj_t * canvas, const lv_area_t * area, uint16_t r); * @param canvas pointer to a canvas * @param color the background color */ -void lv_canvas_fill_bg(lv_obj_t * canvas, lv_color_t color); +void lv_canvas_fill_bg(lv_obj_t * canvas, lv_color_t color, lv_opa_t opa); /** * Draw a rectangle on the canvas From 62f6aa45e61612e66218408a5ecc00adc8c12a68 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 8 Nov 2019 09:20:35 +0100 Subject: [PATCH 09/17] lv_img_rotate optimize anti aliasing --- src/lv_draw/lv_img_buf.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/lv_draw/lv_img_buf.c b/src/lv_draw/lv_img_buf.c index 2ce3db762..bc998b8d8 100644 --- a/src/lv_draw/lv_img_buf.c +++ b/src/lv_draw/lv_img_buf.c @@ -525,7 +525,7 @@ void lv_img_buf_rotate_init(lv_img_rotate_dsc_t * dsc, int16_t angle, const void dsc->chroma_keyed = lv_img_cf_is_chroma_keyed(cf) ? 1 : 0; dsc->has_alpha = lv_img_cf_has_alpha(cf) ? 1 : 0; if(cf == LV_IMG_CF_TRUE_COLOR || cf == LV_IMG_CF_TRUE_COLOR_ALPHA || cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { - dsc->native_color = 0; + dsc->native_color = 1; } dsc->img_dsc.data = src; @@ -715,6 +715,16 @@ static inline bool transform_anti_alias(lv_img_rotate_dsc_t * dsc) a0 = (a00 * xr + (a10 * (255 - xr))) >> 8; a1 = (a01 * xr + (a11 * (255 - xr))) >> 8; dsc->res_opa = (a0 * yr + (a1 * (255 - yr))) >> 8; + + + if(a0 <= LV_OPA_MIN && a1 <= LV_OPA_MIN) return false; + if(a0 <= LV_OPA_MIN) yr = LV_OPA_TRANSP; + if(a1 <= LV_OPA_MIN) yr = LV_OPA_COVER; + if(a00 <= LV_OPA_MIN) xr0 = LV_OPA_TRANSP; + if(a10 <= LV_OPA_MIN) xr0 = LV_OPA_COVER; + if(a01 <= LV_OPA_MIN) xr1 = LV_OPA_TRANSP; + if(a11 <= LV_OPA_MIN) xr1 = LV_OPA_COVER; + } else { xr0 = xr; xr1 = xr; From 18d1fdb3f516409e6820de6b1e2d3df379f387de Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 8 Nov 2019 10:23:49 +0100 Subject: [PATCH 10/17] preloader: fix top point position in dev7.0 arc angle=0 is on the left and not on the bottom as it was in v6.0 --- src/lv_objx/lv_preload.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lv_objx/lv_preload.c b/src/lv_objx/lv_preload.c index fc94358ec..d77dc1a51 100644 --- a/src/lv_objx/lv_preload.c +++ b/src/lv_objx/lv_preload.c @@ -84,6 +84,7 @@ lv_obj_t * lv_preload_create(lv_obj_t * par, const lv_obj_t * copy) ext->arc_length = LV_PRELOAD_DEF_ARC_LENGTH; ext->anim_type = LV_PRELOAD_DEF_ANIM; ext->anim_dir = LV_PRELOAD_DIR_FORWARD; + ext->time = LV_PRELOAD_DEF_SPIN_TIME; /*The signal and design functions are not copied so set them here*/ lv_obj_set_signal_cb(new_preload, lv_preload_signal); @@ -101,7 +102,6 @@ lv_obj_t * lv_preload_create(lv_obj_t * par, const lv_obj_t * copy) lv_obj_set_style(new_preload, &lv_style_pretty_color); } - ext->time = LV_PRELOAD_DEF_SPIN_TIME; } /*Copy an existing pre loader*/ @@ -352,7 +352,8 @@ void lv_preload_spinner_anim(void * ptr, lv_anim_value_t val) lv_obj_t * preload = ptr; lv_preload_ext_t * ext = lv_obj_get_ext_attr(preload); - int16_t angle_start = val - ext->arc_length / 2 + 180; + int16_t angle_start = val - ext->arc_length / 2 - 90; + if(angle_start < 0) angle_start += 360; int16_t angle_end = angle_start + ext->arc_length; angle_start = angle_start % 360; From e29210889a38db46d6186fc64a2aa7eec105253d Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 8 Nov 2019 22:43:58 +0100 Subject: [PATCH 11/17] add image zoom --- src/lv_draw/lv_draw_img.c | 71 ++++++--- src/lv_draw/lv_draw_img.h | 3 +- src/lv_draw/lv_img_buf.c | 298 +++++++++++--------------------------- src/lv_draw/lv_img_buf.h | 84 +++++------ src/lv_objx/lv_canvas.c | 46 +++--- src/lv_objx/lv_canvas.h | 8 +- src/lv_objx/lv_img.c | 74 +++++++++- src/lv_objx/lv_img.h | 35 +++++ src/lv_objx/lv_imgbtn.c | 2 +- 9 files changed, 317 insertions(+), 304 deletions(-) diff --git a/src/lv_draw/lv_draw_img.c b/src/lv_draw/lv_draw_img.c index dbac1a4f4..74f736868 100644 --- a/src/lv_draw/lv_draw_img.c +++ b/src/lv_draw/lv_draw_img.c @@ -26,10 +26,10 @@ * STATIC PROTOTYPES **********************/ 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); + const lv_style_t * style, uint16_t angle, uint16_t zoom, bool antialaias, lv_opa_t opa_scale); static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, const uint8_t * map_p, lv_opa_t opa, - bool chroma_key, bool alpha_byte, const lv_style_t * style, uint16_t angle); + bool chroma_key, bool alpha_byte, const lv_style_t * style, uint16_t angle, uint16_t zoom, bool antialaias); /********************** * STATIC VARIABLES @@ -49,10 +49,11 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, * @param mask the image will be drawn only in this area * @param src pointer to a lv_color_t array which contains the pixels of the image * @param style style of the image + * @param antialias anti-alias transformations (rotate, zoom) or not * @param opa_scale scale down all opacities by the factor */ void lv_draw_img(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) + uint16_t angle, uint16_t zoom, bool antialias, lv_opa_t opa_scale) { if(src == NULL) { LV_LOG_WARN("Image draw: src is NULL"); @@ -62,7 +63,7 @@ void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void * } lv_res_t res; - res = lv_img_draw_core(coords, mask, src, style, angle, opa_scale); + res = lv_img_draw_core(coords, mask, src, style, angle, zoom, antialias, opa_scale); if(res == LV_RES_INV) { LV_LOG_WARN("Image draw error"); @@ -189,7 +190,7 @@ 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) + const lv_style_t * style, uint16_t angle, uint16_t zoom, bool antialias, lv_opa_t opa_scale) { lv_opa_t opa = opa_scale == LV_OPA_COVER ? style->image.opa : (uint16_t)((uint16_t)style->image.opa * opa_scale) >> 8; @@ -211,16 +212,21 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas else if(cdsc->dec_dsc.img_data) { lv_area_t map_area_rot; lv_area_copy(&map_area_rot, coords); - if(angle) { + if(angle || zoom != LV_IMG_ZOOM_NONE) { /*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_coord_t w = lv_area_get_width(coords); + lv_coord_t w_zoom = (((w * zoom) >> 8) - w) / 2; + lv_coord_t h = lv_area_get_height(coords); + lv_coord_t h_zoom = (((h * zoom) >> 8) - h) / 2; + 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; + norm.x1 = coords->x1 - pivot_x - w_zoom; + norm.y1 = coords->y1 - pivot_y - h_zoom; + norm.x2 = coords->x2 - pivot_x + w_zoom; + norm.y2 = coords->y2 - pivot_y + h_zoom; int16_t sinma = lv_trigo_sin(-angle); int16_t cosma = lv_trigo_sin(-angle + 90); @@ -255,7 +261,7 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas successfully.*/ } - lv_draw_map(coords, &mask_com, cdsc->dec_dsc.img_data, opa, chroma_keyed, alpha_byte, style, angle); + lv_draw_map(coords, &mask_com, cdsc->dec_dsc.img_data, opa, chroma_keyed, alpha_byte, style, angle, zoom, antialias); } /* The whole uncompressed image is not available. Try to read it line-by-line*/ else { @@ -292,7 +298,7 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas } - lv_draw_map(&line, &mask_line, buf, opa, chroma_keyed, alpha_byte, style, 0); + lv_draw_map(&line, &mask_line, buf, opa, chroma_keyed, alpha_byte, style, 0, LV_IMG_ZOOM_NONE, false); line.y1++; line.y2++; y++; @@ -312,9 +318,12 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas * @param chroma_keyed true: enable transparency of LV_IMG_LV_COLOR_TRANSP color pixels * @param alpha_byte true: extra alpha byte is inserted for every pixel * @param style style of the image + * @param angle angle in degree + * @param zoom zoom factor + * @param antialias anti-alias transformations (rotate, zoom) or not */ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, const uint8_t * map_p, lv_opa_t opa, - bool chroma_key, bool alpha_byte, const lv_style_t * style, uint16_t angle) + bool chroma_key, bool alpha_byte, const lv_style_t * style, uint16_t angle, uint16_t zoom, bool antialaias) { if(opa < LV_OPA_MIN) return; @@ -338,7 +347,9 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, uint8_t other_mask_cnt = lv_draw_mask_get_cnt(); /*The simplest case just copy the pixels into the VDB*/ - if(angle == 0 && other_mask_cnt == 0 && chroma_key == false && alpha_byte == false && opa == LV_OPA_COVER && style->image.intense == LV_OPA_TRANSP) { + if(other_mask_cnt == 0 && angle == 0 && zoom == LV_IMG_ZOOM_NONE && + chroma_key == false && alpha_byte == false && + opa == LV_OPA_COVER && style->image.intense == LV_OPA_TRANSP) { lv_blend_map(clip_area, map_area, (lv_color_t *)map_p, NULL, LV_DRAW_MASK_RES_FULL_COVER, LV_OPA_COVER, style->image.blend_mode); } /*In the other cases every pixel need to be checked one-by-one*/ @@ -377,14 +388,30 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, } - lv_img_rotate_dsc_t rotate_dsc; - memset(&rotate_dsc, 0, sizeof(lv_img_rotate_dsc_t)); - if(angle) { + bool transform = angle != 0 || zoom != LV_IMG_ZOOM_NONE ? true : false; + lv_img_transform_dsc_t trans_dsc; + memset(&trans_dsc, 0, sizeof(lv_img_transform_dsc_t)); + if(transform) { lv_img_cf_t cf = LV_IMG_CF_TRUE_COLOR; if(alpha_byte) cf = LV_IMG_CF_TRUE_COLOR_ALPHA; else if(chroma_key) cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED; - lv_img_buf_rotate_init(&rotate_dsc, angle, map_p, map_w, map_h, cf, map_w/2, map_h / 2, LV_COLOR_BLACK); + + + trans_dsc.cfg.angle = angle; + trans_dsc.cfg.zoom = zoom; + trans_dsc.cfg.src = map_p; + trans_dsc.cfg.src_w = map_w; + trans_dsc.cfg.src_h = map_h; + trans_dsc.cfg.cf = cf; + trans_dsc.cfg.pivot_x = map_w / 2; + trans_dsc.cfg.pivot_y = map_h / 2; + trans_dsc.cfg.color = style->image.color; + trans_dsc.cfg.antialias = true; + + lv_img_buf_transform_init(&trans_dsc); } + + lv_draw_mask_res_t mask_res; mask_res = (alpha_byte || chroma_key || angle) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; lv_coord_t x; @@ -395,7 +422,7 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, for(x = 0; x < lv_area_get_width(&draw_area); x++, map_px += px_size_byte, px_i++) { - if(angle == 0) { + if(transform == false) { if(alpha_byte) { lv_opa_t px_opa = map_px[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; mask_buf[px_i] = px_opa; @@ -422,13 +449,13 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, bool ret; lv_coord_t rot_x = x + (disp_area->x1 + draw_area.x1) - map_area->x1; lv_coord_t rot_y = y + (disp_area->y1 + draw_area.y1) - map_area->y1; - ret = lv_img_buf_get_px_rotated(&rotate_dsc, rot_x, rot_y); + ret = lv_img_buf_transform(&trans_dsc, rot_x, rot_y); if(ret == false) { mask_buf[px_i] = LV_OPA_TRANSP; continue; } else { - mask_buf[px_i] = rotate_dsc.res_opa; - c.full = rotate_dsc.res_color.full; + mask_buf[px_i] = trans_dsc.res.opa; + c.full = trans_dsc.res.color.full; } } diff --git a/src/lv_draw/lv_draw_img.h b/src/lv_draw/lv_draw_img.h index 7633cc039..fed52911b 100644 --- a/src/lv_draw/lv_draw_img.h +++ b/src/lv_draw/lv_draw_img.h @@ -40,10 +40,11 @@ extern "C" { * @param mask the image will be drawn only in this area * @param src pointer to a lv_color_t array which contains the pixels of the image * @param style style of the image + * @param antialias anti-alias transformations (rotate, zoom) or not * @param opa_scale scale down all opacities by the factor */ void lv_draw_img(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); + uint16_t angle, uint16_t zoom, bool antialaias, lv_opa_t opa_scale); /** * Get the type of an image source diff --git a/src/lv_draw/lv_img_buf.c b/src/lv_draw/lv_img_buf.c index bc998b8d8..89a57708a 100644 --- a/src/lv_draw/lv_img_buf.c +++ b/src/lv_draw/lv_img_buf.c @@ -24,7 +24,7 @@ /********************** * STATIC PROTOTYPES **********************/ -static inline bool transform_anti_alias(lv_img_rotate_dsc_t * dsc); +static inline bool transform_anti_alias(lv_img_transform_dsc_t * dsc); /********************** * STATIC VARIABLES @@ -161,118 +161,6 @@ lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y) return LV_OPA_COVER; } -/** - * Get the color of an image's pixel - * @param dsc an image descriptor - * @param x x coordinate of the point to get - * @param y x coordinate of the point to get - * @param color the color of the image. In case of `LV_IMG_CF_ALPHA_1/2/4/8` this color is used. - * Not used in other cases. - * @param safe true: check out of bounds - * @return color of the point - */ -void lv_img_buf_get_px(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_color_t * px_color, lv_opa_t * px_opa) -{ - uint8_t * buf_u8 = (uint8_t *)dsc->data; - - if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { - uint32_t px = dsc->header.w * y * sizeof(lv_color_t) + x * sizeof(lv_color_t); - memcpy(px_color, &buf_u8[px], sizeof(lv_color_t)); - *px_opa = LV_OPA_COVER; - } else if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) { - uint32_t px = dsc->header.w * y * LV_IMG_PX_SIZE_ALPHA_BYTE + x * LV_IMG_PX_SIZE_ALPHA_BYTE; - memcpy(px_color, &buf_u8[px], sizeof(lv_color_t)); - *px_opa = buf_u8[px + LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; -#if LV_COLOR_SIZE == 32 - p_color.ch.alpha = 0xFF; /*Only the color should be get so use a default alpha value*/ -#endif - } else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT) { - buf_u8 += 4 * 2; - uint8_t bit = x & 0x7; - x = x >> 3; - - /* Get the current pixel. - * dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned - * so the possible real width are 8, 16, 24 ...*/ - uint32_t px = ((dsc->header.w + 7) >> 3) * y + x; - px_color->full = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit); - *px_opa = LV_OPA_COVER; - } else if(dsc->header.cf == LV_IMG_CF_INDEXED_2BIT) { - buf_u8 += 4 * 4; - uint8_t bit = (x & 0x3) * 2; - x = x >> 2; - - /* Get the current pixel. - * dsc->header.w + 3 means rounding up to 4 because the lines are byte aligned - * so the possible real width are 4, 8, 12 ...*/ - uint32_t px = ((dsc->header.w + 3) >> 2) * y + x; - px_color->full = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit); - *px_opa = LV_OPA_COVER; - } else if(dsc->header.cf == LV_IMG_CF_INDEXED_4BIT) { - buf_u8 += 4 * 16; - uint8_t bit = (x & 0x1) * 4; - x = x >> 1; - - /* Get the current pixel. - * dsc->header.w + 1 means rounding up to 2 because the lines are byte aligned - * so the possible real width are 2, 4, 6 ...*/ - uint32_t px = ((dsc->header.w + 1) >> 1) * y + x; - px_color->full = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit); - *px_opa = LV_OPA_COVER; - } else if(dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) { - buf_u8 += 4 * 256; - uint32_t px = dsc->header.w * y + x; - px_color->full = buf_u8[px]; - } else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT || dsc->header.cf == LV_IMG_CF_ALPHA_2BIT || - dsc->header.cf == LV_IMG_CF_ALPHA_4BIT || dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) { - *px_color = color; - *px_opa = LV_OPA_COVER; - } else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT) { - uint8_t bit = x & 0x7; - x = x >> 3; - - /* Get the current pixel. - * dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned - * so the possible real width are 8 ,16, 24 ...*/ - uint32_t px = ((dsc->header.w + 7) >> 3) * y + x; - uint8_t tmp = (buf_u8[px] & (1 << (7 - bit))) >> (7 - bit); - *px_opa = tmp ? LV_OPA_TRANSP : LV_OPA_COVER; - *px_color = color; - } else if(dsc->header.cf == LV_IMG_CF_ALPHA_2BIT) { - const uint8_t opa_table[4] = {0, 85, 170, 255}; /*Opacity mapping with bpp = 2*/ - - uint8_t bit = (x & 0x3) * 2; - x = x >> 2; - - /* Get the current pixel. - * dsc->header.w + 4 means rounding up to 8 because the lines are byte aligned - * so the possible real width are 4 ,8, 12 ...*/ - uint32_t px = ((dsc->header.w + 3) >> 2) * y + x; - uint8_t tmp = (buf_u8[px] & (3 << (6 - bit))) >> (6 - bit); - *px_opa = opa_table[tmp]; - *px_color = color; - } else if(dsc->header.cf == LV_IMG_CF_ALPHA_4BIT) { - const uint8_t opa_table[16] = {0, 17, 34, 51, /*Opacity mapping with bpp = 4*/ - 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255}; - - uint8_t bit = (x & 0x1) * 4; - x = x >> 1; - - /* Get the current pixel. - * dsc->header.w + 1 means rounding up to 8 because the lines are byte aligned - * so the possible real width are 2 ,4, 6 ...*/ - uint32_t px = ((dsc->header.w + 1) >> 1) * y + x; - uint8_t tmp = (buf_u8[px] & (0xF << (4 - bit))) >> (4 - bit); - *px_opa = opa_table[tmp]; - *px_color = color; - } else if(dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) { - uint32_t px = dsc->header.w * y + x; - *px_opa = buf_u8[px]; - *px_color = color; - } -} - - /** * Set the color of a pixel of an image. The alpha channel won't be affected. * @param dsc pointer to an image descriptor @@ -493,48 +381,33 @@ uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf) } /** - * Initialize a descriptor to rotate an image - * @param dsc pointer to an `lv_img_rotate_dsc_t` variable - * @param angle angle to rotate - * @param src image source (array of pixels) - * @param src_w width of the image to rotate - * @param src_h height of the image to rotate - * @param cf color format of the image to rotate - * @param pivot_x pivot x - * @param pivot_y pivot y - * @param color a color used for `LV_IMG_CF_INDEXED_1/2/4/8BIT` color formats + * Initialize a descriptor to tranform an image + * @param dsc pointer to an `lv_img_transform_dsc_t` variable whose `cfg` field is initialized */ -void lv_img_buf_rotate_init(lv_img_rotate_dsc_t * dsc, int16_t angle, const void * src, lv_coord_t src_w, lv_coord_t src_h, - lv_img_cf_t cf, lv_coord_t pivot_x, lv_coord_t pivot_y, lv_color_t color) +void lv_img_buf_transform_init(lv_img_transform_dsc_t * dsc) { - memset(dsc, 0x00, sizeof(lv_img_rotate_dsc_t)); + dsc->tmp.pivot_x_256 = dsc->cfg.pivot_x * 256; + dsc->tmp.pivot_y_256 = dsc->cfg.pivot_y * 256; + dsc->tmp.sinma = lv_trigo_sin(-dsc->cfg.angle); + dsc->tmp.cosma = lv_trigo_sin(-dsc->cfg.angle + 90); - dsc->angle = angle; - dsc->src = src; - dsc->src_w = src_w; - dsc->src_h = src_h; - dsc->cf = cf; - dsc->color = color; - dsc->pivot_x = pivot_x; - dsc->pivot_y = pivot_y; - dsc->pivot_x_256 = pivot_x * 256; - dsc->pivot_y_256 = pivot_y * 256; - dsc->sinma = lv_trigo_sin(-angle); - dsc->cosma = lv_trigo_sin(-angle + 90); - - dsc->chroma_keyed = lv_img_cf_is_chroma_keyed(cf) ? 1 : 0; - dsc->has_alpha = lv_img_cf_has_alpha(cf) ? 1 : 0; - if(cf == LV_IMG_CF_TRUE_COLOR || cf == LV_IMG_CF_TRUE_COLOR_ALPHA || cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { - dsc->native_color = 1; + 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 || dsc->cfg.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { + dsc->tmp.native_color = 1; } - dsc->img_dsc.data = src; - dsc->img_dsc.header.always_zero = 0; - dsc->img_dsc.header.cf = cf; - dsc->img_dsc.header.w = src_w; - dsc->img_dsc.header.h = src_h; + dsc->tmp.img_dsc.data = dsc->cfg.src; + dsc->tmp.img_dsc.header.always_zero = 0; + dsc->tmp.img_dsc.header.cf = dsc->cfg.cf; + dsc->tmp.img_dsc.header.w = dsc->cfg.src_w; + dsc->tmp.img_dsc.header.h = dsc->cfg.src_h; - dsc->res_opa = LV_OPA_COVER; + + dsc->tmp.zoom_inv = (256 * 256) / dsc->cfg.zoom; + + dsc->res.opa = LV_OPA_COVER; + dsc->res.color = dsc->cfg.color; } /** @@ -545,43 +418,36 @@ void lv_img_buf_rotate_init(lv_img_rotate_dsc_t * dsc, int16_t angle, const void * @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_get_px_rotated(lv_img_rotate_dsc_t * dsc, lv_coord_t x, lv_coord_t y) +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->src; + const uint8_t * src_u8 = dsc->cfg.src; /*Get the target point relative coordinates to the pivot*/ - int32_t xt = x - dsc->pivot_x; - int32_t yt = y - dsc->pivot_y; + int32_t xt = x - dsc->cfg.pivot_x; + int32_t yt = y - dsc->cfg.pivot_y; - bool fast = false; - bool zoomed = false; - uint16_t zoom = 128; - uint16_t zoom_inv = (256 / zoom) * 256;; int32_t xs; int32_t ys; - if(!zoomed) { + if(dsc->cfg.zoom == LV_IMG_ZOOM_NONE) { /*Get the source pixel from the upscaled image*/ - xs = ((dsc->cosma * xt - dsc->sinma * yt) >> (LV_TRIGO_SHIFT - 8)) + dsc->pivot_x_256; - ys = ((dsc->sinma * xt + dsc->cosma * yt) >> (LV_TRIGO_SHIFT - 8)) + dsc->pivot_y_256; + 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 *= zoom_inv; - yt *= zoom_inv; - xs = ((dsc->cosma * xt - dsc->sinma * yt) >> (LV_TRIGO_SHIFT)) + dsc->pivot_x_256; - ys = ((dsc->sinma * xt + dsc->cosma * yt) >> (LV_TRIGO_SHIFT)) + dsc->pivot_y_256; + 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; } - // xt = xt / 2; - // yt = yt / 2; - /*Get the integer part of the source pixel*/ int xs_int = xs >> 8; int ys_int = ys >> 8; - if(xs_int >= dsc->src_w) return false; + if(xs_int >= dsc->cfg.src_w) return false; else if(xs_int < 0) return false; - if(ys_int >= dsc->src_h) return false; + if(ys_int >= dsc->cfg.src_h) return false; else if(ys_int < 0) return false; /* If the fractional < 0x70 mix the source pixel with the left/top pixel @@ -590,39 +456,39 @@ bool lv_img_buf_get_px_rotated(lv_img_rotate_dsc_t * dsc, lv_coord_t x, lv_coord uint8_t px_size; uint32_t pxi; - if(dsc->native_color) { - if(dsc->has_alpha == 0) { + if(dsc->tmp.native_color) { + if(dsc->tmp.has_alpha == 0) { px_size = LV_COLOR_SIZE >> 3; - pxi = dsc->src_w * ys_int * px_size + xs_int * px_size; - memcpy(&dsc->res_color, &src_u8[pxi], px_size); + pxi = dsc->cfg.src_w * ys_int * px_size + xs_int * px_size; + memcpy(&dsc->res.color, &src_u8[pxi], px_size); } else { px_size = LV_IMG_PX_SIZE_ALPHA_BYTE; - pxi = dsc->src_w * ys_int * px_size + xs_int * px_size; - memcpy(&dsc->res_color, &src_u8[pxi], px_size - 1); - dsc->res_opa = src_u8[pxi + px_size - 1]; + pxi = dsc->cfg.src_w * ys_int * px_size + xs_int * px_size; + memcpy(&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->img_dsc, xs_int, ys_int, dsc->color); - dsc->res_opa = lv_img_buf_get_px_alpha(&dsc->img_dsc, xs_int, ys_int); + 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->chroma_keyed) { + if(dsc->tmp.chroma_keyed) { lv_color_t ct = LV_COLOR_TRANSP; - if(dsc->res_color.full == ct.full) return false; + if(dsc->res.color.full == ct.full) return false; } - if(fast) return true; + if(dsc->cfg.antialias == false) return true; - dsc->xs = xs; - dsc->ys = ys; - dsc->xs_int = xs_int; - dsc->ys_int = ys_int; - dsc->pxi = pxi; - dsc->px_size = px_size; + 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; @@ -634,23 +500,23 @@ bool lv_img_buf_get_px_rotated(lv_img_rotate_dsc_t * dsc, lv_coord_t x, lv_coord /********************** * STATIC FUNCTIONS **********************/ -static inline bool transform_anti_alias(lv_img_rotate_dsc_t * dsc) +static inline bool transform_anti_alias(lv_img_transform_dsc_t * dsc) { - const uint8_t * src_u8 = dsc->src; + const uint8_t * src_u8 = dsc->cfg.src; /*Get the fractional part of the source pixel*/ - int xs_fract = dsc->xs & 0xff; - int ys_fract = dsc->ys & 0xff; + int xs_fract = dsc->tmp.xs & 0xff; + int ys_fract = dsc->tmp.ys & 0xff; int32_t xn; /*x neightboor*/ lv_opa_t xr; /*x mix ratio*/ if(xs_fract < 0x70) { xn = - 1; - if(dsc->xs_int + xn < 0) return false; + if(dsc->tmp.xs_int + xn < 0) return false; xr = xs_fract + 0x80; } else if(xs_fract > 0x90) { xn = 1; - if(dsc->xs_int + xn >= dsc->src_w) return false; + if(dsc->tmp.xs_int + xn >= dsc->cfg.src_w) return false; xr = (0xFF - xs_fract) + 0x80; } else { xn = 0; @@ -662,12 +528,12 @@ static inline bool transform_anti_alias(lv_img_rotate_dsc_t * dsc) if(ys_fract < 0x70) { yn = - 1; - if(dsc->ys_int + yn < 0) return false; + if(dsc->tmp.ys_int + yn < 0) return false; yr = ys_fract + 0x80; } else if(ys_fract > 0x90) { yn = 1; - if(dsc->ys_int + yn >= dsc->src_h) return false; + if(dsc->tmp.ys_int + yn >= dsc->cfg.src_h) return false; yr = (0xFF - ys_fract) + 0x80; } else { @@ -675,34 +541,34 @@ static inline bool transform_anti_alias(lv_img_rotate_dsc_t * dsc) yr = 0xFF; } - lv_color_t c00 = dsc->res_color; + lv_color_t c00 = dsc->res.color; lv_color_t c01; lv_color_t c10; lv_color_t c11; - lv_opa_t a00 = dsc->res_opa; + lv_opa_t a00 = dsc->res.opa; lv_opa_t a10; lv_opa_t a01; lv_opa_t a11; - if(dsc->native_color) { - memcpy(&c01, &src_u8[dsc->pxi + dsc->px_size * xn], sizeof(lv_color_t)); - memcpy(&c10, &src_u8[dsc->pxi + dsc->src_w * dsc->px_size * yn], sizeof(lv_color_t)); - memcpy(&c11, &src_u8[dsc->pxi + dsc->src_w * dsc->px_size * yn + dsc->px_size * xn], sizeof(lv_color_t)); - if(dsc->has_alpha) { - a10 = src_u8[dsc->pxi + dsc->px_size * xn + dsc->px_size - 1]; - a01 = src_u8[dsc->pxi + dsc->src_w * dsc->px_size * yn + dsc->px_size - 1]; - a11 = src_u8[dsc->pxi + dsc->src_w * dsc->px_size * yn + dsc->px_size * xn + dsc->px_size - 1]; + if(dsc->tmp.native_color) { + memcpy(&c01, &src_u8[dsc->tmp.pxi + dsc->tmp.px_size * xn], sizeof(lv_color_t)); + memcpy(&c10, &src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn], sizeof(lv_color_t)); + memcpy(&c11, &src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn + dsc->tmp.px_size * xn], sizeof(lv_color_t)); + if(dsc->tmp.has_alpha) { + a10 = src_u8[dsc->tmp.pxi + dsc->tmp.px_size * xn + dsc->tmp.px_size - 1]; + a01 = src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn + dsc->tmp.px_size - 1]; + a11 = src_u8[dsc->tmp.pxi + dsc->cfg.src_w * dsc->tmp.px_size * yn + dsc->tmp.px_size * xn + dsc->tmp.px_size - 1]; } } else { - c01 = lv_img_buf_get_px_color(&dsc->img_dsc, dsc->xs_int + xn, dsc->ys_int, dsc->color); - c10 = lv_img_buf_get_px_color(&dsc->img_dsc, dsc->xs_int, dsc->ys_int + yn, dsc->color); - c11 = lv_img_buf_get_px_color(&dsc->img_dsc, dsc->xs_int + xn, dsc->ys_int + yn, dsc->color); + c01 = lv_img_buf_get_px_color(&dsc->tmp.img_dsc, dsc->tmp.xs_int + xn, dsc->tmp.ys_int, dsc->cfg.color); + c10 = lv_img_buf_get_px_color(&dsc->tmp.img_dsc, dsc->tmp.xs_int, dsc->tmp.ys_int + yn, dsc->cfg.color); + c11 = lv_img_buf_get_px_color(&dsc->tmp.img_dsc, dsc->tmp.xs_int + xn, dsc->tmp.ys_int + yn, dsc->cfg.color); - if(dsc->has_alpha) { - a10 = lv_img_buf_get_px_alpha(&dsc->img_dsc, dsc->xs_int + xn, dsc->ys_int); - a01 = lv_img_buf_get_px_alpha(&dsc->img_dsc, dsc->xs_int, dsc->ys_int + yn); - a11 = lv_img_buf_get_px_alpha(&dsc->img_dsc, dsc->xs_int + xn, dsc->ys_int + yn); + if(dsc->tmp.has_alpha) { + a10 = lv_img_buf_get_px_alpha(&dsc->tmp.img_dsc, dsc->tmp.xs_int + xn, dsc->tmp.ys_int); + a01 = lv_img_buf_get_px_alpha(&dsc->tmp.img_dsc, dsc->tmp.xs_int, dsc->tmp.ys_int + yn); + a11 = lv_img_buf_get_px_alpha(&dsc->tmp.img_dsc, dsc->tmp.xs_int + xn, dsc->tmp.ys_int + yn); } } @@ -711,10 +577,10 @@ static inline bool transform_anti_alias(lv_img_rotate_dsc_t * dsc) lv_opa_t a1; lv_opa_t xr0 = xr; lv_opa_t xr1 = xr; - if(dsc->has_alpha) { + if(dsc->tmp.has_alpha) { a0 = (a00 * xr + (a10 * (255 - xr))) >> 8; a1 = (a01 * xr + (a11 * (255 - xr))) >> 8; - dsc->res_opa = (a0 * yr + (a1 * (255 - yr))) >> 8; + dsc->res.opa = (a0 * yr + (a1 * (255 - yr))) >> 8; if(a0 <= LV_OPA_MIN && a1 <= LV_OPA_MIN) return false; @@ -728,13 +594,13 @@ static inline bool transform_anti_alias(lv_img_rotate_dsc_t * dsc) } else { xr0 = xr; xr1 = xr; - dsc->res_opa = LV_OPA_COVER; + dsc->res.opa = LV_OPA_COVER; } lv_color_t c0 = lv_color_mix(c00, c01, xr0); lv_color_t c1 = lv_color_mix(c10, c11, xr1); - dsc->res_color = lv_color_mix(c0, c1, yr); + dsc->res.color = lv_color_mix(c0, c1, yr); return true; } diff --git a/src/lv_draw/lv_img_buf.h b/src/lv_draw/lv_img_buf.h index 1cfa4b436..3c1d82738 100644 --- a/src/lv_draw/lv_img_buf.h +++ b/src/lv_draw/lv_img_buf.h @@ -46,6 +46,8 @@ extern "C" { #define LV_IMG_BUF_SIZE_INDEXED_4BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h) + 4 * 16) #define LV_IMG_BUF_SIZE_INDEXED_8BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h) + 4 * 256) +#define LV_IMG_ZOOM_NONE 256 + /********************** * TYPEDEFS **********************/ @@ -125,38 +127,48 @@ typedef struct const uint8_t * data; } lv_img_dsc_t; - typedef struct { - lv_color_t res_color; - lv_opa_t res_opa; + struct { + const void * src; /*image source (array of pixels)*/ + lv_coord_t src_w; /*width of the image source*/ + lv_coord_t src_h; /*height of the image source*/ + lv_coord_t pivot_x; /*pivot x*/ + lv_coord_t pivot_y; /* pivot y*/ + int16_t angle; /*angle to rotate*/ + uint16_t zoom; /*256 no zoom, 128 half size, 512 double size*/ + lv_color_t color; /*a color used for `LV_IMG_CF_INDEXED_1/2/4/8BIT` color formats*/ + lv_img_cf_t cf; /*color format of the image to rotate*/ + bool antialias; + }cfg; - const void * src; - lv_coord_t src_w; - lv_coord_t src_h; - lv_coord_t pivot_x; - lv_coord_t pivot_y; - int32_t pivot_x_256; - int32_t pivot_y_256; - lv_img_dsc_t img_dsc; - int32_t sinma; - int32_t cosma; - int16_t angle; - lv_color_t color; - lv_img_cf_t cf; + struct { + lv_color_t color; + lv_opa_t opa; + }res; - uint8_t chroma_keyed :1; - uint8_t has_alpha :1; - uint8_t native_color :1; - /*Runtime data*/ - lv_coord_t xs; - lv_coord_t ys; - lv_coord_t xs_int; - lv_coord_t ys_int; - uint32_t pxi; - uint8_t px_size; + struct { + lv_img_dsc_t img_dsc; + int32_t pivot_x_256; + int32_t pivot_y_256; + int32_t sinma; + int32_t cosma; -}lv_img_rotate_dsc_t; + uint8_t chroma_keyed :1; + uint8_t has_alpha :1; + uint8_t native_color :1; + + uint16_t zoom_inv; + + /*Runtime data*/ + lv_coord_t xs; + lv_coord_t ys; + lv_coord_t xs_int; + lv_coord_t ys_int; + uint32_t pxi; + uint8_t px_size; + }tmp; +}lv_img_transform_dsc_t; /********************** * GLOBAL PROTOTYPES @@ -194,8 +206,6 @@ lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y); -void lv_img_buf_get_px(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_color_t * px_color, lv_opa_t * px_opa); - /** * Set the color of a pixel of an image. The alpha channel won't be affected. * @param dsc pointer to an image descriptor @@ -243,20 +253,12 @@ void lv_img_buf_free(lv_img_dsc_t *dsc); */ uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf); + /** * Initialize a descriptor to rotate an image - * @param dsc pointer to an `lv_img_rotate_dsc_t` variable - * @param angle angle to rotate - * @param src image source (array of pixels) - * @param src_w width of the image to rotate - * @param src_h height of the image to rotate - * @param cf color format of the image to rotate - * @param pivot_x pivot x - * @param pivot_y pivot y - * @param color a color used for `LV_IMG_CF_INDEXED_1/2/4/8BIT` color formats + * @param dsc pointer to an `lv_img_transform_dsc_t` variable whose `cfg` field is initialized */ -void lv_img_buf_rotate_init(lv_img_rotate_dsc_t * dsc, int16_t angle, const void * src, lv_coord_t src_w, lv_coord_t src_h, - lv_img_cf_t cf, lv_coord_t pivot_x, lv_coord_t pivot_y, lv_color_t color); +void lv_img_buf_transform_init(lv_img_transform_dsc_t * dsc); /** * Get which color and opa would come to a pixel if it were rotated @@ -266,7 +268,7 @@ void lv_img_buf_rotate_init(lv_img_rotate_dsc_t * dsc, int16_t angle, const void * @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_get_px_rotated(lv_img_rotate_dsc_t * dsc, lv_coord_t x, lv_coord_t y); +bool lv_img_buf_transform(lv_img_transform_dsc_t * dsc, lv_coord_t x, lv_coord_t y); /********************** diff --git a/src/lv_objx/lv_canvas.c b/src/lv_objx/lv_canvas.c index d4e056aa1..4c7fbdaa5 100644 --- a/src/lv_objx/lv_canvas.c +++ b/src/lv_objx/lv_canvas.c @@ -292,20 +292,22 @@ void lv_canvas_copy_buf(lv_obj_t * canvas, const void * to_copy, lv_coord_t x, l } /** - * Rotate and image and store the result on a canvas. + * Transform and image and store the result on a canvas. * @param canvas pointer to a canvas object * @param img pointer to an image descriptor. * Can be the image descriptor of an other canvas too (`lv_canvas_get_img()`). * @param angle the angle of rotation (0..360); + * @param zoom zoom factor (256 no zoom); * @param offset_x offset X to tell where to put the result data on destination canvas * @param offset_y offset X to tell where to put the result data on destination canvas * @param pivot_x pivot X of rotation. Relative to the source canvas * Set to `source width / 2` to rotate around the center * @param pivot_y pivot Y of rotation. Relative to the source canvas * Set to `source height / 2` to rotate around the center + * @param antialias apply anti-aliasing during the transformation. Looks better but slower. */ -void lv_canvas_rotate(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, lv_coord_t offset_x, lv_coord_t offset_y, - int32_t pivot_x, int32_t pivot_y) +void lv_canvas_transform(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, uint16_t zoom, lv_coord_t offset_x, lv_coord_t offset_y, + int32_t pivot_x, int32_t pivot_y, bool antialias) { LV_ASSERT_OBJ(canvas, LV_OBJX_NAME); LV_ASSERT_NULL(img); @@ -320,28 +322,38 @@ void lv_canvas_rotate(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, lv_c int32_t y; bool ret; - lv_img_rotate_dsc_t dsc; - lv_img_buf_rotate_init(&dsc, angle, img->data, img->header.w, img->header.h, img->header.cf, pivot_x, pivot_y, style->image.color); + lv_img_transform_dsc_t dsc; + dsc.cfg.angle = angle; + dsc.cfg.zoom = zoom; + dsc.cfg.src = img->data; + dsc.cfg.src_w = img->header.w; + dsc.cfg.src_h = img->header.h; + dsc.cfg.cf = img->header.cf; + dsc.cfg.pivot_x = pivot_x; + dsc.cfg.pivot_y = pivot_y; + dsc.cfg.color = style->image.color; + dsc.cfg.antialias = antialias; + lv_img_buf_transform_init(&dsc); for(y = -offset_y; y < dest_height - offset_y; y++) { for(x = -offset_x; x < dest_width - offset_x; x++) { - ret = lv_img_buf_get_px_rotated(&dsc, x, y); + ret = lv_img_buf_transform(&dsc, x, y); if(ret == false) continue; if(x + offset_x >= 0 && x + offset_x < dest_width && y + offset_y >= 0 && y + offset_y < dest_height) { /*If the image has no alpha channel just simple set the result color on the canvas*/ if(lv_img_cf_has_alpha(img->header.cf) == false) { - lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res_color); + lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res.color); } else { lv_color_t bg_color = lv_img_buf_get_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, style->image.color); /*If the canvas has no alpha but the image has mix the image's color with * canvas*/ if(lv_img_cf_has_alpha(ext_dst->dsc.header.cf) == false) { - if(dsc.res_opa < LV_OPA_MAX) dsc.res_color = lv_color_mix(dsc.res_color, bg_color, dsc.res_opa); - lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res_color); + if(dsc.res.opa < LV_OPA_MAX) dsc.res.color = lv_color_mix(dsc.res.color, bg_color, dsc.res.opa); + lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res.color); } /*Both the image and canvas has alpha channel. Some extra calculation is required*/ @@ -349,28 +361,28 @@ void lv_canvas_rotate(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, lv_c lv_opa_t bg_opa = lv_img_buf_get_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y); /* Pick the foreground if it's fully opaque or the Background is fully * transparent*/ - if(dsc.res_opa >= LV_OPA_MAX || bg_opa <= LV_OPA_MIN) { - lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res_color); - lv_img_buf_set_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res_opa); + if(dsc.res.opa >= LV_OPA_MAX || bg_opa <= LV_OPA_MIN) { + lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res.color); + lv_img_buf_set_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y, dsc.res.opa); } /*Opaque background: use simple mix*/ else if(bg_opa >= LV_OPA_MAX) { lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, - lv_color_mix(dsc.res_color, bg_color, dsc.res_opa)); + lv_color_mix(dsc.res.color, bg_color, dsc.res.opa)); } /*Both colors have alpha. Expensive calculation need to be applied*/ else { /*Info: * https://en.wikipedia.org/wiki/Alpha_compositing#Analytical_derivation_of_the_over_operator*/ - lv_opa_t opa_res_2 = 255 - ((uint16_t)((uint16_t)(255 - dsc.res_opa) * (255 - bg_opa)) >> 8); + lv_opa_t opa_res_2 = 255 - ((uint16_t)((uint16_t)(255 - dsc.res.opa) * (255 - bg_opa)) >> 8); if(opa_res_2 == 0) { opa_res_2 = 1; /*never happens, just to be sure*/ } - lv_opa_t ratio = (uint16_t)((uint16_t)dsc.res_opa * 255) / opa_res_2; + lv_opa_t ratio = (uint16_t)((uint16_t)dsc.res.opa * 255) / opa_res_2; lv_img_buf_set_px_color(&ext_dst->dsc, x + offset_x, y + offset_y, - lv_color_mix(dsc.res_color, bg_color, ratio)); + lv_color_mix(dsc.res.color, bg_color, ratio)); lv_img_buf_set_px_alpha(&ext_dst->dsc, x + offset_x, y + offset_y, opa_res_2); } } @@ -873,7 +885,7 @@ void lv_canvas_draw_img(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, const voi lv_disp_t * refr_ori = lv_refr_get_disp_refreshing(); lv_refr_set_disp_refreshing(&disp); - lv_draw_img(&coords, &mask, src, style, 0, LV_OPA_COVER); + lv_draw_img(&coords, &mask, src, style, 0, LV_IMG_ZOOM_NONE, false, LV_OPA_COVER); lv_refr_set_disp_refreshing(refr_ori); } diff --git a/src/lv_objx/lv_canvas.h b/src/lv_objx/lv_canvas.h index 9ef6c1a3d..9a648e5c1 100644 --- a/src/lv_objx/lv_canvas.h +++ b/src/lv_objx/lv_canvas.h @@ -151,20 +151,22 @@ void lv_canvas_copy_buf(lv_obj_t * canvas, const void * to_copy, lv_coord_t x, l lv_coord_t h); /** - * Rotate and image and store the result on a canvas. + * Transform and image and store the result on a canvas. * @param canvas pointer to a canvas object * @param img pointer to an image descriptor. * Can be the image descriptor of an other canvas too (`lv_canvas_get_img()`). * @param angle the angle of rotation (0..360); + * @param zoom zoom factor (256 no zoom); * @param offset_x offset X to tell where to put the result data on destination canvas * @param offset_y offset X to tell where to put the result data on destination canvas * @param pivot_x pivot X of rotation. Relative to the source canvas * Set to `source width / 2` to rotate around the center * @param pivot_y pivot Y of rotation. Relative to the source canvas * Set to `source height / 2` to rotate around the center + * @param antialias apply anti-aliasing during the transformation. Looks better but slower. */ -void lv_canvas_rotate(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, lv_coord_t offset_x, lv_coord_t offset_y, - int32_t pivot_x, int32_t pivot_y); +void lv_canvas_transform(lv_obj_t * canvas, lv_img_dsc_t * img, int16_t angle, uint16_t zoom, lv_coord_t offset_x, lv_coord_t offset_y, + int32_t pivot_x, int32_t pivot_y, bool antialias); diff --git a/src/lv_objx/lv_img.c b/src/lv_objx/lv_img.c index d70a1707a..f792867ab 100644 --- a/src/lv_objx/lv_img.c +++ b/src/lv_objx/lv_img.c @@ -80,6 +80,8 @@ lv_obj_t * lv_img_create(lv_obj_t * par, const lv_obj_t * copy) ext->w = lv_obj_get_width(new_img); ext->h = lv_obj_get_height(new_img); ext->angle = 0; + ext->zoom = LV_IMG_ZOOM_NONE; + ext->antialias = LV_ANTIALIAS ? 1 : 0; ext->auto_size = 1; ext->offset.x = 0; ext->offset.y = 0; @@ -269,10 +271,47 @@ void lv_img_set_angle(lv_obj_t * img, int16_t angle) if(angle < 0 || angle >= 360) angle = angle % 360; lv_img_ext_t * ext = lv_obj_get_ext_attr(img); + if(angle == ext->angle) return; + ext->angle = angle; lv_obj_refresh_ext_draw_pad(img); lv_obj_invalidate(img); +} +/** + * Set the zoom factor of the image. + * @param img pointer to an image object + * @param zoom the zoom factor. + * - 256 or LV_ZOOM_IMG_NONE for no zoom + * - <256: scale down + * - >256 scale up + * - 128 half size + * - 512 double size + */ +void lv_img_set_zoom(lv_obj_t * img, uint16_t zoom) +{ + lv_img_ext_t * ext = lv_obj_get_ext_attr(img); + if(zoom == ext->zoom) return; + + if(zoom == 0) zoom = 1; + + ext->zoom = zoom; + lv_obj_refresh_ext_draw_pad(img); + lv_obj_invalidate(img); +} + +/** + * Enable/disable anti-aliasing for the transformations (rotate, zoom) or not + * @param img pointer to an image object + * @param antialias true: anti-aliased; false: not anti-aliased + */ +void lv_img_set_antialais(lv_obj_t * img, bool antialias) +{ + lv_img_ext_t * ext = lv_obj_get_ext_attr(img); + if(antialias == ext->antialias) return; + + ext->antialias = antialias; + lv_obj_invalidate(img); } /*===================== @@ -366,6 +405,34 @@ uint16_t lv_img_get_angle(lv_obj_t * img) return ext->angle; } +/** + * Get the zoom factor of the image. + * @param img pointer to an image object + * @return zoom factor (256: no zoom) + */ +uint16_t lv_img_get_zoom(lv_obj_t * img) +{ + LV_ASSERT_OBJ(img, LV_OBJX_NAME); + + lv_img_ext_t * ext = lv_obj_get_ext_attr(img); + + return ext->zoom; +} + +/** + * Get whether the transformations (rotate, zoom) are anti-aliased or not + * @param img pointer to an image object + * @return true: anti-aliased; false: not anti-aliased + */ +bool lv_img_get_antialais(lv_obj_t * img) +{ + LV_ASSERT_OBJ(img, LV_OBJX_NAME); + + lv_img_ext_t * ext = lv_obj_get_ext_attr(img); + + return ext->antialias ? true : false; +} + /********************** * STATIC FUNCTIONS **********************/ @@ -414,7 +481,7 @@ static lv_design_res_t lv_img_design(lv_obj_t * img, const lv_area_t * clip_area cords_tmp.x1 = coords.x1; cords_tmp.x2 = coords.x1 + ext->w - 1; for(; cords_tmp.x1 < coords.x2; cords_tmp.x1 += ext->w, cords_tmp.x2 += ext->w) { - lv_draw_img(&cords_tmp, clip_area, ext->src, style, ext->angle, opa_scale); + lv_draw_img(&cords_tmp, clip_area, ext->src, style, ext->angle, ext->zoom, ext->antialias, opa_scale); } } } else if(ext->src_type == LV_IMG_SRC_SYMBOL) { @@ -426,7 +493,7 @@ static lv_design_res_t lv_img_design(lv_obj_t * img, const lv_area_t * clip_area } else { /*Trigger the error handler of image drawer*/ LV_LOG_WARN("lv_img_design: image source type is unknown"); - lv_draw_img(&img->coords, clip_area, NULL, style, 0, opa_scale); + lv_draw_img(&img->coords, clip_area, NULL, style, 0, LV_IMG_ZOOM_NONE, false, opa_scale); } } @@ -464,9 +531,10 @@ static lv_res_t lv_img_signal(lv_obj_t * img, lv_signal_t sign, void * param) } } else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) { /*If the image has angle provide enough room for the rotated corners */ - if(ext->angle) { + if(ext->angle && ext->zoom) { lv_sqrt_res_t ds; lv_sqrt(ext->w * ext->w + ext->h * ext->h, &ds); + ds.i = (ds.i * ext->zoom + 0) >> 8; /*+10 to be sure anything won't be clipped*/ lv_coord_t d = (ds.i - LV_MATH_MIN(ext->w, ext->h)) / 2; img->ext_draw_pad = LV_MATH_MAX(img->ext_draw_pad, d); diff --git a/src/lv_objx/lv_img.h b/src/lv_objx/lv_img.h index cb02a1655..d9a308e2f 100644 --- a/src/lv_objx/lv_img.h +++ b/src/lv_objx/lv_img.h @@ -43,9 +43,11 @@ typedef struct lv_coord_t w; /*Width of the image (Handled by the library)*/ lv_coord_t h; /*Height of the image (Handled by the library)*/ uint16_t angle; + uint16_t zoom; /*256 means no zoom, 512 double size, 128 hasl size*/ uint8_t src_type : 2; /*See: lv_img_src_t*/ uint8_t auto_size : 1; /*1: automatically set the object size to the image size*/ uint8_t cf : 5; /*Color format from `lv_img_color_format_t`*/ + uint8_t antialias :1; /*Apply anti-aliasing in transformations (rotate, zoom)*/ } lv_img_ext_t; /*Styles*/ @@ -109,6 +111,25 @@ void lv_img_set_offset_y(lv_obj_t * img, lv_coord_t y); */ void lv_img_set_angle(lv_obj_t * img, int16_t angle); +/** + * Set the zoom factor of the image. + * @param img pointer to an image object + * @param zoom the zoom factor. + * - 256 or LV_ZOOM_IMG_NONE for no zoom + * - <256: scale down + * - >256 scale up + * - 128 half size + * - 512 double size + */ +void lv_img_set_zoom(lv_obj_t * img, uint16_t zoom); + +/** + * Enable/disable anti-aliasing for the transformations (rotate, zoom) or not + * @param img pointer to an image object + * @param antialias true: anti-aliased; false: not anti-aliased + */ +void lv_img_set_antialais(lv_obj_t * img, bool antialias); + /** * Set the style of an image * @param img pointer to an image object @@ -167,6 +188,20 @@ lv_coord_t lv_img_get_offset_y(lv_obj_t * img); */ uint16_t lv_img_get_angle(lv_obj_t * img); +/** + * Get the zoom factor of the image. + * @param img pointer to an image object + * @return zoom factor (256: no zoom) + */ +uint16_t lv_img_get_zoom(lv_obj_t * img); + +/** + * Get whether the transformations (rotate, zoom) are anti-aliased or not + * @param img pointer to an image object + * @return true: anti-aliased; false: not anti-aliased + */ +bool lv_img_get_antialais(lv_obj_t * img); + /** * Get the style of an image object * @param img pointer to an image object diff --git a/src/lv_objx/lv_imgbtn.c b/src/lv_objx/lv_imgbtn.c index d264f6a2d..16a468689 100644 --- a/src/lv_objx/lv_imgbtn.c +++ b/src/lv_objx/lv_imgbtn.c @@ -303,7 +303,7 @@ static lv_design_res_t lv_imgbtn_design(lv_obj_t * imgbtn, const lv_area_t * cli if(lv_img_src_get_type(src) == LV_IMG_SRC_SYMBOL) { lv_draw_label(&imgbtn->coords, clip_area, style, opa_scale, src, LV_TXT_FLAG_NONE, NULL, NULL, NULL); } else { - lv_draw_img(&imgbtn->coords, clip_area, src, style, 0, opa_scale); + lv_draw_img(&imgbtn->coords, clip_area, src, style, 0, LV_IMG_ZOOM_NONE, false, opa_scale); } #else const void * src = ext->img_src_left[state]; From 42cde3188865a3f61492a549553eb59d1d21da40 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 8 Nov 2019 22:58:09 +0100 Subject: [PATCH 12/17] minor img transform fixes --- src/lv_objx/lv_img.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lv_objx/lv_img.c b/src/lv_objx/lv_img.c index f792867ab..982bb8d90 100644 --- a/src/lv_objx/lv_img.c +++ b/src/lv_objx/lv_img.c @@ -273,6 +273,7 @@ void lv_img_set_angle(lv_obj_t * img, int16_t angle) lv_img_ext_t * ext = lv_obj_get_ext_attr(img); if(angle == ext->angle) return; + lv_obj_invalidate(img); ext->angle = angle; lv_obj_refresh_ext_draw_pad(img); lv_obj_invalidate(img); @@ -295,6 +296,7 @@ void lv_img_set_zoom(lv_obj_t * img, uint16_t zoom) if(zoom == 0) zoom = 1; + lv_obj_invalidate(img); ext->zoom = zoom; lv_obj_refresh_ext_draw_pad(img); lv_obj_invalidate(img); @@ -531,7 +533,7 @@ static lv_res_t lv_img_signal(lv_obj_t * img, lv_signal_t sign, void * param) } } else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) { /*If the image has angle provide enough room for the rotated corners */ - if(ext->angle && ext->zoom) { + if(ext->angle || ext->zoom != LV_IMG_ZOOM_NONE) { lv_sqrt_res_t ds; lv_sqrt(ext->w * ext->w + ext->h * ext->h, &ds); ds.i = (ds.i * ext->zoom + 0) >> 8; /*+10 to be sure anything won't be clipped*/ From 5f1d1f417463754ef722cefaa12ac2cfef1b21db Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 8 Nov 2019 23:07:35 +0100 Subject: [PATCH 13/17] minor img transform fix --- src/lv_draw/lv_draw_img.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_draw/lv_draw_img.c b/src/lv_draw/lv_draw_img.c index 74f736868..f28c47ebb 100644 --- a/src/lv_draw/lv_draw_img.c +++ b/src/lv_draw/lv_draw_img.c @@ -406,7 +406,7 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, trans_dsc.cfg.pivot_x = map_w / 2; trans_dsc.cfg.pivot_y = map_h / 2; trans_dsc.cfg.color = style->image.color; - trans_dsc.cfg.antialias = true; + trans_dsc.cfg.antialias = antialaias; lv_img_buf_transform_init(&trans_dsc); } From eb90f3f41829e0206eea93b6a5fbb93f2be14e86 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 8 Nov 2019 23:12:07 +0100 Subject: [PATCH 14/17] revert accidentally deleted lv_img_buf_set_px_color --- src/lv_draw/lv_img_buf.c | 62 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/lv_draw/lv_img_buf.c b/src/lv_draw/lv_img_buf.c index 2b79c7b17..0b65e684e 100644 --- a/src/lv_draw/lv_img_buf.c +++ b/src/lv_draw/lv_img_buf.c @@ -216,6 +216,68 @@ void lv_img_buf_set_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_ } } +/** + * Set the color of a pixel of an image. The alpha channel won't be affected. + * @param dsc pointer to an image descriptor + * @param x x coordinate of the point to set + * @param y x coordinate of the point to set + * @param c color of the point + * @param safe true: check out of bounds + */ +void lv_img_buf_set_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t c) +{ + uint8_t * buf_u8 = (uint8_t *)dsc->data; + + if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR || dsc->header.cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { + uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3; + uint32_t px = dsc->header.w * y * px_size + x * px_size; + memcpy(&buf_u8[px], &c, px_size); + } else if(dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) { + uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf) >> 3; + uint32_t px = dsc->header.w * y * px_size + x * px_size; + memcpy(&buf_u8[px], &c, px_size - 1); /*-1 to not overwrite the alpha value*/ + } else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT) { + buf_u8 += sizeof(lv_color32_t) * 2; /*Skip the palette*/ + + uint8_t bit = x & 0x7; + x = x >> 3; + + /* Get the current pixel. + * dsc->header.w + 7 means rounding up to 8 because the lines are byte aligned + * so the possible real width are 8 ,16, 24 ...*/ + uint32_t px = ((dsc->header.w + 7) >> 3) * y + x; + buf_u8[px] = buf_u8[px] & ~(1 << (7 - bit)); + buf_u8[px] = buf_u8[px] | ((c.full & 0x1) << (7 - bit)); + } else if(dsc->header.cf == LV_IMG_CF_INDEXED_2BIT) { + buf_u8 += sizeof(lv_color32_t) * 4; /*Skip the palette*/ + uint8_t bit = (x & 0x3) * 2; + x = x >> 2; + + /* Get the current pixel. + * dsc->header.w + 3 means rounding up to 4 because the lines are byte aligned + * so the possible real width are 4, 8 ,12 ...*/ + uint32_t px = ((dsc->header.w + 3) >> 2) * y + x; + + buf_u8[px] = buf_u8[px] & ~(3 << (6 - bit)); + buf_u8[px] = buf_u8[px] | ((c.full & 0x3) << (6 - bit)); + } else if(dsc->header.cf == LV_IMG_CF_INDEXED_4BIT) { + buf_u8 += sizeof(lv_color32_t) * 16; /*Skip the palette*/ + uint8_t bit = (x & 0x1) * 4; + x = x >> 1; + + /* Get the current pixel. + * dsc->header.w + 1 means rounding up to 2 because the lines are byte aligned + * so the possible real width are 2 ,4, 6 ...*/ + uint32_t px = ((dsc->header.w + 1) >> 1) * y + x; + buf_u8[px] = buf_u8[px] & ~(0xF << (4 - bit)); + buf_u8[px] = buf_u8[px] | ((c.full & 0xF) << (4 - bit)); + } else if(dsc->header.cf == LV_IMG_CF_INDEXED_8BIT) { + buf_u8 += sizeof(lv_color32_t) * 256; /*Skip the palette*/ + uint32_t px = dsc->header.w * y + x; + buf_u8[px] = c.full; + } +} + /** * Set the palette color of an indexed image. Valid only for `LV_IMG_CF_INDEXED1/2/4/8` * @param dsc pointer to an image descriptor From 40459e01c95eed578f3fcea7a9b76bcadad53e6d Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Sat, 9 Nov 2019 00:57:26 +0100 Subject: [PATCH 15/17] change lv_objmask default style to transparent --- src/lv_objx/lv_objmask.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_objx/lv_objmask.c b/src/lv_objx/lv_objmask.c index 98fe0a5b7..9b103c896 100644 --- a/src/lv_objx/lv_objmask.c +++ b/src/lv_objx/lv_objmask.c @@ -71,7 +71,7 @@ lv_obj_t * lv_objmask_create(lv_obj_t * par, const lv_obj_t * copy) /*Init the new object mask object mask*/ if(copy == NULL) { - lv_objmask_set_style(new_objmask, LV_OBJMASK_STYLE_BG, &lv_style_plain); + lv_objmask_set_style(new_objmask, LV_OBJMASK_STYLE_BG, &lv_style_transp); } /*Copy an existing object mask*/ From 3ed0cd444a22539dd60b9eff943e00effa38d3cc Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Mon, 11 Nov 2019 12:32:13 +0100 Subject: [PATCH 16/17] lv_task: fix crash after executing one shot tasks --- src/lv_misc/lv_task.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lv_misc/lv_task.c b/src/lv_misc/lv_task.c index af0c95aa6..777d33076 100644 --- a/src/lv_misc/lv_task.c +++ b/src/lv_misc/lv_task.c @@ -123,6 +123,7 @@ LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void) task_interrupter = LV_GC_ROOT(_lv_task_act); /*Check all tasks again from the highest priority */ end_flag = false; + if(task_deleted) task_interrupter = NULL; break; } } @@ -133,6 +134,7 @@ LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void) if(lv_task_exec(LV_GC_ROOT(_lv_task_act))) { task_interrupter = LV_GC_ROOT(_lv_task_act); /*Check all tasks again from the highest priority */ end_flag = false; + if(task_deleted) task_interrupter = NULL; break; } } From f8d5d3146976676ae8381341ebfa488b8ff96395 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 12 Nov 2019 09:45:40 +0100 Subject: [PATCH 17/17] fix typo in lv_img_set/get_antialias --- src/lv_objx/lv_img.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lv_objx/lv_img.c b/src/lv_objx/lv_img.c index 982bb8d90..b6c6fe50f 100644 --- a/src/lv_objx/lv_img.c +++ b/src/lv_objx/lv_img.c @@ -307,7 +307,7 @@ void lv_img_set_zoom(lv_obj_t * img, uint16_t zoom) * @param img pointer to an image object * @param antialias true: anti-aliased; false: not anti-aliased */ -void lv_img_set_antialais(lv_obj_t * img, bool antialias) +void lv_img_set_antialias(lv_obj_t * img, bool antialias) { lv_img_ext_t * ext = lv_obj_get_ext_attr(img); if(antialias == ext->antialias) return; @@ -426,7 +426,7 @@ uint16_t lv_img_get_zoom(lv_obj_t * img) * @param img pointer to an image object * @return true: anti-aliased; false: not anti-aliased */ -bool lv_img_get_antialais(lv_obj_t * img) +bool lv_img_get_antialias(lv_obj_t * img) { LV_ASSERT_OBJ(img, LV_OBJX_NAME);