diff --git a/docs/details/base-widget/styles/style-properties.rst b/docs/details/base-widget/styles/style-properties.rst
index 00c6df4be..752c24dfd 100644
--- a/docs/details/base-widget/styles/style-properties.rst
+++ b/docs/details/base-widget/styles/style-properties.rst
@@ -1369,7 +1369,7 @@ An initialized ``lv_style_transition_dsc_t`` to describe a transition.
blend_mode
~~~~~~~~~~
-Describes how to blend the colors to the background. Possible values are `LV_BLEND_MODE_NORMAL/ADDITIVE/SUBTRACTIVE/MULTIPLY`
+Describes how to blend the colors to the background. Possible values are `LV_BLEND_MODE_NORMAL/ADDITIVE/SUBTRACTIVE/MULTIPLY/DIFFERENCE`
.. raw:: html
diff --git a/scripts/style_api_gen.py b/scripts/style_api_gen.py
index a37ea4d27..af976bc9d 100755
--- a/scripts/style_api_gen.py
+++ b/scripts/style_api_gen.py
@@ -391,7 +391,7 @@ props = [
{'name': 'BLEND_MODE',
'style_type': 'num', 'var_type': 'lv_blend_mode_t' , 'default':'`LV_BLEND_MODE_NORMAL`', 'inherited': 0, 'layout': 0, 'ext_draw': 0,
- 'dsc': "Describes how to blend the colors to the background. Possible values are `LV_BLEND_MODE_NORMAL/ADDITIVE/SUBTRACTIVE/MULTIPLY`"},
+ 'dsc': "Describes how to blend the colors to the background. Possible values are `LV_BLEND_MODE_NORMAL/ADDITIVE/SUBTRACTIVE/MULTIPLY/DIFFERENCE`"},
{'name': 'LAYOUT',
'style_type': 'num', 'var_type': 'uint16_t', 'default':0, 'inherited': 0, 'layout': 1, 'ext_draw': 0,
diff --git a/src/draw/sw/blend/lv_draw_sw_blend_to_al88.c b/src/draw/sw/blend/lv_draw_sw_blend_to_al88.c
index 4110fe8a2..6cbf6602d 100644
--- a/src/draw/sw/blend/lv_draw_sw_blend_to_al88.c
+++ b/src/draw/sw/blend/lv_draw_sw_blend_to_al88.c
@@ -1018,6 +1018,9 @@ static inline void LV_ATTRIBUTE_FAST_MEM blend_non_normal_pixel(lv_color16a_t *
case LV_BLEND_MODE_MULTIPLY:
res.lumi = (dest->lumi * src.lumi) >> 8;
break;
+ case LV_BLEND_MODE_DIFFERENCE:
+ res.lumi = LV_ABS(dest->lumi - src.lumi);
+ break;
default:
LV_LOG_WARN("Not supported blend mode: %d", mode);
return;
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 fc063b277..11d61ff62 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
@@ -1046,6 +1046,11 @@ static inline void LV_ATTRIBUTE_FAST_MEM blend_non_normal_pixel(lv_color32_t * d
res.green = (dest->green * src.green) >> 8;
res.blue = (dest->blue * src.blue) >> 8;
break;
+ case LV_BLEND_MODE_DIFFERENCE:
+ res.red = LV_ABS(dest->red - src.red);
+ res.green = LV_ABS(dest->green - src.green);
+ res.blue = LV_ABS(dest->blue - src.blue);
+ break;
default:
LV_LOG_WARN("Not supported blend mode: %d", mode);
return;
diff --git a/src/draw/sw/blend/lv_draw_sw_blend_to_i1.c b/src/draw/sw/blend/lv_draw_sw_blend_to_i1.c
index 829acecd0..88b66849e 100644
--- a/src/draw/sw/blend/lv_draw_sw_blend_to_i1.c
+++ b/src/draw/sw/blend/lv_draw_sw_blend_to_i1.c
@@ -1066,6 +1066,9 @@ static inline void LV_ATTRIBUTE_FAST_MEM blend_non_normal_pixel(uint8_t * dest_b
case LV_BLEND_MODE_MULTIPLY:
res = (dest_lumi * src_lumi) >> 8;
break;
+ case LV_BLEND_MODE_DIFFERENCE:
+ res = LV_ABS(dest_lumi - src_lumi);
+ break;
default:
LV_LOG_WARN("Not supported blend mode: %d", mode);
return;
diff --git a/src/draw/sw/blend/lv_draw_sw_blend_to_l8.c b/src/draw/sw/blend/lv_draw_sw_blend_to_l8.c
index 5c080f502..c24ddfe5a 100644
--- a/src/draw/sw/blend/lv_draw_sw_blend_to_l8.c
+++ b/src/draw/sw/blend/lv_draw_sw_blend_to_l8.c
@@ -880,6 +880,9 @@ static inline void LV_ATTRIBUTE_FAST_MEM blend_non_normal_pixel(uint8_t * dest,
case LV_BLEND_MODE_MULTIPLY:
res = (*dest * src_lumi) >> 8;
break;
+ case LV_BLEND_MODE_DIFFERENCE:
+ res = LV_ABS(*dest - src_lumi);
+ break;
default:
LV_LOG_WARN("Not supported blend mode: %d", mode);
return;
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 a05bf2337..6303286cb 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
@@ -495,6 +495,10 @@ static void LV_ATTRIBUTE_FAST_MEM i1_image_blend(lv_draw_sw_blend_image_dsc_t *
((((dest_buf_u16[dest_x] >> 5) & 0x3F) * ((l8_to_rgb565(chan_val) >> 2) & 0x3F) >> 6) << 5) |
(((dest_buf_u16[dest_x] & 0x1F) * (l8_to_rgb565(chan_val) & 0x1F)) >> 5);
break;
+ case LV_BLEND_MODE_DIFFERENCE:
+ /*Difference blending mode*/
+ res = (LV_ABS(dest_buf_u16[dest_x] - l8_to_rgb565(chan_val)));
+ break;
default:
LV_LOG_WARN("Not supported blend mode: %d", dsc->blend_mode);
return;
@@ -613,6 +617,11 @@ static void LV_ATTRIBUTE_FAST_MEM al88_image_blend(lv_draw_sw_blend_image_dsc_t
res += ((dest_buf_c16[dest_x].green * g) >> 6) << 5;
res += (dest_buf_c16[dest_x].blue * rb) >> 5;
break;
+ case LV_BLEND_MODE_DIFFERENCE:
+ res = (LV_ABS(dest_buf_c16[dest_x].red - rb)) << 11;
+ res += (LV_ABS(dest_buf_c16[dest_x].green - g)) << 5;
+ res += LV_ABS(dest_buf_c16[dest_x].blue - rb);
+ break;
default:
LV_LOG_WARN("Not supported blend mode: %d", dsc->blend_mode);
return;
@@ -728,6 +737,11 @@ static void LV_ATTRIBUTE_FAST_MEM l8_image_blend(lv_draw_sw_blend_image_dsc_t *
res += ((dest_buf_c16[dest_x].green * g) >> 6) << 5;
res += (dest_buf_c16[dest_x].blue * rb) >> 5;
break;
+ case LV_BLEND_MODE_DIFFERENCE:
+ res = (LV_ABS(dest_buf_c16[dest_x].red - rb)) << 11;
+ res += (LV_ABS(dest_buf_c16[dest_x].green - g)) << 5;
+ res += LV_ABS(dest_buf_c16[dest_x].blue - rb);
+ break;
default:
LV_LOG_WARN("Not supported blend mode: %d", dsc->blend_mode);
return;
@@ -841,6 +855,11 @@ static void LV_ATTRIBUTE_FAST_MEM rgb565_image_blend(lv_draw_sw_blend_image_dsc_
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;
+ case LV_BLEND_MODE_DIFFERENCE:
+ res = (LV_ABS(dest_buf_c16[x].red - src_buf_c16[x].red)) << 11;
+ res += (LV_ABS(dest_buf_c16[x].green - src_buf_c16[x].green)) << 5;
+ res += LV_ABS(dest_buf_c16[x].blue - src_buf_c16[x].blue);
+ break;
default:
LV_LOG_WARN("Not supported blend mode: %d", dsc->blend_mode);
return;
@@ -951,6 +970,11 @@ static void LV_ATTRIBUTE_FAST_MEM rgb888_image_blend(lv_draw_sw_blend_image_dsc_
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;
+ case LV_BLEND_MODE_DIFFERENCE:
+ res = (LV_ABS(dest_buf_c16[dest_x].red - (src_buf_u8[src_x + 2] >> 3))) << 11;
+ res += (LV_ABS(dest_buf_c16[dest_x].green - (src_buf_u8[src_x + 1] >> 2))) << 5;
+ res += LV_ABS(dest_buf_c16[dest_x].blue - (src_buf_u8[src_x + 0] >> 3));
+ break;
default:
LV_LOG_WARN("Not supported blend mode: %d", dsc->blend_mode);
return;
@@ -1064,6 +1088,11 @@ static void LV_ATTRIBUTE_FAST_MEM argb8888_image_blend(lv_draw_sw_blend_image_ds
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;
+ case LV_BLEND_MODE_DIFFERENCE:
+ res = (LV_ABS(dest_buf_c16[dest_x].red - (src_buf_u8[src_x + 2] >> 3))) << 11;
+ res += (LV_ABS(dest_buf_c16[dest_x].green - (src_buf_u8[src_x + 1] >> 2))) << 5;
+ res += LV_ABS(dest_buf_c16[dest_x].blue - (src_buf_u8[src_x + 0] >> 3));
+ break;
default:
LV_LOG_WARN("Not supported blend mode: %d", dsc->blend_mode);
return;
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 b5065eb28..926ba61be 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
@@ -922,6 +922,11 @@ static inline void LV_ATTRIBUTE_FAST_MEM blend_non_normal_pixel(uint8_t * dest,
res[1] = (dest[1] * src.green) >> 8;
res[2] = (dest[2] * src.red) >> 8;
break;
+ case LV_BLEND_MODE_DIFFERENCE:
+ res[0] = LV_ABS((int16_t)dest[0] - src.blue);
+ res[1] = LV_ABS((int16_t)dest[1] - src.green);
+ res[2] = LV_ABS((int16_t)dest[2] - src.red);
+ break;
default:
LV_LOG_WARN("Not supported blend mode: %d", mode);
return;
diff --git a/src/misc/lv_style.h b/src/misc/lv_style.h
index f417bbeac..ae4ecf8f9 100644
--- a/src/misc/lv_style.h
+++ b/src/misc/lv_style.h
@@ -91,6 +91,7 @@ typedef enum {
LV_BLEND_MODE_ADDITIVE, /**< Add the respective color channels*/
LV_BLEND_MODE_SUBTRACTIVE,/**< Subtract the foreground from the background*/
LV_BLEND_MODE_MULTIPLY, /**< Multiply the foreground and background*/
+ LV_BLEND_MODE_DIFFERENCE, /**< Absolute difference between foreground and background*/
} lv_blend_mode_t;
/**
diff --git a/src/others/xml/lv_xml_base_types.c b/src/others/xml/lv_xml_base_types.c
index 259d6b9b6..896de4989 100644
--- a/src/others/xml/lv_xml_base_types.c
+++ b/src/others/xml/lv_xml_base_types.c
@@ -190,6 +190,7 @@ lv_blend_mode_t lv_xml_blend_mode_to_enum(const char * txt)
if(lv_streq("additive", txt)) return LV_BLEND_MODE_ADDITIVE;
if(lv_streq("subtractive", txt)) return LV_BLEND_MODE_SUBTRACTIVE;
if(lv_streq("multiply", txt)) return LV_BLEND_MODE_MULTIPLY;
+ if(lv_streq("difference", txt)) return LV_BLEND_MODE_DIFFERENCE;
LV_LOG_WARN("%s is an unknown value for blend_mode", txt);
return 0; /*Return 0 in lack of a better option. */
diff --git a/xmls/globals.xml b/xmls/globals.xml
index 7c81e23bc..ead6602eb 100644
--- a/xmls/globals.xml
+++ b/xmls/globals.xml
@@ -77,6 +77,7 @@
+