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