Home | History | Annotate | Download | only in src
      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