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 template <typename T_hsl>
00075 T_rgb operator()(const T_hsl& hsl) const;
00076
00077 };
00078
00079 typedef f_hsl_to_rgb_< value::rgb<8> > f_hsl_to_rgb_3x8_t;
00080 typedef f_hsl_to_rgb_< value::rgb<16> > f_hsl_to_rgb_3x16_t;
00081
00082 extern f_hsl_to_rgb_3x8_t f_hsl_to_rgb_3x8;
00083 extern f_hsl_to_rgb_3x16_t f_hsl_to_rgb_3x16;
00084
00085
00086 # ifndef MLN_INCLUDE_ONLY
00087
00088 # ifndef MLN_WO_GLOBAL_VARS
00089
00092 f_hsl_to_rgb_3x8_t f_hsl_to_rgb_3x8;
00093 f_hsl_to_rgb_3x16_t f_hsl_to_rgb_3x16;
00095 # endif // !MLN_WO_GLOBAL_VARS
00096
00097
00101 template <typename T_rgb>
00102 template <typename T_hsl>
00103 inline
00104 T_rgb
00105 f_hsl_to_rgb_<T_rgb>::operator()(const T_hsl& hsl) const
00106 {
00107 typedef typename T_rgb::red_t red_t;
00108 typedef typename T_rgb::green_t green_t;
00109 typedef typename T_rgb::blue_t blue_t;
00110
00111 static math::round<red_t> to_r;
00112 static math::round<green_t> to_g;
00113 static math::round<blue_t> to_b;
00114
00115 const float q = (hsl.lum() < 0.5) ? hsl.lum() * (1.0 + hsl.sat()) :
00116 hsl.lum() + hsl.sat() - (hsl.lum() * hsl.sat());
00117 const float p = 2.0 * hsl.lum() - q;
00118 const float hk = hsl.hue() / 360.0;
00119 float tr = hk + (1.0 / 3.0);
00120 float tg = hk;
00121 float tb = hk - (1.0 / 3.0);
00122
00123 if (tr < 0.0)
00124 tr += 1.0;
00125 if (tr > 1.0)
00126 tr -= 1.0;
00127
00128 if (tg < 0.0)
00129 tg += 1.0;
00130 if (tg > 1.0)
00131 tg -= 1.0;
00132
00133 if (tb < 0.0)
00134 tb += 1.0;
00135 if (tb > 1.0)
00136 tb -= 1.0;
00137
00138
00139 float red;
00140 if (tr < (1.0 / 6.0))
00141 red = p + ((q - p) * 6 * tr);
00142 else if (tr < (1.0 / 2.0))
00143 red = q;
00144 else if (tr < (2.0 / 3.0))
00145 red = p + ((q - p) * 6 * ((2.0 / 3.0) - tr));
00146 else
00147 red = p;
00148
00149
00150 float green;
00151 if (tg < (1.0 / 6.0))
00152 green = p + ((q - p) * 6 * tg);
00153 else if (tg < (1.0 / 2.0))
00154 green = q;
00155 else if (tg < (2.0 / 3.0))
00156 green = p + ((q - p) * 6 * ((2.0 / 3.0) - tg));
00157 else
00158 green = p;
00159
00160
00161 float blue;
00162 if (tb < (1.0 / 6.0))
00163 blue = p + ((q - p) * 6 * tb);
00164 else if (tb < (1.0 / 2.0))
00165 blue = q;
00166 else if (tb < (2.0 / 3.0))
00167 blue = p + ((q - p) * 6 * ((2.0 / 3.0) - tb));
00168 else
00169 blue = p;
00170
00171
00172 red_t r = to_r(red * 255);
00173 green_t g = to_g(green * 255);
00174 blue_t b = to_b(blue * 255);
00175
00176 T_rgb rgb_result(r, g, b);
00177
00178 return rgb_result;
00179 }
00180
00181 # endif // !MLN_INCLUDE_ONLY
00182
00183 }
00184
00185 }
00186
00187 }
00188
00189
00190 #endif // ! MLN_FUN_V2V_HSL_TO_RGB_HH