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 #ifndef OLENA_CONVERT_RGBHSI_HH
00030 # define OLENA_CONVERT_RGBHSI_HH
00031
00032 # include <oln/convert/abstract/colorconv.hh>
00033
00034 # include <ntg/basics.hh>
00035 # include <ntg/color/rgb.hh>
00036 # include <ntg/color/hsi.hh>
00037
00038 # include <sstream>
00039
00046 namespace oln {
00047
00048 using namespace ntg;
00049
00050 namespace convert {
00051
00052 static const float sqrt3_3 = sqrt(3) / 3;
00053 static const float inv_sqrt6 = 1 / sqrt(6);
00054 static const float inv_sqrt2 = 1 / sqrt(2);
00055
00060 template<unsigned inbits, unsigned outbits>
00061 struct f_rgb_to_hsi
00062 : public abstract::color_conversion<3, inbits, rgb_traits,
00063 3, outbits, hsi_traits, f_rgb_to_hsi<inbits, outbits> >
00064 {
00065 color<3, inbits, hsi_traits>
00066 doit(const color<3, outbits, rgb_traits>& v) const
00067 {
00068 vec<3, float> in = v.to_float();
00069 vec<3, float> out;
00070 out[hsi_I] =
00071 sqrt3_3 * in[rgb_R] + sqrt3_3 * in[rgb_G] + sqrt3_3 * in[rgb_B];
00072 const float v1 = inv_sqrt2 * in[rgb_G] - inv_sqrt2 * in[rgb_B];
00073 const float v2 = 2 * inv_sqrt6 * in[rgb_R] - inv_sqrt6 * in[rgb_G]
00074 - inv_sqrt6 * in[rgb_B];
00075 out[hsi_H] = atan2(v2, v1) / M_PI * 180.0;
00076 if (out[hsi_H] < 0)
00077 out[hsi_H] += 360.0;
00078 assert(out[hsi_H] >= 0);
00079 out[hsi_S] = sqrt(v1 * v1 + v2 * v2);
00080 return out;
00081 }
00082
00083 static std::string
00084 name()
00085 {
00086 std::ostringstream s;
00087 s << "f_rgb_to_hsi<" << inbits << ", " << outbits << '>';
00088 s.str();
00089 }
00090 };
00091
00096 template <unsigned inbits, unsigned outbits>
00097 color<3, outbits, hsi_traits>
00098 rgb_to_hsi(const color<3, inbits, rgb_traits>& v)
00099 {
00100 f_rgb_to_hsi<inbits, outbits> f;
00101
00102 return f(v);
00103 }
00104
00109 template<unsigned inbits, unsigned outbits>
00110 struct f_hsi_to_rgb
00111 : public abstract::color_conversion<3, inbits, hsi_traits,
00112 3, outbits, rgb_traits, f_hsi_to_rgb<inbits, outbits> >
00113 {
00114 color<3, outbits, rgb_traits>
00115 doit(const color<3, inbits, hsi_traits>& v) const
00116 {
00117 vec<3, float> in = v.to_float();
00118 vec<3, float> out;
00119 const float h = in[hsi_H] / 180.0 * M_PI;
00120 const float v1 = in[hsi_S] * cos(h);
00121 const float v2 = in[hsi_S] * sin(h);
00122 out[rgb_R] = sqrt3_3 * in[hsi_I] + 2 * inv_sqrt6 * v2;
00123 out[rgb_G] = sqrt3_3 * in[hsi_I] + inv_sqrt2 * v1 - inv_sqrt6 * v2;
00124 out[rgb_B] = sqrt3_3 * in[hsi_I] - inv_sqrt2 * v1 - inv_sqrt6 * v2;
00125 return out;
00126 }
00127
00128 static std::string
00129 name()
00130 {
00131 std::ostringstream s;
00132 s << "f_hsi_to_rgb<" << inbits << ", " << outbits << '>';
00133 s.str();
00134 }
00135 };
00136
00141 template <unsigned inbits, unsigned outbits>
00142 color<3, outbits, rgb_traits>
00143 hsi_to_rgb (const color<3, inbits, hsi_traits>& v)
00144 {
00145 f_hsi_to_rgb<inbits, outbits> f;
00146
00147 return f(v);
00148 }
00149
00150 }
00151 }
00152
00153 #endif // OLENA_CONVERT_RGBHSI_HH