diff --git a/demos/render/lv_demo_render.c b/demos/render/lv_demo_render.c index 5bfb53461..abd465e8a 100644 --- a/demos/render/lv_demo_render.c +++ b/demos/render/lv_demo_render.c @@ -692,13 +692,127 @@ static void layer_normal_cb(lv_obj_t * parent) layer_core_cb(parent, LV_BLEND_MODE_NORMAL); } -static void layer_additive_cb(lv_obj_t * parent) +static void create_blend_mode_image_buffer(lv_obj_t * canvas) { - return; /*Not working*/ + lv_canvas_fill_bg(canvas, lv_color_hex3(0x844), LV_OPA_COVER); + + lv_layer_t layer; + lv_canvas_init_layer(canvas, &layer); + + lv_draw_label_dsc_t dsc; + lv_draw_label_dsc_init(&dsc); + dsc.color = lv_color_hex(0xff0000); + dsc.text = "R"; + + lv_area_t coords = {0, 0, 100, 60}; + + lv_draw_label(&layer, &dsc, &coords); + dsc.color = lv_color_hex(0x00ff00); + dsc.text = "G"; + coords.x1 = 11; + lv_draw_label(&layer, &dsc, &coords); + + dsc.color = lv_color_hex(0x0000ff); + dsc.text = "B"; + coords.x1 = 23; + lv_draw_label(&layer, &dsc, &coords); + + dsc.color = lv_color_hex(0xffffff); + dsc.text = "W"; + coords.y1 = 14; + coords.x1 = 4; + lv_draw_label(&layer, &dsc, &coords); + + dsc.color = lv_color_hex(0x000000); + dsc.text = "K"; + coords.x1 = 20; + lv_draw_label(&layer, &dsc, &coords); + + lv_canvas_finish_layer(canvas, &layer); +} + +static lv_obj_t * create_blend_mode_obj(lv_obj_t * parent, int32_t col, int32_t row, const void * src, + lv_blend_mode_t blend_mode) +{ + lv_obj_t * obj = lv_image_create(parent); + lv_image_set_src(obj, src); + lv_image_set_blend_mode(obj, blend_mode); + lv_obj_set_style_image_opa(obj, opa_saved, 0); + lv_obj_set_style_image_recolor(obj, lv_color_hex(0x00ff00), 0); + + add_to_cell(obj, col, row); + + return obj; +} + +static void blend_mode_cb(lv_obj_t * parent) +{ + + static const int32_t grid_cols[] = {53, 53, 53, 53, 53, 53, 53, 53, 53, LV_GRID_TEMPLATE_LAST}; + static const int32_t grid_rows[] = {32, 40, 40, 40, 40, 40, 40, LV_GRID_TEMPLATE_LAST}; + lv_obj_set_grid_dsc_array(parent, grid_cols, grid_rows); /*Make the parent darker for additive blending*/ - lv_obj_set_style_bg_color(parent, lv_color_hex3(0x008), 0); - layer_core_cb(parent, LV_BLEND_MODE_ADDITIVE); + lv_obj_set_style_bg_color(parent, lv_color_hex(0x808080), 0); + + static uint8_t buf_rgb565[LV_CANVAS_BUF_SIZE(36, 30, 16, LV_DRAW_BUF_STRIDE_ALIGN)]; + static uint8_t buf_rgb888[LV_CANVAS_BUF_SIZE(36, 30, 24, LV_DRAW_BUF_STRIDE_ALIGN)]; + static uint8_t buf_xrgb8888[LV_CANVAS_BUF_SIZE(36, 30, 32, LV_DRAW_BUF_STRIDE_ALIGN)]; + static uint8_t buf_argb8888[LV_CANVAS_BUF_SIZE(36, 30, 32, LV_DRAW_BUF_STRIDE_ALIGN)]; + + /*The canvas will stay in the top left corner to show the original image*/ + lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); + + const char * cf_txt[] = {"RGB565", "RGB888.", "XRGB8888", "ARGB8888"}; + lv_color_format_t cf_values[] = {LV_COLOR_FORMAT_RGB565, LV_COLOR_FORMAT_RGB888, LV_COLOR_FORMAT_XRGB8888, LV_COLOR_FORMAT_ARGB8888}; + uint8_t * cf_bufs[] = {buf_rgb565, buf_rgb888, buf_xrgb8888, buf_argb8888}; + static lv_image_dsc_t image_dscs[4]; + + const char * mode_txt[] = {"Add.", "Sub.", "Mul."}; + lv_blend_mode_t mode_values[] = {LV_BLEND_MODE_ADDITIVE, LV_BLEND_MODE_SUBTRACTIVE, LV_BLEND_MODE_MULTIPLY}; + + uint32_t m; + for(m = 0; m < 3; m++) { + lv_obj_t * mode_label = lv_label_create(parent); + lv_label_set_text(mode_label, mode_txt[m]); + lv_obj_set_grid_cell(mode_label, LV_GRID_ALIGN_CENTER, 0, 1, LV_GRID_ALIGN_CENTER, 1 + m * 2, 2); + } + + uint32_t cf; + for(cf = 0; cf < 4; cf++) { + lv_obj_t * cf_label = lv_label_create(parent); + lv_label_set_text(cf_label, cf_txt[cf]); + lv_obj_set_grid_cell(cf_label, LV_GRID_ALIGN_CENTER, 1 + cf * 2, 2, LV_GRID_ALIGN_CENTER, 0, 1); + + lv_canvas_set_buffer(canvas, cf_bufs[cf], 36, 30, cf_values[cf]); + create_blend_mode_image_buffer(canvas); + lv_img_dsc_t * img_src = lv_canvas_get_image(canvas); + image_dscs[cf] = *img_src; + + for(m = 0; m < 3; m++) { + lv_obj_t * img; + img = create_blend_mode_obj(parent, 1 + cf * 2, 1 + m * 2, &image_dscs[cf], mode_values[m]); + + img = create_blend_mode_obj(parent, 2 + cf * 2, 1 + m * 2, &image_dscs[cf], mode_values[m]); + lv_image_set_rotation(img, 200); + + img = create_blend_mode_obj(parent, 1 + cf * 2, 2 + m * 2, &image_dscs[cf], mode_values[m]); + lv_obj_set_style_image_recolor_opa(img, LV_OPA_50, 0); + + img = create_blend_mode_obj(parent, 2 + cf * 2, 2 + m * 2, &image_dscs[cf], mode_values[m]); + lv_image_set_rotation(img, 200); + lv_obj_set_style_image_recolor_opa(img, LV_OPA_50, 0); + } + } + + /*Show the recolored image to show the original image*/ + lv_obj_t * img_recolored = lv_image_create(parent); + lv_image_set_src(img_recolored, lv_canvas_get_image(canvas)); + lv_obj_set_style_image_recolor(img_recolored, lv_color_hex(0x00ff00), 0); + lv_obj_set_style_image_recolor_opa(img_recolored, LV_OPA_50, 0); + lv_obj_set_y(img_recolored, 30); + lv_obj_add_flag(img_recolored, LV_OBJ_FLAG_IGNORE_LAYOUT); + } /********************** @@ -717,7 +831,7 @@ static scene_dsc_t scenes[] = { {.name = "arc_image", .create_cb = arc_image_cb}, {.name = "triangle", .create_cb = triangle_cb}, {.name = "layer_normal", .create_cb = layer_normal_cb}, - {.name = "layer_additive", .create_cb = layer_additive_cb}, + {.name = "blend_mode", .create_cb = blend_mode_cb}, {.name = "", .create_cb = NULL} }; diff --git a/demos/render/lv_demo_render.h b/demos/render/lv_demo_render.h index 1ef8b160d..76c668679 100644 --- a/demos/render/lv_demo_render.h +++ b/demos/render/lv_demo_render.h @@ -36,6 +36,7 @@ typedef enum { LV_DEMO_RENDER_SCENE_ARC_IMAGE, LV_DEMO_RENDER_SCENE_TRIANGLE, LV_DEMO_RENDER_SCENE_LAYER_NORMAL, + LV_DEMO_RENDER_SCENE_BLEND_MODE, _LV_DEMO_RENDER_SCENE_NUM, } lv_demo_render_scene_t; diff --git a/src/core/lv_refr.c b/src/core/lv_refr.c index d1bcf5880..b8a867657 100644 --- a/src/core/lv_refr.c +++ b/src/core/lv_refr.c @@ -838,7 +838,7 @@ static lv_result_t layer_get_area(lv_layer_t * layer, lv_obj_t * obj, lv_layer_t } *layer_area_out = inverse_clip_coords_for_obj; - lv_area_increase(layer_area_out, 1, 1); /*To avoid rounding error*/ + lv_area_increase(layer_area_out, 5, 5); /*To avoid rounding error*/ } else if(layer_type == LV_LAYER_TYPE_SIMPLE) { lv_area_t clip_coords_for_obj; diff --git a/src/dev/sdl/lv_sdl_window.c b/src/dev/sdl/lv_sdl_window.c index 4da9a0a44..e43085bc2 100644 --- a/src/dev/sdl/lv_sdl_window.c +++ b/src/dev/sdl/lv_sdl_window.c @@ -340,6 +340,7 @@ static void texture_resize(lv_display_t * disp) #else #error("Unsupported color format") #endif + // px_format = SDL_PIXELFORMAT_BGR24; dsc->texture = SDL_CreateTexture(dsc->renderer, px_format, SDL_TEXTUREACCESS_STATIC, hor_res, ver_res); diff --git a/src/draw/sw/blend/lv_draw_sw_blend_to_argb8888.c b/src/draw/sw/blend/lv_draw_sw_blend_to_argb8888.c index 5dbdeaa80..91c886643 100644 --- a/src/draw/sw/blend/lv_draw_sw_blend_to_argb8888.c +++ b/src/draw/sw/blend/lv_draw_sw_blend_to_argb8888.c @@ -495,7 +495,7 @@ void lv_color_mix_with_alpha_cache_init(lv_color_mix_alpha_cache_t * cache) LV_ATTRIBUTE_FAST_MEM static inline void blend_non_normal_pixel(lv_color32_t * dest, lv_color32_t src, lv_blend_mode_t mode, lv_color_mix_alpha_cache_t * cache) { - lv_color32_t res = {0, 0, 0, 0}; + lv_color32_t res; switch(mode) { case LV_BLEND_MODE_ADDITIVE: res.red = LV_MIN(dest->red + src.red, 255); @@ -516,6 +516,7 @@ LV_ATTRIBUTE_FAST_MEM static inline void blend_non_normal_pixel(lv_color32_t * d LV_LOG_WARN("Not supported blend mode: %d", mode); return; } + res.alpha = src.alpha; *dest = lv_color_32_32_mix(res, *dest, cache); } diff --git a/src/draw/sw/blend/lv_draw_sw_blend_to_rgb565.c b/src/draw/sw/blend/lv_draw_sw_blend_to_rgb565.c index a596dc4d3..e4e659af4 100644 --- a/src/draw/sw/blend/lv_draw_sw_blend_to_rgb565.c +++ b/src/draw/sw/blend/lv_draw_sw_blend_to_rgb565.c @@ -282,28 +282,28 @@ LV_ATTRIBUTE_FAST_MEM static void rgb565_image_blend(_lv_draw_sw_blend_image_dsc } } else { - lv_color16_t * dest_buf_c16 = (lv_color16_t *) dest_buf_u16; - lv_color16_t * src_buf_c16 = (lv_color16_t *) src_buf_u16; uint16_t res = 0; for(y = 0; y < h; y++) { + lv_color16_t * dest_buf_c16 = (lv_color16_t *) dest_buf_u16; + lv_color16_t * src_buf_c16 = (lv_color16_t *) src_buf_u16; for(x = 0; x < w; x++) { switch(dsc->blend_mode) { case LV_BLEND_MODE_ADDITIVE: if(src_buf_u16[x] == 0x0000) continue; /*Do not add pure black*/ - res = LV_MIN(dest_buf_c16[x].red + src_buf_c16[x].red, 31); - res += LV_MIN(dest_buf_c16[x].green + src_buf_c16[x].green, 63); + res = (LV_MIN(dest_buf_c16[x].red + src_buf_c16[x].red, 31)) << 11; + res += (LV_MIN(dest_buf_c16[x].green + src_buf_c16[x].green, 63)) << 5; res += LV_MIN(dest_buf_c16[x].blue + src_buf_c16[x].blue, 31); break; case LV_BLEND_MODE_SUBTRACTIVE: if(src_buf_u16[x] == 0x0000) continue; /*Do not subtract pure black*/ - res = LV_MAX(dest_buf_c16[x].red - src_buf_c16[x].red, 0); - res += LV_MAX(dest_buf_c16[x].green - src_buf_c16[x].green, 0); + res = (LV_MAX(dest_buf_c16[x].red - src_buf_c16[x].red, 0)) << 11; + res += (LV_MAX(dest_buf_c16[x].green - src_buf_c16[x].green, 0)) << 5; res += LV_MAX(dest_buf_c16[x].blue - src_buf_c16[x].blue, 0); break; case LV_BLEND_MODE_MULTIPLY: if(src_buf_u16[x] == 0xffff) continue; /*Do not multiply with pure white (considered as 1)*/ - res = (dest_buf_c16[x].red * src_buf_c16[x].red) >> 5; - res += (dest_buf_c16[x].green * src_buf_c16[x].green) >> 6; + res = ((dest_buf_c16[x].red * src_buf_c16[x].red) >> 5) << 11; + res += ((dest_buf_c16[x].green * src_buf_c16[x].green) >> 6) << 5; res += (dest_buf_c16[x].blue * src_buf_c16[x].blue) >> 5; break; default: @@ -312,7 +312,7 @@ LV_ATTRIBUTE_FAST_MEM static void rgb565_image_blend(_lv_draw_sw_blend_image_dsc } if(mask_buf == NULL) { - lv_color_16_16_mix(res, dest_buf_u16[x], opa); + dest_buf_u16[x] = lv_color_16_16_mix(res, dest_buf_u16[x], opa); } else { if(opa >= LV_OPA_MAX) dest_buf_u16[x] = lv_color_16_16_mix(res, dest_buf_u16[x], mask_buf[x]); @@ -384,28 +384,27 @@ LV_ATTRIBUTE_FAST_MEM static void rgb888_image_blend(_lv_draw_sw_blend_image_dsc mask_buf += mask_stride; } } - } else { - lv_color16_t * dest_buf_c16 = (lv_color16_t *) dest_buf_u16; uint16_t res = 0; for(y = 0; y < h; y++) { + lv_color16_t * dest_buf_c16 = (lv_color16_t *) dest_buf_u16; for(dest_x = 0, src_x = 0; dest_x < w; dest_x++, src_x += src_px_size) { switch(dsc->blend_mode) { case LV_BLEND_MODE_ADDITIVE: - res = LV_MIN(dest_buf_c16[dest_x].red + (src_buf_u8[src_x + 0] >> 3), 31); - res += LV_MIN(dest_buf_c16[dest_x].green + (src_buf_u8[src_x + 1] >> 2), 63); - res += LV_MIN(dest_buf_c16[dest_x].blue + (src_buf_u8[src_x + 2] >> 3), 31); + res = (LV_MIN(dest_buf_c16[dest_x].red + (src_buf_u8[src_x + 2] >> 3), 31)) << 11; + res += (LV_MIN(dest_buf_c16[dest_x].green + (src_buf_u8[src_x + 1] >> 2), 63)) << 5; + res += LV_MIN(dest_buf_c16[dest_x].blue + (src_buf_u8[src_x + 0] >> 3), 31); break; case LV_BLEND_MODE_SUBTRACTIVE: - res = LV_MAX(dest_buf_c16[dest_x].red - (src_buf_u8[src_x + 0] >> 3), 0); - res += LV_MAX(dest_buf_c16[dest_x].green - (src_buf_u8[src_x + 1] >> 2), 0); - res += LV_MAX(dest_buf_c16[dest_x].blue - (src_buf_u8[src_x + 2] >> 3), 0); + res = (LV_MAX(dest_buf_c16[dest_x].red - (src_buf_u8[src_x + 2] >> 3), 0)) << 11; + res += (LV_MAX(dest_buf_c16[dest_x].green - (src_buf_u8[src_x + 1] >> 2), 0)) << 5; + res += LV_MAX(dest_buf_c16[dest_x].blue - (src_buf_u8[src_x + 0] >> 3), 0); break; case LV_BLEND_MODE_MULTIPLY: - res = (dest_buf_c16[dest_x].red * (src_buf_u8[src_x + 0] >> 3)) >> 5; - res += (dest_buf_c16[dest_x].green * (src_buf_u8[src_x + 1] >> 2)) >> 6; - res += (dest_buf_c16[dest_x].blue * (src_buf_u8[src_x + 2] >> 3)) >> 5; + res = ((dest_buf_c16[dest_x].red * (src_buf_u8[src_x + 2] >> 3)) >> 5) << 11; + res += ((dest_buf_c16[dest_x].green * (src_buf_u8[src_x + 1] >> 2)) >> 6) << 5; + res += (dest_buf_c16[dest_x].blue * (src_buf_u8[src_x + 1] >> 3)) >> 5; break; default: LV_LOG_WARN("Not supported blend mode: %d", dsc->blend_mode); @@ -413,7 +412,7 @@ LV_ATTRIBUTE_FAST_MEM static void rgb888_image_blend(_lv_draw_sw_blend_image_dsc } if(mask_buf == NULL) { - lv_color_16_16_mix(res, dest_buf_u16[dest_x], opa); + dest_buf_u16[dest_x] = lv_color_16_16_mix(res, dest_buf_u16[dest_x], opa); } else { if(opa >= LV_OPA_MAX) dest_buf_u16[dest_x] = lv_color_16_16_mix(res, dest_buf_u16[dest_x], mask_buf[dest_x]); @@ -488,25 +487,25 @@ LV_ATTRIBUTE_FAST_MEM static void argb8888_image_blend(_lv_draw_sw_blend_image_d } } else { - lv_color16_t * dest_buf_c16 = (lv_color16_t *) dest_buf_u16; uint16_t res = 0; for(y = 0; y < h; y++) { + lv_color16_t * dest_buf_c16 = (lv_color16_t *) dest_buf_u16; for(dest_x = 0, src_x = 0; dest_x < w; dest_x++, src_x += 4) { switch(dsc->blend_mode) { case LV_BLEND_MODE_ADDITIVE: - res = LV_MIN(dest_buf_c16[dest_x].red + (src_buf_u8[src_x + 0] >> 3), 31); - res += LV_MIN(dest_buf_c16[dest_x].green + (src_buf_u8[src_x + 1] >> 2), 63); - res += LV_MIN(dest_buf_c16[dest_x].blue + (src_buf_u8[src_x + 2] >> 3), 31); + res = (LV_MIN(dest_buf_c16[dest_x].red + (src_buf_u8[src_x + 2] >> 3), 31)) << 11; + res += (LV_MIN(dest_buf_c16[dest_x].green + (src_buf_u8[src_x + 1] >> 2), 63)) << 5; + res += LV_MIN(dest_buf_c16[dest_x].blue + (src_buf_u8[src_x + 0] >> 3), 31); break; case LV_BLEND_MODE_SUBTRACTIVE: - res = LV_MAX(dest_buf_c16[dest_x].red - (src_buf_u8[src_x + 0] >> 3), 0); - res += LV_MAX(dest_buf_c16[dest_x].green - (src_buf_u8[src_x + 1] >> 2), 0); - res += LV_MAX(dest_buf_c16[dest_x].blue - (src_buf_u8[src_x + 2] >> 3), 0); + res = (LV_MAX(dest_buf_c16[dest_x].red - (src_buf_u8[src_x + 2] >> 3), 0)) << 11; + res += (LV_MAX(dest_buf_c16[dest_x].green - (src_buf_u8[src_x + 1] >> 2), 0)) << 5; + res += LV_MAX(dest_buf_c16[dest_x].blue - (src_buf_u8[src_x + 0] >> 3), 0); break; case LV_BLEND_MODE_MULTIPLY: - res = (dest_buf_c16[dest_x].red * (src_buf_u8[src_x + 0] >> 3)) >> 5; - res += (dest_buf_c16[dest_x].green * (src_buf_u8[src_x + 1] >> 2)) >> 6; - res += (dest_buf_c16[dest_x].blue * (src_buf_u8[src_x + 2] >> 3)) >> 5; + res = ((dest_buf_c16[dest_x].red * (src_buf_u8[src_x + 2] >> 3)) >> 5) << 11; + res += ((dest_buf_c16[dest_x].green * (src_buf_u8[src_x + 1] >> 2)) >> 6) << 5; + res += (dest_buf_c16[dest_x].blue * (src_buf_u8[src_x + 0] >> 3)) >> 5; break; default: LV_LOG_WARN("Not supported blend mode: %d", dsc->blend_mode); @@ -514,10 +513,10 @@ LV_ATTRIBUTE_FAST_MEM static void argb8888_image_blend(_lv_draw_sw_blend_image_d } if(mask_buf == NULL && opa >= LV_OPA_MAX) { - lv_color_16_16_mix(res, dest_buf_u16[dest_x], src_buf_u8[src_x + 3]); + dest_buf_u16[dest_x] = lv_color_16_16_mix(res, dest_buf_u16[dest_x], src_buf_u8[src_x + 3]); } else if(mask_buf == NULL && opa < LV_OPA_MAX) { - lv_color_16_16_mix(res, dest_buf_u16[dest_x], LV_OPA_MIX2(opa, src_buf_u8[src_x + 3])); + dest_buf_u16[dest_x] = lv_color_16_16_mix(res, dest_buf_u16[dest_x], LV_OPA_MIX2(opa, src_buf_u8[src_x + 3])); } else { if(opa >= LV_OPA_MAX) dest_buf_u16[dest_x] = lv_color_16_16_mix(res, dest_buf_u16[dest_x], mask_buf[dest_x]); diff --git a/src/draw/sw/blend/lv_draw_sw_blend_to_rgb888.c b/src/draw/sw/blend/lv_draw_sw_blend_to_rgb888.c index c75d0e96e..64f1b3d3b 100644 --- a/src/draw/sw/blend/lv_draw_sw_blend_to_rgb888.c +++ b/src/draw/sw/blend/lv_draw_sw_blend_to_rgb888.c @@ -195,6 +195,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_blend_color_to_rgb888(_lv_draw_sw_blend_fi LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_blend_image_to_rgb888(_lv_draw_sw_blend_image_dsc_t * dsc, uint32_t dest_px_size) { + switch(dsc->src_color_format) { case LV_COLOR_FORMAT_RGB565: rgb565_image_blend(dsc, dest_px_size); @@ -492,19 +493,19 @@ LV_ATTRIBUTE_FAST_MEM static inline void blend_non_normal_pixel(uint8_t * dest, uint8_t res[3] = {0, 0, 0}; switch(mode) { case LV_BLEND_MODE_ADDITIVE: - res[0] = LV_MIN(dest[0] + src.red, 255); + res[0] = LV_MIN(dest[0] + src.blue, 255); res[1] = LV_MIN(dest[1] + src.green, 255); - res[2] = LV_MIN(dest[2] + src.blue, 255); + res[2] = LV_MIN(dest[2] + src.red, 255); break; case LV_BLEND_MODE_SUBTRACTIVE: - res[0] = LV_MAX(dest[0] - src.red, 0); + res[0] = LV_MAX(dest[0] - src.blue, 0); res[1] = LV_MAX(dest[1] - src.green, 0); - res[2] = LV_MAX(dest[2] - src.blue, 0); + res[2] = LV_MAX(dest[2] - src.red, 0); break; case LV_BLEND_MODE_MULTIPLY: - res[0] = (dest[0] * src.red) >> 8; + res[0] = (dest[0] * src.blue) >> 8; res[1] = (dest[1] * src.green) >> 8; - res[2] = (dest[2] * src.blue) >> 8; + res[2] = (dest[2] * src.red) >> 8; break; default: LV_LOG_WARN("Not supported blend mode: %d", mode); @@ -517,10 +518,6 @@ LV_ATTRIBUTE_FAST_MEM static inline void lv_color_24_24_mix(const uint8_t * src, { if(mix == 0) return; - // dest[0] = 0xff; - // dest[1] = 0x00; - // dest[2] = 0x00; - // return; if(mix >= LV_OPA_MAX) { dest[0] = src[0]; diff --git a/src/widgets/image/lv_image.c b/src/widgets/image/lv_image.c index 74da95960..448653dca 100644 --- a/src/widgets/image/lv_image.c +++ b/src/widgets/image/lv_image.c @@ -237,6 +237,7 @@ void lv_image_set_offset_y(lv_obj_t * obj, int32_t y) void lv_image_set_rotation(lv_obj_t * obj, int32_t angle) { + LV_ASSERT_OBJ(obj, MY_CLASS); lv_image_t * img = (lv_image_t *)obj; if(img->align > _LV_IMAGE_ALIGN_AUTO_TRANSFORM) { @@ -281,6 +282,8 @@ void lv_image_set_rotation(lv_obj_t * obj, int32_t angle) void lv_image_set_pivot(lv_obj_t * obj, int32_t x, int32_t y) { + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_image_t * img = (lv_image_t *)obj; if(img->align > _LV_IMAGE_ALIGN_AUTO_TRANSFORM) { x = 0; @@ -323,6 +326,8 @@ void lv_image_set_pivot(lv_obj_t * obj, int32_t x, int32_t y) void lv_image_set_scale(lv_obj_t * obj, uint32_t zoom) { + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_image_t * img = (lv_image_t *)obj; /*If scale is set internally, do no overwrite it*/ @@ -337,6 +342,8 @@ void lv_image_set_scale(lv_obj_t * obj, uint32_t zoom) void lv_image_set_scale_x(lv_obj_t * obj, uint32_t zoom) { + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_image_t * img = (lv_image_t *)obj; /*If scale is set internally, do no overwrite it*/ @@ -351,6 +358,8 @@ void lv_image_set_scale_x(lv_obj_t * obj, uint32_t zoom) void lv_image_set_scale_y(lv_obj_t * obj, uint32_t zoom) { + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_image_t * img = (lv_image_t *)obj; /*If scale is set internally, do no overwrite it*/ @@ -363,8 +372,24 @@ void lv_image_set_scale_y(lv_obj_t * obj, uint32_t zoom) scale_update(obj, img->scale_x, zoom); } +void lv_image_set_blend_mode(lv_obj_t * obj, lv_blend_mode_t blend_mode) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + + /*If scale is set internally, do no overwrite it*/ + if(img->blend_mode == blend_mode) return; + + img->blend_mode = blend_mode; + + lv_obj_invalidate(obj); +} + void lv_image_set_antialias(lv_obj_t * obj, bool antialias) { + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_image_t * img = (lv_image_t *)obj; if(antialias == img->antialias) return; @@ -375,6 +400,7 @@ void lv_image_set_antialias(lv_obj_t * obj, bool antialias) void lv_image_set_align(lv_obj_t * obj, lv_image_align_t align) { LV_ASSERT_OBJ(obj, MY_CLASS); + lv_image_t * img = (lv_image_t *)obj; if(align == img->align) return; @@ -462,6 +488,15 @@ int32_t lv_image_get_scale_y(lv_obj_t * obj) return img->scale_y; } +lv_blend_mode_t lv_image_get_blend_mode(lv_obj_t * obj) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + + lv_image_t * img = (lv_image_t *)obj; + + return img->blend_mode; +} + bool lv_image_get_antialias(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); @@ -474,7 +509,9 @@ bool lv_image_get_antialias(lv_obj_t * obj) lv_image_align_t lv_image_get_align(lv_obj_t * obj) { LV_ASSERT_OBJ(obj, MY_CLASS); + lv_image_t * img = (lv_image_t *)obj; + return img->align; } @@ -671,6 +708,7 @@ static void draw_image(lv_event_t * e) draw_dsc.scale_y = img->scale_y; draw_dsc.rotation = img->rotation; draw_dsc.antialias = img->antialias; + draw_dsc.blend_mode = img->blend_mode; draw_dsc.src = img->src; lv_area_t img_area = {obj->coords.x1, obj->coords.y1, diff --git a/src/widgets/image/lv_image.h b/src/widgets/image/lv_image.h index e6e8c0e37..bc2671fd6 100644 --- a/src/widgets/image/lv_image.h +++ b/src/widgets/image/lv_image.h @@ -47,10 +47,11 @@ typedef struct { uint32_t scale_x; /**< 256 means no zoom, 512 double size, 128 half size*/ uint32_t scale_y; /**< 256 means no zoom, 512 double size, 128 half size*/ lv_point_t pivot; /**< Rotation center of the image*/ - uint8_t src_type : 2; /**< See: lv_image_src_t*/ - uint8_t cf : 5; /**< Color format from `lv_color_format_t`*/ - uint8_t antialias : 1; /**< Apply anti-aliasing in transformations (rotate, zoom)*/ - uint8_t align: 4; /**< Image size mode when image size and object size is different. See `lv_image_align_t`*/ + uint32_t src_type : 2; /**< See: lv_image_src_t*/ + uint32_t cf : 5; /**< Color format from `lv_color_format_t`*/ + uint32_t antialias : 1; /**< Apply anti-aliasing in transformations (rotate, zoom)*/ + uint32_t align: 4; /**< Image size mode when image size and object size is different. See `lv_image_align_t`*/ + uint32_t blend_mode: 4; /**< Element of `lv_blend_mode_t`*/ } lv_image_t; LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_image_class; @@ -202,6 +203,13 @@ void lv_image_set_scale_x(lv_obj_t * obj, uint32_t zoom); */ void lv_image_set_scale_y(lv_obj_t * obj, uint32_t zoom); +/** + * Set the blend mode of an image. + * @param obj pointer to an image object + * @param blend_mode the new blend mode + */ +void lv_image_set_blend_mode(lv_obj_t * obj, lv_blend_mode_t blend_mode); + /** * Enable/disable anti-aliasing for the transformations (rotate, zoom) or not. * The quality is better with anti-aliasing looks better but slower. @@ -282,6 +290,13 @@ int32_t lv_image_get_scale_x(lv_obj_t * obj); */ int32_t lv_image_get_scale_y(lv_obj_t * obj); +/** + * Get the current blend mode of the image + * @param obj pointer to an image object + * @return the current blend mode + */ +lv_blend_mode_t lv_image_get_blend_mode(lv_obj_t * obj); + /** * Get whether the transformations (rotate, zoom) are anti-aliased or not * @param obj pointer to an image object diff --git a/tests/ref_imgs/draw/render/argb8888/demo_render_blend_mode_opa_128.png b/tests/ref_imgs/draw/render/argb8888/demo_render_blend_mode_opa_128.png new file mode 100644 index 000000000..2680ebbcf Binary files /dev/null and b/tests/ref_imgs/draw/render/argb8888/demo_render_blend_mode_opa_128.png differ diff --git a/tests/ref_imgs/draw/render/argb8888/demo_render_blend_mode_opa_255.png b/tests/ref_imgs/draw/render/argb8888/demo_render_blend_mode_opa_255.png new file mode 100644 index 000000000..62cb27d5f Binary files /dev/null and b/tests/ref_imgs/draw/render/argb8888/demo_render_blend_mode_opa_255.png differ diff --git a/tests/ref_imgs/draw/render/argb8888/demo_render_layer_normal_opa_128.png b/tests/ref_imgs/draw/render/argb8888/demo_render_layer_normal_opa_128.png index bca80cba6..6842f1724 100644 Binary files a/tests/ref_imgs/draw/render/argb8888/demo_render_layer_normal_opa_128.png and b/tests/ref_imgs/draw/render/argb8888/demo_render_layer_normal_opa_128.png differ diff --git a/tests/ref_imgs/draw/render/argb8888/demo_render_layer_normal_opa_255.png b/tests/ref_imgs/draw/render/argb8888/demo_render_layer_normal_opa_255.png index c66ae4a7a..1d7b63015 100644 Binary files a/tests/ref_imgs/draw/render/argb8888/demo_render_layer_normal_opa_255.png and b/tests/ref_imgs/draw/render/argb8888/demo_render_layer_normal_opa_255.png differ diff --git a/tests/ref_imgs/draw/render/rgb565/demo_render_blend_mode_opa_128.png b/tests/ref_imgs/draw/render/rgb565/demo_render_blend_mode_opa_128.png new file mode 100644 index 000000000..706152411 Binary files /dev/null and b/tests/ref_imgs/draw/render/rgb565/demo_render_blend_mode_opa_128.png differ diff --git a/tests/ref_imgs/draw/render/rgb565/demo_render_blend_mode_opa_255.png b/tests/ref_imgs/draw/render/rgb565/demo_render_blend_mode_opa_255.png new file mode 100644 index 000000000..c526a2c90 Binary files /dev/null and b/tests/ref_imgs/draw/render/rgb565/demo_render_blend_mode_opa_255.png differ diff --git a/tests/ref_imgs/draw/render/rgb565/demo_render_layer_additive_opa_128.png b/tests/ref_imgs/draw/render/rgb565/demo_render_layer_additive_opa_128.png new file mode 100644 index 000000000..464f6043c Binary files /dev/null and b/tests/ref_imgs/draw/render/rgb565/demo_render_layer_additive_opa_128.png differ diff --git a/tests/ref_imgs/draw/render/rgb565/demo_render_layer_additive_opa_255.png b/tests/ref_imgs/draw/render/rgb565/demo_render_layer_additive_opa_255.png new file mode 100644 index 000000000..06aa5b02b Binary files /dev/null and b/tests/ref_imgs/draw/render/rgb565/demo_render_layer_additive_opa_255.png differ diff --git a/tests/ref_imgs/draw/render/rgb565/demo_render_layer_normal_opa_128.png b/tests/ref_imgs/draw/render/rgb565/demo_render_layer_normal_opa_128.png index f51dcd468..629d4f666 100644 Binary files a/tests/ref_imgs/draw/render/rgb565/demo_render_layer_normal_opa_128.png and b/tests/ref_imgs/draw/render/rgb565/demo_render_layer_normal_opa_128.png differ diff --git a/tests/ref_imgs/draw/render/rgb565/demo_render_layer_normal_opa_255.png b/tests/ref_imgs/draw/render/rgb565/demo_render_layer_normal_opa_255.png index 269b3653f..4a06d684c 100644 Binary files a/tests/ref_imgs/draw/render/rgb565/demo_render_layer_normal_opa_255.png and b/tests/ref_imgs/draw/render/rgb565/demo_render_layer_normal_opa_255.png differ diff --git a/tests/ref_imgs/draw/render/rgb888/demo_render_blend_mode_opa_128.png b/tests/ref_imgs/draw/render/rgb888/demo_render_blend_mode_opa_128.png new file mode 100644 index 000000000..2680ebbcf Binary files /dev/null and b/tests/ref_imgs/draw/render/rgb888/demo_render_blend_mode_opa_128.png differ diff --git a/tests/ref_imgs/draw/render/rgb888/demo_render_blend_mode_opa_255.png b/tests/ref_imgs/draw/render/rgb888/demo_render_blend_mode_opa_255.png new file mode 100644 index 000000000..62cb27d5f Binary files /dev/null and b/tests/ref_imgs/draw/render/rgb888/demo_render_blend_mode_opa_255.png differ diff --git a/tests/ref_imgs/draw/render/rgb888/demo_render_layer_additive_opa_128.png b/tests/ref_imgs/draw/render/rgb888/demo_render_layer_additive_opa_128.png new file mode 100644 index 000000000..62bfe16ad Binary files /dev/null and b/tests/ref_imgs/draw/render/rgb888/demo_render_layer_additive_opa_128.png differ diff --git a/tests/ref_imgs/draw/render/rgb888/demo_render_layer_additive_opa_255.png b/tests/ref_imgs/draw/render/rgb888/demo_render_layer_additive_opa_255.png new file mode 100644 index 000000000..0c6e3d788 Binary files /dev/null and b/tests/ref_imgs/draw/render/rgb888/demo_render_layer_additive_opa_255.png differ diff --git a/tests/ref_imgs/draw/render/rgb888/demo_render_layer_normal_opa_128.png b/tests/ref_imgs/draw/render/rgb888/demo_render_layer_normal_opa_128.png index 711e3f680..146218ea1 100644 Binary files a/tests/ref_imgs/draw/render/rgb888/demo_render_layer_normal_opa_128.png and b/tests/ref_imgs/draw/render/rgb888/demo_render_layer_normal_opa_128.png differ diff --git a/tests/ref_imgs/draw/render/rgb888/demo_render_layer_normal_opa_255.png b/tests/ref_imgs/draw/render/rgb888/demo_render_layer_normal_opa_255.png index c8ce3fcd7..3fdcb264f 100644 Binary files a/tests/ref_imgs/draw/render/rgb888/demo_render_layer_normal_opa_255.png and b/tests/ref_imgs/draw/render/rgb888/demo_render_layer_normal_opa_255.png differ diff --git a/tests/ref_imgs/draw/render/xrgb8888/demo_render_blend_mode_opa_128.png b/tests/ref_imgs/draw/render/xrgb8888/demo_render_blend_mode_opa_128.png new file mode 100644 index 000000000..2680ebbcf Binary files /dev/null and b/tests/ref_imgs/draw/render/xrgb8888/demo_render_blend_mode_opa_128.png differ diff --git a/tests/ref_imgs/draw/render/xrgb8888/demo_render_blend_mode_opa_255.png b/tests/ref_imgs/draw/render/xrgb8888/demo_render_blend_mode_opa_255.png new file mode 100644 index 000000000..62cb27d5f Binary files /dev/null and b/tests/ref_imgs/draw/render/xrgb8888/demo_render_blend_mode_opa_255.png differ diff --git a/tests/ref_imgs/draw/render/xrgb8888/demo_render_layer_additive_opa_128.png b/tests/ref_imgs/draw/render/xrgb8888/demo_render_layer_additive_opa_128.png new file mode 100644 index 000000000..62bfe16ad Binary files /dev/null and b/tests/ref_imgs/draw/render/xrgb8888/demo_render_layer_additive_opa_128.png differ diff --git a/tests/ref_imgs/draw/render/xrgb8888/demo_render_layer_additive_opa_255.png b/tests/ref_imgs/draw/render/xrgb8888/demo_render_layer_additive_opa_255.png new file mode 100644 index 000000000..0c6e3d788 Binary files /dev/null and b/tests/ref_imgs/draw/render/xrgb8888/demo_render_layer_additive_opa_255.png differ diff --git a/tests/ref_imgs/draw/render/xrgb8888/demo_render_layer_normal_opa_128.png b/tests/ref_imgs/draw/render/xrgb8888/demo_render_layer_normal_opa_128.png index 711e3f680..146218ea1 100644 Binary files a/tests/ref_imgs/draw/render/xrgb8888/demo_render_layer_normal_opa_128.png and b/tests/ref_imgs/draw/render/xrgb8888/demo_render_layer_normal_opa_128.png differ diff --git a/tests/ref_imgs/draw/render/xrgb8888/demo_render_layer_normal_opa_255.png b/tests/ref_imgs/draw/render/xrgb8888/demo_render_layer_normal_opa_255.png index c8ce3fcd7..3fdcb264f 100644 Binary files a/tests/ref_imgs/draw/render/xrgb8888/demo_render_layer_normal_opa_255.png and b/tests/ref_imgs/draw/render/xrgb8888/demo_render_layer_normal_opa_255.png differ diff --git a/tests/ref_imgs/widgets/obj_flag_overflow_visible_1_4.png b/tests/ref_imgs/widgets/obj_flag_overflow_visible_1_4.png index d2a59684d..edb631250 100644 Binary files a/tests/ref_imgs/widgets/obj_flag_overflow_visible_1_4.png and b/tests/ref_imgs/widgets/obj_flag_overflow_visible_1_4.png differ