FastLED 3.9.3
Loading...
Searching...
No Matches
hsv2rgb.cpp
Go to the documentation of this file.
1
3
5#define FASTLED_INTERNAL
6#include <stdint.h>
7
8#include "FastLED.h"
9
10FASTLED_NAMESPACE_BEGIN
11
13void hsv2rgb_raw_C (const struct CHSV & hsv, struct CRGB & rgb);
15void hsv2rgb_raw_avr(const struct CHSV & hsv, struct CRGB & rgb);
16
17#if defined(__AVR__) && !defined( LIB8_ATTINY )
18void hsv2rgb_raw(const struct CHSV & hsv, struct CRGB & rgb)
19{
20 hsv2rgb_raw_avr( hsv, rgb);
21}
22#else
23void hsv2rgb_raw(const struct CHSV & hsv, struct CRGB & rgb)
24{
25 hsv2rgb_raw_C( hsv, rgb);
26}
27#endif
28
29
31#define APPLY_DIMMING(X) (X)
32
35#define HSV_SECTION_6 (0x20)
36
39#define HSV_SECTION_3 (0x40)
40
41void hsv2rgb_raw_C (const struct CHSV & hsv, struct CRGB & rgb)
42{
43 // Convert hue, saturation and brightness ( HSV/HSB ) to RGB
44 // "Dimming" is used on saturation and brightness to make
45 // the output more visually linear.
46
47 // Apply dimming curves
48 uint8_t value = APPLY_DIMMING( hsv.val); // cppcheck-suppress selfAssignment
49 uint8_t saturation = hsv.sat;
50
51 // The brightness floor is minimum number that all of
52 // R, G, and B will be set to.
53 uint8_t invsat = APPLY_DIMMING( 255 - saturation); // cppcheck-suppress selfAssignment
54 uint8_t brightness_floor = (value * invsat) / 256;
55
56 // The color amplitude is the maximum amount of R, G, and B
57 // that will be added on top of the brightness_floor to
58 // create the specific hue desired.
59 uint8_t color_amplitude = value - brightness_floor;
60
61 // Figure out which section of the hue wheel we're in,
62 // and how far offset we are withing that section
63 uint8_t section = hsv.hue / HSV_SECTION_3; // 0..2
64 uint8_t offset = hsv.hue % HSV_SECTION_3; // 0..63
65
66 uint8_t rampup = offset; // 0..63
67 uint8_t rampdown = (HSV_SECTION_3 - 1) - offset; // 63..0
68
69 // We now scale rampup and rampdown to a 0-255 range -- at least
70 // in theory, but here's where architecture-specific decsions
71 // come in to play:
72 // To scale them up to 0-255, we'd want to multiply by 4.
73 // But in the very next step, we multiply the ramps by other
74 // values and then divide the resulting product by 256.
75 // So which is faster?
76 // ((ramp * 4) * othervalue) / 256
77 // or
78 // ((ramp ) * othervalue) / 64
79 // It depends on your processor architecture.
80 // On 8-bit AVR, the "/ 256" is just a one-cycle register move,
81 // but the "/ 64" might be a multicycle shift process. So on AVR
82 // it's faster do multiply the ramp values by four, and then
83 // divide by 256.
84 // On ARM, the "/ 256" and "/ 64" are one cycle each, so it's
85 // faster to NOT multiply the ramp values by four, and just to
86 // divide the resulting product by 64 (instead of 256).
87 // Moral of the story: trust your profiler, not your insticts.
88
89 // Since there's an AVR assembly version elsewhere, we'll
90 // assume what we're on an architecture where any number of
91 // bit shifts has roughly the same cost, and we'll remove the
92 // redundant math at the source level:
93
94 // // scale up to 255 range
95 // //rampup *= 4; // 0..252
96 // //rampdown *= 4; // 0..252
97
98 // compute color-amplitude-scaled-down versions of rampup and rampdown
99 uint8_t rampup_amp_adj = (rampup * color_amplitude) / (256 / 4);
100 uint8_t rampdown_amp_adj = (rampdown * color_amplitude) / (256 / 4);
101
102 // add brightness_floor offset to everything
103 uint8_t rampup_adj_with_floor = rampup_amp_adj + brightness_floor;
104 uint8_t rampdown_adj_with_floor = rampdown_amp_adj + brightness_floor;
105
106
107 if( section ) {
108 if( section == 1) {
109 // section 1: 0x40..0x7F
110 rgb.r = brightness_floor;
111 rgb.g = rampdown_adj_with_floor;
112 rgb.b = rampup_adj_with_floor;
113 } else {
114 // section 2; 0x80..0xBF
115 rgb.r = rampup_adj_with_floor;
116 rgb.g = brightness_floor;
117 rgb.b = rampdown_adj_with_floor;
118 }
119 } else {
120 // section 0: 0x00..0x3F
121 rgb.r = rampdown_adj_with_floor;
122 rgb.g = rampup_adj_with_floor;
123 rgb.b = brightness_floor;
124 }
125}
126
127
128
129#if defined(__AVR__) && !defined( LIB8_ATTINY )
130void hsv2rgb_raw_avr(const struct CHSV & hsv, struct CRGB & rgb)
131{
132 uint8_t hue, saturation, value;
133
134 hue = hsv.hue;
135 saturation = hsv.sat;
136 value = hsv.val;
137
138 // Saturation more useful the other way around
139 saturation = 255 - saturation;
140 uint8_t invsat = APPLY_DIMMING( saturation ); // cppcheck-suppress selfAssignment
141
142 // Apply dimming curves
143 value = APPLY_DIMMING( value ); // cppcheck-suppress selfAssignment
144
145 // The brightness floor is minimum number that all of
146 // R, G, and B will be set to, which is value * invsat
147 uint8_t brightness_floor;
148
149 asm volatile(
150 "mul %[value], %[invsat] \n"
151 "mov %[brightness_floor], r1 \n"
152 : [brightness_floor] "=r" (brightness_floor)
153 : [value] "r" (value),
154 [invsat] "r" (invsat)
155 : "r0", "r1"
156 );
157
158 // The color amplitude is the maximum amount of R, G, and B
159 // that will be added on top of the brightness_floor to
160 // create the specific hue desired.
161 uint8_t color_amplitude = value - brightness_floor;
162
163 // Figure how far we are offset into the section of the
164 // color wheel that we're in
165 uint8_t offset = hsv.hue & (HSV_SECTION_3 - 1); // 0..63
166 uint8_t rampup = offset * 4; // 0..252
167
168
169 // compute color-amplitude-scaled-down versions of rampup and rampdown
170 uint8_t rampup_amp_adj;
171 uint8_t rampdown_amp_adj;
172
173 asm volatile(
174 "mul %[rampup], %[color_amplitude] \n"
175 "mov %[rampup_amp_adj], r1 \n"
176 "com %[rampup] \n"
177 "mul %[rampup], %[color_amplitude] \n"
178 "mov %[rampdown_amp_adj], r1 \n"
179 : [rampup_amp_adj] "=&r" (rampup_amp_adj),
180 [rampdown_amp_adj] "=&r" (rampdown_amp_adj),
181 [rampup] "+r" (rampup)
182 : [color_amplitude] "r" (color_amplitude)
183 : "r0", "r1"
184 );
185
186
187 // add brightness_floor offset to everything
188 uint8_t rampup_adj_with_floor = rampup_amp_adj + brightness_floor;
189 uint8_t rampdown_adj_with_floor = rampdown_amp_adj + brightness_floor;
190
191
192 // keep gcc from using "X" as the index register for storing
193 // results back in the return structure. AVR's X register can't
194 // do "std X+q, rnn", but the Y and Z registers can.
195 // if the pointer to 'rgb' is in X, gcc will add all kinds of crazy
196 // extra instructions. Simply killing X here seems to help it
197 // try Y or Z first.
198 asm volatile( "" : : : "r26", "r27" );
199
200
201 if( hue & 0x80 ) {
202 // section 2: 0x80..0xBF
203 rgb.r = rampup_adj_with_floor;
204 rgb.g = brightness_floor;
205 rgb.b = rampdown_adj_with_floor;
206 } else {
207 if( hue & 0x40) {
208 // section 1: 0x40..0x7F
209 rgb.r = brightness_floor;
210 rgb.g = rampdown_adj_with_floor;
211 rgb.b = rampup_adj_with_floor;
212 } else {
213 // section 0: 0x00..0x3F
214 rgb.r = rampdown_adj_with_floor;
215 rgb.g = rampup_adj_with_floor;
216 rgb.b = brightness_floor;
217 }
218 }
219
220 cleanup_R1();
221}
222// End of AVR asm implementation
223
224#endif
225
226void hsv2rgb_spectrum( const struct CHSV& hsv, CRGB& rgb)
227{
228 CHSV hsv2(hsv);
229 hsv2.hue = scale8( hsv2.hue, 191);
230 hsv2rgb_raw(hsv2, rgb);
231}
232
233
241#define FORCE_REFERENCE(var) asm volatile( "" : : "r" (var) )
242
243
245#define K255 255
246#define K171 171
247#define K170 170
248#define K85 85
250
251void hsv2rgb_rainbow( const CHSV& hsv, CRGB& rgb)
252{
253 // Yellow has a higher inherent brightness than
254 // any other color; 'pure' yellow is perceived to
255 // be 93% as bright as white. In order to make
256 // yellow appear the correct relative brightness,
257 // it has to be rendered brighter than all other
258 // colors.
259 // Level Y1 is a moderate boost, the default.
260 // Level Y2 is a strong boost.
261 const uint8_t Y1 = 1;
262 const uint8_t Y2 = 0;
263
264 // G2: Whether to divide all greens by two.
265 // Depends GREATLY on your particular LEDs
266 const uint8_t G2 = 0;
267
268 // Gscale: what to scale green down by.
269 // Depends GREATLY on your particular LEDs
270 const uint8_t Gscale = 0;
271
272
273 uint8_t hue = hsv.hue;
274 uint8_t sat = hsv.sat;
275 uint8_t val = hsv.val;
276
277 uint8_t offset = hue & 0x1F; // 0..31
278
279 // offset8 = offset * 8
280 uint8_t offset8 = offset;
281 {
282#if defined(__AVR__)
283 // Left to its own devices, gcc turns "x <<= 3" into a loop
284 // It's much faster and smaller to just do three single-bit shifts
285 // So this business is to force that.
286 offset8 <<= 1;
287 asm volatile("");
288 offset8 <<= 1;
289 asm volatile("");
290 offset8 <<= 1;
291#else
292 // On ARM and other non-AVR platforms, we just shift 3.
293 offset8 <<= 3;
294#endif
295 }
296
297 uint8_t third = scale8( offset8, (256 / 3)); // max = 85
298
299 uint8_t r, g, b;
300
301 if( ! (hue & 0x80) ) {
302 // 0XX
303 if( ! (hue & 0x40) ) {
304 // 00X
305 //section 0-1
306 if( ! (hue & 0x20) ) {
307 // 000
308 //case 0: // R -> O
309 r = K255 - third;
310 g = third;
311 b = 0;
313 } else {
314 // 001
315 //case 1: // O -> Y
316 if( Y1 ) {
317 r = K171;
318 g = K85 + third ;
319 b = 0;
321 }
322 if( Y2 ) {
323 r = K170 + third;
324 //uint8_t twothirds = (third << 1);
325 uint8_t twothirds = scale8( offset8, ((256 * 2) / 3)); // max=170
326 g = K85 + twothirds;
327 b = 0;
329 }
330 }
331 } else {
332 //01X
333 // section 2-3
334 if( ! (hue & 0x20) ) {
335 // 010
336 //case 2: // Y -> G
337 if( Y1 ) {
338 //uint8_t twothirds = (third << 1);
339 uint8_t twothirds = scale8( offset8, ((256 * 2) / 3)); // max=170
340 r = K171 - twothirds;
341 g = K170 + third;
342 b = 0;
344 }
345 if( Y2 ) {
346 r = K255 - offset8;
347 g = K255;
348 b = 0;
350 }
351 } else {
352 // 011
353 // case 3: // G -> A
354 r = 0;
356 g = K255 - third;
357 b = third;
358 }
359 }
360 } else {
361 // section 4-7
362 // 1XX
363 if( ! (hue & 0x40) ) {
364 // 10X
365 if( ! ( hue & 0x20) ) {
366 // 100
367 //case 4: // A -> B
368 r = 0;
370 //uint8_t twothirds = (third << 1);
371 uint8_t twothirds = scale8( offset8, ((256 * 2) / 3)); // max=170
372 g = K171 - twothirds; //K170?
373 b = K85 + twothirds;
374
375 } else {
376 // 101
377 //case 5: // B -> P
378 r = third;
379 g = 0;
381 b = K255 - third;
382
383 }
384 } else {
385 if( ! (hue & 0x20) ) {
386 // 110
387 //case 6: // P -- K
388 r = K85 + third;
389 g = 0;
391 b = K171 - third;
392
393 } else {
394 // 111
395 //case 7: // K -> R
396 r = K170 + third;
397 g = 0;
399 b = K85 - third;
400
401 }
402 }
403 }
404
405 // This is one of the good places to scale the green down,
406 // although the client can scale green down as well.
407 if( G2 ) g = g >> 1;
408 if( Gscale ) g = scale8_video_LEAVING_R1_DIRTY( g, Gscale);
409
410 // Scale down colors if we're desaturated at all
411 // and add the brightness_floor to r, g, and b.
412 if( sat != 255 ) {
413 if( sat == 0) {
414 r = 255; b = 255; g = 255;
415 } else {
416 uint8_t desat = 255 - sat;
417 desat = scale8_video( desat, desat);
418
419 uint8_t satscale = 255 - desat;
420 //satscale = sat; // uncomment to revert to pre-2021 saturation behavior
421
422 //nscale8x3_video( r, g, b, sat);
423#if (FASTLED_SCALE8_FIXED==1)
424 r = scale8_LEAVING_R1_DIRTY( r, satscale);
425 g = scale8_LEAVING_R1_DIRTY( g, satscale);
426 b = scale8_LEAVING_R1_DIRTY( b, satscale);
427 cleanup_R1();
428#else
429 if( r ) r = scale8( r, satscale) + 1;
430 if( g ) g = scale8( g, satscale) + 1;
431 if( b ) b = scale8( b, satscale) + 1;
432#endif
433 uint8_t brightness_floor = desat;
434 r += brightness_floor;
435 g += brightness_floor;
436 b += brightness_floor;
437 }
438 }
439
440 // Now scale everything down if we're at value < 255.
441 if( val != 255 ) {
442
443 val = scale8_video_LEAVING_R1_DIRTY( val, val);
444 if( val == 0 ) {
445 r=0; g=0; b=0;
446 } else {
447 // nscale8x3_video( r, g, b, val);
448#if (FASTLED_SCALE8_FIXED==1)
449 r = scale8_LEAVING_R1_DIRTY( r, val);
450 g = scale8_LEAVING_R1_DIRTY( g, val);
451 b = scale8_LEAVING_R1_DIRTY( b, val);
452 cleanup_R1();
453#else
454 if( r ) r = scale8( r, val) + 1;
455 if( g ) g = scale8( g, val) + 1;
456 if( b ) b = scale8( b, val) + 1;
457#endif
458 }
459 }
460
461 // Here we have the old AVR "missing std X+n" problem again
462 // It turns out that fixing it winds up costing more than
463 // not fixing it.
464 // To paraphrase Dr Bronner, profile! profile! profile!
465 //asm volatile( "" : : : "r26", "r27" );
466 //asm volatile (" movw r30, r26 \n" : : : "r30", "r31");
467 rgb.r = r;
468 rgb.g = g;
469 rgb.b = b;
470}
471
472
473void hsv2rgb_raw(const struct CHSV * phsv, struct CRGB * prgb, int numLeds) {
474 for(int i = 0; i < numLeds; ++i) {
475 hsv2rgb_raw(phsv[i], prgb[i]);
476 }
477}
478
479void hsv2rgb_rainbow( const struct CHSV* phsv, struct CRGB * prgb, int numLeds) {
480 for(int i = 0; i < numLeds; ++i) {
481 hsv2rgb_rainbow(phsv[i], prgb[i]);
482 }
483}
484
485void hsv2rgb_spectrum( const struct CHSV* phsv, struct CRGB * prgb, int numLeds) {
486 for(int i = 0; i < numLeds; ++i) {
487 hsv2rgb_spectrum(phsv[i], prgb[i]);
488 }
489}
490
491
493#define FIXFRAC8(N,D) (((N)*256)/(D))
494
495// This function is only an approximation, and it is not
496// nearly as fast as the normal HSV-to-RGB conversion.
497// See extended notes in the .h file.
499{
500 uint8_t r = rgb.r;
501 uint8_t g = rgb.g;
502 uint8_t b = rgb.b;
503 uint8_t h, s, v;
504
505 // find desaturation
506 uint8_t desat = 255;
507 if( r < desat) desat = r;
508 if( g < desat) desat = g;
509 if( b < desat) desat = b;
510
511 // remove saturation from all channels
512 r -= desat;
513 g -= desat;
514 b -= desat;
515
516 //Serial.print("desat="); Serial.print(desat); Serial.println("");
517
518 //uint8_t orig_desat = sqrt16( desat * 256);
519 //Serial.print("orig_desat="); Serial.print(orig_desat); Serial.println("");
520
521 // saturation is opposite of desaturation
522 s = 255 - desat;
523 //Serial.print("s.1="); Serial.print(s); Serial.println("");
524
525 if( s != 255 ) {
526 // undo 'dimming' of saturation
527 s = 255 - sqrt16( (255-s) * 256);
528 }
529 // without lib8tion: float ... ew ... sqrt... double ew, or rather, ew ^ 0.5
530 // if( s != 255 ) s = (255 - (256.0 * sqrt( (float)(255-s) / 256.0)));
531 //Serial.print("s.2="); Serial.print(s); Serial.println("");
532
533
534 // at least one channel is now zero
535 // if all three channels are zero, we had a
536 // shade of gray.
537 if( (r + g + b) == 0) {
538 // we pick hue zero for no special reason
539 return CHSV( 0, 0, 255 - s);
540 }
541
542 // scale all channels up to compensate for desaturation
543 if( s < 255) {
544 if( s == 0) s = 1;
545 uint32_t scaleup = 65535 / (s);
546 r = ((uint32_t)(r) * scaleup) / 256;
547 g = ((uint32_t)(g) * scaleup) / 256;
548 b = ((uint32_t)(b) * scaleup) / 256;
549 }
550 //Serial.print("r.2="); Serial.print(r); Serial.println("");
551 //Serial.print("g.2="); Serial.print(g); Serial.println("");
552 //Serial.print("b.2="); Serial.print(b); Serial.println("");
553
554 uint16_t total = r + g + b;
555
556 //Serial.print("total="); Serial.print(total); Serial.println("");
557
558 // scale all channels up to compensate for low values
559 if( total < 255) {
560 if( total == 0) total = 1;
561 uint32_t scaleup = 65535 / (total);
562 r = ((uint32_t)(r) * scaleup) / 256;
563 g = ((uint32_t)(g) * scaleup) / 256;
564 b = ((uint32_t)(b) * scaleup) / 256;
565 }
566 //Serial.print("r.3="); Serial.print(r); Serial.println("");
567 //Serial.print("g.3="); Serial.print(g); Serial.println("");
568 //Serial.print("b.3="); Serial.print(b); Serial.println("");
569
570 if( total > 255 ) {
571 v = 255;
572 } else {
573 v = qadd8(desat,total);
574 // undo 'dimming' of brightness
575 if( v != 255) v = sqrt16( v * 256);
576 // without lib8tion: float ... ew ... sqrt... double ew, or rather, ew ^ 0.5
577 // if( v != 255) v = (256.0 * sqrt( (float)(v) / 256.0));
578
579 }
580
581 //Serial.print("v="); Serial.print(v); Serial.println("");
582
583
584#if 0
585
586 //#else
587 if( v != 255) {
588 // this part could probably use refinement/rethinking,
589 // (but it doesn't overflow & wrap anymore)
590 uint16_t s16;
591 s16 = (s * 256);
592 s16 /= v;
593 //Serial.print("s16="); Serial.print(s16); Serial.println("");
594 if( s16 < 256) {
595 s = s16;
596 } else {
597 s = 255; // clamp to prevent overflow
598 }
599 }
600#endif
601
602 //Serial.print("s.3="); Serial.print(s); Serial.println("");
603
604
605 // since this wasn't a pure shade of gray,
606 // the interesting question is what hue is it
607
608
609
610 // start with which channel is highest
611 // (ties don't matter)
612 uint8_t highest = r;
613 if( g > highest) highest = g;
614 if( b > highest) highest = b;
615
616 if( highest == r ) {
617 // Red is highest.
618 // Hue could be Purple/Pink-Red,Red-Orange,Orange-Yellow
619 if( g == 0 ) {
620 // if green is zero, we're in Purple/Pink-Red
621 h = (HUE_PURPLE + HUE_PINK) / 2;
622 h += scale8( qsub8(r, 128), FIXFRAC8(48,128));
623 } else if ( (r - g) > g) {
624 // if R-G > G then we're in Red-Orange
625 h = HUE_RED;
626 h += scale8( g, FIXFRAC8(32,85));
627 } else {
628 // R-G < G, we're in Orange-Yellow
629 h = HUE_ORANGE;
630 h += scale8( qsub8((g - 85) + (171 - r), 4), FIXFRAC8(32,85)); //221
631 }
632
633 } else if ( highest == g) {
634 // Green is highest
635 // Hue could be Yellow-Green, Green-Aqua
636 if( b == 0) {
637 // if Blue is zero, we're in Yellow-Green
638 // G = 171..255
639 // R = 171.. 0
640 h = HUE_YELLOW;
641 uint8_t radj = scale8( qsub8(171,r), 47); //171..0 -> 0..171 -> 0..31
642 uint8_t gadj = scale8( qsub8(g,171), 96); //171..255 -> 0..84 -> 0..31;
643 uint8_t rgadj = radj + gadj;
644 uint8_t hueadv = rgadj / 2;
645 h += hueadv;
646 //h += scale8( qadd8( 4, qadd8((g - 128), (128 - r))),
647 // FIXFRAC8(32,255)); //
648 } else {
649 // if Blue is nonzero we're in Green-Aqua
650 if( (g-b) > b) {
651 h = HUE_GREEN;
652 h += scale8( b, FIXFRAC8(32,85));
653 } else {
654 h = HUE_AQUA;
655 h += scale8( qsub8(b, 85), FIXFRAC8(8,42));
656 }
657 }
658
659 } else /* highest == b */ {
660 // Blue is highest
661 // Hue could be Aqua/Blue-Blue, Blue-Purple, Purple-Pink
662 if( r == 0) {
663 // if red is zero, we're in Aqua/Blue-Blue
664 h = HUE_AQUA + ((HUE_BLUE - HUE_AQUA) / 4);
665 h += scale8( qsub8(b, 128), FIXFRAC8(24,128));
666 } else if ( (b-r) > r) {
667 // B-R > R, we're in Blue-Purple
668 h = HUE_BLUE;
669 h += scale8( r, FIXFRAC8(32,85));
670 } else {
671 // B-R < R, we're in Purple-Pink
672 h = HUE_PURPLE;
673 h += scale8( qsub8(r, 85), FIXFRAC8(32,85));
674 }
675 }
676
677 h += 1;
678 return CHSV( h, s, v);
679}
680
681// Examples that need work:
682// 0,192,192
683// 192,64,64
684// 224,32,32
685// 252,0,126
686// 252,252,0
687// 252,252,126
688
689FASTLED_NAMESPACE_END
central include file for FastLED, defines the CFastLED class/object
void hsv2rgb_raw(const struct CHSV &hsv, struct CRGB &rgb)
Convert an HSV value to RGB using a mathematically straight spectrum.
Definition hsv2rgb.cpp:23
void hsv2rgb_spectrum(const struct CHSV &hsv, CRGB &rgb)
Convert an HSV value to RGB using a mathematically straight spectrum.
Definition hsv2rgb.cpp:226
CHSV rgb2hsv_approximate(const CRGB &rgb)
Recover approximate HSV values from RGB.
Definition hsv2rgb.cpp:498
LIB8STATIC_ALWAYS_INLINE uint8_t qadd8(uint8_t i, uint8_t j)
Add one byte to another, saturating at 0xFF.
Definition math8.h:31
LIB8STATIC uint8_t sqrt16(uint16_t x)
Square root for 16-bit integers.
Definition math8.h:524
LIB8STATIC_ALWAYS_INLINE uint8_t qsub8(uint8_t i, uint8_t j)
Subtract one byte from another, saturating at 0x00.
Definition math8.h:103
void hsv2rgb_rainbow(const CHSV &hsv, CRGB &rgb)
Forward declaration of hsv2rgb_rainbow here, to avoid circular dependencies.
Definition hsv2rgb.cpp:251
uint8_t r
Red channel value.
Definition crgb.h:43
uint8_t g
Green channel value.
Definition crgb.h:47
uint8_t b
Blue channel value.
Definition crgb.h:51
LIB8STATIC_ALWAYS_INLINE void cleanup_R1()
Clean up the r1 register after a series of *LEAVING_R1_DIRTY calls.
Definition scale8.h:333
LIB8STATIC_ALWAYS_INLINE uint8_t scale8_LEAVING_R1_DIRTY(uint8_t i, fract8 scale)
This version of scale8() does not clean up the R1 register on AVR.
Definition scale8.h:170
LIB8STATIC_ALWAYS_INLINE uint8_t scale8_video_LEAVING_R1_DIRTY(uint8_t i, fract8 scale)
This version of scale8_video() does not clean up the R1 register on AVR.
Definition scale8.h:262
LIB8STATIC_ALWAYS_INLINE uint8_t scale8_video(uint8_t i, fract8 scale)
The "video" version of scale8() guarantees that the output will be only be zero if one or both of the...
Definition scale8.h:117
LIB8STATIC_ALWAYS_INLINE uint8_t scale8(uint8_t i, fract8 scale)
Scale one byte by a second one, which is treated as the numerator of a fraction whose denominator is ...
Definition scale8.h:34
#define APPLY_DIMMING(X)
Apply dimming compensation to values.
Definition hsv2rgb.cpp:31
#define FIXFRAC8(N, D)
Convert a fractional input into a constant.
Definition hsv2rgb.cpp:493
#define FORCE_REFERENCE(var)
Force a variable reference to avoid compiler over-optimization.
Definition hsv2rgb.cpp:241
void hsv2rgb_raw_avr(const struct CHSV &hsv, struct CRGB &rgb)
HSV to RGB implementation in raw C, for the AVR platform only.
void hsv2rgb_raw_C(const struct CHSV &hsv, struct CRGB &rgb)
HSV to RGB implementation in raw C, platform independent.
Definition hsv2rgb.cpp:41
#define HSV_SECTION_3
Divide the color wheel into four sections, 64 elements each.
Definition hsv2rgb.cpp:39
Representation of an HSV pixel (hue, saturation, value (aka brightness)).
Definition chsv.h:11
uint8_t hue
Color hue.
Definition chsv.h:18
uint8_t sat
Color saturation.
Definition chsv.h:25
uint8_t val
Color value (brightness).
Definition chsv.h:32
Representation of an RGB pixel (Red, Green, Blue)
Definition crgb.h:39