diff --git a/examples/widgets/img/lv_example_img_1.c b/examples/widgets/img/lv_example_img_1.c index 76ef1f41e..473a686c2 100644 --- a/examples/widgets/img/lv_example_img_1.c +++ b/examples/widgets/img/lv_example_img_1.c @@ -4,11 +4,14 @@ void lv_example_img_1(void) { - LV_IMG_DECLARE(img_cogwheel_argb); + LV_IMG_DECLARE(rgb565a8); lv_obj_t * img1 = lv_img_create(lv_scr_act()); - lv_img_set_src(img1, &img_cogwheel_argb); + lv_img_set_src(img1, &rgb565a8); lv_obj_align(img1, LV_ALIGN_CENTER, 0, -20); - lv_obj_set_size(img1, 200, 200); +// lv_obj_set_size(img1, 200, 200); + + lv_img_set_angle(img1, 100); + lv_img_set_antialias(img1, 0); lv_obj_t * img2 = lv_img_create(lv_scr_act()); lv_img_set_src(img2, LV_SYMBOL_OK "Accept"); diff --git a/src/draw/lv_draw_img.c b/src/draw/lv_draw_img.c index 08e26c415..dca3d9786 100644 --- a/src/draw/lv_draw_img.c +++ b/src/draw/lv_draw_img.c @@ -236,12 +236,7 @@ LV_ATTRIBUTE_FAST_MEM static lv_res_t decode_and_draw(lv_draw_ctx_t * draw_ctx, if(cdsc == NULL) return LV_RES_INV; - - lv_img_cf_t cf; - if(lv_img_cf_is_chroma_keyed(cdsc->dec_dsc.header.cf)) cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED; - else if(LV_IMG_CF_ALPHA_8BIT == cdsc->dec_dsc.header.cf) cf = LV_IMG_CF_ALPHA_8BIT; - else if(lv_img_cf_has_alpha(cdsc->dec_dsc.header.cf)) cf = LV_IMG_CF_TRUE_COLOR_ALPHA; - else cf = LV_IMG_CF_TRUE_COLOR; + lv_img_cf_t cf = cdsc->dec_dsc.header.cf; if(cf == LV_IMG_CF_ALPHA_8BIT) { if(draw_dsc->angle || draw_dsc->zoom != LV_IMG_ZOOM_NONE) { diff --git a/src/draw/lv_img_buf.c b/src/draw/lv_img_buf.c index 342eebd6c..82286d0c0 100644 --- a/src/draw/lv_img_buf.c +++ b/src/draw/lv_img_buf.c @@ -54,7 +54,7 @@ lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t 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 || - dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA) { + dsc->header.cf == LV_IMG_CF_TRUE_COLOR_ALPHA || dsc->header.cf == LV_IMG_CF_RGB565A8) { 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; lv_memcpy_small(&p_color, &buf_u8[px], sizeof(lv_color_t)); @@ -386,6 +386,7 @@ uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf) case LV_IMG_CF_TRUE_COLOR: return LV_IMG_BUF_SIZE_TRUE_COLOR(w, h); case LV_IMG_CF_TRUE_COLOR_ALPHA: + case LV_IMG_CF_RGB565A8: return LV_IMG_BUF_SIZE_TRUE_COLOR_ALPHA(w, h); case LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED: return LV_IMG_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h); diff --git a/src/draw/lv_img_decoder.c b/src/draw/lv_img_decoder.c index 6b4ce6428..13050b8b7 100644 --- a/src/draw/lv_img_decoder.c +++ b/src/draw/lv_img_decoder.c @@ -361,7 +361,8 @@ lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder lv_img_cf_t cf = dsc->header.cf; /*Process true color formats*/ - if(cf == LV_IMG_CF_TRUE_COLOR || cf == LV_IMG_CF_TRUE_COLOR_ALPHA || cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED || + if(cf == LV_IMG_CF_TRUE_COLOR || cf == LV_IMG_CF_TRUE_COLOR_ALPHA || + cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED || cf == LV_IMG_CF_RGB565A8 || cf == LV_IMG_CF_ALPHA_8BIT) { if(dsc->src_type == LV_IMG_SRC_VARIABLE) { /*In case of uncompressed formats the image stored in the ROM/RAM. diff --git a/src/draw/sw/lv_draw_sw_img.c b/src/draw/sw/lv_draw_sw_img.c index 2c7a7858e..b9ed267e0 100644 --- a/src/draw/sw/lv_draw_sw_img.c +++ b/src/draw/sw/lv_draw_sw_img.c @@ -80,6 +80,19 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_img_decoded(struct _lv_draw_ctx_t * draw_c blend_dsc.blend_area = coords; lv_draw_sw_blend(draw_ctx, &blend_dsc); } +#if LV_COLOR_DEPTH == 16 + else if(!mask_any && !transform && cf == LV_IMG_CF_RGB565A8 && draw_dsc->recolor_opa == LV_OPA_TRANSP) { + lv_coord_t src_w = lv_area_get_width(coords); + lv_coord_t src_h = lv_area_get_height(coords); + blend_dsc.src_buf = (const lv_color_t *)src_buf; + blend_dsc.mask_buf = (const void *)src_buf; + blend_dsc.mask_buf += sizeof(lv_color_t) * src_w * src_h; + blend_dsc.blend_area = coords; + blend_dsc.mask_area = coords; + blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; + lv_draw_sw_blend(draw_ctx, &blend_dsc); + } +#endif /*In the other cases every pixel need to be checked one-by-one*/ else { blend_area.x1 = draw_ctx->clip_area->x1; diff --git a/src/draw/sw/lv_draw_sw_transform.c b/src/draw/sw/lv_draw_sw_transform.c index 9a480a286..b73d16b50 100644 --- a/src/draw/sw/lv_draw_sw_transform.c +++ b/src/draw/sw/lv_draw_sw_transform.c @@ -54,9 +54,15 @@ static void rgb_no_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, l int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, int32_t x_end, lv_color_t * cbuf, uint8_t * abuf); +#if LV_COLOR_DEPTH == 16 +static void rgb565a8_no_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, + int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, + int32_t x_end, lv_color_t * cbuf, uint8_t * abuf); +#endif + static void argb_and_rgb_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, - int32_t x_end, lv_color_t * cbuf, uint8_t * abuf, bool has_alpha); + int32_t x_end, lv_color_t * cbuf, uint8_t * abuf, lv_img_cf_t cf); /********************** * STATIC VARIABLES @@ -101,7 +107,6 @@ void lv_draw_sw_transform(lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, lv_coord_t dest_w = lv_area_get_width(dest_area); lv_coord_t dest_h = lv_area_get_height(dest_area); lv_coord_t y; - bool has_alpha = lv_img_cf_has_alpha(cf); for(y = 0; y < dest_h; y++) { int32_t xs1_ups, ys1_ups, xs2_ups, ys2_ups; @@ -120,17 +125,22 @@ void lv_draw_sw_transform(lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, int32_t ys_ups = ys1_ups + 1 * ys_step_256 / 2 / 256; if(draw_dsc->antialias == 0) { - if(cf == LV_IMG_CF_TRUE_COLOR_ALPHA) { - argb_no_aa(src_buf, src_w, src_h, src_stride, xs_ups, ys_ups, xs_step_256, ys_step_256, dest_w, cbuf, abuf); - } - else { - rgb_no_aa(src_buf, src_w, src_h, src_stride, xs_ups, ys_ups, xs_step_256, ys_step_256, dest_w, cbuf, abuf); + switch(cf) { + case LV_IMG_CF_TRUE_COLOR_ALPHA: + argb_no_aa(src_buf, src_w, src_h, src_stride, xs_ups, ys_ups, xs_step_256, ys_step_256, dest_w, cbuf, abuf); + break; + case LV_IMG_CF_TRUE_COLOR: + rgb_no_aa(src_buf, src_w, src_h, src_stride, xs_ups, ys_ups, xs_step_256, ys_step_256, dest_w, cbuf, abuf); + break; + case LV_IMG_CF_RGB565A8: + rgb565a8_no_aa(src_buf, src_w, src_h, src_stride, xs_ups, ys_ups, xs_step_256, ys_step_256, dest_w, cbuf, abuf); + break; } } else { - argb_and_rgb_aa(src_buf, src_w, src_h, src_stride, xs_ups, ys_ups, xs_step_256, ys_step_256, dest_w, cbuf, abuf, - has_alpha); + argb_and_rgb_aa(src_buf, src_w, src_h, src_stride, xs_ups, ys_ups, xs_step_256, ys_step_256, dest_w, cbuf, abuf, cf); } + cbuf += dest_w; abuf += dest_w; } @@ -160,14 +170,18 @@ static void rgb_no_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, l abuf[x] = 0; } else { - const uint8_t * src_tmp = src; - src_tmp += (ys_int * src_stride * sizeof(lv_color_t)) + xs_int * sizeof(lv_color_t); #if LV_COLOR_DEPTH == 8 - cbuf[x].full = src_tmp[0]; + const uint8_t * src_tmp = src; + src_tmp += (ys_int * src_stride + xs_int; + cbuf[x].full = src_tmp[0]; #elif LV_COLOR_DEPTH == 16 - cbuf[x].full = src_tmp[0] + (src_tmp[1] << 8); + const lv_color_t * src_tmp = (const lv_color_t *)src; + src_tmp += ys_int * src_stride + xs_int; + cbuf[x] = *src_tmp; #elif LV_COLOR_DEPTH == 32 + const uint8_t * src_tmp = src; + src_tmp += (ys_int * src_stride * sizeof(lv_color_t)) + xs_int * sizeof(lv_color_t); cbuf[x].full = *((uint32_t *)src_tmp); #endif } @@ -207,14 +221,64 @@ static void argb_no_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, } } -static void argb_and_rgb_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, - int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, - int32_t x_end, lv_color_t * cbuf, uint8_t * abuf, bool has_alpha) +#if LV_COLOR_DEPTH == 16 +static void rgb565a8_no_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, + int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, + int32_t x_end, lv_color_t * cbuf, uint8_t * abuf) { - int32_t xs_ups_start = xs_ups; int32_t ys_ups_start = ys_ups; - const int32_t px_size = has_alpha ? LV_IMG_PX_SIZE_ALPHA_BYTE : sizeof(lv_color_t); + + lv_coord_t x; + for(x = 0; x < x_end; x++) { + xs_ups = xs_ups_start + ((xs_step * x) >> 8); + ys_ups = ys_ups_start + ((ys_step * x) >> 8); + + int32_t xs_int = xs_ups >> 8; + int32_t ys_int = ys_ups >> 8; + if(xs_int < 0 || xs_int >= src_w || ys_int < 0 || ys_int >= src_h) { + abuf[x] = 0; + } + else { + const lv_color_t * src_tmp = (const lv_color_t *)src; + src_tmp += ys_int * src_stride + xs_int; + cbuf[x] = *src_tmp; + + const lv_opa_t * a_tmp = src + src_stride * src_h * sizeof(lv_color_t); + a_tmp += ys_int * src_stride + xs_int; + abuf[x] = *a_tmp; + } + } +} +#endif + + +static void argb_and_rgb_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride, + int32_t xs_ups, int32_t ys_ups, int32_t xs_step, int32_t ys_step, + int32_t x_end, lv_color_t * cbuf, uint8_t * abuf, lv_img_cf_t cf) +{ + int32_t xs_ups_start = xs_ups; + int32_t ys_ups_start = ys_ups; + bool has_alpha; + int32_t px_size; + switch(cf) { + case LV_IMG_CF_TRUE_COLOR: + has_alpha = false; + px_size = sizeof(lv_color_t); + break; + case LV_IMG_CF_TRUE_COLOR_ALPHA: + has_alpha = true; + px_size = LV_IMG_PX_SIZE_ALPHA_BYTE; + break; +#if LV_COLOR_DEPTH == 16 + case LV_IMG_CF_RGB565A8: + has_alpha = true; + px_size = sizeof(lv_color_t); + break; +#endif + default: + return; + } lv_coord_t x; for(x = 0; x < x_end; x++) { @@ -230,7 +294,6 @@ static void argb_and_rgb_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t sr continue; } - /*Get the direction the hor and ver neighbor *`fract` will be in range of 0x00..0xFF and `next` (+/-1) indicates the direction*/ int32_t xs_fract = xs_ups & 0xFF; @@ -258,6 +321,7 @@ static void argb_and_rgb_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t sr const uint8_t * src_tmp = src; src_tmp += (ys_int * src_stride * px_size) + xs_int * px_size; + if(xs_int + x_next >= 0 && xs_int + x_next <= src_w - 1 && ys_int + y_next >= 0 && @@ -271,9 +335,23 @@ static void argb_and_rgb_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t sr lv_color_t c_hor; if(has_alpha) { - lv_opa_t a_base = px_base[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; - lv_opa_t a_ver = px_ver[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; - lv_opa_t a_hor = px_hor[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; + lv_opa_t a_base; + lv_opa_t a_ver; + lv_opa_t a_hor; +#if LV_COLOR_DEPTH == 16 + if(cf == LV_IMG_CF_RGB565A8) { + const lv_opa_t * a_tmp = src + src_stride * src_h * sizeof(lv_color_t); + a_base = *(a_tmp + (ys_int * src_stride) + xs_int); + a_hor = *(a_tmp + (ys_int * src_stride) + xs_int + x_next); + a_ver = *(a_tmp + ((ys_int + y_next) * src_stride) + xs_int); + } + else +#endif + { + a_base = px_base[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; + a_ver = px_ver[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; + a_hor = px_hor[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; + } if(a_ver != a_base) a_ver = ((a_ver * ys_fract) + (a_base * (0x100 - ys_fract))) >> 8; if(a_hor != a_base) a_hor = ((a_hor * xs_fract) + (a_base * (0x100 - xs_fract))) >> 8; @@ -321,8 +399,19 @@ static void argb_and_rgb_aa(const uint8_t * src, lv_coord_t src_w, lv_coord_t sr #elif LV_COLOR_DEPTH == 32 cbuf[x].full = *((uint32_t *)src_tmp); #endif - - lv_opa_t a = has_alpha ? src_tmp[LV_IMG_PX_SIZE_ALPHA_BYTE - 1] : 0xff; + lv_opa_t a; + switch(cf) { + case LV_IMG_CF_TRUE_COLOR_ALPHA: + a = src_tmp[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; + break; +#if LV_COLOR_DEPTH == 16 + case LV_IMG_CF_RGB565A8: + a = *(src + src_stride * src_h * sizeof(lv_color_t) + (ys_int * src_stride) + xs_int); + break; +#endif + default: + a = 0xff; + } if((xs_int == 0 && x_next < 0) || (xs_int == src_w - 1 && x_next > 0)) { abuf[x] = (a * (0xFF - xs_fract)) >> 8;