rgbhsl.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_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; // undefined
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   } // convert
00227 } // oln
00228 
00229 #endif // OLENA_CONVERT_RGBHSL_HH

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