Skip to content

Commit 6ef0578

Browse files
authored
color_blend accuracy improvements
For 8bit blends, we adopt the new blend8() logic from FastLED. The WLED color_clend function is based on very old FastLED code, that was replaced 3 years ago due to serious rounding problems.
1 parent 776718b commit 6ef0578

File tree

1 file changed

+26
-17
lines changed

1 file changed

+26
-17
lines changed

wled00/colors.cpp

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,33 @@ IRAM_ATTR_YN __attribute__((hot)) uint32_t color_blend(uint32_t color1, uint32_t
1212
const uint_fast16_t blendmax = b16 ? 0xFFFF : 0xFF;
1313
if(blend >= blendmax) return color2;
1414
const uint_fast8_t shift = b16 ? 16 : 8;
15-
const uint_fast16_t blend2 = blendmax - blend; // WLEDMM pre-calculate value
1615

17-
uint32_t w1 = W(color1);
18-
uint32_t r1 = R(color1);
19-
uint32_t g1 = G(color1);
20-
uint32_t b1 = B(color1);
21-
22-
uint32_t w2 = W(color2);
23-
uint32_t r2 = R(color2);
24-
uint32_t g2 = G(color2);
25-
uint32_t b2 = B(color2);
26-
27-
uint32_t w3 = ((w2 * blend) + (w1 * blend2)) >> shift;
28-
uint32_t r3 = ((r2 * blend) + (r1 * blend2)) >> shift;
29-
uint32_t g3 = ((g2 * blend) + (g1 * blend2)) >> shift;
30-
uint32_t b3 = ((b2 * blend) + (b1 * blend2)) >> shift;
31-
32-
return RGBW32(r3, g3, b3, w3);
16+
uint16_t w1 = W(color1); // WLEDMM 16bit to make sure the compiler uses 32bit (not 64bit) for the math
17+
uint16_t r1 = R(color1);
18+
uint16_t g1 = G(color1);
19+
uint16_t b1 = B(color1);
20+
21+
uint16_t w2 = W(color2);
22+
uint16_t r2 = R(color2);
23+
uint16_t g2 = G(color2);
24+
uint16_t b2 = B(color2);
25+
26+
if (b16 == false) {
27+
// WLEDMM based on fastled blend8() - better accuracy for 8bit
28+
uint8_t w3 = (w1+w2 == 0) ? 0 : (((w1 << 8)|w2) + (w2 * blend) - (w1*blend) ) >> 8;
29+
uint8_t r3 = (((r1 << 8)|r2) + (r2 * blend) - (r1*blend) ) >> 8;
30+
uint8_t g3 = (((g1 << 8)|g2) + (g2 * blend) - (g1*blend) ) >> 8;
31+
uint8_t b3 = (((b1 << 8)|b2) + (b2 * blend) - (b1*blend) ) >> 8;
32+
return RGBW32(r3, g3, b3, w3);
33+
} else {
34+
// old code has lots of "jumps" due to roundding errors
35+
const uint_fast16_t blend2 = blendmax - blend; // WLEDMM pre-calculate value
36+
uint32_t w3 = ((w2 * blend) + (w1 * blend2)) >> shift;
37+
uint32_t r3 = ((r2 * blend) + (r1 * blend2)) >> shift;
38+
uint32_t g3 = ((g2 * blend) + (g1 * blend2)) >> shift;
39+
uint32_t b3 = ((b2 * blend) + (b1 * blend2)) >> shift;
40+
return RGBW32(r3, g3, b3, w3);
41+
}
3342
}
3443

3544
/*

0 commit comments

Comments
 (0)