rgbhsl.hh

Go to the documentation of this file.
00001 // Copyright (C) 2001, 2002, 2003, 2004  EPITA Research and Development Laboratory
00002 //
00003 // This file is part of the Olena Library.  This library is free
00004 // software; you can redistribute it and/or modify it under the terms
00005 // of the GNU General Public License version 2 as published by the
00006 // Free Software Foundation.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this library; see the file COPYING.  If not, write to
00015 // the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
00016 // MA 02111-1307, USA.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software library 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
00022 // produce an executable, this file does not by itself cause the
00023 // resulting executable to be covered by the GNU General Public
00024 // License.  This exception does not however invalidate any other
00025 // reasons why the executable file might be covered by the GNU General
00026 // Public License.
00027 
00028 
00029 #ifndef OLENA_CONVERT_NRGBHSL_HH
00030 # define OLENA_CONVERT_NRGBHSL_HH
00031 
00032 # include <oln/basics.hh>
00033 # include <oln/convert/abstract/colorconv.hh>
00034 
00035 # include <ntg/basics.hh>
00036 # include <ntg/color/nrgb.hh>
00037 # include <ntg/color/hsl.hh>
00038 
00039 # include <mlc/contract.hh>
00040 
00041 # include <cstdlib>
00042 # include <sstream>
00043 
00049 namespace oln {
00050 
00051   using namespace ntg;
00052 
00053   namespace convert {
00082     template<unsigned inbits, unsigned outbits>
00083     struct f_rgb_to_hsl
00084       : public abstract::color_conversion<3, inbits, rgb_traits,
00085                                           3, outbits, hsl_traits, f_rgb_to_hsl<inbits, outbits> >
00086     {
00087       color<3, outbits, hsl_traits>
00088       doit(const color<3, inbits, rgb_traits>& v) const
00089       {
00090         vec<3, float> in = v.to_float();
00091         vec<3, float> out;
00092 
00093         float max_in = ntg::max(in[rgb_R], std::max(in[rgb_B], in[rgb_G]));
00094         float min_in = ntg::min(in[rgb_R], std::min(in[rgb_B], in[rgb_G]));
00095         float diff = max_in-min_in;
00096 
00097         out[hsl_L] = (max_in + min_in) / 2;
00098         if (std::abs(diff) <= FLT_EPSILON){
00099           out[hsl_S] = 0;
00100           out[hsl_H] = 0; // undefined
00101         }
00102         else {
00103           if (out[hsl_L] <= 0.5)
00104             out[hsl_S] = diff / (max_in + min_in);
00105           else
00106             out[hsl_S] = diff / (2 - max_in - min_in);
00107 
00108 
00109           float r_dist = (max_in - in[rgb_R]) / diff;
00110           float g_dist = (max_in - in[rgb_G]) / diff;
00111           float b_dist = (max_in - in[rgb_B]) / diff;
00112 
00113           if (in[rgb_R] == max_in)
00114             out[hsl_H] = b_dist - g_dist;
00115           else if(in[rgb_G] == max_in)
00116             out[hsl_H] = 2 + r_dist - b_dist;
00117           else if(in[rgb_B] == max_in)
00118             out[hsl_H] = 4 + g_dist - r_dist;
00119 
00120           out[hsl_H] *= 60;
00121           if(out[hsl_H] < 0)
00122             out[hsl_H] += 360;
00123         }
00124         return out;
00125       }
00126 
00127       static std::string
00128       name()
00129       {
00130         std::ostringstream s;
00131         s << "f_rgb_to_hsl<" << inbits << ", " << outbits << '>';
00132         s.str();
00133       }
00134     };
00135 
00140     template <unsigned inbits, unsigned outbits>
00141     color<3, inbits, hsl_traits>
00142     rgb_to_hsl(const color<3, outbits, rgb_traits>& v)
00143     {
00144       f_rgb_to_hsl<inbits, outbits> f;
00145       return f(v);
00146     }
00147 
00148     namespace internal {
00149       float
00150       RGB(float q1, float q2, float hue)
00151       {
00152         if (hue >= 360)
00153           hue -= 360;
00154         if (hue < 0)
00155           hue += 360;
00156         if (hue < 60)
00157           return q1 + (q2 - q1) * hue / 60;
00158         else if (hue < 180)
00159           return q2;
00160         else if (hue < 240)
00161           return q1 + (q2 - q1) * (240 - hue) / 60;
00162         else
00163           return q1;
00164       }
00165     }
00166 
00171     template<unsigned inbits, unsigned outbits>
00172     struct f_hsl_to_rgb
00173       : public abstract::color_conversion<3, inbits, hsl_traits,
00174                                           3, outbits, rgb_traits, f_hsl_to_rgb<inbits, outbits> >
00175     {
00176       color<3, outbits, rgb_traits>
00177       doit(const color<3, inbits, hsl_traits>& v) const
00178       {
00179         vec<3, float> in = v.to_float();
00180         vec<3, float> out;
00181         float p2;
00182 
00183         if(in[hsl_L] < 0.5)
00184           p2 = in[hsl_L] * (1+in[hsl_S]);
00185         else
00186           p2 = in[hsl_L] + in[hsl_S] - (in[hsl_L] * in[hsl_S]);
00187 
00188         float p1 = 2 * in[hsl_L] - p2;
00189 
00190         if(in[hsl_S] == 0)
00191           out[rgb_R] = out[rgb_G] = out[rgb_B] = in[hsl_L];
00192         else
00193           {
00194             out[rgb_R] = internal::RGB(p1, p2, in[hsl_H] + 120);
00195             out[rgb_G] = internal::RGB(p1, p2, in[hsl_H]);
00196             out[rgb_B] = internal::RGB(p1, p2, in[hsl_H] - 120);
00197           }
00198 
00199         return out;
00200       }
00201 
00202       static std::string
00203       name()
00204       {
00205         std::ostringstream s;
00206         s << "f_hsl_to_rgb<" << inbits << ", " << outbits << '>';
00207         s.str();
00208       }
00209     };
00210 
00215     template<unsigned inbits, unsigned outbits>
00216     color<3, outbits, rgb_traits>
00217     hsl_to_rgb(const color<3, inbits, hsl_traits>& v)
00218     {
00219       f_hsl_to_rgb<inbits, outbits> f;
00220       return f(v);
00221     }
00222 
00223   } // convert
00224 } // oln
00225 
00226 #endif // OLENA_CONVERT_RGBHSL_HH

Generated on Thu Apr 15 20:13:14 2004 for Olena by doxygen 1.3.6-20040222