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 559 of file hsv2rgb.cpp.hpp.
560{
561
562
563 fl::u16 r = rgb.r;
565 fl::u16 b = rgb.b;
567
568
570 if( r < desat) desat = r;
571 if( g < desat) desat =
g;
572 if( b < desat) desat = b;
573
574
575 r -= desat;
577 b -= desat;
578
579
580
581
582
583
584
585 s = 255 - desat;
586
587
588 if( s != 255 ) {
589
590 s = 255 - fl::sqrt16( (255-s) * 256);
591 }
592
593
594
595
596
597
598
599
600 if( (r + g + b) == 0) {
601
602 return CHSV( 0, 0, 255 - s);
603 }
604
605
606 if( s < 255) {
607 if( s == 0) s = 1;
608 fl::u32 scaleup = 65535 / (s);
609 r = ((fl::u32)(r) * scaleup) / 256;
610 g = ((fl::u32)(
g) * scaleup) / 256;
611 b = ((fl::u32)(b) * scaleup) / 256;
612 }
613
614
615
616
617 fl::u16 total = r +
g + b;
618
619
620
621
622
623
624 if( total != 255) {
625 if( total == 0) total = 1;
626 fl::u32 scaleup = 65535 / (total);
627 r = ((fl::u32)(r) * scaleup) / 256;
628 g = ((fl::u32)(
g) * scaleup) / 256;
629 b = ((fl::u32)(b) * scaleup) / 256;
630 }
631
632
633
634
635 if( total > 255 ) {
636 v = 255;
637 } else {
638 v = qadd8(desat,total);
639
640 if( v != 255) v = fl::sqrt16( v * 256);
641
642
643
644 }
645
646
647
648
649#if 0
650
651
652 if( v != 255) {
653
654
655 fl::u16 s16;
656 s16 = (s * 256);
657 s16 /= v;
658
659 if( s16 < 256) {
660 s = s16;
661 } else {
662 s = 255;
663 }
664 }
665#endif
666
667
668
669
670
671
672
673
674
675
676
677 fl::u16 highest = r;
678 if( g > highest) highest =
g;
679 if( b > highest) highest = b;
680
681 if( highest == r ) {
682
683
684 if( g == 0 ) {
685
687 h += scale8( qsub8(r, 128),
FIXFRAC8(48,128));
688 } else if ( (r - g) > g) {
689
692 } else {
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
709 h += scale8( qsub8((g - 85) + (255 - r), 4),
FIXFRAC8(32,170));
710 }
711
712 } else if ( highest == g) {
713
714
715 if( b == 0) {
716
717
718
720 fl::u8 radj = scale8( qsub8(171,r), 47);
721 fl::u8 gadj = scale8( qsub8(g,171), 96);
722 fl::u8 rgadj = radj + gadj;
723 fl::u8 hueadv = rgadj / 2;
724 h += hueadv;
725
726
727 } else {
728
729 if( (g-b) > b) {
732 } else {
734 h += scale8( qsub8(b, 85),
FIXFRAC8(8,42));
735 }
736 }
737
738 } else {
739
740
741 if( r == 0) {
742
744 h += scale8( qsub8(b, 128),
FIXFRAC8(24,128));
745 } else if ( (b-r) > r) {
746
749 } else {
750
752 h += scale8( qsub8(r, 85),
FIXFRAC8(32,85));
753 }
754 }
755
756 h += 1;
757 return CHSV( h, s, v);
758}
@ 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.