
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox ChangeLog: 2009-04-29 Etienne FOLIO <folio@lrde.epita.fr> HSV type. * folio/mln/fun/v2v/rgb_to_hsv.hh: New conversions. * folio/mln/fun/v2v: New folder. * folio/mln/fun: New folder. * folio/mln/value/circular.hh: Comment a part of unused code. * folio/mln/value/hsv.hh: New HSV type. * folio/test/value/hsv.cc: New tests file for HSV type. --- mln/fun/v2v/rgb_to_hsv.hh | 148 ++++++++++++++++ mln/value/circular.hh | 4 mln/value/hsv.hh | 419 ++++++++++++++++++++++++++++++++++++++++++++++ test/value/hsv.cc | 13 + 4 files changed, 582 insertions(+), 2 deletions(-) Index: trunk/milena/sandbox/folio/test/value/hsv.cc =================================================================== --- trunk/milena/sandbox/folio/test/value/hsv.cc (revision 0) +++ trunk/milena/sandbox/folio/test/value/hsv.cc (revision 3723) @@ -0,0 +1,13 @@ + +#include <mln/core/image/image2d.hh> +#include "../../mln/value/hsv.hh" +#include "../../mln/value/circular.hh" + +int main() +{ + using namespace mln; + using namespace mln::value; + + image2d< hsv_< circular<16, 0, 360>, float, float > > ima; + +} Index: trunk/milena/sandbox/folio/mln/fun/v2v/rgb_to_hsv.hh =================================================================== --- trunk/milena/sandbox/folio/mln/fun/v2v/rgb_to_hsv.hh (revision 0) +++ trunk/milena/sandbox/folio/mln/fun/v2v/rgb_to_hsv.hh (revision 3723) @@ -0,0 +1,148 @@ +// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to +// produce an executable, this file does not by itself cause the +// resulting executable to be covered by the GNU General Public +// License. +// reasons why the executable file might be covered by the GNU General +// Public License. + +/// \file mln/fin/v2v/rgb_to_hsv.hh +/// +/// Conversion between RGB and HSV. +/// +/// \todo Write a better doc. +/// \todo Correct/write preconditions. + + +#ifndef MLN_FUN_V2V_RGB_TO_HSV_HH +# define MLN_FUN_V2V_RGB_TO_HSV_HH + +# include <cmath> + +# include <mln/trait/value_.hh> +# include <mln/math/max.hh> +# include <mln/math/min.hh> + +# include <mln/value/rgb.hh> + +namespace mln +{ + + namespace fun + { + + namespace v2v + { + + template <typename T_hsv> + struct f_rgb_to_hsv_ : public Function_v2v< f_rgb_to_hsv_<T_hsv> > + { + typedef T_hsv result; + + template <typename T_rgb> + T_hsv operator()(const T_rgb& rgb) const; + }; + + template <typename T_rgb> + struct f_hsv_to_rgb_ : public Function_v2v< f_hsv_to_rgb_<T_rgb> > + { + typedef T_rgb result; + + template <typename T_hsv> + T_rgb operator()(const T_hsv& hsv) const; + }; + + +# ifndef MLN_INCLUDE_ONLY + + + template <typename T_hsv> + template <typename T_rgb> + inline + T_hsv + f_rgb_to_hsv_<T_hsv>::operator()(const T_rgb& rgb) const + { + T_hsv hsv; + + // FIXME: take rgb [[0..1], [0..1], [0..1]] + + typename T_rgb::red_t rmax = + math::max(rgb.red(), math::max(rgb.green(), rgb.blue())); + + typename T_rgb::red_t rmin = + math::min(rgb.red(), math::min(rgb.green(), rgb.blue())); + + if (rmax == rmin) + hsv.hue() = 0; + else if (rmax == rgb.red()) + hsv.hue() = (60. * (rgb.green() - rgb.blue()) / (rmax - rmin)); + else if (rmax == rgb.green()) + hsv.hue() = (60. * (rgb.blue() - rgb.red()) / (rmax - rmin)) + 120.; + else if (rmax == rgb.blue()) + hsv.hue() = (60. * (rgb.red() - rgb.green()) / (rmax - rmin)) + 240.; + + hsv.sat() = (rmax == 0) ? 0 : (1 - rmin / rmax); + hsv.val() = rmax; + + // return hsv [[0..360], [0..1], [0..1]] + return hsv; + } + + + template <typename T_rgb> + template <typename T_hsv> + inline + T_rgb + f_hsv_to_rgb_<T_rgb>::operator()(const T_hsv& hsv) const + { + // take hsv [[0..360], [0..1], [0..1]] + + float i = floor(hsv.hue() / 60); + float f = hsv.hue() / 60 - i; + float p = hsv.val() * (1 - hsv.sat()); + float q = hsv.val() * (1 - f * hsv.sat()); + float t = hsv.val() * (1 - (1 - f) * hsv.sat()); + + T_rgb rgb; + switch(i) + { + case 0: rgb = T_rgb(hsv.val(), t, p); break; + case 1: rgb = T_rgb(q, hsv.val(), p); break; + case 2: rgb = T_rgb(p, hsv.val(), t); break; + case 3: rgb = T_rgb(p, q, hsv.val()); break; + case 4: rgb = T_rgb(t, p, hsv.val()); break; + case 5: rgb = T_rgb(hsv.val(), p, q); break; + } + + // FIXME: return rgb [[0..1], [0..1], [0..1]] + return rgb; + } + +# endif // !MLN_INCLUDE_ONLY + + } // end of namespace fun::v2v + + } // end of namespace fun + +} // end of namespace mln + +#endif // ! MLN_FUN_V2V_RGB_TO_HSV_HH Index: trunk/milena/sandbox/folio/mln/value/circular.hh =================================================================== --- trunk/milena/sandbox/folio/mln/value/circular.hh (revision 3722) +++ trunk/milena/sandbox/folio/mln/value/circular.hh (revision 3723) @@ -153,8 +153,8 @@ template <unsigned n, int inf, int sup> std::ostream& operator<<(std::ostream& ostr, const circular<n, inf, sup>& f); - template <unsigned n, int inf, int sup, unsigned m, int inf2, int sup2> - bool approx_equal(const circular<n, inf, sup>& lhs, const circular<m, inf2, sup2>& rhs); + // template <unsigned n, int inf, int sup, unsigned m, int inf2, int sup2> + // bool approx_equal(const circular<n, inf, sup>& lhs, const circular<m, inf2, sup2>& rhs); template <unsigned n, int inf, int sup> bool approx_equal(const circular<n, inf, sup>& lhs, const float f); Index: trunk/milena/sandbox/folio/mln/value/hsv.hh =================================================================== --- trunk/milena/sandbox/folio/mln/value/hsv.hh (revision 0) +++ trunk/milena/sandbox/folio/mln/value/hsv.hh (revision 3723) @@ -0,0 +1,419 @@ +// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory +// (LRDE) +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to +// produce an executable, this file does not by itself cause the +// resulting executable to be covered by the GNU General Public +// License. This exception does not however invalidate any other +// reasons why the executable file might be covered by the GNU General +// Public License. + +/// \file mln/value/hsv.hh +/// +/// Color class. +/// +/// \todo Write a better doc. +/// \todo Cleanup/Revamp! +/// \todo Need for more preconditions? + +#ifndef MLN_VALUE_HSV_HH +# define MLN_VALUE_HSV_HH + +#include <mln/value/ops.hh> + +#include <mln/value/concept/vectorial.hh> +#include <mln/value/int_u.hh> +#include <mln/algebra/vec.hh> + +#include "circular.hh" + +// Used in from_to +#include "../fun/v2v/rgb_to_hsv.hh" + + +namespace mln +{ + + // Forward declarations. + namespace value + { + + template <typename H, typename S, typename V> + class hsv_; + + } + + + + namespace convert + { + + namespace over_load + { + + // ? + template <int n> + void + from_to_(const value::rgb<n>& from, + value::hsv_<value::circular<n, 0, 360>, float, float>& to); + + } // end of namespace mln::convert::over_load + + } // end of namespace mln::convert + + + + namespace trait + { + + // ? + + template <typename H, typename S, typename V> + struct set_precise_binary_< op::plus, + mln::value::hsv_<H, S, V>, + mln::value::hsv_<H, S, V> > + { + typedef mln::value::hsv_<H, S, V> ret; + }; + + template <typename H, typename S, typename V> + struct set_precise_binary_< op::minus, + mln::value::hsv_<H, S, V>, + mln::value::hsv_<H, S, V> > + { + typedef mln::value::hsv_<H, S, V> ret; + }; + + template <typename H, typename S, typename V, typename S2> + struct set_precise_binary_< op::times, + mln::value::hsv_<H, S, V>, + mln::value::scalar_<S2> > + { + typedef mln::value::hsv_<H, S, V> ret; + }; + + template <typename H, typename S, typename V, typename S2> + struct set_precise_binary_< op::div, + mln::value::hsv_<H, S, V>, + mln::value::scalar_<S2> > + { + typedef mln::value::hsv_<H, S, V> ret; + }; + + + // FIXME : Is there any way more generic? a way to factor + // set_precise_binary_< op::div, + // mln::value::hsv_<H, S, V>, + // mln::value::scalar_<S> > + // and + // set_precise_binary_< op::div, + // mln::value::hsv_<H, S, V>, + // mln::value::int_u<m> > + // as for op::times. + + template <typename H, typename S, typename V, unsigned m> + struct set_precise_binary_< op::times, + mln::value::hsv_<H, S, V>, + mln::value::int_u<m> > + { + typedef mln::value::hsv_<H, S, V> ret; + }; + + template <typename H, typename S, typename V, unsigned m> + struct set_precise_binary_< op::div, + mln::value::hsv_<H, S, V>, + mln::value::int_u<m> > + { + typedef mln::value::hsv_<H, S, V> ret; + }; + + + template <typename H, typename S, typename V> + struct value_< mln::value::hsv_<H, S, V> > + { + enum { + dim = 3, + nbits = (sizeof (H) + sizeof (S) + sizeof (V)) * 8, // ? + card = mln_value_card_from_(nbits) + }; + + typedef trait::value::nature::vectorial nature; + typedef trait::value::kind::color kind; + typedef mln_value_quant_from_(card) quant; + + typedef H comp_0; + typedef S comp_1; + typedef V comp_2; + + typedef mln::value::hsv_<H, S, V> sum; + }; + + } // end of namespace trait + + + namespace value + { + + // ? + template <typename E> + struct HSV : Object<E> + { + }; + + + template <typename H, typename S, typename V> + class hsv_ : public HSV< hsv_<H, S, V> > + { + public: + + /// Constructor without argument. + hsv_() + { + } + + hsv_(const literal::zero_t&) + : hue_(0), + sat_(0), + val_(0) + { + } + + /// Constructor from component values. + hsv_(const H& hue, const S& sat, const V& lum) + { + mln_precondition(hue >= 0); + mln_precondition(sat >= 0); + mln_precondition(val >= 0); + mln_precondition(hue <= 1.); // ? + mln_precondition(sat <= 1.); + mln_precondition(val <= 1.); + hue_ = hue; + sat_ = sat; + val_ = val; + } + + /// Read-only access to the hue component. + const H& hue() const; + const S& sat() const; + const V& val() const; + + // ? + // hue(float), hue(H) instead? + + /// Read-write access to the hue component. + H& hue(); + S& sat(); + V& val(); + + private: + H hue_; + S sat_; + V val_; + }; + + /// Print an hsv \p c into the output stream \p ostr. + /// + /// \param[in,out] ostr An output stream. + /// \param[in] c An rgb. + /// + /// \return The modified output stream \p ostr. + template <typename H, typename S, typename V> + std::ostream& operator<<(std::ostream& ostr, const hsv_<H, S, V>& c); + + + /// Addition. + /// { + template <typename H, typename S, typename V> + hsv_<H, S, V> + operator+(const hsv_<H, S, V>& lhs, const hsv_<H, S, V>& rhs); + /// \} + + /// Subtraction. + /// \{ + template <typename H, typename S, typename V> + hsv_<H, S, V> + operator-(const hsv_<H, S, V>& lhs, const hsv_<H, S, V>& rhs); + /// \} + + /// Product. + /// \{ + template <typename H, typename S, typename V, typename S2> + hsv_<H, S, V> + operator*(const hsv_<H, S, V>& lhs, const mln::value::scalar_<S2>& s); + /// \} + + /// Division. + /// \{ + template <typename H, typename S, typename V, typename S2> + hsv_<H, S, V> + operator/(const hsv_<H, S, V>& lhs, const mln::value::scalar_<S2>& s); + /// \} + + } // end of namespace mln::value + + + + // More forward declarations + namespace fun + { + namespace v2v + { + + template <typename T_hsv> + struct f_rgb_to_hsv_; + +// typedef f_rgb_to_hsv_<value::hsv_f> f_rgb_to_hsv_f_t; +// extern f_rgb_to_hsv_f_t f_rgb_to_hsv_f; + + } + + } + +# ifndef MLN_INCLUDE_ONLY + + + namespace value + { + + template <typename H, typename S, typename V> + const H& + hsv_<H, S, V>::hue() const + { + return this->hue_; + } + + template <typename H, typename S, typename V> + const S& + hsv_<H, S, V>::sat() const + { + return this->sat_; + } + + template <typename H, typename S, typename V> + const V& + hsv_<H, S, V>::val() const + { + return this->val_; + } + + template <typename H, typename S, typename V> + H& + hsv_<H, S, V>::hue() + { + return this->hue_; + } + + template <typename H, typename S, typename V> + S& + hsv_<H, S, V>::sat() + { + return this->sat_; + } + + template <typename H, typename S, typename V> + V& + hsv_<H, S, V>::val() + { + return this->val_; + } + + + template <typename H, typename S, typename V> + inline + std::ostream& operator<<(std::ostream& ostr, const hsv_<H, S, V>& v) + { + return ostr << '(' << debug::format(v.hue()) + << ',' << debug::format(v.sat()) + << ',' << debug::format(v.val()) + << ')'; + } + + + template <typename H, typename S, typename V> + hsv_<H, S, V> + operator+(const hsv_<H, S, V>& lhs, const hsv_<H, S, V>& rhs) + { + return hsv_<H, S, V>(lhs.hue() + rhs.hue(), + lhs.sat() + rhs.sat(), + lhs.val() + rhs.val()); + } + + + template <typename H, typename S, typename V> + hsv_<H, S, V> + operator-(const hsv_<H, S, V>& lhs, const hsv_<H, S, V>& rhs) + { + return hsv_<H, S, V>(lhs.hue() - rhs.hue(), + lhs.sat() - rhs.sat(), + lhs.val() - rhs.val()); + } + + + template <typename H, typename S, typename V, typename S2> + hsv_<H, S, V> + operator*(const hsv_<H, S, V>& lhs, const mln::value::scalar_<S2>& s) + { + return hsv_<H, S, V>(lhs.hue() * s, + lhs.sat() * s, + lhs.val() * s); + } + + + template <typename H, typename S, typename V, typename S2> + hsv_<H, S, V> + operator/(const hsv_<H, S, V>& lhs, const mln::value::scalar_<S2>& s) + { + return hsv_<H, S, V>(lhs.hue() / s, + lhs.sat() / s, + lhs.val() / s); + } + + } // end of namespace mln::value + + + namespace convert + { + + namespace over_load + { + + // ? + template <int n> + inline + void + from_to_(const value::rgb<n>& from, + value::hsv_<value::circular<n, 0, 360>, float, float>& to) + { + to = fun::v2v::f_rgb_to_hsv_< + value::hsv_<value::circular<n, 0, 360>, float, float> >(from); + } + + } // end of namespace mln::convert::over_load + + } // end of namespace mln::convert + + +# endif // ! MLN_INCLUDE_ONLY + + +} // end of namespace mln + +#endif // ! MLN_VALUE_HSV_HH