diff options
author | Daniel Garcia <danielgarcia@gmail.com> | 2016-01-23 10:40:10 +0300 |
---|---|---|
committer | Daniel Garcia <danielgarcia@gmail.com> | 2016-01-23 10:40:10 +0300 |
commit | 6d6aca7330c4c2e1b29cf791dbf2550692da59d2 (patch) | |
tree | debfea01124507eb37ff9d91b506205f0822cf88 | |
parent | 566e69235963dafb00fbb7cbc5a7d4f09f3ed3b1 (diff) | |
parent | ce4bfbc878d5be4cf5aecd9268bd2a4520a41363 (diff) |
Merge branch 'master' of https://github.com/FastLED/FastLED
-rw-r--r-- | hsv2rgb.cpp | 191 |
1 files changed, 131 insertions, 60 deletions
diff --git a/hsv2rgb.cpp b/hsv2rgb.cpp index 17c20c4c..49056d51 100644 --- a/hsv2rgb.cpp +++ b/hsv2rgb.cpp @@ -286,22 +286,22 @@ void hsv2rgb_rainbow( const CHSV& hsv, CRGB& rgb) // Level Y2 is a strong boost. const uint8_t Y1 = 1; const uint8_t Y2 = 0; - + // G2: Whether to divide all greens by two. // Depends GREATLY on your particular LEDs const uint8_t G2 = 0; - + // Gscale: what to scale green down by. // Depends GREATLY on your particular LEDs const uint8_t Gscale = 0; - - + + uint8_t hue = hsv.hue; uint8_t sat = hsv.sat; uint8_t val = hsv.val; - + uint8_t offset = hue & 0x1F; // 0..31 - + // offset8 = offset * 8 uint8_t offset8 = offset; { @@ -319,11 +319,11 @@ void hsv2rgb_rainbow( const CHSV& hsv, CRGB& rgb) offset8 <<= 3; #endif } - + uint8_t third = scale8( offset8, (256 / 3)); - + uint8_t r, g, b; - + if( ! (hue & 0x80) ) { // 0XX if( ! (hue & 0x40) ) { @@ -397,7 +397,7 @@ void hsv2rgb_rainbow( const CHSV& hsv, CRGB& rgb) uint8_t twothirds = scale8( offset8, ((256 * 2) / 3)); g = K171 - twothirds; b = K85 + twothirds; - + } else { // 101 //case 5: // B -> P @@ -405,7 +405,7 @@ void hsv2rgb_rainbow( const CHSV& hsv, CRGB& rgb) g = 0; FORCE_REFERENCE(g); b = K255 - third; - + } } else { if( ! (hue & 0x20) ) { @@ -415,7 +415,7 @@ void hsv2rgb_rainbow( const CHSV& hsv, CRGB& rgb) g = 0; FORCE_REFERENCE(g); b = K171 - third; - + } else { // 111 //case 7: // K -> R @@ -423,38 +423,53 @@ void hsv2rgb_rainbow( const CHSV& hsv, CRGB& rgb) g = 0; FORCE_REFERENCE(g); b = K85 - third; - + } } } - + // This is one of the good places to scale the green down, // although the client can scale green down as well. if( G2 ) g = g >> 1; if( Gscale ) g = scale8_video_LEAVING_R1_DIRTY( g, Gscale); - + // Scale down colors if we're desaturated at all // and add the brightness_floor to r, g, and b. if( sat != 255 ) { - - nscale8x3_video( r, g, b, sat); - - uint8_t desat = 255 - sat; - desat = scale8( desat, desat); - - uint8_t brightness_floor = desat; - r += brightness_floor; - g += brightness_floor; - b += brightness_floor; + if( sat == 0) { + r = 255; b = 255; g = 255; + } else { + //nscale8x3_video( r, g, b, sat); + if( r ) r = scale8_LEAVING_R1_DIRTY( r, sat) + 1; + if( g ) g = scale8_LEAVING_R1_DIRTY( g, sat) + 1; + if( b ) b = scale8_LEAVING_R1_DIRTY( b, sat) + 1; + cleanup_R1(); + + uint8_t desat = 255 - sat; + desat = scale8( desat, desat); + + uint8_t brightness_floor = desat; + r += brightness_floor; + g += brightness_floor; + b += brightness_floor; + } } - + // Now scale everything down if we're at value < 255. if( val != 255 ) { - + val = scale8_video_LEAVING_R1_DIRTY( val, val); - nscale8x3_video( r, g, b, val); + if( val == 0 ) { + r=0; g=0; b=0; + } else { + // nscale8x3_video( r, g, b, val); + if( r ) r = scale8_LEAVING_R1_DIRTY( r, val) + 1; + if( g ) g = scale8_LEAVING_R1_DIRTY( g, val) + 1; + if( b ) b = scale8_LEAVING_R1_DIRTY( b, val) + 1; + cleanup_R1(); + } } - + // Here we have the old AVR "missing std X+n" problem again // It turns out that fixing it winds up costing more than // not fixing it. @@ -498,41 +513,72 @@ CHSV rgb2hsv_approximate( const CRGB& rgb) uint8_t g = rgb.g; uint8_t b = rgb.b; uint8_t h, s, v; - + // find desaturation uint8_t desat = 255; if( r < desat) desat = r; if( g < desat) desat = g; if( b < desat) desat = b; - + // remove saturation from all channels r -= desat; g -= desat; b -= desat; - + + //Serial.print("desat="); Serial.print(desat); Serial.println(""); + + //uint8_t orig_desat = sqrt16( desat * 256); + //Serial.print("orig_desat="); Serial.print(orig_desat); Serial.println(""); + + // saturation is opposite of desaturation + s = 255 - desat; + //Serial.print("s.1="); Serial.print(s); Serial.println(""); + + if( s != 255 ) { + // undo 'dimming' of saturation + s = 255 - sqrt16( (255-s) * 256); + } + // without lib8tion: float ... ew ... sqrt... double ew, or rather, ew ^ 0.5 + // if( s != 255 ) s = (255 - (256.0 * sqrt( (float)(255-s) / 256.0))); + //Serial.print("s.2="); Serial.print(s); Serial.println(""); + + // at least one channel is now zero - // if all three channels are zero, we had a // shade of gray. - - uint16_t total = r + g + b; - - if( total == 0) { + if( (r + g + b) == 0) { // we pick hue zero for no special reason - return CHSV( 0, 0, desat); + return CHSV( 0, 0, 255 - s); } - - // since this wasn't a pure shade of gray, - // the interesting question is what hue is it - - // scale all channels up to a total of 255 - if( total != 255) { + + // scale all channels up to compensate for desaturation + if( s < 255) { + if( s == 0) s = 1; + uint32_t scaleup = 65535 / (s); + r = ((uint32_t)(r) * scaleup) / 256; + g = ((uint32_t)(g) * scaleup) / 256; + b = ((uint32_t)(b) * scaleup) / 256; + } + //Serial.print("r.2="); Serial.print(r); Serial.println(""); + //Serial.print("g.2="); Serial.print(g); Serial.println(""); + //Serial.print("b.2="); Serial.print(b); Serial.println(""); + + uint16_t total = r + g + b; + + //Serial.print("total="); Serial.print(total); Serial.println(""); + + // scale all channels up to compensate for low values + if( total < 255) { + if( total == 0) total = 1; uint32_t scaleup = 65535 / (total); r = ((uint32_t)(r) * scaleup) / 256; g = ((uint32_t)(g) * scaleup) / 256; b = ((uint32_t)(b) * scaleup) / 256; } - + //Serial.print("r.3="); Serial.print(r); Serial.println(""); + //Serial.print("g.3="); Serial.print(g); Serial.println(""); + //Serial.print("b.3="); Serial.print(b); Serial.println(""); + if( total > 255 ) { v = 255; } else { @@ -541,35 +587,44 @@ CHSV rgb2hsv_approximate( const CRGB& rgb) if( v != 255) v = sqrt16( v * 256); // without lib8tion: float ... ew ... sqrt... double ew, or rather, ew ^ 0.5 // if( v != 255) v = (256.0 * sqrt( (float)(v) / 256.0)); - + } - - // saturation is opposite of desaturation - s = 255 - desat; + + //Serial.print("v="); Serial.print(v); Serial.println(""); + + +#if 0 + + //#else if( v != 255) { // this part could probably use refinement/rethinking, // (but it doesn't overflow & wrap anymore) uint16_t s16; s16 = (s * 256); s16 /= v; + //Serial.print("s16="); Serial.print(s16); Serial.println(""); if( s16 < 256) { s = s16; } else { s = 255; // clamp to prevent overflow } } - - // undo 'dimming' of saturation - if( s != 255 ) s = 255 - sqrt16( (255-s) * 256); - // without lib8tion: float ... ew ... sqrt... double ew, or rather, ew ^ 0.5 - // if( s != 255 ) s = (255 - (256.0 * sqrt( (float)(255-s) / 256.0))); - +#endif + + //Serial.print("s.3="); Serial.print(s); Serial.println(""); + + + // since this wasn't a pure shade of gray, + // the interesting question is what hue is it + + + // start with which channel is highest // (ties don't matter) uint8_t highest = r; if( g > highest) highest = g; if( b > highest) highest = b; - + if( highest == r ) { // Red is highest. // Hue could be Purple/Pink-Red,Red-Orange,Orange-Yellow @@ -586,14 +641,22 @@ CHSV rgb2hsv_approximate( const CRGB& rgb) h = HUE_ORANGE; h += scale8( qsub8((g - 85) + (171 - r), 4), FIXFRAC8(32,85)); //221 } - + } else if ( highest == g) { // Green is highest // Hue could be Yellow-Green, Green-Aqua if( b == 0) { // if Blue is zero, we're in Yellow-Green + // G = 171..255 + // R = 171.. 0 h = HUE_YELLOW; - h += scale8( qadd8( qadd8((g - 128), (128 - r)), 4), FIXFRAC8(32,255)); // + uint8_t radj = scale8( qsub8(171,r), 47); //171..0 -> 0..171 -> 0..31 + uint8_t gadj = scale8( qsub8(g,171), 96); //171..255 -> 0..84 -> 0..31; + uint8_t rgadj = radj + gadj; + uint8_t hueadv = rgadj / 2; + h += hueadv; + //h += scale8( qadd8( 4, qadd8((g - 128), (128 - r))), + // FIXFRAC8(32,255)); // } else { // if Blue is nonzero we're in Green-Aqua if( (g-b) > b) { @@ -604,7 +667,7 @@ CHSV rgb2hsv_approximate( const CRGB& rgb) h += scale8( qsub8(b, 85), FIXFRAC8(8,42)); } } - + } else /* highest == b */ { // Blue is highest // Hue could be Aqua/Blue-Blue, Blue-Purple, Purple-Pink @@ -622,9 +685,17 @@ CHSV rgb2hsv_approximate( const CRGB& rgb) h += scale8( qsub8(r, 85), FIXFRAC8(32,85)); } } - + h += 1; return CHSV( h, s, v); } +// Examples that need work: +// 0,192,192 +// 192,64,64 +// 224,32,32 +// 252,0,126 +// 252,252,0 +// 252,252,126 + FASTLED_NAMESPACE_END |