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
00028
00029
00030 #ifndef OLENA_CONVERT_NRGBHSL_HH
00031 # define OLENA_CONVERT_NRGBHSL_HH
00032
00033 # include <oln/basics.hh>
00034 # include <oln/convert/abstract/colorconv.hh>
00035 # include <oln/convert/float_cmp.hh>
00036
00037 # include <ntg/basics.hh>
00038 # include <ntg/color/rgb.hh>
00039 # include <ntg/color/hsl.hh>
00040
00041 # include <mlc/contract.hh>
00042
00043 # include <cstdlib>
00044 # include <sstream>
00045
00051 namespace oln {
00052
00053 using namespace ntg;
00054
00055 namespace convert {
00084 template<unsigned inbits, unsigned outbits>
00085 struct f_rgb_to_hsl
00086 : public abstract::color_conversion<3, inbits, rgb_traits,
00087 3, outbits, hsl_traits, f_rgb_to_hsl<inbits, outbits> >
00088 {
00089 color<3, outbits, hsl_traits>
00090 doit(const color<3, inbits, rgb_traits>& v) const
00091 {
00092 vec<3, float> in = v.to_float();
00093 vec<3, float> out;
00094
00095 float max_in = ntg::max(in[rgb_R], std::max(in[rgb_B], in[rgb_G]));
00096 float min_in = ntg::min(in[rgb_R], std::min(in[rgb_B], in[rgb_G]));
00097 float diff = max_in-min_in;
00098
00099 out[hsl_L] = (max_in + min_in) / 2;
00100 if (approx_eq (diff, 0))
00101 {
00102 out[hsl_S] = 0;
00103 out[hsl_H] = 0;
00104 }
00105 else {
00106 if (out[hsl_L] <= 0.5)
00107 out[hsl_S] = diff / (max_in + min_in);
00108 else
00109 out[hsl_S] = diff / (2 - max_in - min_in);
00110
00111
00112 float r_dist = (max_in - in[rgb_R]) / diff;
00113 float g_dist = (max_in - in[rgb_G]) / diff;
00114 float b_dist = (max_in - in[rgb_B]) / diff;
00115
00116 if (approx_eq(in[rgb_R], max_in))
00117 out[hsl_H] = b_dist - g_dist;
00118 else if(approx_eq(in[rgb_G], max_in))
00119 out[hsl_H] = 2 + r_dist - b_dist;
00120 else if(approx_eq(in[rgb_B], max_in))
00121 out[hsl_H] = 4 + g_dist - r_dist;
00122
00123 out[hsl_H] *= 60;
00124 if(out[hsl_H] < 0)
00125 out[hsl_H] += 360;
00126 }
00127 return out;
00128 }
00129
00130 static std::string
00131 name()
00132 {
00133 std::ostringstream s;
00134 s << "f_rgb_to_hsl<" << inbits << ", " << outbits << '>';
00135 return s.str();
00136 }
00137 };
00138
00143 template <unsigned inbits, unsigned outbits>
00144 color<3, inbits, hsl_traits>
00145 rgb_to_hsl(const color<3, outbits, rgb_traits>& v)
00146 {
00147 f_rgb_to_hsl<inbits, outbits> f;
00148 return f(v);
00149 }
00150
00151 namespace internal {
00152 float
00153 RGB(float q1, float q2, float hue)
00154 {
00155 if (hue >= 360)
00156 hue -= 360;
00157 if (hue < 0)
00158 hue += 360;
00159 if (hue < 60)
00160 return q1 + (q2 - q1) * hue / 60;
00161 else if (hue < 180)
00162 return q2;
00163 else if (hue < 240)
00164 return q1 + (q2 - q1) * (240 - hue) / 60;
00165 else
00166 return q1;
00167 }
00168 }
00169
00174 template<unsigned inbits, unsigned outbits>
00175 struct f_hsl_to_rgb
00176 : public abstract::color_conversion<3, inbits, hsl_traits,
00177 3, outbits, rgb_traits, f_hsl_to_rgb<inbits, outbits> >
00178 {
00179 color<3, outbits, rgb_traits>
00180 doit(const color<3, inbits, hsl_traits>& v) const
00181 {
00182 vec<3, float> in = v.to_float();
00183 vec<3, float> out;
00184 float p2;
00185
00186 if(in[hsl_L] < 0.5)
00187 p2 = in[hsl_L] * (1+in[hsl_S]);
00188 else
00189 p2 = in[hsl_L] + in[hsl_S] - (in[hsl_L] * in[hsl_S]);
00190
00191 float p1 = 2 * in[hsl_L] - p2;
00192
00193 if(approx_eq (in[hsl_S], 0))
00194 out[rgb_R] = out[rgb_G] = out[rgb_B] = in[hsl_L];
00195 else
00196 {
00197 out[rgb_R] = internal::RGB(p1, p2, in[hsl_H] + 120);
00198 out[rgb_G] = internal::RGB(p1, p2, in[hsl_H]);
00199 out[rgb_B] = internal::RGB(p1, p2, in[hsl_H] - 120);
00200 }
00201
00202 return out;
00203 }
00204
00205 static std::string
00206 name()
00207 {
00208 std::ostringstream s;
00209 s << "f_hsl_to_rgb<" << inbits << ", " << outbits << '>';
00210 return s.str();
00211 }
00212 };
00213
00218 template<unsigned inbits, unsigned outbits>
00219 color<3, outbits, rgb_traits>
00220 hsl_to_rgb(const color<3, inbits, hsl_traits>& v)
00221 {
00222 f_hsl_to_rgb<inbits, outbits> f;
00223 return f(v);
00224 }
00225
00226 }
00227 }
00228
00229 #endif // OLENA_CONVERT_RGBHSL_HH