#include "HSL.h" #include "RGB.h" #include "YUV.h" #include "../utility.h" namespace meow{ template inline HSL::HSL(){ } template inline HSL::HSL(T const& h, T const& s, T const& l){ hsl_[0] = h; hsl_[1] = s; hsl_[2] = l; } template inline HSL::HSL(T const* hsl){ for(int i = 0; i < 3; i++) hsl_[i] = hsl[i]; } template inline T HSL::h() const { return hsl_[0]; } template inline T HSL::s() const { return hsl_[1]; } template inline T HSL::l() const { return hsl_[2]; } template inline T HSL::hsl(size_t i) const { return hsl_[std::min((size_t)3 - 1, i)]; } template inline T HSL::lsh(size_t i)const{return hsl(2-i);} template inline T HSL::h(T const& val){return (hsl_[0]=val);} template inline T HSL::s(T const& val){return (hsl_[1]=val);} template inline T HSL::l(T const& val){return (hsl_[2]=val);} template inline T HSL::hsl(size_t i, T const& val){ return (hsl_[std::min((size_t)3 - 1, i)] = val); } template inline T HSL::lsh(size_t i, T const& val){ return hsl(2 - i, val); } inline HSLf:: HSLf(): HSL(){ } inline HSLf::~HSLf(){ } inline HSLf::HSLf(double const&h,double const&s,double const&l):HSL(h,s,l){} inline HSLf::HSLf(double const* hsl):HSL(hsl){} inline double HSLf::hMin() const { return 0.0; } inline double HSLf::hMax() const { return 2.0 * PI; } inline double HSLf::sMin() const { return 0.0; } inline double HSLf::sMax() const { return 1.0; } inline double HSLf::lMin() const { return 0.0; } inline double HSLf::lMax() const { return 1.0; } template inline void RGB_to_HSL(RGB const& rgb, HSL* hsl){ double r = normalize(rgb.rMin(), rgb.rMax(), rgb.r()); double g = normalize(rgb.gMin(), rgb.gMax(), rgb.g()); double b = normalize(rgb.bMin(), rgb.bMax(), rgb.b()); double mx = std::max(std::max(r, g), b); double mn = std::min(std::min(r, g), b); double h, s, l; if (mx == mn ) h = 0; else if(mx == r && g >= b) h = PI/3.0 * (g-b) / (mx-mn); else if(mx == r && g < b) h = PI/3.0 * (g-b) / (mx-mn) + PI * 2.0; else if(mx == g ) h = PI/3.0 * (b-r) / (mx-mn) + PI/3.0*2.0; else h = PI/3.0 * (r-g) / (mx-mn) + PI/3.0*4.0; l = 0.5 * (mx + mn); if (l == 0 || mx == mn) s = 0; else if(l < 0.5 ) s = (mx - mn) / (2.0 * l); else s = (mx - mn) / (2 - 2.0 * l); hsl->h(h); hsl->s(s); hsl->l(l); } template inline void HSL_to_RGB(HSL const& hsl, RGB* rgb){ double h = normalize(hsl.hMin(), hsl.hMax(), hsl.h()); double s = normalize(hsl.sMin(), hsl.sMax(), hsl.s()); double l = normalize(hsl.lMin(), hsl.lMax(), hsl.l()); if(s == 0){ rgb->r(denormalize(rgb->rMin(), rgb->rMax(), l)); rgb->g(denormalize(rgb->gMin(), rgb->gMax(), l)); rgb->b(denormalize(rgb->bMin(), rgb->bMax(), l)); return ; } double q = (l < 0.5 ? (l * (1 + s)) : (l + s - (l * s))); double p = 2 * l - q; double t_r = h + 1.0 / 3.0; double t_g = h; double t_b = h - 1.0 / 3.0; if(t_r < 0) t_r = t_r + 1.0; if(t_r > 1) t_r = t_r - 1.0; if(t_g < 0) t_g = t_g + 1.0; if(t_g > 1) t_g = t_g - 1.0; if(t_b < 0) t_b = t_b + 1.0; if(t_b > 1) t_b = t_b - 1.0; double r, g, b; if (t_r < 1.0 / 6.0) r = p + (q - p) * 6 * t_r; else if(t_r < 0.5 ) r = q; else if(t_r < 2.0 / 3.0) r = p + (q - p) * 6 * (2.0 / 3.0 - t_r); else r = p; if (t_g < 1.0 / 6.0) g = p + (q - p) * 6 * t_g; else if(t_g < 0.5 ) g = q; else if(t_g < 2.0 / 3.0) g = p + (q - p) * 6 * (2.0 / 3.0 - t_g); else g = p; if (t_b < 1.0 / 6.0) b = p + (q - p) * 6 * t_b; else if(t_b < 0.5 ) b = q; else if(t_b < 2.0 / 3.0) b = p + (q - p) * 6 * (2.0 / 3.0 - t_b); else b = p; rgb->r(denormalize(rgb->rMin(), rgb->rMax(), r)); rgb->g(denormalize(rgb->gMin(), rgb->gMax(), g)); rgb->b(denormalize(rgb->bMin(), rgb->bMax(), b)); } template inline void YUV_to_HSL(YUV const& yuv, HSL* hsl){ RGBf tmp; YUV_to_RGB(yuv, &tmp); RGB_to_HSL(tmp, hsl); } template inline void HSL_to_YUV(HSL const& hsl, YUV* yuv){ RGBf tmp; HSL_to_RGB(hsl, &tmp); RGB_to_YUV(tmp, yuv); } }