Recover approximate HSV values from RGB.
These values are approximate, not exact. Why is this "only" an approximation? Because not all RGB colors have HSV equivalents! For example, there is no HSV value that will ever convert to RGB(255,255,0) using the code provided in this library. So if you try to convert RGB(255,255,0) "back" to HSV, you'll necessarily get only an approximation. Emphasis has been placed on getting the "hue" as close as usefully possible, but even that's a bit of a challenge. The 8-bit HSV and 8-bit RGB color spaces are not a "bijection".
Nevertheless, this function does a pretty good job, particularly at recovering the 'hue' from fully saturated RGB colors that originally came from HSV rainbow colors. So if you start with CHSV(hue_in,255,255), and convert that to RGB, and then convert it back to HSV using this function, the resulting output hue will either exactly the same, or very close (+/-1). The more desaturated the original RGB color is, the rougher the approximation, and the less accurate the results.
- Note
- This function is a long-term work in progress; expect results to change slightly over time as this function is refined and improved.
- Note
- This function is most accurate when the input is an RGB color that came from a fully-saturated HSV color to start with. E.g. CHSV( hue, 255, 255) -> CRGB -> CHSV will give best results.
- Note
- This function is not nearly as fast as HSV-to-RGB. It is provided for those situations when the need for this function cannot be avoided, or when extremely high performance is not needed.
- See also
- https://en.wikipedia.org/wiki/Bijection
- Parameters
-
| rgb | an RGB value to convert |
- Returns
- the approximate HSV equivalent of the RGB value
Definition at line 551 of file hsv2rgb.cpp.hpp.
552{
557
558
560 if( r < desat) desat = r;
561 if( g < desat) desat = g;
562 if( b < desat) desat = b;
563
564
565 r -= desat;
566 g -= desat;
567 b -= desat;
568
569
570
571
572
573
574
575 s = 255 - desat;
576
577
578 if( s != 255 ) {
579
580 s = 255 - fl::sqrt16( (255-s) * 256);
581 }
582
583
584
585
586
587
588
589
590 if( (r + g + b) == 0) {
591
592 return CHSV( 0, 0, 255 - s);
593 }
594
595
596 if( s < 255) {
597 if( s == 0) s = 1;
598 fl::u32 scaleup = 65535 / (s);
599 r = ((fl::u32)(r) * scaleup) / 256;
600 g = ((fl::u32)(g) * scaleup) / 256;
601 b = ((fl::u32)(b) * scaleup) / 256;
602 }
603
604
605
606
607 fl::u16 total = r + g + b;
608
609
610
611
612 if( total < 255) {
613 if( total == 0) total = 1;
614 fl::u32 scaleup = 65535 / (total);
615 r = ((fl::u32)(r) * scaleup) / 256;
616 g = ((fl::u32)(g) * scaleup) / 256;
617 b = ((fl::u32)(b) * scaleup) / 256;
618 }
619
620
621
622
623 if( total > 255 ) {
624 v = 255;
625 } else {
626 v = qadd8(desat,total);
627
628 if( v != 255) v = fl::sqrt16( v * 256);
629
630
631
632 }
633
634
635
636
637#if 0
638
639
640 if( v != 255) {
641
642
643 fl::u16 s16;
644 s16 = (s * 256);
645 s16 /= v;
646
647 if( s16 < 256) {
648 s = s16;
649 } else {
650 s = 255;
651 }
652 }
653#endif
654
655
656
657
658
659
660
661
662
663
664
666 if( g > highest) highest = g;
667 if( b > highest) highest = b;
668
669 if( highest == r ) {
670
671
672 if( g == 0 ) {
673
675 h += scale8( qsub8(r, 128),
FIXFRAC8(48,128));
676 } else if ( (r - g) > g) {
677
680 } else {
681
683 h += scale8( qsub8((g - 85) + (171 - r), 4),
FIXFRAC8(32,85));
684 }
685
686 } else if ( highest == g) {
687
688
689 if( b == 0) {
690
691
692
694 fl::u8 radj = scale8( qsub8(171,r), 47);
695 fl::u8 gadj = scale8( qsub8(g,171), 96);
696 fl::u8 rgadj = radj + gadj;
697 fl::u8 hueadv = rgadj / 2;
698 h += hueadv;
699
700
701 } else {
702
703 if( (g-b) > b) {
706 } else {
708 h += scale8( qsub8(b, 85),
FIXFRAC8(8,42));
709 }
710 }
711
712 } else {
713
714
715 if( r == 0) {
716
718 h += scale8( qsub8(b, 128),
FIXFRAC8(24,128));
719 } else if ( (b-r) > r) {
720
723 } else {
724
726 h += scale8( qsub8(r, 85),
FIXFRAC8(32,85));
727 }
728 }
729
730 h += 1;
731 return CHSV( h, s, v);
732}
@ HUE_PURPLE
Purple (270°)
#define FIXFRAC8(N, D)
Convert a fractional input into a constant.
References FIXFRAC8, HUE_AQUA, HUE_BLUE, HUE_GREEN, HUE_ORANGE, HUE_PINK, HUE_PURPLE, HUE_RED, and HUE_YELLOW.