aboutsummaryrefslogblamecommitdiffstats
path: root/meowpp/colors/HSL_Space.h
blob: 52c218f20a020a645783534e7305000180f8d3bb (plain) (tree)
1
2
3
4
5
6
7
8



                              

                      

                           









                                                                                                
  








































































































































































                                                                                
#ifndef   colors_HSL_Space_H__
#define   colors_HSL_Space_H__

#include "Color3_Space.h"
#include "RGB_Space.h"
#include "YUV_Space.h"

#include "../geo/Vectors.h"
#include "../math/utility.h"

#include <cstdlib>

namespace meow {

/*!
 * @brief 以浮點數\b Y(亮度), \b U(色度), \b V(濃度) 三個值所組成的色彩空間
 *
 * 其中範圍都介於0.0~1.0之間
 *
 * @author cat_leopard
 */
class HSLf_Space: public Color3_Space<double> {
public:
  HSLf_Space(): Color3_Space<double>(Vector3D<double>(   0.0, 0.0, 0.0),
                                     Vector3D<double>(PI*2.0, 1.0, 1.0),
                                     Vector3D<double>(   0.0, 0.0, 0.0)) {
  }
  HSLf_Space(double c): Color3_Space<double>(Vector3D<double>(   0.0, 0.0, 0.0),
                                             Vector3D<double>(PI*2.0, 1.0, 1.0),
                                             Vector3D<double>(     c,   c,   c))
  { }
  HSLf_Space(Vector3D<double> const& v):
  Color3_Space<double>(Vector3D<double>(0.0, 0.0, 0.0),
                       Vector3D<double>(1.0, 1.0, 1.0),
                       Vector3D<double>(v)) {
  }
  HSLf_Space(HSL_Space const& b): Color3_Space<double>(b) {
  }
  ~HSLf_Space() {
  }
  double const& hslMin(size_t i) const { return min(i); }
  double const&   hMin(        ) const { return min(0); }
  double const&   sMin(        ) const { return min(1); }
  double const&   lMin(        ) const { return min(2); }
  double const& hslMax(size_t i) const { return max(i); }
  double const&   hMax(        ) const { return max(0); }
  double const&   sMax(        ) const { return max(1); }
  double const&   lMax(        ) const { return max(2); }
  double const& hsl(size_t i) const { return val(i); }
  double const&   h(        ) const { return hsl(0); }
  double const&   s(        ) const { return hsl(1); }
  double const&   l(        ) const { return hsl(2); }
  double const& hsl(size_t i, double c) { return val(i, c); }
  double const&   h(          double c) { return hsl(0, c); }
  double const&   s(          double c) { return hsl(1, c); }
  double const&   l(          double c) { return hsl(2, c); }
  double& hslGet(size_t i) { return valGet(i); }
  double&   hGet(        ) { return hslGet(0); }
  double&   sGet(        ) { return hslGet(1); }
  double&   lGet(        ) { return hslGet(2); }
  HSLf_Space& operator=(HSLf_Space const& b) {
    copyFrom(b);
    return *this;
  }
  HSLf_Space operator+(HSLf_Space const& b) const {
    return HSLf_Space(val_ + b.val_);
  }
  HSLf_Space operator-(HSLf_Space const& b) const {
    return HSLf_Space(val_ - b.val_);
  }
  HSLf_Space operator*(double const& c) const {
    return HSLf_Space(val_ * c);
  }
  HSLf_Space operator/(double const& c) const {
    return HSLf_Space(val_ / c);
  }
  double operator*(HSLf_Space const& b) const {
    return val_ * b.val_;
  }
};

/*!
 * @brief \c RGBf_Space to \c HSLf_Space
 */
inline void colorTransformate(RGBf_Space const& rgb, HSLf_Space* 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);
}

/*!
 * @brief \c YUVf_Space to \c HSLf_Space
 */
inline void colorTransformate(YUVf_Space const& yuv, HSLf_Space* hsl) {
  RGBf_Space tmp;
  colorTransformate(yuv, &tmp);
  colorTransformate(tmp, hsl);
}

/*!
 * @brief \c HSLf_Space to \c RGBf_Space
 */
inline void colorTransformate(HSLf_Space const& hsl, RGBf_Space* 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));
}

/*!
 * @brief \c HSLf_Space to \c YUVf_Space
 */
inline void colorTransformate(HSLf_Space const& hsl, YUVf_Space* yuv) {
  RGBf_Space tmp;
  colorTransformate(hsl, &tmp);
  colorTransformate(tmp, yuv);
}

/*!
 * @brief \c HSLf_Space to \c RGBi_Space
 */
inline void colorTransformate(HSLf_Space const& hsl, RGBi_Space* rgb) {
  RGBf_Space tmp;
  colorTransformate(hsl, &tmp);
  rgb->copyFrom(tmp);
}


/*!
 * @brief \c RGBi_Space to \c HSLf_Space
 */
inline void colorTransformate(RGBi_Space const& rgb, HSLf_Space* hsl) {
  RGBf_Space tmp;
  tmp.copyFrom(rgb);
  colorTransformate(rgb, hsl);
}

} // meow


#endif // colors_HSL_Space_H__