Branch data Line data Source code
1 : : #ifndef bqtColorHH 2 : : #define bqtColorHH 3 : : /** @file rendering/color.hh 4 : : * @brief Defines conversions between different color formats and parsing colors defined in strings. 5 : : */ 6 : : 7 : : #include <array> 8 : : #include <string> 9 : : #include <algorithm> 10 : : 11 : : /** ParseColorName() parses the given string and returns 12 : : * a corresponding RGB color as a 24-bit integer. 13 : : * 14 : : * Recognized formats are: 15 : : * #RGB (each color channel is 4-bit hexadecimal number; range: 0-F) 16 : : * #RRGGBB (each color channel is 8-bit hexadecimal number; range: 00-FF) 17 : : * rgb:R/G/B (each color channel is 4-bit hexadecimal number; range: 0-F) 18 : : * rgbi:1/1/1 (each color channel is a decimal floating point value; range: 0-1) 19 : : * gold (color names recognized by X11 are recognized, case sensitive) 20 : : * Anything else produces undefined results. 21 : : */ 22 : : unsigned ParseColorName(std::string_view s); 23 : : unsigned ParseColorName(std::u32string_view s); 24 : : 25 : : /** Unpack() unpacks an RGB color in a 24-bit integer 26 : : * to its constituent r,g,b components. 27 : : */ 28 : 1055071 : inline constexpr std::array<unsigned,3> Unpack(unsigned rgb) 29 : : { 30 : 1055066 : return { rgb>>16, (rgb>>8)&0xFF, rgb&0xFF }; 31 : : } 32 : : 33 : : /** Repack() is the inverse of Unpack(). 34 : : * 35 : : * Packs an RGB color represented in three color channels 36 : : * into a single 24-bit integer. 37 : : */ 38 : 1055020 : inline constexpr unsigned Repack(std::array<unsigned,3> rgb) 39 : : { 40 [ + + + - : 1055020 : if(rgb[0] > 255 || rgb[1] > 255 || rgb[2] > 255) [[unlikely]] - + ] 41 : 2 : { 42 : : // Clamp with desaturation: 43 [ + - ]: 2 : float l = (rgb[0]*299u + rgb[1]*587u + rgb[2]*114u)*1e-3f, s = 1.f; 44 [ + - + + ]: 3 : if(rgb[0] > 255) s = std::min(s, (l-255.f) / (l-rgb[0])); 45 [ + + - + ]: 2 : if(rgb[1] > 255) s = std::min(s, (l-255.f) / (l-rgb[1])); 46 [ + + - + ]: 2 : if(rgb[2] > 255) s = std::min(s, (l-255.f) / (l-rgb[2])); 47 [ + + ]: 2 : rgb[0] = (rgb[0] - l) * s + l + 0.5f; 48 : 2 : rgb[1] = (rgb[1] - l) * s + l + 0.5f; 49 : 2 : rgb[2] = (rgb[2] - l) * s + l + 0.5f; 50 [ + + ]: 2 : return (std::min(rgb[0],255u)<<16) 51 [ + + ]: 2 : + (std::min(rgb[1],255u)<<8) 52 [ + + ]: 3 : + (std::min(rgb[2],255u)<<0); 53 : : } 54 : 1055018 : return (rgb[0] << 16) 55 : 1055018 : + (rgb[1] << 8) 56 : 1055018 : + (rgb[2] << 0); 57 : : } 58 : : 59 : : /** Mix() mixes two colors such 60 : : * that the resulting color is (color1*fac1 + color2*fac2) / sum. 61 : : */ 62 : 1055017 : inline constexpr unsigned Mix(unsigned color1,unsigned color2, 63 : : unsigned fac1,unsigned fac2, 64 : : unsigned sum) 65 : : { 66 : 1055017 : auto a = Unpack(color1), b = Unpack(color2); 67 [ + + ]: 4220068 : for(unsigned n=0; n<3; ++n) a[n] = (a[n]*fac1 + b[n]*fac2)/(sum); 68 : 1055017 : return Repack(a); 69 : : } 70 : : 71 : : /** cmy2rgb() Converts CMY into RGB 72 : : */ 73 : 7 : inline unsigned cmy2rgb(unsigned cmy) 74 : : { 75 [ - - - - ]: 7 : return ~cmy & 0xFFFFFF; 76 : : } 77 : : /** cmyk2rgb() Converts CMYK into RGB 78 : : */ 79 : 7 : inline unsigned cmyk2rgb(unsigned cmyk) 80 : : { 81 : 7 : return Mix(0u, ~cmyk >> 8, cmyk & 255, ~cmyk & 255, 255); 82 : : } 83 : : 84 : : #endif