rgbhsv.hh

Go to the documentation of this file.
00001 // Copyright (C) 2001, 2002, 2003, 2004, 2006 EPITA Research and
00002 // Development Laboratory
00003 //
00004 // This file is part of the Olena Library.  This library is free
00005 // software; you can redistribute it and/or modify it under the terms
00006 // of the GNU General Public License version 2 as published by the
00007 // Free Software Foundation.
00008 //
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this library; see the file COPYING.  If not, write to
00016 // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017 // Boston, MA 02110-1301, USA.
00018 //
00019 // As a special exception, you may use this file as part of a free
00020 // software library without restriction.  Specifically, if other files
00021 // instantiate templates or use macros or inline functions from this
00022 // file, or you compile this file and link it with other files to
00023 // produce an executable, this file does not by itself cause the
00024 // resulting executable to be covered by the GNU General Public
00025 // License.  This exception does not however invalidate any other
00026 // reasons why the executable file might be covered by the GNU General
00027 // Public License.
00028 
00029 
00030 #ifndef OLENA_CONVERT_RGBHSV_HH
00031 # define OLENA_CONVERT_RGBHSV_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/hsv.hh>
00040 
00041 # include <mlc/contract.hh>
00042 
00043 # include <sstream>
00044 
00049 namespace oln {
00050 
00051   using namespace ntg;
00052 
00053   namespace convert {
00054 
00059     template<unsigned inbits, unsigned outbits>
00060     struct f_rgb_to_hsv
00061       : public abstract::color_conversion<3, inbits, rgb_traits,
00062                                           3, outbits, hsv_traits, f_rgb_to_hsv<inbits, outbits> >
00063     {
00064       color<3, outbits, hsv_traits>
00065       doit(const color<3, inbits, rgb_traits>& v) const
00066       {
00067         vec<3, float> in = v.to_float();
00068         vec<3, float> out;
00069         float max_in = std::max(in[rgb_R], std::max(in[rgb_B], in[rgb_G]));
00070         float min_in = std::min(in[rgb_R], std::min(in[rgb_B], in[rgb_G]));
00071         float delta = max_in - min_in;
00072 
00073 
00074         out[hsv_V] = max_in;
00075 
00076         if (approx_neq(max_in, 0))
00077           out[hsv_S] = delta / max_in;
00078         else
00079           out[hsv_S] = 0;
00080 
00081         if (approx_eq(out[hsv_S], 0))
00082           out[hsv_H] = -1;   // undefined
00083         else {
00084           if (approx_eq(in[rgb_R], max_in))
00085             out[hsv_H] = (in[rgb_G] - in[rgb_B]) / delta;
00086           else if (approx_eq(in[rgb_G], max_in))
00087             out[hsv_H] = 2 + (in[rgb_B] - in[rgb_R]) / delta;
00088           else
00089             out[hsv_H] = 4 + (in[rgb_R] - in[rgb_G]) / delta;
00090           out[hsv_H] *= 60;
00091           if (out[hsv_H] < 0)
00092             out[hsv_H] += 360;
00093         }
00094 
00095         return out;
00096       }
00097 
00098       static std::string
00099       name()
00100       {
00101         std::ostringstream s;
00102         s << "f_rgb_to_hsv<" << inbits << ", " << outbits << '>';
00103         return s.str();
00104       }
00105     };
00106 
00111     template <unsigned inbits, unsigned outbits>
00112     color<3, outbits, hsv_traits>
00113     rgb_to_hsv(const color<3, inbits, rgb_traits>& v)
00114     {
00115       f_rgb_to_hsv<inbits, outbits> f;
00116       return f(v);
00117     }
00118 
00123     template<unsigned inbits, unsigned outbits>
00124     struct f_hsv_to_rgb
00125       : public abstract::color_conversion<3, inbits, hsv_traits,
00126                                 3, outbits, rgb_traits, f_hsv_to_rgb<inbits, outbits> >
00127     {
00128       color<3, outbits, rgb_traits>
00129       doit(const color<3, inbits, hsv_traits>& v) const
00130       {
00131         vec<3, float> in = v.to_float();
00132         vec<3, float> out;
00133 
00134         if(approx_eq(in[hsv_S], 0))
00135           out[rgb_G] = out[rgb_B] = out[rgb_R] = in[hsv_V];
00136         else
00137           {
00138             in[hsv_H] /= 60;
00139             int i = (int)floor (in[hsv_H]);
00140             float f = in[hsv_H] - i;
00141             float p = in[hsv_V] * (1 - in[hsv_S]);
00142             float q = in[hsv_V] * (1 - in[hsv_S] * f);
00143             float t = in[hsv_V] * (1 - in[hsv_S] * (1 - f));
00144 
00145             switch (i){
00146             case 0:
00147             case 6:
00148               out[rgb_R] = in[hsv_V];
00149               out[rgb_G] = t;
00150               out[rgb_B] = p;
00151               break;
00152             case 1:
00153               out[rgb_R] = q;
00154               out[rgb_G] = in[hsv_V];
00155               out[rgb_B] = p;
00156               break;
00157             case 2:
00158               out[rgb_R] = p;
00159               out[rgb_G] = in[hsv_V];
00160               out[rgb_B] = t;
00161               break;
00162             case 3:
00163               out[rgb_R] = p;
00164               out[rgb_G] = q;
00165               out[rgb_B] = in[hsv_V];
00166               break;
00167             case 4:
00168               out[rgb_R] = t;
00169               out[rgb_G] = p;
00170               out[rgb_B] = in[hsv_V];
00171               break;
00172             default:
00173               out[rgb_R] = in[hsv_V];
00174               out[rgb_G] = p;
00175               out[rgb_B] = q;
00176               break;
00177             }
00178           }
00179         return out;
00180       }
00181 
00182       static std::string
00183       name()
00184       {
00185         std::ostringstream s;
00186         s << "f_hsv_to_rgb<" << inbits << ", " << outbits << '>';
00187         return s.str();
00188       }
00189     };
00190 
00195     template <unsigned inbits, unsigned outbits>
00196     color<3, outbits, rgb_traits>
00197     hsv_to_rgb(const color<3, inbits, hsv_traits>& v)
00198     {
00199       f_hsv_to_rgb<inbits, outbits> f;
00200       return f(v);
00201     }
00202 
00203   } // convert
00204 } // oln
00205 
00206 #endif // OLENA_CONVERT_RGBHSV_HH

Generated on Tue Feb 20 20:20:31 2007 for Olena by  doxygen 1.5.1