aboutsummaryrefslogtreecommitdiffstats
path: root/meowpp/colors/HSV.hpp
blob: 1838d0d4f2041f91e20f5f25556e51edd1fb520d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include "HSV.h"

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

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

#include <cstdlib>

#include <algorithm>

namespace meow{
  template<class T>
  inline HSV<T>::HSV(){ }
  template<class T>
  inline HSV<T>::HSV(T const& h, T const& s, T const& v){
    hsv_[0] = h; hsv_[1] = s; hsv_[2] = v;
  }
  template<class T>
  inline HSV<T>::HSV(T const* hsv){
    for(int i = 0; i < 3; i++) hsv_[i] = hsv[i];
  }

  template<class T>
  inline T HSV<T>::h() const { return hsv_[0]; }
  template<class T>
  inline T HSV<T>::s() const { return hsv_[1]; }
  template<class T>
  inline T HSV<T>::v() const { return hsv_[2]; }
  template<class T>
  inline T HSV<T>::hsv(size_t i) const {
    return hsv_[std::min((size_t)3 - 1, i)];
  }
  template<class T>
  inline T HSV<T>::vsh(size_t i)const{return hsv(2-i);}
  template<class T>
  inline T HSV<T>::h(T const& val){return (hsv_[0]=val);}
  template<class T>
  inline T HSV<T>::s(T const& val){return (hsv_[1]=val);}
  template<class T>
  inline T HSV<T>::v(T const& val){return (hsv_[2]=val);}
  template<class T>
  inline T HSV<T>::hsv(size_t i, T const& val){
    return (hsv_[std::min((size_t)3 - 1, i)] = val);
  }
  template<class T>
  inline T HSV<T>::vsh(size_t i, T const& val){
    return hsv(2 - i, val);
  }





  inline HSVf:: HSVf():  HSV(){ }
  inline HSVf::~HSVf(){ }
  inline HSVf::HSVf(double const&h,double const&s,double const&v):HSV(h,s,v){}
  inline HSVf::HSVf(double const* hsv):HSV(hsv){}
  inline double HSVf::hMin() const { return 0.0; }
  inline double HSVf::hMax() const { return 2.0 * PI; }
  inline double HSVf::sMin() const { return 0.0; }
  inline double HSVf::sMax() const { return 1.0; }
  inline double HSVf::vMin() const { return 0.0; }
  inline double HSVf::vMax() const { return 1.0; }




  template<class HSV_T1, class HSV_T2>
  inline void HSV_to_HSV(HSV<HSV_T1> const& a, HSV<HSV_T2>* b){
    double h = normalize(a.hMin(), a.hMax(), a.h());
    double s = normalize(a.sMin(), a.sMax(), a.s());
    double v = normalize(a.vMin(), a.vMax(), a.v());
    b->h(denormalize(b->hMin(), b->hMax(), h));
    b->s(denormalize(b->sMin(), b->sMax(), s));
    b->v(denormalize(b->vMin(), b->vMax(), v));
  }
  template<class RGB_T, class HSV_T>
  inline void RGB_to_HSV(RGB<RGB_T> const& rgb, HSV<HSV_T>* hsv){
    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, v;
    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;
    if(mx == 0) s = 0;
    else        s = 1 - mn / mx;
    v = mx;
    hsv->h(h);
    hsv->s(s);
    hsv->v(v);
  }
  template<class HSV_T, class RGB_T>
  inline void HSV_to_RGB(HSV<HSV_T> const& hsv, RGB<RGB_T>* rgb){
    double h = normalize(hsv.hMin(), hsv.hMax(), hsv.h()) * 360;
    double s = normalize(hsv.sMin(), hsv.sMax(), hsv.s());
    double v = normalize(hsv.vMin(), hsv.vMax(), hsv.v());
    int hi = (int)h / 60 % 6;
    double f = h / 60.0 - hi;
    double p = v * (1 - s);
    double q = v * (1 - f * s);
    double t = v * (1 - (1 - f) * s);
    double r, g, b;
    if     (hi == 0){ r = v; g = t; b = p; }
    else if(hi == 1){ r = q; g = v; b = p; }
    else if(hi == 2){ r = p; g = v; b = t; }
    else if(hi == 3){ r = p; g = q; b = v; }
    else if(hi == 4){ r = t; g = p; b = v; }
    else            { r = v; g = p; b = q; }
    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 HSV_T>
  inline void YUV_to_HSV(YUV<YUV_T> const& yuv, HSV<HSV_T>* hsv){
    RGBf tmp;
    YUV_to_RGB(yuv, &tmp);
    RGB_to_HSV(tmp,  hsv);
  }
  template<class HSV_T, class YUV_T>
  inline void HSV_to_YUV(HSV<HSV_T> const& hsv, YUV<YUV_T>* yuv){
    RGBf tmp;
    HSV_to_RGB(hsv, &tmp);
    RGB_to_YUV(tmp,  yuv);
  }
  template<class HSL_T, class HSV_T>
  inline void HSL_to_HSV(HSL<HSL_T> const& hsl, HSV<HSV_T>* hsv){
    RGBf tmp;
    HSL_to_RGB(hsl, &tmp);
    RGB_to_HSV(tmp,  hsv);
  }
  template<class HSV_T, class HSL_T>
  inline void HSV_to_HSL(HSV<HSV_T> const& hsv, HSL<HSL_T>* hsl){
    RGBf tmp;
    HSV_to_RGB(hsv, &tmp);
    RGB_to_HSL(tmp,  hsl);
  }
}