@@ -1668,27 +1668,31 @@ void WS2812FX::service() {
16681668 #endif
16691669}
16701670
1671+ namespace {
1672+ static uint8_t top (uint8_t a, uint8_t b){ return uint8_t (a); };
1673+ static uint8_t bottom (uint8_t a, uint8_t b){ return uint8_t (b); };
1674+ static uint8_t add (uint8_t a, uint8_t b){ return qadd8 (a, b); }; // { unsigned t = a+b; return t>255 ? 255 : t; }
1675+ static uint8_t subtract (uint8_t a, uint8_t b){ return uint8_t (b > a ? (b - a) : 0 ); };
1676+ static uint8_t difference (uint8_t a, uint8_t b){ return uint8_t (b > a ? (b - a) : (a - b)); };
1677+ static uint8_t average (uint8_t a, uint8_t b){ return uint8_t ((a + b) >> 1 ); };
1678+ static uint8_t multiply (uint8_t a, uint8_t b){ return uint8_t ((a * b) / 255 ); }; // origianl uses a & b in range [0,1]
1679+ static uint8_t divide (uint8_t a, uint8_t b){ return uint8_t (a > b ? (b*255 ) / a : 255 ); };
1680+ static uint8_t lighten (uint8_t a, uint8_t b){ return uint8_t (a > b ? a : b); };
1681+ static uint8_t darken (uint8_t a, uint8_t b){ return uint8_t (a < b ? a : b); };
1682+ static uint8_t screen (uint8_t a, uint8_t b){ return uint8_t (255 - multiply (~a,~b)); }; // 255 - (255-a)*(255-b)/255
1683+ static uint8_t overlay (uint8_t a, uint8_t b){ return uint8_t (b<128 ? 2 *a*b/255 : (255 - 2 *~a*~b/255 )); };
1684+ static uint8_t hardlight (uint8_t a, uint8_t b){ return uint8_t (a<128 ? 2 *a*b/255 : (255 - 2 *~a*~b/255 )); };
1685+ static uint8_t softlight (uint8_t a, uint8_t b){ return uint8_t ((b*b*(255 -2 *a)/255 + 2 *a*b)/255 ); }; // Pegtop's formula (1 - 2a)b^2 + 2ab
1686+ static uint8_t dodge (uint8_t a, uint8_t b){ return divide (~a,b); };
1687+ static uint8_t burn (uint8_t a, uint8_t b){ return uint8_t (~divide (a,~b)); };
1688+ }
1689+
1690+
16711691void WS2812FX::blendSegment (const Segment &topSegment) {
16721692 // https://en.wikipedia.org/wiki/Blend_modes but using a for top layer & b for bottom layer
1673- constexpr auto top = [](uint8_t a, uint8_t b){ return uint8_t (a); };
1674- constexpr auto bottom = [](uint8_t a, uint8_t b){ return uint8_t (b); };
1675- constexpr auto add = [](uint8_t a, uint8_t b){ return qadd8 (a, b); }; // { unsigned t = a+b; return t>255 ? 255 : t; }
1676- constexpr auto subtract = [](uint8_t a, uint8_t b){ return uint8_t (b > a ? (b - a) : 0 ); };
1677- constexpr auto difference = [](uint8_t a, uint8_t b){ return uint8_t (b > a ? (b - a) : (a - b)); };
1678- constexpr auto average = [](uint8_t a, uint8_t b){ return uint8_t ((a + b) >> 1 ); };
1679- constexpr auto multiply = [](uint8_t a, uint8_t b){ return uint8_t ((a * b) / 255 ); }; // origianl uses a & b in range [0,1]
1680- constexpr auto divide = [](uint8_t a, uint8_t b){ return uint8_t (a > b ? (b*255 ) / a : 255 ); };
1681- constexpr auto lighten = [](uint8_t a, uint8_t b){ return uint8_t (a > b ? a : b); };
1682- constexpr auto darken = [](uint8_t a, uint8_t b){ return uint8_t (a < b ? a : b); };
1683- constexpr auto screen = [](uint8_t a, uint8_t b){ return uint8_t (255 - multiply (~a,~b)); }; // 255 - (255-a)*(255-b)/255
1684- constexpr auto overlay = [](uint8_t a, uint8_t b){ return uint8_t (b<128 ? 2 *a*b/255 : (255 - 2 *~a*~b/255 )); };
1685- constexpr auto hardlight = [](uint8_t a, uint8_t b){ return uint8_t (a<128 ? 2 *a*b/255 : (255 - 2 *~a*~b/255 )); };
1686- constexpr auto softlight = [](uint8_t a, uint8_t b){ return uint8_t ((b*b*(255 -2 *a)/255 + 2 *a*b)/255 ); }; // Pegtop's formula (1 - 2a)b^2 + 2ab
1687- constexpr auto dodge = [](uint8_t a, uint8_t b){ return divide (~a,b); };
1688- constexpr auto burn = [](uint8_t a, uint8_t b){ return uint8_t (~divide (a,~b)); };
16891693
16901694 typedef uint8_t (*FuncType)(uint8_t , uint8_t );
1691- FuncType funcs[] = {
1695+ const static FuncType funcs[] = {
16921696 top, bottom,
16931697 add, subtract, difference, average,
16941698 multiply, divide, lighten, darken, screen, overlay,
0 commit comments