URL:
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-04-29 Etienne FOLIO <folio(a)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