Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
hsl_to_rgb.hh
1 // Copyright (C) 2008, 2009, 2011 EPITA Research and Development
2 // Laboratory (LRDE)
3 //
4 // This file is part of Olena.
5 //
6 // Olena is free software: you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation, version 2 of the License.
9 //
10 // Olena is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // As a special exception, you may use this file as part of a free
19 // software project without restriction. Specifically, if other files
20 // instantiate templates or use macros or inline functions from this
21 // file, or you compile this file and link it with other files to produce
22 // an executable, this file does not by itself cause the resulting
23 // executable to be covered by the GNU General Public License. This
24 // exception does not however invalidate any other reasons why the
25 // executable file might be covered by the GNU General Public License.
26 
27 #ifndef MLN_FUN_V2V_HSL_TO_RGB_HH
28 # define MLN_FUN_V2V_HSL_TO_RGB_HH
29 
35 
36 # include <cmath>
37 
38 # include <mln/math/round.hh>
39 # include <mln/math/max.hh>
40 # include <mln/math/min.hh>
41 
42 # include <mln/trait/value_.hh>
43 
44 # include <mln/value/rgb.hh>
45 
46 
47 
48 namespace mln
49 {
50 
51  // Forward declarations
52  namespace value
53  {
54  template <typename H, typename S, typename L> class hsl_;
55  typedef hsl_<float, float, float> hsl_f;
56  template <unsigned n> struct rgb;
57  }
58 
59  namespace fun
60  {
61 
62  namespace v2v
63  {
64 
68  //
69  template <typename T_rgb>
70  struct f_hsl_to_rgb_ : public Function_v2v< f_hsl_to_rgb_<T_rgb> >
71  {
72  typedef T_rgb result;
73 
74 
75  f_hsl_to_rgb_();
76 
77  template <typename T_hsl>
78  T_rgb operator()(const T_hsl& hsl) const;
79 
80  };
81 
82  typedef f_hsl_to_rgb_< value::rgb<8> > f_hsl_to_rgb_3x8_t;
83  typedef f_hsl_to_rgb_< value::rgb<16> > f_hsl_to_rgb_3x16_t;
84 
85  extern f_hsl_to_rgb_3x8_t f_hsl_to_rgb_3x8;
86  extern f_hsl_to_rgb_3x16_t f_hsl_to_rgb_3x16;
87 
88 
89 # ifndef MLN_INCLUDE_ONLY
90 
91 # ifndef MLN_WO_GLOBAL_VARS
92 
95  f_hsl_to_rgb_3x8_t f_hsl_to_rgb_3x8;
96  f_hsl_to_rgb_3x16_t f_hsl_to_rgb_3x16;
98 # endif // !MLN_WO_GLOBAL_VARS
99 
100  template <typename T_rgb>
101  f_hsl_to_rgb_<T_rgb>::f_hsl_to_rgb_()
102  {
103  }
104 
108  template <typename T_rgb>
109  template <typename T_hsl>
110  inline
111  T_rgb
112  f_hsl_to_rgb_<T_rgb>::operator()(const T_hsl& hsl) const
113  {
114  typedef typename T_rgb::red_t red_t;
115  typedef typename T_rgb::green_t green_t;
116  typedef typename T_rgb::blue_t blue_t;
117 
118  static math::round<red_t> to_r;
119  static math::round<green_t> to_g;
120  static math::round<blue_t> to_b;
121 
122  const float q = (hsl.lum() < 0.5) ? hsl.lum() * (1.0 + hsl.sat()) :
123  hsl.lum() + hsl.sat() - (hsl.lum() * hsl.sat());
124  const float p = 2.0 * hsl.lum() - q;
125  const float hk = hsl.hue() / 360.0; // hk = normalized hue
126  float tr = hk + (1.0 / 3.0);
127  float tg = hk;
128  float tb = hk - (1.0 / 3.0);
129 
130  if (tr < 0.0)
131  tr += 1.0;
132  if (tr > 1.0)
133  tr -= 1.0;
134 
135  if (tg < 0.0)
136  tg += 1.0;
137  if (tg > 1.0)
138  tg -= 1.0;
139 
140  if (tb < 0.0)
141  tb += 1.0;
142  if (tb > 1.0)
143  tb -= 1.0;
144 
145  // Red.
146  float red;
147  if (tr < (1.0 / 6.0))
148  red = p + ((q - p) * 6 * tr);
149  else if (tr < (1.0 / 2.0))
150  red = q;
151  else if (tr < (2.0 / 3.0))
152  red = p + ((q - p) * 6 * ((2.0 / 3.0) - tr));
153  else
154  red = p;
155 
156  // Green.
157  float green;
158  if (tg < (1.0 / 6.0))
159  green = p + ((q - p) * 6 * tg);
160  else if (tg < (1.0 / 2.0))
161  green = q;
162  else if (tg < (2.0 / 3.0))
163  green = p + ((q - p) * 6 * ((2.0 / 3.0) - tg));
164  else
165  green = p;
166 
167  // Blue.
168  float blue;
169  if (tb < (1.0 / 6.0))
170  blue = p + ((q - p) * 6 * tb);
171  else if (tb < (1.0 / 2.0))
172  blue = q;
173  else if (tb < (2.0 / 3.0))
174  blue = p + ((q - p) * 6 * ((2.0 / 3.0) - tb));
175  else
176  blue = p;
177 
178  // Each component is in [0, 1].
179  red_t r = to_r(red * 255);
180  green_t g = to_g(green * 255);
181  blue_t b = to_b(blue * 255);
182 
183  T_rgb rgb_result(r, g, b);
184 
185  return rgb_result;
186  }
187 
188 # endif // !MLN_INCLUDE_ONLY
189 
190  } // end of namespace fun::v2v
191 
192  } // end of namespace fun
193 
194 } // end of namespace mln
195 
196 
197 #endif // ! MLN_FUN_V2V_HSL_TO_RGB_HH