Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FastLED/FastLED.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kriegsman <kriegsman@tr.org>2017-01-20 05:57:30 +0300
committerMark Kriegsman <kriegsman@tr.org>2017-01-20 05:57:30 +0300
commit60f90b69902c0515bedcd1cddbd0c61be10f902a (patch)
treec59f691d369193b92b1768d310839cb42222922a
parent94e46e3978b9f2bce8f76383ff9a19879b245ad0 (diff)
Fixed loss-of-precision bug in pixel blending. Pixel blending should be a little smoother now and free from error noise in the low bits. This includes palette colors returned from ColorFromPalette, which are now slightly smoother. Also introduced a new lib8tion function, blend8( byte, byte, fract8). The new pixel blending should have negligible effect on code size, and it is ever so slightly faster than the old version with the error. Fixes #404.
-rw-r--r--colorutils.cpp10
-rw-r--r--fastled_config.h14
-rw-r--r--keywords.txt1
-rw-r--r--lib8tion/math8.h46
4 files changed, 67 insertions, 4 deletions
diff --git a/colorutils.cpp b/colorutils.cpp
index 2db7c466..8df7557b 100644
--- a/colorutils.cpp
+++ b/colorutils.cpp
@@ -234,6 +234,8 @@ CRGB& nblend( CRGB& existing, const CRGB& overlay, fract8 amountOfOverlay )
return existing;
}
+#if 0
+ // Old blend method which unfortunately had some rounding errors
fract8 amountOfKeep = 255 - amountOfOverlay;
existing.red = scale8_LEAVING_R1_DIRTY( existing.red, amountOfKeep)
@@ -244,7 +246,13 @@ CRGB& nblend( CRGB& existing, const CRGB& overlay, fract8 amountOfOverlay )
+ scale8_LEAVING_R1_DIRTY( overlay.blue, amountOfOverlay);
cleanup_R1();
-
+#else
+ // Corrected blend method, with no loss-of-precision rounding errors
+ existing.red = blend8( existing.red, overlay.red, amountOfOverlay);
+ existing.green = blend8( existing.green, overlay.green, amountOfOverlay);
+ existing.blue = blend8( existing.blue, overlay.blue, amountOfOverlay);
+#endif
+
return existing;
}
diff --git a/fastled_config.h b/fastled_config.h
index b1d5d83b..690a21d0 100644
--- a/fastled_config.h
+++ b/fastled_config.h
@@ -33,10 +33,18 @@
// had a problem where scale8(255,255) would give you 254. This is now fixed, and that
// fix is enabled by default. However, if for some reason you have code that is not
// working right as a result of this (e.g. code that was expecting the old scale8 behavior)
-// you can disable it here
-
+// you can disable it here.
#define FASTLED_SCALE8_FIXED 1
-// define FASTLED_SCALE8_FIXED 0
+// #define FASTLED_SCALE8_FIXED 0
+
+// Use this toggle whether to use 'fixed' FastLED pixel blending, including ColorFromPalette.
+// The prior pixel blend functions had integer-rounding math errors that led to
+// small errors being inadvertently added to the low bits of blended colors, including colors
+// retrieved from color palettes using LINEAR_BLEND. This is now fixed, and the
+// fix is enabled by default. However, if for some reason you wish to run with the old
+// blending, including the integer rounding and color errors, you can disable the bugfix here.
+#define FASTLED_BLEND_FIXED 1
+// #define FASTLED_BLEND_FIXED 0
// Use this to determine how many times FastLED will attempt to re-transmit a frame if interrupted
// for too long by interrupts.
diff --git a/keywords.txt b/keywords.txt
index 1db689df..509c806c 100644
--- a/keywords.txt
+++ b/keywords.txt
@@ -109,6 +109,7 @@ triwave8 KEYWORD2
quadwave8 KEYWORD2
cubicwave8 KEYWORD2
sqrt16 KEYWORD2
+blend8 KEYWORD2
# Color util methods
blend KEYWORD2
diff --git a/lib8tion/math8.h b/lib8tion/math8.h
index f2b5f9cb..8ed6a57e 100644
--- a/lib8tion/math8.h
+++ b/lib8tion/math8.h
@@ -1,6 +1,8 @@
#ifndef __INC_LIB8TION_MATH_H
#define __INC_LIB8TION_MATH_H
+#include "scale8.h"
+
///@ingroup lib8tion
///@defgroup Math Basic math operations
@@ -406,5 +408,49 @@ LIB8STATIC uint8_t sqrt16(uint16_t x)
return low - 1;
}
+/// blend a variable proproportion(0-255) of one byte to another
+/// @param a - the starting byte value
+/// @param b - the byte value to blend toward
+/// @param amountOfB - the proportion (0-255) of b to blend
+/// @returns a byte value between a and b, inclusive
+#if (FASTLED_BLEND_FIXED == 1)
+LIB8STATIC uint8_t blend8( uint8_t a, uint8_t b, uint8_t amountOfB)
+{
+ uint16_t partial;
+ uint8_t result;
+
+ uint8_t amountOfA = 255 - amountOfB;
+
+ partial = (a * amountOfA);
+#if (FASTLED_SCALE8_FIXED == 1)
+ partial += a;
+#endif
+
+ partial += (b * amountOfB);
+#if (FASTLED_SCALE8_FIXED == 1)
+ partial += b;
+#endif
+
+ result = partial >> 8;
+
+ return result;
+}
+
+#else
+LIB8STATIC uint8_t blend8( uint8_t a, uint8_t b, uint8_t amountOfB)
+{
+ // This version loses precision in the integer math
+ // and can actually return results outside of the range
+ // from a to b. Its use is not recommended.
+ uint8_t result;
+ uint8_t amountOfA = 255 - amountOfB;
+ result = scale8_LEAVING_R1_DIRTY( a, amountOfA)
+ + scale8_LEAVING_R1_DIRTY( b, amountOfB);
+ cleanup_R1();
+ return result;
+}
+#endif
+
+
///@}
#endif