00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef MLN_FUN_V2V_HSL_TO_RGB_HH
00028 # define MLN_FUN_V2V_HSL_TO_RGB_HH
00029
00035
00036 # include <cmath>
00037
00038 # include <mln/math/round.hh>
00039 # include <mln/math/max.hh>
00040 # include <mln/math/min.hh>
00041
00042 # include <mln/trait/value_.hh>
00043
00044 # include <mln/value/rgb.hh>
00045
00046
00047
00048 namespace mln
00049 {
00050
00051
00052 namespace value
00053 {
00054 template <typename H, typename S, typename L> class hsl_;
00055 typedef hsl_<float, float, float> hsl_f;
00056 template <unsigned n> struct rgb;
00057 }
00058
00059 namespace fun
00060 {
00061
00062 namespace v2v
00063 {
00064
00068
00069 template <typename T_rgb>
00070 struct f_hsl_to_rgb_ : public Function_v2v< f_hsl_to_rgb_<T_rgb> >
00071 {
00072 typedef T_rgb result;
00073
00074
00075 f_hsl_to_rgb_();
00076
00077 template <typename T_hsl>
00078 T_rgb operator()(const T_hsl& hsl) const;
00079
00080 };
00081
00082 typedef f_hsl_to_rgb_< value::rgb<8> > f_hsl_to_rgb_3x8_t;
00083 typedef f_hsl_to_rgb_< value::rgb<16> > f_hsl_to_rgb_3x16_t;
00084
00085 extern f_hsl_to_rgb_3x8_t f_hsl_to_rgb_3x8;
00086 extern f_hsl_to_rgb_3x16_t f_hsl_to_rgb_3x16;
00087
00088
00089 # ifndef MLN_INCLUDE_ONLY
00090
00091 # ifndef MLN_WO_GLOBAL_VARS
00092
00095 f_hsl_to_rgb_3x8_t f_hsl_to_rgb_3x8;
00096 f_hsl_to_rgb_3x16_t f_hsl_to_rgb_3x16;
00098 # endif // !MLN_WO_GLOBAL_VARS
00099
00100 template <typename T_rgb>
00101 f_hsl_to_rgb_<T_rgb>::f_hsl_to_rgb_()
00102 {
00103 }
00104
00108 template <typename T_rgb>
00109 template <typename T_hsl>
00110 inline
00111 T_rgb
00112 f_hsl_to_rgb_<T_rgb>::operator()(const T_hsl& hsl) const
00113 {
00114 typedef typename T_rgb::red_t red_t;
00115 typedef typename T_rgb::green_t green_t;
00116 typedef typename T_rgb::blue_t blue_t;
00117
00118 static math::round<red_t> to_r;
00119 static math::round<green_t> to_g;
00120 static math::round<blue_t> to_b;
00121
00122 const float q = (hsl.lum() < 0.5) ? hsl.lum() * (1.0 + hsl.sat()) :
00123 hsl.lum() + hsl.sat() - (hsl.lum() * hsl.sat());
00124 const float p = 2.0 * hsl.lum() - q;
00125 const float hk = hsl.hue() / 360.0;
00126 float tr = hk + (1.0 / 3.0);
00127 float tg = hk;
00128 float tb = hk - (1.0 / 3.0);
00129
00130 if (tr < 0.0)
00131 tr += 1.0;
00132 if (tr > 1.0)
00133 tr -= 1.0;
00134
00135 if (tg < 0.0)
00136 tg += 1.0;
00137 if (tg > 1.0)
00138 tg -= 1.0;
00139
00140 if (tb < 0.0)
00141 tb += 1.0;
00142 if (tb > 1.0)
00143 tb -= 1.0;
00144
00145
00146 float red;
00147 if (tr < (1.0 / 6.0))
00148 red = p + ((q - p) * 6 * tr);
00149 else if (tr < (1.0 / 2.0))
00150 red = q;
00151 else if (tr < (2.0 / 3.0))
00152 red = p + ((q - p) * 6 * ((2.0 / 3.0) - tr));
00153 else
00154 red = p;
00155
00156
00157 float green;
00158 if (tg < (1.0 / 6.0))
00159 green = p + ((q - p) * 6 * tg);
00160 else if (tg < (1.0 / 2.0))
00161 green = q;
00162 else if (tg < (2.0 / 3.0))
00163 green = p + ((q - p) * 6 * ((2.0 / 3.0) - tg));
00164 else
00165 green = p;
00166
00167
00168 float blue;
00169 if (tb < (1.0 / 6.0))
00170 blue = p + ((q - p) * 6 * tb);
00171 else if (tb < (1.0 / 2.0))
00172 blue = q;
00173 else if (tb < (2.0 / 3.0))
00174 blue = p + ((q - p) * 6 * ((2.0 / 3.0) - tb));
00175 else
00176 blue = p;
00177
00178
00179 red_t r = to_r(red * 255);
00180 green_t g = to_g(green * 255);
00181 blue_t b = to_b(blue * 255);
00182
00183 T_rgb rgb_result(r, g, b);
00184
00185 return rgb_result;
00186 }
00187
00188 # endif // !MLN_INCLUDE_ONLY
00189
00190 }
00191
00192 }
00193
00194 }
00195
00196
00197 #endif // ! MLN_FUN_V2V_HSL_TO_RGB_HH