aboutsummaryrefslogblamecommitdiffstats
path: root/meowpp/colors/HSL.hpp
blob: 18c01dc4325add9475ebd1d41d1c148fe2d5ff6b (plain) (tree)








































































































































                                                                              
#include "HSL.h"

#include "RGB.h"
#include "YUV.h"

#include "../utility.h"

namespace meow{
  template<class T>
  inline HSL<T>::HSL(){ }
  template<class T>
  inline HSL<T>::HSL(T const& h, T const& s, T const& l){
    hsl_[0] = h; hsl_[1] = s; hsl_[2] = l;
  }
  template<class T>
  inline HSL<T>::HSL(T const* hsl){
    for(int i = 0; i < 3; i++) hsl_[i] = hsl[i];
  }

  template<class T>
  inline T HSL<T>::h() const { return hsl_[0]; }
  template<class T>
  inline T HSL<T>::s() const { return hsl_[1]; }
  template<class T>
  inline T HSL<T>::l() const { return hsl_[2]; }
  template<class T>
  inline T HSL<T>::hsl(size_t i) const {
    return hsl_[std::min((size_t)3 - 1, i)];
  }
  template<class T>
  inline T HSL<T>::lsh(size_t i)const{return hsl(2-i);}
  template<class T>
  inline T HSL<T>::h(T const& val){return (hsl_[0]=val);}
  template<class T>
  inline T HSL<T>::s(T const& val){return (hsl_[1]=val);}
  template<class T>
  inline T HSL<T>::l(T const& val){return (hsl_[2]=val);}
  template<class T>
  inline T HSL<T>::hsl(size_t i, T const& val){
    return (hsl_[std::min((size_t)3 - 1, i)] = val);
  }
  template<class T>
  inline T HSL<T>::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<class RGB_T, class HSL_T>
  inline void RGB_to_HSL(RGB<RGB_T> const& rgb, HSL<HSL_T>* 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<class HSL_T, class RGB_T>
  inline void HSL_to_RGB(HSL<HSL_T> const& hsl, RGB<RGB_T>* 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<class YUV_T, class HSL_T>
  inline void YUV_to_HSL(YUV<YUV_T> const& yuv, HSL<HSL_T>* hsl){
    RGBf tmp;
    YUV_to_RGB(yuv, &tmp);
    RGB_to_HSL(tmp,  hsl);
  }
  template<class HSL_T, class YUV_T>
  inline void HSL_to_YUV(HSL<HSL_T> const& hsl, YUV<YUV_T>* yuv){
    RGBf tmp;
    HSL_to_RGB(hsl, &tmp);
    RGB_to_YUV(tmp,  yuv);
  }
}