diff options
author | Mark Kriegsman <kriegsman@tr.org> | 2014-12-13 04:59:26 +0300 |
---|---|---|
committer | Mark Kriegsman <kriegsman@tr.org> | 2014-12-13 04:59:26 +0300 |
commit | f873455c0f27d7bfacf744effc681f585dc52c19 (patch) | |
tree | 3cac8f544e2efdd2a8384e309a266d35203bd2f5 | |
parent | 061d4373c484b3f462a6cadd2c0f87f3b222e557 (diff) |
Added nblendPaletteTowardPalette as a toplevel function for palette crossfade support... I suspect there will be some small changes coming to this, but here it is.
-rw-r--r-- | colorutils.cpp | 29 | ||||
-rw-r--r-- | colorutils.h | 36 |
2 files changed, 65 insertions, 0 deletions
diff --git a/colorutils.cpp b/colorutils.cpp index 3667855f..0c747ba4 100644 --- a/colorutils.cpp +++ b/colorutils.cpp @@ -723,3 +723,32 @@ void SetupPartyColors(CRGBPalette16& pal) } #endif + +void nblendPaletteTowardPalette( CRGBPalette16& current, CRGBPalette16& target, uint8_t maxChanges) +{ + uint8_t* p1; + uint8_t* p2; + uint8_t changes = 0; + + p1 = (uint8_t*)current.entries; + p2 = (uint8_t*)target.entries; + + const uint8_t totalChannels = sizeof(CRGBPalette16); + for( byte i = 0; i < totalChannels; i++) { + // if the values are equal, no changes are needed + if( p1[i] == p2[i] ) { continue; } + + // if the current value is less than the target, increase it by one + if( p1[i] < p2[i] ) { p1[i]++; changes++; } + + // if the current value is greater than the target, + // increase it by one (or two if it's still greater). + if( p1[i] > p2[i] ) { + p1[i]--; changes++; + if( p1[i] > p2[i] ) { p1[i]--; } + } + + // if we've hit the maximum number of changes, exit + if( changes >= maxChanges) { break; } + } +} diff --git a/colorutils.h b/colorutils.h index 120b685f..5750cad6 100644 --- a/colorutils.h +++ b/colorutils.h @@ -840,4 +840,40 @@ void map_data_into_colors_through_palette( } } +// nblendPaletteTowardPalette: +// Alter one palette by making it slightly more like +// a 'target palette', used for palette cross-fades. +// +// It does this by comparing each of the R, G, and B channels +// of each entry in the current palette to the corresponding +// entry in the target palette and making small adjustments: +// If the Red channel is too low, it will be increased. +// If the Red channel is too high, it will be slightly reduced. +// ... and likewise for Green and Blue channels. +// +// Additionally, there are two significant visual improvements +// to this algorithm implemented here. First is this: +// When increasing a channel, it is stepped up by ONE. +// When decreasing a channel, it is stepped down by TWO. +// Due to the way the eye perceives light, and the way colors +// are represented in RGB, this produces a more uniform apparent +// brightness when cross-fading between most palette colors. +// +// The second visual tweak is limiting the number of changes +// that will be made to the palette at once. If all the palette +// entries are changed at once, it can give a muddled appearance. +// However, if only a few palette entries are changed at once, +// you get a visually smoother transition: in the middle of the +// cross-fade your current palette will actually contain some +// colors from the old palette, a few blended colors, and some +// colors from the new palette. +// The maximum number of possible palette changes per call +// is 48 (sixteen color entries time three channels each). +// The default 'maximim number of changes' here is 12, meaning +// that only approximately a quarter of the palette entries +// will be changed per call. +void nblendPaletteTowardPalette( CRGBPalette16& currentPalette, + CRGBPalette16& targetPalette, + uint8_t maxChanges=24); + #endif |