Created
March 19, 2025 14:21
-
-
Save GitMoDu/7587a97b1dd6479da7af89a24e9e46ae to your computer and use it in GitHub Desktop.
Cpp converter of HSV to RGB888 using integer-only math.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /// <summary> | |
| /// Converts HSV to RGB888 using integer-only math. | |
| /// </summary> | |
| /// <param name="hue">Hue angle [0 ; UINT16_MAX], corresponds to [0 ; 360] degrees color wheel.</param> | |
| /// <param name="saturation">Saturation value [0 ; 255].</param> | |
| /// <param name="value">Brightness value [0 ; 255].</param> | |
| /// <returns>uint32 RGB888 color, where the color is represented as 0xRRGGBB.</returns> | |
| static uint32_t HsvToRgb(const uint16_t hue, const uint8_t saturation, const uint8_t value) | |
| { | |
| static constexpr uint8_t Segments = 6; | |
| if (saturation == 0) | |
| { | |
| // Achromatic (gray). | |
| return ((uint32_t)value << 16) | |
| | ((uint16_t)value << 8) | |
| | value; | |
| } | |
| else | |
| { | |
| // Scale hue to fit into the number of segments. | |
| const uint16_t hueScaled = ((uint32_t)hue * Segments) >> 8; | |
| const uint8_t hueSegment = (hueScaled >> 8) % Segments; | |
| const uint8_t f = hueScaled & UINT8_MAX; | |
| // Calculate intermediate values. | |
| const uint8_t p = (((uint16_t)value * (UINT8_MAX - saturation)) / UINT8_MAX); | |
| const uint8_t fs = (((uint16_t)f * saturation) / UINT8_MAX); | |
| const uint8_t q = (((uint16_t)value * (UINT8_MAX - fs)) / UINT8_MAX); | |
| const uint8_t fsR = (((uint16_t)(UINT8_MAX - f) * saturation) / UINT8_MAX); | |
| const uint8_t t = (((uint16_t)value * (UINT8_MAX - fsR)) / UINT8_MAX); | |
| // Determine the RGB values based on the hue segment. | |
| switch (hueSegment % Segments) | |
| { | |
| case 0: // Red is dominant. | |
| return ((uint32_t)value << 16) | |
| | ((uint16_t)t << 8) | |
| | p; | |
| case 1: // Green is dominant. | |
| return ((uint32_t)q << 16) | |
| | ((uint16_t)value << 8) | |
| | p; | |
| case 2: // Green is dominant. | |
| return ((uint32_t)p << 16) | |
| | ((uint16_t)value << 8) | |
| | t; | |
| case 3: // Blue is dominant. | |
| return ((uint32_t)p << 16) | |
| | ((uint16_t)q << 8) | |
| | value; | |
| case 4: // Blue is dominant. | |
| return ((uint32_t)t << 16) | |
| | ((uint16_t)p << 8) | |
| | value; | |
| case (Segments - 1): // Red is dominant. | |
| default: | |
| return ((uint32_t)value << 16) | |
| | ((uint16_t)p << 8) | |
| | q; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment