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