Milena (Olena)
User documentation 2.0a Id
|
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