1 #include <kms++util/color.h> 2 3 namespace kms 4 { 5 RGB::RGB() 6 { 7 r = g = b = 0; 8 a = 255; 9 } 10 11 RGB::RGB(uint8_t r, uint8_t g, uint8_t b) 12 :RGB(255, r, g, b) 13 { 14 } 15 16 RGB::RGB(uint8_t a, uint8_t r, uint8_t g, uint8_t b) 17 { 18 this->r = r; 19 this->g = g; 20 this->b = b; 21 this->a = a; 22 } 23 24 RGB::RGB(uint32_t argb) 25 { 26 this->b = (argb >> 0) & 0xff; 27 this->g = (argb >> 8) & 0xff; 28 this->r = (argb >> 16) & 0xff; 29 this->a = (argb >> 24) & 0xff; 30 } 31 32 uint32_t RGB::rgb888() const 33 { 34 return (r << 16) | (g << 8) | (b << 0); 35 } 36 37 uint32_t RGB::bgr888() const 38 { 39 return (b << 16) | (g << 8) | (r << 0); 40 } 41 42 uint32_t RGB::argb8888() const 43 { 44 return (a << 24) | (r << 16) | (g << 8) | (b << 0); 45 } 46 47 uint32_t RGB::abgr8888() const 48 { 49 return (a << 24) | (b << 16) | (g << 8) | (r << 0); 50 } 51 52 uint16_t RGB::rgb565() const 53 { 54 return ((r >> 3) << 11) | ((g >> 2) << 5) | ((b >> 3) << 0); 55 } 56 57 uint16_t RGB::bgr565() const 58 { 59 return ((b >> 3) << 11) | ((g >> 2) << 5) | ((r >> 3) << 0); 60 } 61 62 YUV RGB::yuv(YUVType type) const 63 { 64 return YUV(*this, type); 65 } 66 67 #define CF_ONE (256) 68 #define CF(a, b, c) { ((int) ((a) * CF_ONE)), ((int) ((b) * CF_ONE)), ((int) ((c) * CF_ONE)) } 69 #define CLAMP(a) ((a) > (CF_ONE-1) ? (CF_ONE-1) : (a) < 0 ? 0 : (a)) 70 71 const int YUVcoef[static_cast<unsigned>(YUVType::MAX)][3][3] = { 72 [static_cast<unsigned>(YUVType::BT601_Lim)] = { 73 CF( 0.257, 0.504, 0.098), 74 CF(-0.148, -0.291, 0.439), 75 CF( 0.439, -0.368, -0.071) }, 76 [static_cast<unsigned>(YUVType::BT601_Full)] = { 77 CF( 0.299, 0.587, 0.114), 78 CF(-0.169, -0.331, 0.500), 79 CF( 0.500, -0.419, -0.081) }, 80 [static_cast<unsigned>(YUVType::BT709_Lim)] = { 81 CF( 0.1826, 0.6142, 0.0620), 82 CF(-0.1006, -0.3386, 0.4392), 83 CF( 0.4392, -0.3989, -0.0403) }, 84 [static_cast<unsigned>(YUVType::BT709_Full)] = { 85 CF( 0.2126, 0.7152, 0.0722), 86 CF(-0.1146, -0.3854, 0.5000), 87 CF( 0.5000, -0.4542, -0.0468) }, 88 }; 89 90 const int YUVoffset[static_cast<unsigned>(YUVType::MAX)][3] = { 91 [static_cast<unsigned>(YUVType::BT601_Lim)] = CF(0.0625, 0.5, 0.5), 92 [static_cast<unsigned>(YUVType::BT601_Full)] = CF( 0, 0.5, 0.5), 93 [static_cast<unsigned>(YUVType::BT709_Lim)] = CF(0.0625, 0.5, 0.5), 94 [static_cast<unsigned>(YUVType::BT709_Full)] = CF( 0, 0.5, 0.5), 95 }; 96 97 YUV::YUV() 98 { 99 y = u = v = a = 0; 100 } 101 102 YUV::YUV(uint8_t y, uint8_t u, uint8_t v) 103 { 104 this->y = y; 105 this->u = u; 106 this->v = v; 107 this->a = 0; 108 } 109 110 static inline 111 uint8_t MAKE_YUV_Y(uint8_t r, uint8_t g, uint8_t b, YUVType type) 112 { 113 unsigned tidx = static_cast<unsigned>(type); 114 115 return CLAMP(((YUVcoef[tidx][0][0] * r + YUVcoef[tidx][0][1] * g + 116 YUVcoef[tidx][0][2] * b + CF_ONE/2) / CF_ONE) + 117 YUVoffset[tidx][0]); 118 } 119 120 static inline 121 uint8_t MAKE_YUV_U(uint8_t r, uint8_t g, uint8_t b, YUVType type) 122 { 123 unsigned tidx = static_cast<unsigned>(type); 124 125 return CLAMP(((YUVcoef[tidx][1][0] * r + YUVcoef[tidx][1][1] * g + 126 YUVcoef[tidx][1][2] * b + CF_ONE/2) / CF_ONE) + 127 YUVoffset[tidx][1]); 128 } 129 130 static inline 131 uint8_t MAKE_YUV_V(uint8_t r, uint8_t g, uint8_t b, YUVType type) 132 { 133 unsigned tidx = static_cast<unsigned>(type); 134 135 return CLAMP(((YUVcoef[tidx][2][0] * r + YUVcoef[tidx][2][1] * g + 136 YUVcoef[tidx][2][2] * b + CF_ONE/2) / CF_ONE) + 137 YUVoffset[tidx][2]); 138 } 139 140 YUV::YUV(const RGB& rgb, YUVType type) 141 { 142 this->y = MAKE_YUV_Y(rgb.r, rgb.g, rgb.b, type); 143 this->u = MAKE_YUV_U(rgb.r, rgb.g, rgb.b, type); 144 this->v = MAKE_YUV_V(rgb.r, rgb.g, rgb.b, type); 145 this->a = rgb.a; 146 } 147 } 148