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_RGBHSV_HH
00030 # define OLENA_CONVERT_RGBHSV_HH
00031
00032 # include <oln/basics.hh>
00033 # include <oln/convert/abstract/colorconv.hh>
00034
00035 # include <ntg/basics.hh>
00036 # include <ntg/color/rgb.hh>
00037 # include <ntg/color/hsv.hh>
00038
00039 # include <mlc/contract.hh>
00040
00041 # include <sstream>
00042
00047 namespace oln {
00048
00049 using namespace ntg;
00050
00051 namespace convert {
00052
00057 template<unsigned inbits, unsigned outbits>
00058 struct f_rgb_to_hsv
00059 : public abstract::color_conversion<3, inbits, rgb_traits,
00060 3, outbits, hsv_traits, f_rgb_to_hsv<inbits, outbits> >
00061 {
00062 color<3, outbits, hsv_traits>
00063 doit(const color<3, inbits, rgb_traits>& v) const
00064 {
00065 vec<3, float> in = v.to_float();
00066 vec<3, float> out;
00067 float max_in = std::max(in[rgb_R], std::max(in[rgb_B], in[rgb_G]));
00068 float min_in = std::min(in[rgb_R], std::min(in[rgb_B], in[rgb_G]));
00069 float delta = max_in - min_in;
00070
00071
00072 out[hsv_V] = max_in;
00073
00074 if (max_in != 0)
00075 out[hsv_S] = delta / max_in;
00076 else
00077 out[hsv_S] = 0;
00078
00079 if (out[hsv_S] == 0)
00080 out[hsv_H] = -1;
00081 else {
00082 if (in[rgb_R] == max_in)
00083 out[hsv_H] = (in[rgb_G] - in[rgb_B]) / delta;
00084 else if (in[rgb_G] == max_in)
00085 out[hsv_H] = 2 + (in[rgb_B] - in[rgb_R]) / delta;
00086 else
00087 out[hsv_H] = 4 + (in[rgb_R] - in[rgb_G]) / delta;
00088 out[hsv_H] *= 60;
00089 if (out[hsv_H] < 0)
00090 out[hsv_H] += 360;
00091 }
00092
00093 return out;
00094 }
00095
00096 static std::string
00097 name()
00098 {
00099 std::ostringstream s;
00100 s << "f_rgb_to_hsv<" << inbits << ", " << outbits << '>';
00101 s.str();
00102 }
00103 };
00104
00109 template <unsigned inbits, unsigned outbits>
00110 color<3, outbits, hsv_traits>
00111 rgb_to_hsv(const color<3, inbits, rgb_traits>& v)
00112 {
00113 f_rgb_to_hsv<inbits, outbits> f;
00114 return f(v);
00115 }
00116
00121 template<unsigned inbits, unsigned outbits>
00122 struct f_hsv_to_rgb
00123 : public abstract::color_conversion<3, inbits, hsv_traits,
00124 3, outbits, rgb_traits, f_hsv_to_rgb<inbits, outbits> >
00125 {
00126 color<3, outbits, rgb_traits>
00127 doit(const color<3, inbits, hsv_traits>& v) const
00128 {
00129 vec<3, float> in = v.to_float();
00130 vec<3, float> out;
00131
00132 if(in[hsv_S] == 0)
00133 out[rgb_G] = out[rgb_B] = out[rgb_R] = in[hsv_V];
00134 else
00135 {
00136 in[hsv_H] /= 60;
00137 int i = (int)floor (in[hsv_H]);
00138 float f = in[hsv_H] - i;
00139 float p = in[hsv_V] * (1 - in[hsv_S]);
00140 float q = in[hsv_V] * (1 - in[hsv_S] * f);
00141 float t = in[hsv_V] * (1 - in[hsv_S] * (1 - f));
00142
00143 switch (i){
00144 case 0:
00145 case 6:
00146 out[rgb_R] = in[hsv_V];
00147 out[rgb_G] = t;
00148 out[rgb_B] = p;
00149 break;
00150 case 1:
00151 out[rgb_R] = q;
00152 out[rgb_G] = in[hsv_V];
00153 out[rgb_B] = p;
00154 break;
00155 case 2:
00156 out[rgb_R] = p;
00157 out[rgb_G] = in[hsv_V];
00158 out[rgb_B] = t;
00159 break;
00160 case 3:
00161 out[rgb_R] = p;
00162 out[rgb_G] = q;
00163 out[rgb_B] = in[hsv_V];
00164 break;
00165 case 4:
00166 out[rgb_R] = t;
00167 out[rgb_G] = p;
00168 out[rgb_B] = in[hsv_V];
00169 break;
00170 default:
00171 out[rgb_R] = in[hsv_V];
00172 out[rgb_G] = p;
00173 out[rgb_B] = q;
00174 break;
00175 }
00176 }
00177 return out;
00178 }
00179
00180 static std::string
00181 name()
00182 {
00183 std::ostringstream s;
00184 s << "f_hsv_to_rgb<" << inbits << ", " << outbits << '>';
00185 s.str();
00186 }
00187 };
00188
00193 template <unsigned inbits, unsigned outbits>
00194 color<3, outbits, rgb_traits>
00195 hsv_to_rgb(const color<3, inbits, hsv_traits>& v)
00196 {
00197 f_hsv_to_rgb<inbits, outbits> f;
00198 return f(v);
00199 }
00200
00201 }
00202 }
00203
00204 #endif // OLENA_CONVERT_RGBHSV_HH