Milena (Olena)  User documentation 2.0a Id
hsl_to_rgb.hh
00001 // Copyright (C) 2008, 2009, 2011 EPITA Research and Development
00002 // Laboratory (LRDE)
00003 //
00004 // This file is part of Olena.
00005 //
00006 // Olena is free software: you can redistribute it and/or modify it under
00007 // the terms of the GNU General Public License as published by the Free
00008 // Software Foundation, version 2 of the License.
00009 //
00010 // Olena is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with Olena.  If not, see <http://www.gnu.org/licenses/>.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software project without restriction.  Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to produce
00022 // an executable, this file does not by itself cause the resulting
00023 // executable to be covered by the GNU General Public License.  This
00024 // exception does not however invalidate any other reasons why the
00025 // executable file might be covered by the GNU General Public License.
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   // Forward declarations
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; // hk = normalized hue
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         // Red.
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         // Green.
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         // Blue.
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         // Each component is in [0, 1].
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     } // end of namespace fun::v2v
00191 
00192   } // end of namespace fun
00193 
00194 } // end of namespace mln
00195 
00196 
00197 #endif // ! MLN_FUN_V2V_HSL_TO_RGB_HH
 All Classes Namespaces Functions Variables Typedefs Enumerator