diff options
author | Mark Kriegsman <kriegsman@tr.org> | 2014-10-11 16:21:14 +0400 |
---|---|---|
committer | Mark Kriegsman <kriegsman@tr.org> | 2014-10-11 16:21:14 +0400 |
commit | c18ee923241103a33f2024582bb4785f3ac5ea81 (patch) | |
tree | 78af7c9990fc45aa77701ba6b7d7cf8c97fe9144 | |
parent | baf6dfaf9eb1ea4e57956398f42555d0d0e3d828 (diff) |
Added CHSVPalette16, CHSVPalette256, and map_data_into_colors_through_palette( data, NUM_LEDS, leds, palette), which saves typing, and lets you focus on 'data' and 'palette' separately.
-rw-r--r-- | colorpalettes.cpp | 16 | ||||
-rw-r--r-- | colorpalettes.h | 16 | ||||
-rw-r--r-- | colorutils.cpp | 103 | ||||
-rw-r--r-- | colorutils.h | 274 |
4 files changed, 352 insertions, 57 deletions
diff --git a/colorpalettes.cpp b/colorpalettes.cpp index 9591279a..8cec8980 100644 --- a/colorpalettes.cpp +++ b/colorpalettes.cpp @@ -24,7 +24,7 @@ // use each one, so you only 'pay for' those you actually use. -extern const TProgmemPalette16 CloudColors_p PROGMEM = +extern const TProgmemRGBPalette16 CloudColors_p PROGMEM = { CRGB::Blue, CRGB::DarkBlue, @@ -47,7 +47,7 @@ extern const TProgmemPalette16 CloudColors_p PROGMEM = CRGB::SkyBlue }; -extern const TProgmemPalette16 LavaColors_p PROGMEM = +extern const TProgmemRGBPalette16 LavaColors_p PROGMEM = { CRGB::Black, CRGB::Maroon, @@ -70,7 +70,7 @@ extern const TProgmemPalette16 LavaColors_p PROGMEM = }; -extern const TProgmemPalette16 OceanColors_p PROGMEM = +extern const TProgmemRGBPalette16 OceanColors_p PROGMEM = { CRGB::MidnightBlue, CRGB::DarkBlue, @@ -93,7 +93,7 @@ extern const TProgmemPalette16 OceanColors_p PROGMEM = CRGB::LightSkyBlue }; -extern const TProgmemPalette16 ForestColors_p PROGMEM = +extern const TProgmemRGBPalette16 ForestColors_p PROGMEM = { CRGB::DarkGreen, CRGB::DarkGreen, @@ -117,7 +117,7 @@ extern const TProgmemPalette16 ForestColors_p PROGMEM = }; // HSV Rainbow -extern const TProgmemPalette16 RainbowColors_p PROGMEM = +extern const TProgmemRGBPalette16 RainbowColors_p PROGMEM = { 0xFF0000, 0xD52A00, 0xAB5500, 0xAB7F00, 0xABAB00, 0x56D500, 0x00FF00, 0x00D52A, @@ -127,7 +127,7 @@ extern const TProgmemPalette16 RainbowColors_p PROGMEM = // HSV Rainbow colors with alternatating stripes of black #define RainbowStripesColors_p RainbowStripeColors_p -extern const TProgmemPalette16 RainbowStripeColors_p PROGMEM = +extern const TProgmemRGBPalette16 RainbowStripeColors_p PROGMEM = { 0xFF0000, 0x000000, 0xAB5500, 0x000000, 0xABAB00, 0x000000, 0x00FF00, 0x000000, @@ -139,7 +139,7 @@ extern const TProgmemPalette16 RainbowStripeColors_p PROGMEM = // Basically, everything but the greens, which tend to make // people's skin look unhealthy. This palette is good for // lighting at a club or party, where it'll be shining on people. -extern const TProgmemPalette16 PartyColors_p PROGMEM = +extern const TProgmemRGBPalette16 PartyColors_p PROGMEM = { 0x5500AB, 0x84007C, 0xB5004B, 0xE5001B, 0xE81700, 0xB84700, 0xAB7700, 0xABAB00, @@ -153,7 +153,7 @@ extern const TProgmemPalette16 PartyColors_p PROGMEM = // the usual 0-255, as the last 15 colors will be // 'wrapping around' from the hot end to the cold end, // which looks wrong. -extern const TProgmemPalette16 HeatColors_p PROGMEM = +extern const TProgmemRGBPalette16 HeatColors_p PROGMEM = { 0x000000, 0x330000, 0x660000, 0x990000, 0xCC0000, 0xFF0000, diff --git a/colorpalettes.h b/colorpalettes.h index b9622694..340349d4 100644 --- a/colorpalettes.h +++ b/colorpalettes.h @@ -13,23 +13,23 @@ // use each one, so you only 'pay for' those you actually use. -extern const TProgmemPalette16 CloudColors_p PROGMEM; -extern const TProgmemPalette16 LavaColors_p PROGMEM; -extern const TProgmemPalette16 OceanColors_p PROGMEM; -extern const TProgmemPalette16 ForestColors_p PROGMEM; +extern const TProgmemRGBPalette16 CloudColors_p PROGMEM; +extern const TProgmemRGBPalette16 LavaColors_p PROGMEM; +extern const TProgmemRGBPalette16 OceanColors_p PROGMEM; +extern const TProgmemRGBPalette16 ForestColors_p PROGMEM; // HSV Rainbow -extern const TProgmemPalette16 RainbowColors_p PROGMEM; +extern const TProgmemRGBPalette16 RainbowColors_p PROGMEM; // HSV Rainbow colors with alternatating stripes of black #define RainbowStripesColors_p RainbowStripeColors_p -extern const TProgmemPalette16 RainbowStripeColors_p PROGMEM; +extern const TProgmemRGBPalette16 RainbowStripeColors_p PROGMEM; // HSV color ramp: blue purple ping red orange yellow (and back) // Basically, everything but the greens, which tend to make // people's skin look unhealthy. This palette is good for // lighting at a club or party, where it'll be shining on people. -extern const TProgmemPalette16 PartyColors_p PROGMEM; +extern const TProgmemRGBPalette16 PartyColors_p PROGMEM; // Approximate "black body radiation" palette, akin to // the FastLED 'HeatColor' function. @@ -37,6 +37,6 @@ extern const TProgmemPalette16 PartyColors_p PROGMEM; // the usual 0-255, as the last 15 colors will be // 'wrapping around' from the hot end to the cold end, // which looks wrong. -extern const TProgmemPalette16 HeatColors_p PROGMEM; +extern const TProgmemRGBPalette16 HeatColors_p PROGMEM; #endif diff --git a/colorutils.cpp b/colorutils.cpp index 6a12fb11..781651a8 100644 --- a/colorutils.cpp +++ b/colorutils.cpp @@ -456,41 +456,98 @@ CRGB ColorFromPalette( const CRGBPalette256& pal, uint8_t index, uint8_t brightn } -void UpscalePalette(const CRGBPalette16& srcpal16, CRGBPalette256& destpal256) +CHSV ColorFromPalette( const struct CHSVPalette16& pal, uint8_t index, uint8_t brightness, TBlendType blendType) { - for( int i = 0; i < 256; i++) { - destpal256[(uint8_t)(i)] = ColorFromPalette( srcpal16, i); + uint8_t hi4 = index >> 4; + uint8_t lo4 = index & 0x0F; + + // CRGB rgb1 = pal[ hi4]; + const CHSV* entry = &(pal[0]) + hi4; + + uint8_t hue1 = entry->hue; + uint8_t sat1 = entry->sat; + uint8_t val1 = entry->val; + + uint8_t blend = lo4 && (blendType != NOBLEND); + + if( blend ) { + + if( hi4 == 15 ) { + entry = &(pal[0]); + } else { + entry++; + } + + uint8_t f2 = lo4 << 4; + uint8_t f1 = 256 - f2; + + uint8_t hue2 = entry->hue; + uint8_t sat2 = entry->sat; + uint8_t val2 = entry->val; + + sat1 = scale8_LEAVING_R1_DIRTY( sat1, f1); + val1 = scale8_LEAVING_R1_DIRTY( val1, f1); + + sat2 = scale8_LEAVING_R1_DIRTY( sat2, f2); + val2 = scale8_LEAVING_R1_DIRTY( val2, f2); + + // cleanup_R1(); + + // These sums can't overflow, so no qadd8 needed. + sat1 += sat2; + val1 += val2; + + uint8_t deltaHue = (uint8_t)(hue2 - hue1); + if( deltaHue & 0x80 ) { + // go backwards + hue1 -= scale8( 256 - deltaHue, f2); + } else { + // go forwards + hue1 += scale8( deltaHue, f2); + } + + cleanup_R1(); + } + + if( brightness != 255) { + val1 = scale8_video( val1, brightness); } + + return CHSV( hue1, sat1, val1); } -#if 0 -// replaced by PartyColors_p -void SetupPartyColors(CRGBPalette16& pal) -{ - fill_gradient( pal, 0, CHSV( HUE_PURPLE,255,255), 7, CHSV(HUE_YELLOW - 18,255,255), FORWARD_HUES); - fill_gradient( pal, 8, CHSV( HUE_ORANGE,255,255), 15, CHSV(HUE_BLUE + 18,255,255), BACKWARD_HUES); -} -#endif -void fill_palette(CRGB* L, uint16_t N, uint8_t startIndex, uint8_t incIndex, - const CRGBPalette16& pal, uint8_t brightness, TBlendType blendType) +CHSV ColorFromPalette( const struct CHSVPalette256& pal, uint8_t index, uint8_t brightness, TBlendType) { - uint8_t colorIndex = startIndex; - for( uint16_t i = 0; i < N; i++) { - L[i] = ColorFromPalette( pal, colorIndex, brightness, blendType); - colorIndex += incIndex; + CHSV hsv;// = *( &(pal[0]) + index ); + + if( brightness != 255) { + hsv.value = scale8_video( hsv.value, brightness); } + + return hsv; } -void fill_palette(CRGB* L, uint16_t N, uint8_t startIndex, uint8_t incIndex, - const CRGBPalette256& pal, uint8_t brightness, TBlendType blendType) +void UpscalePalette(const struct CRGBPalette16& srcpal16, struct CRGBPalette256& destpal256) { - uint8_t colorIndex = startIndex; - for( uint16_t i = 0; i < N; i++) { - L[i] = ColorFromPalette( pal, colorIndex, brightness, blendType); - colorIndex += incIndex; + for( int i = 0; i < 256; i++) { + destpal256[(uint8_t)(i)] = ColorFromPalette( srcpal16, i); } } +void UpscalePalette(const struct CHSVPalette16& srcpal16, struct CHSVPalette256& destpal256) +{ + for( int i = 0; i < 256; i++) { + destpal256[(uint8_t)(i)] = ColorFromPalette( srcpal16, i); + } +} +#if 0 +// replaced by PartyColors_p +void SetupPartyColors(CRGBPalette16& pal) +{ + fill_gradient( pal, 0, CHSV( HUE_PURPLE,255,255), 7, CHSV(HUE_YELLOW - 18,255,255), FORWARD_HUES); + fill_gradient( pal, 8, CHSV( HUE_ORANGE,255,255), 15, CHSV(HUE_BLUE + 18,255,255), BACKWARD_HUES); +} +#endif diff --git a/colorutils.h b/colorutils.h index c2e1ec65..1a3a8d85 100644 --- a/colorutils.h +++ b/colorutils.h @@ -253,7 +253,7 @@ CRGB HeatColor( uint8_t temperature); // Palettes // -// Palettes map an 8-bit value (0..255) to an RGB color. +// RGB Palettes map an 8-bit value (0..255) to an RGB color. // // You can create any color palette you wish; a couple of starters // are provided: Forest, Clouds, Lava, Ocean, Rainbow, and Rainbow Stripes. @@ -309,11 +309,189 @@ CRGB HeatColor( uint8_t temperature); class CRGBPalette16; class CRGBPalette256; -typedef prog_uint32_t TProgmemPalette16[16]; +class CHSVPalette16; +class CHSVPalette256; +typedef prog_uint32_t TProgmemRGBPalette16[16]; +typedef prog_uint32_t TProgmemHSVPalette16[16]; +#define TProgmemPalette16 TProgmemRGBPalette16 // Convert a 16-entry palette to a 256-entry palette -void UpscalePalette(const CRGBPalette16& srcpal16, CRGBPalette256& destpal256); +void UpscalePalette(const struct CRGBPalette16& srcpal16, struct CRGBPalette256& destpal256); +void UpscalePalette(const struct CHSVPalette16& srcpal16, struct CHSVPalette256& destpal256); +class CHSVPalette16 { +public: + CHSV entries[16]; + CHSVPalette16() {}; + CHSVPalette16( const CHSV& c00,const CHSV& c01,const CHSV& c02,const CHSV& c03, + const CHSV& c04,const CHSV& c05,const CHSV& c06,const CHSV& c07, + const CHSV& c08,const CHSV& c09,const CHSV& c10,const CHSV& c11, + const CHSV& c12,const CHSV& c13,const CHSV& c14,const CHSV& c15 ) + { + entries[0]=c00; entries[1]=c01; entries[2]=c02; entries[3]=c03; + entries[4]=c04; entries[5]=c05; entries[6]=c06; entries[7]=c07; + entries[8]=c08; entries[9]=c09; entries[10]=c10; entries[11]=c11; + entries[12]=c12; entries[13]=c13; entries[14]=c14; entries[15]=c15; + }; + + CHSVPalette16( const CHSVPalette16& rhs) + { + memmove8( &(entries[0]), &(rhs.entries[0]), sizeof( entries)); + } + CHSVPalette16& operator=( const CHSVPalette16& rhs) + { + memmove8( &(entries[0]), &(rhs.entries[0]), sizeof( entries)); + return *this; + } + + CHSVPalette16( const TProgmemHSVPalette16& rhs) + { + for( uint8_t i = 0; i < 16; i++) { + CRGB xyz = pgm_read_dword_near( rhs + i); + entries[i].hue = xyz.red; + entries[i].sat = xyz.green; + entries[i].val = xyz.blue; + } + } + CHSVPalette16& operator=( const TProgmemHSVPalette16& rhs) + { + for( uint8_t i = 0; i < 16; i++) { + CRGB xyz = pgm_read_dword_near( rhs + i); + entries[i].hue = xyz.red; + entries[i].sat = xyz.green; + entries[i].val = xyz.blue; + } + return *this; + } + + inline CHSV& operator[] (uint8_t x) __attribute__((always_inline)) + { + return entries[x]; + } + inline const CHSV& operator[] (uint8_t x) const __attribute__((always_inline)) + { + return entries[x]; + } + + inline CHSV& operator[] (int x) __attribute__((always_inline)) + { + return entries[(uint8_t)x]; + } + inline const CHSV& operator[] (int x) const __attribute__((always_inline)) + { + return entries[(uint8_t)x]; + } + + operator CHSV*() + { + return &(entries[0]); + } + + CHSVPalette16( const CHSV& c1) + { + fill_solid( &(entries[0]), 16, c1); + } + CHSVPalette16( const CHSV& c1, const CHSV& c2) + { + fill_gradient( &(entries[0]), 16, c1, c2); + } + CHSVPalette16( const CHSV& c1, const CHSV& c2, const CHSV& c3) + { + fill_gradient( &(entries[0]), 16, c1, c2, c3); + } + CHSVPalette16( const CHSV& c1, const CHSV& c2, const CHSV& c3, const CHSV& c4) + { + fill_gradient( &(entries[0]), 16, c1, c2, c3, c4); + } + +}; + +class CHSVPalette256 { +public: + CHSV entries[256]; + CHSVPalette256() {}; + CHSVPalette256( const CHSV& c00,const CHSV& c01,const CHSV& c02,const CHSV& c03, + const CHSV& c04,const CHSV& c05,const CHSV& c06,const CHSV& c07, + const CHSV& c08,const CHSV& c09,const CHSV& c10,const CHSV& c11, + const CHSV& c12,const CHSV& c13,const CHSV& c14,const CHSV& c15 ) + { + CHSVPalette16 p16(c00,c01,c02,c03,c04,c05,c06,c07, + c08,c09,c10,c11,c12,c13,c14,c15); + *this = p16; + }; + + CHSVPalette256( const CHSVPalette256& rhs) + { + memmove8( &(entries[0]), &(rhs.entries[0]), sizeof( entries)); + } + CHSVPalette256& operator=( const CHSVPalette256& rhs) + { + memmove8( &(entries[0]), &(rhs.entries[0]), sizeof( entries)); + return *this; + } + + CHSVPalette256( const CHSVPalette16& rhs16) + { + UpscalePalette( rhs16, *this); + } + CHSVPalette256& operator=( const CHSVPalette16& rhs16) + { + UpscalePalette( rhs16, *this); + return *this; + } + + CHSVPalette256( const TProgmemRGBPalette16& rhs) + { + CHSVPalette16 p16(rhs); + *this = p16; + } + CHSVPalette256& operator=( const TProgmemRGBPalette16& rhs) + { + CHSVPalette16 p16(rhs); + *this = p16; + return *this; + } + + inline CHSV& operator[] (uint8_t x) __attribute__((always_inline)) + { + return entries[x]; + } + inline const CHSV& operator[] (uint8_t x) const __attribute__((always_inline)) + { + return entries[x]; + } + + inline CHSV& operator[] (int x) __attribute__((always_inline)) + { + return entries[(uint8_t)x]; + } + inline const CHSV& operator[] (int x) const __attribute__((always_inline)) + { + return entries[(uint8_t)x]; + } + + operator CHSV*() + { + return &(entries[0]); + } + + CHSVPalette256( const CHSV& c1) + { + fill_solid( &(entries[0]), 256, c1); + } + CHSVPalette256( const CHSV& c1, const CHSV& c2) + { + fill_gradient( &(entries[0]), 256, c1, c2); + } + CHSVPalette256( const CHSV& c1, const CHSV& c2, const CHSV& c3) + { + fill_gradient( &(entries[0]), 256, c1, c2, c3); + } + CHSVPalette256( const CHSV& c1, const CHSV& c2, const CHSV& c3, const CHSV& c4) + { + fill_gradient( &(entries[0]), 256, c1, c2, c3, c4); + } +}; class CRGBPalette16 { public: @@ -340,13 +518,27 @@ public: return *this; } - CRGBPalette16( const TProgmemPalette16& rhs) + CRGBPalette16( const CHSVPalette16& rhs) + { + for( uint8_t i = 0; i < 16; i++) { + entries[i] = rhs.entries[i]; // implicit HSV-to-RGB conversion + } + } + CRGBPalette16& operator=( const CHSVPalette16& rhs) + { + for( uint8_t i = 0; i < 16; i++) { + entries[i] = rhs.entries[i]; // implicit HSV-to-RGB conversion + } + return *this; + } + + CRGBPalette16( const TProgmemRGBPalette16& rhs) { for( uint8_t i = 0; i < 16; i++) { entries[i] = pgm_read_dword_near( rhs + i); } } - CRGBPalette16& operator=( const TProgmemPalette16& rhs) + CRGBPalette16& operator=( const TProgmemRGBPalette16& rhs) { for( uint8_t i = 0; i < 16; i++) { entries[i] = pgm_read_dword_near( rhs + i); @@ -438,6 +630,20 @@ public: return *this; } + CRGBPalette256( const CHSVPalette256& rhs) + { + for( int i = 0; i < 256; i++) { + entries[i] = rhs.entries[i]; // implicit HSV-to-RGB conversion + } + } + CRGBPalette256& operator=( const CHSVPalette256& rhs) + { + for( int i = 0; i < 256; i++) { + entries[i] = rhs.entries[i]; // implicit HSV-to-RGB conversion + } + return *this; + } + CRGBPalette256( const CRGBPalette16& rhs16) { UpscalePalette( rhs16, *this); @@ -448,12 +654,12 @@ public: return *this; } - CRGBPalette256( const TProgmemPalette16& rhs) + CRGBPalette256( const TProgmemRGBPalette16& rhs) { CRGBPalette16 p16(rhs); *this = p16; } - CRGBPalette256& operator=( const TProgmemPalette16& rhs) + CRGBPalette256& operator=( const TProgmemRGBPalette16& rhs) { CRGBPalette16 p16(rhs); *this = p16; @@ -519,6 +725,9 @@ public: }; + + + typedef enum { NOBLEND=0, BLEND=1 } TBlendType; CRGB ColorFromPalette( const CRGBPalette16& pal, @@ -531,20 +740,49 @@ CRGB ColorFromPalette( const CRGBPalette256& pal, uint8_t brightness=255, TBlendType blendType=NOBLEND ); +CHSV ColorFromPalette( const CHSVPalette16& pal, + uint8_t index, + uint8_t brightness=255, + TBlendType blendType=BLEND); -// Fill a range of LEDs with a sequece of entryies from a palette -void fill_palette(CRGB* L, uint16_t N, - uint8_t startIndex, uint8_t incIndex, - const CRGBPalette16& pal, - uint8_t brightness=255, - TBlendType blendType=BLEND); +CHSV ColorFromPalette( const CHSVPalette256& pal, + uint8_t index, + uint8_t brightness=255, + TBlendType blendType=NOBLEND ); -void fill_palette(CRGB* L, uint16_t N, - uint8_t startIndex, uint8_t incIndex, - const CRGBPalette256& pal, - uint8_t brightness=255, - TBlendType blendType=NOBLEND); +// Fill a range of LEDs with a sequece of entryies from a palette +template <typename PALETTE> +void fill_palette(CRGB* L, uint16_t N, uint8_t startIndex, uint8_t incIndex, + const PALETTE& pal, uint8_t brightness, TBlendType blendType) +{ + uint8_t colorIndex = startIndex; + for( uint16_t i = 0; i < N; i++) { + L[i] = ColorFromPalette( pal, colorIndex, brightness, blendType); + colorIndex += incIndex; + } +} +template <typename PALETTE> +void map_data_into_colors_through_palette( + uint8_t *dataArray, uint16_t dataCount, + CRGB* targetColorArray, + const PALETTE& pal, + uint8_t brightness=255, + uint8_t opacity=255, + TBlendType blendType=BLEND) +{ + for( uint16_t i = 0; i < dataCount; i++) { + uint8_t d = dataArray[i]; + CRGB rgb = ColorFromPalette( pal, d, brightness, blendType); + if( opacity == 255 ) { + targetColorArray[i] = rgb; + } else { + targetColorArray[i].nscale8( 256 - opacity); + rgb.nscale8_video( opacity); + targetColorArray[i] += rgb; + } + } +} #endif |