Olena-patches
  Threads by month 
                
            - ----- 2025 -----
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
August 2007
- 2 participants
- 18 discussions
                    
                        https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from  Thierry Geraud  <thierry.geraud(a)lrde.epita.fr>
	Augment morphology.
	* mln/value/cast.hh: Rename as...
	* mln/core/cast_image.hh: ...this.
	Update.
	* mln/core/concept/value.hh (cast): Move to and rename as...
	* mln/value/cast.hh (cast_image): ...this, here.
	* tests/cast_image.cc: Update.
	* mln/morpho/thickening.hh: New.
	* mln/morpho/laplacian.hh: New.
	* mln/morpho/thick_miss.hh: New.
	* mln/morpho/thin_fit.hh: New.
	* mln/morpho/thinning.hh: New.
	* tests/morpho_thinning.cc: New.
	* tests/morpho_laplacian.cc: New.
	* tests/morpho_hit_or_miss.cc: Update.
	* mln/morpho/plus.hh (mln_postcondition): Remove.
	* mln/morpho/minus.hh: Remove dead lines.
	* mln/morpho/hit_or_miss.hh: Augment doc.
	Add postconditions.
	Add a FIXME.
	* mln/io/save_pgm.hh: Rewrite.
	* mln/arith/plus.hh (plus_cst, plus_cst_inplace): New.
	* img/picasso.pgm: Invert.
 img/picasso.pgm             |    0 
 mln/arith/plus.hh           |   31 ++++++++++++++
 mln/core/cast_image.hh      |   50 +++++++++++-------------
 mln/core/concept/value.hh   |   48 +----------------------
 mln/io/save_pgm.hh          |   72 +++++++++++++++++++++++++++++++---
 mln/morpho/hit_or_miss.hh   |   41 +++++++++++++++----
 mln/morpho/laplacian.hh     |   83 ++++++++++++++++++++++++++++++++++++++++
 mln/morpho/minus.hh         |    3 -
 mln/morpho/plus.hh          |    3 -
 mln/morpho/thick_miss.hh    |   79 ++++++++++++++++++++++++++++++++++++++
 mln/morpho/thickening.hh    |   79 ++++++++++++++++++++++++++++++++++++++
 mln/morpho/thin_fit.hh      |   79 ++++++++++++++++++++++++++++++++++++++
 mln/morpho/thinning.hh      |   91 ++++++++++++++++++++++++++++++++++++++++++++
 tests/cast_image.cc         |    6 +-
 tests/morpho_hit_or_miss.cc |    6 +-
 tests/morpho_laplacian.cc   |   63 ++++++++++++++++++++++++++++++
 tests/morpho_thinning.cc    |   69 +++++++++++++++++++++++++++++++++
 17 files changed, 705 insertions(+), 98 deletions(-)
Index: tests/cast_image.cc
--- tests/cast_image.cc	(revision 1063)
+++ tests/cast_image.cc	(working copy)
@@ -27,14 +27,14 @@
 
 /*! \file tests/cast_image.cc
  *
- * \brief Tests on mln::value::cast_image.
+ * \brief Tests on mln::cast_image.
  */
 
 #include <mln/core/image2d_b.hh>
 #include <mln/fun/p2b/chess.hh>
 #include <mln/level/fill.hh>
 #include <mln/debug/println.hh>
-#include <mln/value/cast.hh>
+#include <mln/core/cast_image.hh>
 
 
 int main()
@@ -44,5 +44,5 @@
   image2d_b<bool> ima(8, 8);
   level::fill(ima, fun::p2b::chess);
   debug::println(ima);
-  debug::println( value::cast<int>(ima) );
+  debug::println( cast_image<int>(ima) );
 }
Index: tests/morpho_thinning.cc
--- tests/morpho_thinning.cc	(revision 0)
+++ tests/morpho_thinning.cc	(revision 0)
@@ -0,0 +1,69 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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 tests/morpho_thinning.cc
+ *
+ * \brief Test on mln::morpho::thinning.
+ */
+
+#include <mln/core/image2d_b.hh>
+#include <mln/value/int_u8.hh>
+
+#include <mln/core/win/rectangle2d.hh>
+#include <mln/core/window2d.hh>
+
+#include <mln/io/load_pgm.hh>
+#include <mln/io/save_pgm.hh>
+
+#include <mln/morpho/thinning.hh>
+
+
+int main()
+{
+  using namespace mln;
+  using value::int_u8;
+
+  bool fg[] = { 0, 0, 0,
+		0, 1, 0,
+		0, 0, 0 };
+  window2d win_fg = make::window2d(fg);
+
+  bool bg[] = { 0, 0, 0,
+		1, 0, 1,
+		0, 0, 0 };
+  window2d win_bg = make::window2d(bg);
+
+  border::thickness = 2;
+
+  image2d_b<int_u8>
+    pic = io::load_pgm("../img/picasso.pgm"),
+    out(pic.domain());
+
+  morpho::thinning(pic, win_fg, win_bg, out);
+
+  io::save_pgm(out, "out.pgm");
+}
Index: tests/morpho_hit_or_miss.cc
--- tests/morpho_hit_or_miss.cc	(revision 1063)
+++ tests/morpho_hit_or_miss.cc	(working copy)
@@ -76,10 +76,10 @@
   border::thickness = 2;
 
   image2d_b<int_u8>
-    lena = io::load_pgm("../img/picasso.pgm"),
-    out(lena.domain());
+    pic = io::load_pgm("../img/picasso.pgm"),
+    out(pic.domain());
 
-  morpho::hit_or_miss(lena, win_hit, win_miss, out);
+  morpho::hit_or_miss(pic, win_hit, win_miss, out);
 
   io::save_pgm(out, "out.pgm");
 }
Index: tests/morpho_laplacian.cc
--- tests/morpho_laplacian.cc	(revision 0)
+++ tests/morpho_laplacian.cc	(revision 0)
@@ -0,0 +1,63 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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 tests/morpho_laplacian.cc
+ *
+ * \brief Test on mln::morpho::laplacian.
+ */
+
+#include <mln/core/image2d_b.hh>
+#include <mln/core/win/rectangle2d.hh>
+
+#include <mln/io/load_pgm.hh>
+#include <mln/io/save_pgm.hh>
+
+#include <mln/value/int_u_sat.hh>
+#include <mln/core/cast_image.hh>
+#include <mln/pw/image.hh>
+#include <mln/arith/plus.hh>
+
+#include <mln/morpho/laplacian.hh>
+
+
+
+int main()
+{
+  using namespace mln;
+  using value::int_u8;
+
+  win::rectangle2d rect(5, 5);
+  border::thickness = 2;
+
+  image2d_b<int_u8> lena = io::load_pgm("../img/tiny.pgm");
+  image2d_b<int> lap(lena.domain());
+  morpho::laplacian(lena, rect, lap);
+
+  image2d_b< value::int_u_sat<8> > out(lena.domain());
+  arith::plus_cst(lap, 128, out);
+  io::save_pgm(out, "out.pgm");
+}
Index: mln/core/cast_image.hh
--- mln/core/cast_image.hh	(revision 1063)
+++ mln/core/cast_image.hh	(working copy)
@@ -25,29 +25,27 @@
 // reasons why the executable file might be covered by the GNU General
 // Public License.
 
-#ifndef MLN_VALUE_CAST_HH
-# define MLN_VALUE_CAST_HH
+#ifndef MLN_CORE_CAST_IMAGE_HH
+# define MLN_CORE_CAST_IMAGE_HH
 
-/*! \file mln/value/cast.hh
+/*! \file mln/core/cast_image.hh
  *
  * \brief Definition of an image class FIXME
  */
 
 # include <mln/core/concept/image.hh>
 # include <mln/value/set.hh>
+# include <mln/value/cast.hh>
 
 
 namespace mln
 {
 
-  namespace value
-  {
-
     /*! \brief FIXME
      *
      */
     template <typename T, typename I>
-    struct cast_image : public mln::internal::image_base_< mln_pset(I), cast_image<T,I> >
+  struct cast_image_ : public mln::internal::image_base_< mln_pset(I), cast_image_<T,I> >
     {
       /// Point_Site associated type.
       typedef mln_psite(I) psite;
@@ -62,14 +60,14 @@
       typedef T rvalue;
 
       /// Return type of read-write access.
-      typedef void lvalue; // FIXME
+    typedef T lvalue;
 
       /// Value set associated type.
       typedef mln::value::set<T> vset;
 
 
       /// Constructor.
-      cast_image(const Image<I>& ima);
+    cast_image_(const Image<I>& ima);
 
 
       /// Test if this image has been initialized.
@@ -84,8 +82,8 @@
       /// Read-only access of pixel value at point site \p p.
       T operator()(const psite& p) const;
 
-      /// Read-write access is present but disabled.
-      void operator()(const psite&);
+    /// Mutable access is only OK for reading (not writing).
+    T operator()(const psite& p);
 
       /// Give the set of values of the image.
       const vset& values() const;
@@ -104,11 +102,11 @@
 
 
     template <typename T, typename I>
-    cast_image<T,I>
-    cast(const Image<I>& ima)
+  cast_image_<T,I>
+  cast_image(const Image<I>& ima)
     {
       mln_precondition(exact(ima).has_data());
-      cast_image<T,I> tmp(ima);
+    cast_image_<T,I> tmp(ima);
       return tmp;
     }
   
@@ -117,59 +115,57 @@
 # ifndef MLN_INCLUDE_ONLY
 
     template <typename T, typename I>
-    cast_image<T,I>::cast_image(const Image<I>& ima)
+  cast_image_<T,I>::cast_image_(const Image<I>& ima)
       : ima_(exact(ima))
     {
       mln_precondition(exact(ima).has_data());
     }
 
     template <typename T, typename I>
-    bool cast_image<T,I>::has_data() const
+  bool cast_image_<T,I>::has_data() const
     {
       mln_invariant(ima_.has_data());
       return true;
     }
 
     template <typename T, typename I>
-    bool cast_image<T,I>::owns_(const psite& p) const
+  bool cast_image_<T,I>::owns_(const psite& p) const
     {
       return ima_.owns_(p);
     }
 
     template <typename T, typename I>
     const mln_pset(I)&
-    cast_image<T,I>::domain() const
+  cast_image_<T,I>::domain() const
     {
       return ima_.domain();
     }
 
     template <typename T, typename I>
     T
-    cast_image<T,I>::operator()(const psite& p) const
+  cast_image_<T,I>::operator()(const psite& p) const
     {
       mln_precondition(ima_.owns_(p));
-      return ima_(p);
+    return mln::value::cast<T>( ima_(p) );
     }
 
     template <typename T, typename I>
-    void
-    cast_image<T,I>::operator()(const psite&)
+  T
+  cast_image_<T,I>::operator()(const psite& p)
     {
-      mln_invariant(0); // FIXME: Turn into a compile-time error...
+    return mln::value::cast<T>( ima_(p) );
     }
 
     template <typename T, typename I>
     const mln::value::set<T>&
-    cast_image<T,I>::values() const
+  cast_image_<T,I>::values() const
     {
       return vset::the();
     }
   
 # endif // ! MLN_INCLUDE_ONLY
 
-  } // end of namespace mln::value
-
 } // end of namespace mln
 
 
-#endif // ! MLN_VALUE_CAST_HH
+#endif // ! MLN_CORE_CAST_IMAGE_HH
Index: mln/core/concept/value.hh
--- mln/core/concept/value.hh	(revision 1063)
+++ mln/core/concept/value.hh	(working copy)
@@ -63,17 +63,6 @@
 
 
 
-  namespace value
-  {
-
-    /// Cast a value \p src from type \c Src to type \c Dest. 
-    template <typename Dest, typename Src>
-    Dest cast(const Src& src);
-
-  } // end of namespace mln::value
-
-
-
 # ifndef MLN_INCLUDE_ONLY
 
   template <typename E>
@@ -99,43 +88,12 @@
     return exact(*this);
   }
 
-
-  namespace value
-  {
-
-    namespace internal
-    {
-
-      template <typename S>
-      const S&
-      cast_(const S& src, ...)
-      {
-	return src;
-      }
-
-      template <typename T, typename S>
-      typename S::equiv
-      cast_(const T&, const Value<S>& src)
-      {
-	return exact(src);
-      }
-
-    } // end of namespace mln::value::internal
-
-
-    template <typename Dest, typename Src>
-    Dest cast(const Src& src)
-    {
-      return internal::cast_(src, src);
-    }
-
-
-  } // end of namespace mln::value
-
-
 # endif // ! MLN_INCLUDE_ONLY
 
 } // end of namespace mln
 
 
+# include <mln/value/cast.hh>
+
+
 #endif // ! MLN_CORE_CONCEPT_VALUE_HH
Index: mln/morpho/thickening.hh
--- mln/morpho/thickening.hh	(revision 0)
+++ mln/morpho/thickening.hh	(revision 0)
@@ -0,0 +1,79 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_MORPHO_THICKENING_HH
+# define MLN_MORPHO_THICKENING_HH
+
+/*! \file mln/morpho/thickening.hh
+ *
+ * \brief Morphological thickening.
+ */
+
+# include <mln/morpho/hit_or_miss.hh>
+
+
+namespace mln
+{
+
+  namespace morpho
+  {
+
+
+    /*! Morphological thickening.
+     *
+     * This operator is THICK_B = Id + HMT_B, where B = (Bfg, Bbg).
+     */
+    template <typename I, typename Wfg, typename Wbg, typename O>
+    void thickening(const Image<I>& input,
+		    const Window<Wfg>& win_fg, const Window<Wbg>& win_bg,
+		    Image<O>& output);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I, typename Wfg, typename Wbg, typename O>
+    void thickening(const Image<I>& input,
+		  const Window<Wfg>& win_fg, const Window<Wbg>& win_bg,
+		  Image<O>& output)
+    {
+      mln_precondition(exact(output).domain() = exact(input).domain());
+      mln_precondition(exact(win_bg).is_centered());
+      mln_precondition(set::inter(exact(win_fg), exact(win_bg)).is_empty());
+
+      O temp(exact(input).domain());
+      hit_or_miss(input, win_fg, win_bg, temp);
+      morpho::plus(input, temp, output);
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MORPHO_THICKENING_HH
Index: mln/morpho/plus.hh
--- mln/morpho/plus.hh	(revision 1063)
+++ mln/morpho/plus.hh	(working copy)
@@ -85,10 +85,7 @@
     {
       mln_precondition(exact(rhs).domain() = exact(lhs).domain());
       mln_precondition(exact(output).domain() = exact(lhs).domain());
-
       impl::plus_(mln_value_kind(I)(), exact(lhs), exact(rhs), output);
-
-      mln_postcondition(output <= lhs);
     }
 
     template <typename I, typename J>
Index: mln/morpho/laplacian.hh
--- mln/morpho/laplacian.hh	(revision 0)
+++ mln/morpho/laplacian.hh	(revision 0)
@@ -0,0 +1,83 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_MORPHO_LAPLACIAN_HH
+# define MLN_MORPHO_LAPLACIAN_HH
+
+/*! \file mln/morpho/laplacian.hh
+ *
+ * \brief Morphological laplacian.
+ *
+ * \todo Save memory.
+ */
+
+# include <mln/morpho/includes.hh>
+
+
+namespace mln
+{
+
+  namespace morpho
+  {
+
+    /*! Morphological laplacian.
+     *
+     * This operator is (d_B - Id) - (Id - e_B). 
+     */
+    template <typename I, typename W, typename O>
+    void laplacian(const Image<I>& input, const Window<W>& win,
+		   Image<O>& output);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I, typename W, typename O>
+    void laplacian(const Image<I>& input, const Window<W>& win, Image<O>& output)
+    {
+      mln_precondition(exact(output).domain() = exact(input).domain());
+      mln_precondition(! exact(win).is_empty());
+
+      dilation(input, win, output); // output = dilation
+      morpho::minus_inplace(output, input); // now output = dilation - input
+
+      O temp(exact(input).domain());
+      {
+	O temp_(exact(input).domain());
+	erosion(input, win, temp_); // temp_ = erosion
+	morpho::minus(input, temp_, temp); // temp = input - erosion
+      }
+      morpho::minus_inplace(output, temp); // now output = (dilation - input) - (input - erosion)
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MORPHO_LAPLACIAN_HH
Index: mln/morpho/minus.hh
--- mln/morpho/minus.hh	(revision 1063)
+++ mln/morpho/minus.hh	(working copy)
@@ -64,9 +64,7 @@
 		  const Image<I>& lhs, const Image<J>& rhs,
 		  Image<O>& output)
       {
-	// FIXME: mln_precondition(rhs <= lhs);
 	return logical::and_not(lhs, rhs, output);
-	// FIXME: mln_postcondition(output <= lhs);
       }
 
       template <typename K, typename I, typename J, typename O>
@@ -87,7 +85,6 @@
     {
       mln_precondition(exact(rhs).domain() = exact(lhs).domain());
       mln_precondition(exact(output).domain() = exact(lhs).domain());
-
       impl::minus_(mln_value_kind(I)(), exact(lhs), exact(rhs), output);
     }
 
Index: mln/morpho/thick_miss.hh
--- mln/morpho/thick_miss.hh	(revision 0)
+++ mln/morpho/thick_miss.hh	(revision 0)
@@ -0,0 +1,79 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_MORPHO_THICK_MISS_HH
+# define MLN_MORPHO_THICK_MISS_HH
+
+/*! \file mln/morpho/thick_miss.hh
+ *
+ * \brief Morphological thick-miss.
+ */
+
+# include <mln/morpho/hit_or_miss.hh>
+
+
+namespace mln
+{
+
+  namespace morpho
+  {
+
+
+    /*! Morphological thick-miss.
+     *
+     * This operator is THICK_B = Id + HMTopeBG_B, where B = (Bfg, Bbg).
+     */
+    template <typename I, typename Wfg, typename Wbg, typename O>
+    void thick_miss(const Image<I>& input,
+		    const Window<Wfg>& win_fg, const Window<Wbg>& win_bg,
+		    Image<O>& output);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I, typename Wfg, typename Wbg, typename O>
+    void thick_miss(const Image<I>& input,
+		  const Window<Wfg>& win_fg, const Window<Wbg>& win_bg,
+		  Image<O>& output)
+    {
+      mln_precondition(exact(output).domain() = exact(input).domain());
+      mln_precondition(exact(win_miss).is_centered());
+      mln_precondition(set::inter(exact(win_fg), exact(win_bg)).is_empty());
+
+      O temp(exact(input).domain());
+      hit_or_miss_background_opening(input, win_fg, win_bg, temp);
+      morpho::plus(input, temp, output);
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MORPHO_THICK_MISS_HH
Index: mln/morpho/thin_fit.hh
--- mln/morpho/thin_fit.hh	(revision 0)
+++ mln/morpho/thin_fit.hh	(revision 0)
@@ -0,0 +1,79 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_MORPHO_THIN_FIT_HH
+# define MLN_MORPHO_THIN_FIT_HH
+
+/*! \file mln/morpho/thin_fit.hh
+ *
+ * \brief Morphological thin-fit.
+ */
+
+# include <mln/morpho/hit_or_miss.hh>
+
+
+namespace mln
+{
+
+  namespace morpho
+  {
+
+
+    /*! Morphological thin-fit.
+     *
+     * This operator is THIN_B = Id - HMTope_B where B = (Bfg, Bbg).
+     */
+    template <typename I, typename Wfg, typename Wbg, typename O>
+    void thin_fit(const Image<I>& input,
+		  const Window<Wfg>& win_fg, const Window<Wbg>& win_bg,
+		  Image<O>& output);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I, typename Wfg, typename Wbg, typename O>
+    void thin_fit(const Image<I>& input,
+		  const Window<Wfg>& win_fg, const Window<Wbg>& win_bg,
+		  Image<O>& output)
+    {
+      mln_precondition(exact(output).domain() = exact(input).domain());
+      mln_precondition(exact(win_fg).is_centered());
+      mln_precondition(set::inter(exact(win_fg), exact(win_bg)).is_empty());
+
+      O temp(exact(input).domain());
+      hit_or_miss_opening(input, win_fg, win_bg, temp);
+      morpho::minus(input, temp, output);
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MORPHO_THIN_FIT_HH
Index: mln/morpho/thinning.hh
--- mln/morpho/thinning.hh	(revision 0)
+++ mln/morpho/thinning.hh	(revision 0)
@@ -0,0 +1,91 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_MORPHO_THINNING_HH
+# define MLN_MORPHO_THINNING_HH
+
+/*! \file mln/morpho/thinning.hh
+ *
+ * \brief Morphological thinning.
+ */
+
+# include <mln/morpho/hit_or_miss.hh>
+# include <mln/morpho/thickening.hh>
+
+
+namespace mln
+{
+
+  namespace morpho
+  {
+
+
+    /*! Morphological thinning.
+     *
+     * This operator is THIN_B = Id - HMT_B, where B = (Bfg, Bbg).
+     */
+    template <typename I, typename Wfg, typename Wbg, typename O>
+    void thinning(const Image<I>& input,
+		  const Window<Wfg>& win_fg, const Window<Wbg>& win_bg,
+		  Image<O>& output);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I, typename Wfg, typename Wbg, typename O>
+    void thinning(const Image<I>& input,
+		  const Window<Wfg>& win_fg, const Window<Wbg>& win_bg,
+		  Image<O>& output)
+    {
+      mln_precondition(exact(output).domain() = exact(input).domain());
+      mln_precondition(exact(win_fg).is_centered());
+      mln_precondition(set::inter(exact(win_fg), exact(win_bg)).is_empty());
+
+      O temp(exact(input).domain());
+      hit_or_miss(input, win_fg, win_bg, temp);
+      morpho::minus(input, temp, output);
+      // FIXME: Pass postcondition!
+#  ifndef NDEBUG
+      {
+	O temp(exact(input).domain());
+	complementation(input, temp);
+	O output_(exact(input).domain());
+	thickening(temp, win_bg, win_fg, output_);
+	complementation_inplace(output_);
+	mln_postcondition(output_ = output);
+      }
+#  endif // ! NDEBUG
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MORPHO_THINNING_HH
Index: mln/morpho/hit_or_miss.hh
--- mln/morpho/hit_or_miss.hh	(revision 1063)
+++ mln/morpho/hit_or_miss.hh	(working copy)
@@ -61,7 +61,7 @@
 
     /*! Morphological hit-or-miss opening.
      *
-     * This operator is d_(-Bh) o HMT_(Bh,Bm).
+     * This operator is HMTope_(Bh,Bm) = d_(-Bh) o HMT_(Bh,Bm).
      */
     template <typename I, typename Wh, typename Wm, typename O>
     void hit_or_miss_opening(const Image<I>& input,
@@ -70,7 +70,7 @@
 
     /*! Morphological hit-or-miss opening of the background.
      *
-     * This operator is FIXME.
+     * This operator is HMTopeBG = HMTope_(Bm,Bh) o C = d_(-Bm) o HMT_(Bh,Bm).
      */
     template <typename I, typename Wh, typename Wm, typename O>
     void hit_or_miss_background_opening(const Image<I>& input,
@@ -79,7 +79,7 @@
 
     /*! Morphological hit-or-miss closing.
      *
-     * This operator is FIXME.
+     * This operator is C o HMTope o C.
      */
     template <typename I, typename Wh, typename Wm, typename O>
     void hit_or_miss_closing(const Image<I>& input,
@@ -88,7 +88,7 @@
 
     /*! Morphological hit-or-miss closing of the background.
      *
-     * This operator is FIXME.
+     * This operator is C o HMTopeBG o C.
      */
     template <typename I, typename Wh, typename Wm, typename O>
     void hit_or_miss_background_closing(const Image<I>& input,
@@ -150,7 +150,8 @@
 		erosion(input, win_hit,  ero_fg);
 		dilation(input, win_miss, dil_bg);
 		level::fill(output,
-			    fun::p2v::ternary(pw::value(input) = pw::value(ero_fg) && pw::value(dil_bg) < pw::value(input),
+			    fun::p2v::ternary(pw::value(input) = pw::value(ero_fg)
+					        && pw::value(dil_bg) < pw::value(input),
 					      pw::value(input) - pw::value(dil_bg),
 					      pw::cst(V::zero)));
 	      }
@@ -160,12 +161,13 @@
 		erosion(input, win_miss, ero_bg);
 		dilation(input, win_hit, dil_fg);
 		level::fill(output,
-			    fun::p2v::ternary(pw::value(input) = pw::value(dil_fg) && pw::value(ero_bg) > pw::value(input),
+			    fun::p2v::ternary(pw::value(input) = pw::value(dil_fg)
+					        && pw::value(ero_bg) > pw::value(input),
 					      pw::value(ero_bg) - pw::value(input),
 					      pw::cst(V::zero)));
 	      }
 	    else
-	      level::fill(output, pw::cst(V::zero));
+	      level::fill(output, V::zero);
 	  }
 	else // Unconstrained: UHMT.
 	  {
@@ -201,6 +203,7 @@
       O temp(exact(input).domain());
       hit_or_miss(input, win_hit, win_miss, temp);
       dilation(temp, geom::sym(win_hit), output);
+      // FIXME: Postcondition.
     }
 
     template <typename I, typename Wh, typename Wm, typename O>
@@ -209,7 +212,18 @@
 					Image<O>& output)
     {
       impl::hit_or_miss_preconditions_(input, win_hit, win_miss, output);
-      hit_or_miss_opening(input, win_miss, win_hit, output);
+      O temp(exact(input).domain());
+      complementation(input, temp);
+      hit_or_miss_opening(temp, win_miss, win_hit, output);
+#  ifndef NDEBUG
+      {
+	O temp(exact(input).domain());
+	hit_or_miss(input, win_hit, win_miss, temp);
+	O output_(exact(input).domain());
+	dilation(temp, geom::sym(win_miss), output_);
+	mln_postcondition(output_ = output);
+      }
+#  endif // ! NDEBUG
     }
 
     template <typename I, typename Wh, typename Wm, typename O>
@@ -222,6 +236,7 @@
       complementation(input, temp);
       hit_or_miss_opening(temp, win_hit, win_miss, output);
       complementation_inplace(output);
+      // FIXME: Postcondition.
     }
 
     template <typename I, typename Wh, typename Wm, typename O>
@@ -231,6 +246,16 @@
     {
       impl::hit_or_miss_preconditions_(input, win_hit, win_miss, output);
       hit_or_miss_closing(input, win_miss, win_hit, output);
+#  ifndef NDEBUG
+      {
+	O temp(exact(input).domain());
+	complementation(input, temp);
+	O output_(exact(input).domain());
+	hit_or_miss_background_opening(temp, win_hit, win_miss, output_);
+	complementation_inplace(output_);
+	mln_postcondition(output_ = output);
+      }
+#  endif // ! NDEBUG
     }
 
 # endif // ! MLN_INCLUDE_ONLY
Index: mln/io/save_pgm.hh
--- mln/io/save_pgm.hh	(revision 1063)
+++ mln/io/save_pgm.hh	(working copy)
@@ -32,20 +32,37 @@
 # include <iostream>
 # include <fstream>
 
-# include <mln/core/image2d_b.hh>
 # include <mln/geom/size2d.hh>
-# include <mln/value/int_u8.hh>
+# include <mln/metal/equal.hh>
+# include <mln/metal/bexpr.hh>
 
 
 namespace mln
 {
 
+  // Fwd decl.
+  namespace value {
+    template <unsigned> class int_u;
+    template <unsigned> class int_u_sat;
+  }
+
+
   namespace io
   {
 
-    void save_pgm(const image2d_b<value::int_u8>& ima, const std::string& filename)
+    template <typename I>
+    void save_pgm(const Image<I>& ima, const std::string& filename);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    namespace impl
+    {
+
+      template <typename I>
+      void save_pgm_header_(const I& ima, const std::string& filename,
+			    std::ofstream& file)
     {
-      std::ofstream file(filename.c_str());
       if (! file)
 	{
 	  std::cerr << "error: cannot open file '" << filename
@@ -53,14 +70,22 @@
 	  abort();
 	}
       file << "P5" << std::endl;
-      file << "# olena" << std::endl;
+	file << "# milena" << std::endl;
       file << geom::ncols(ima) << ' ' << geom::nrows(ima) << std::endl;
       file << "255" << std::endl;
+      }
+
+      template <typename I>
+      void save_pgm_(const Fast_Image<I>& ima_, const std::string& filename)
+      {
+	const I& ima = exact(ima_);
+	std::ofstream file(filename.c_str());
+	save_pgm_header_(ima, filename, file);
       const int
 	min_row = geom::min_row(ima),
 	max_row = geom::max_row(ima);
       point2d p;
-      if (sizeof(value::int_u8) = 1)
+	if (sizeof(mln_value(I)) = 1)
 	{
 	  p.col() = geom::min_col(ima);
 	  size_t len = geom::ncols(ima);
@@ -82,6 +107,41 @@
 	}
     }
 
+      template <typename I>
+      void save_pgm_(const Image<I>& ima_, const std::string& filename)
+      {
+	const I& ima = exact(ima_);
+	std::ofstream file(filename.c_str());
+	save_pgm_header_(ima, filename, file);
+	const int
+	  min_row = geom::min_row(ima),
+	  max_row = geom::max_row(ima),
+	  min_col = geom::min_col(ima),
+	  max_col = geom::max_col(ima);
+	point2d p;
+	for (p.row() = min_row; p.row() <= max_row; ++p.row())
+	  for (p.col() = min_col; p.col() <= max_col; ++p.col())
+	    {
+	      unsigned char c = ima(p);
+	      file.write((char*)(&c), 1);
+	    }
+      }
+
+    } // end of namespace mln::io::impl
+
+
+    template <typename I>
+    void save_pgm(const Image<I>& ima, const std::string& filename)
+    {
+      mln::metal::or_<
+	mln::metal::equal<mln_value(I), value::int_u<8> >,
+	mln::metal::equal<mln_value(I), value::int_u_sat<8> >
+	>::check();
+      impl::save_pgm_(exact(ima), filename);
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
   } // end of namespace mln::io
 
 } // end of namespace mln
Index: mln/arith/plus.hh
--- mln/arith/plus.hh	(revision 1063)
+++ mln/arith/plus.hh	(working copy)
@@ -31,10 +31,15 @@
 /*! \file mln/arith/plus.hh
  *
  * \brief Point-wise addition between images.
+ *
+ * \todo Speedup versions with cst.
  */
 
 # include <mln/core/concept/image.hh>
 
+# include <mln/pw/cst.hh>
+# include <mln/pw/image.hh>
+
 
 namespace mln
 {
@@ -54,6 +59,18 @@
     void plus(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output);
 
 
+    /*! Point-wise addition of the value \p val to image \p input.
+     *
+     * \param[in] input The image.
+     * \param[in] val The value.
+     * \param[out] output The result image.
+     *
+     * \pre \p output.domain = \p input.domain
+     */
+    template <typename I, typename V, typename O>
+    void plus_cst(const Image<I>& input, const V& val, Image<O>& output);
+
+
     /*! Point-wise addition of image \p rhs in image \p lhs.
      *
      * \param[in] lhs First operand image (subject to addition).
@@ -127,6 +144,13 @@
       impl::plus_(exact(lhs), exact(rhs), exact(output));
     }
 
+    template <typename I, typename V, typename O>
+    void plus_cst(const Image<I>& input, const V& val, Image<O>& output)
+    {
+      mln_precondition(exact(output).domain() = exact(input).domain());
+      plus(input, pw::cst(val) | exact(input).domain(), output); // Calls the previous version.
+    }
+
     template <typename L, typename R>
     void plus_inplace(Image<L>& lhs, const Image<R>& rhs)
     {
@@ -134,6 +158,13 @@
       impl::plus_inplace_(exact(lhs), exact(rhs));
     }
 
+    template <typename I, typename V>
+    void plus_cst_inplace(Image<I>& input, const V& val)
+    {
+      mln_precondition(exact(input).has_data());
+      plus_inplace(input, pw::cst(val) | exact(input).domain()); // Calls the previous version.
+    }
+
 # endif // ! MLN_INCLUDE_ONLY
 
   } // end of namespace mln::arith
Index: img/picasso.pgm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from  Thierry Geraud  <thierry.geraud(a)lrde.epita.fr>
	Add hit-or-miss and p2v ternary+elif functions.
	* tests/morpho_hit_or_miss.cc: New.
	* mln/fun/p2v/elifs.hh: New.
	* mln/fun/p2v/ternary.hh: New.
	* mln/morpho/min.hh: New.
	* mln/morpho/hit_or_miss.hh: New.
	* mln/arith/min.hh: New.
	* mln/value/int_u_sat.hh: New.
	* img/picasso.pgm: New.
	* mln/arith/revert.hh: Fix.
	* mln/morpho/includes.hh: Update.
 img/picasso.pgm             |    0 
 mln/arith/min.hh            |  147 ++++++++++++++++++++++++++
 mln/arith/revert.hh         |    2 
 mln/fun/p2v/elifs.hh        |   84 +++++++++++++++
 mln/fun/p2v/ternary.hh      |  117 +++++++++++++++++++++
 mln/morpho/hit_or_miss.hh   |  243 ++++++++++++++++++++++++++++++++++++++++++++
 mln/morpho/includes.hh      |    4 
 mln/morpho/min.hh           |  121 +++++++++++++++++++++
 mln/value/int_u_sat.hh      |  191 ++++++++++++++++++++++++++++++++++
 tests/morpho_hit_or_miss.cc |   85 +++++++++++++++
 10 files changed, 992 insertions(+), 2 deletions(-)
Index: tests/morpho_hit_or_miss.cc
--- tests/morpho_hit_or_miss.cc	(revision 0)
+++ tests/morpho_hit_or_miss.cc	(revision 0)
@@ -0,0 +1,85 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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 tests/morpho_hit_or_miss.cc
+ *
+ * \brief Test on mln::morpho::hit_or_miss.
+ */
+
+#include <mln/core/image2d_b.hh>
+#include <mln/value/int_u8.hh>
+
+#include <mln/core/win/rectangle2d.hh>
+#include <mln/core/window2d.hh>
+#include <mln/geom/shift.hh>
+#include <mln/set/diff.hh>
+
+#include <mln/io/load_pgm.hh>
+#include <mln/io/save_pgm.hh>
+#include <mln/level/fill.hh>
+#include <mln/level/stretch.hh>
+
+#include <mln/morpho/hit_or_miss.hh>
+
+
+int main()
+{
+  using namespace mln;
+  using value::int_u8;
+
+  window2d win_hit = geom::shift(win::rectangle2d(3, 3),
+				 make::dpoint2d(+1, +1));
+  window2d win_miss = set::diff(win::rectangle2d(5, 5), win_hit);
+
+  {
+    bool hit[] = { 0, 0, 0, 0, 0,
+		   0, 0, 0, 0, 0,
+		   0, 0, 1, 1, 1,
+		   0, 0, 1, 1, 1,
+		   0, 0, 1, 1, 1 };
+    window2d win_hit_ = make::window2d(hit);
+    mln_precondition(win_hit_ = win_hit);
+
+    bool miss[] = { 1, 1, 1, 1, 1,
+		    1, 1, 1, 1, 1,
+		    1, 1, 0, 0, 0,
+		    1, 1, 0, 0, 0,
+		    1, 1, 0, 0, 0 };
+    window2d win_miss_ = make::window2d(miss);
+    mln_precondition(win_miss_ = win_miss);
+  }
+
+  border::thickness = 2;
+
+  image2d_b<int_u8>
+    lena = io::load_pgm("../img/picasso.pgm"),
+    out(lena.domain());
+
+  morpho::hit_or_miss(lena, win_hit, win_miss, out);
+
+  io::save_pgm(out, "out.pgm");
+}
Index: mln/fun/p2v/elifs.hh
--- mln/fun/p2v/elifs.hh	(revision 0)
+++ mln/fun/p2v/elifs.hh	(revision 0)
@@ -0,0 +1,84 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_FUN_P2V_ELIFS_HH
+# define MLN_FUN_P2V_ELIFS_HH
+
+/*! \file mln/fun/p2v/elifs.hh
+ *
+ * \brief FIXME.
+ */
+
+# include <mln/fun/p2v/ternary.hh>
+
+
+namespace mln
+{
+
+  namespace fun
+  {
+
+    namespace p2v
+    {
+
+      template <typename T1, typename N1,
+		typename T2, typename N2,
+		typename O>
+      ternary_<T1, N1,
+	       ternary_<T2, N2, O> >
+      elifs(const Function_p2b<T1>& f_if_1, const Function_p2v<N1>& f_then_1,
+	    const Function_p2b<T2>& f_if_2, const Function_p2v<N2>& f_then_2,
+	    const Function_p2v<O>&  f_otherwise);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+      template <typename T1, typename N1,
+		typename T2, typename N2,
+		typename O>
+      ternary_<T1, N1,
+	       ternary_<T2, N2, O> >
+      elifs(const Function_p2b<T1>& f_if_1, const Function_p2v<N1>& f_then_1,
+	    const Function_p2b<T2>& f_if_2, const Function_p2v<N2>& f_then_2,
+	    const Function_p2v<O>&  f_otherwise)
+      {
+	typedef ternary_<T2, N2, O> T2_N2_O;
+	T2_N2_O f_otherwise_1(f_if_2, f_then_2, f_otherwise);
+	ternary_<T1, N1, T2_N2_O> tmp(f_if_1, f_then_1, f_otherwise_1);
+	return tmp;
+      }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+    } // end of namespace mln::fun::p2v
+
+  } // end of namespace mln::fun
+
+} // end of namespace mln
+
+
+#endif // ! MLN_FUN_P2V_ELIFS_HH
Index: mln/fun/p2v/ternary.hh
--- mln/fun/p2v/ternary.hh	(revision 0)
+++ mln/fun/p2v/ternary.hh	(revision 0)
@@ -0,0 +1,117 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_FUN_P2V_TERNARY_HH
+# define MLN_FUN_P2V_TERNARY_HH
+
+/*! \file mln/fun/p2v/ternary.hh
+ *
+ * \brief FIXME.
+ */
+
+# include <mln/fun/internal/selector.hh>
+
+
+namespace mln
+{
+
+  namespace fun
+  {
+
+    namespace p2v
+    {
+
+      template <typename P, typename T, typename F>
+      struct ternary_
+	: fun::internal::selector_p2_<mln_result(T), ternary_<P,T,F> >::ret
+      {
+	typedef mln_result(T) result;
+
+	ternary_(const Function_p2b<P>& f_pred,
+		 const Function_p2v<T>& f_true,
+		 const Function_p2v<F>& f_false);
+
+	template <typename Pt>
+	result operator()(const Pt& p) const;
+
+      protected:
+	const P f_pred_;
+	const T f_true_;
+	const F f_false_;
+      };
+    
+    
+      template <typename P, typename T, typename F>
+      ternary_<P, T, F>
+      ternary(const Function_p2b<P>& f_pred,
+	      const Function_p2v<T>& f_true,
+	      const Function_p2v<F>& f_false);
+    
+
+# ifndef MLN_INCLUDE_ONLY
+
+      template <typename P, typename T, typename F>
+      ternary_<P,T,F>::ternary_(const Function_p2b<P>& f_pred,
+				const Function_p2v<T>& f_true,
+				const Function_p2v<F>& f_false)
+	: f_pred_(exact(f_pred)),
+	  f_true_(exact(f_true)),
+	  f_false_(exact(f_false))
+      {
+      }
+
+      template <typename P, typename T, typename F>
+      template <typename Pt>
+      mln_result(T)
+	ternary_<P,T,F>::operator()(const Pt& p) const
+      {
+	return f_pred_(p) ? f_true_(p) : f_false_(p);
+      }
+
+
+      template <typename P, typename T, typename F>
+      ternary_<P, T, F>
+      ternary(const Function_p2b<P>& f_pred,
+	      const Function_p2v<T>& f_true,
+	      const Function_p2v<F>& f_false)
+      {
+	ternary_<P, T, F> tmp(exact(f_pred),
+			      exact(f_true),
+			      exact(f_false));
+	return tmp;
+      }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+    } // end of namespace mln::fun::p2v
+
+  } // end of namespace mln::fun
+
+} // end of namespace mln
+
+
+#endif // ! MLN_FUN_P2V_TERNARY_HH
Index: mln/morpho/min.hh
--- mln/morpho/min.hh	(revision 0)
+++ mln/morpho/min.hh	(revision 0)
@@ -0,0 +1,121 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_MORPHO_MIN_HH
+# define MLN_MORPHO_MIN_HH
+
+# include <mln/level/compare.hh>
+# include <mln/logical/and.hh>
+# include <mln/arith/min.hh>
+
+
+namespace mln
+{
+
+  namespace morpho
+  {
+
+    /*! Morphological min: either a logical "and" (if morpho on sets)
+     *  or an arithmetical min (if morpho on functions).
+     */
+    template <typename I, typename J, typename O>
+    void min(const Image<I>& lhs, const Image<J>& rhs,
+	     Image<O>& output);
+
+    /*! Morphological min, inplace version: either a logical "and" (if
+     *  morpho on sets) or an arithmetical min (if morpho on
+     *  functions).
+     */
+    template <typename I, typename J>
+    void min_inplace(Image<I>& lhs, const Image<J>& rhs);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    namespace impl
+    {
+
+      template <typename I, typename J, typename O>
+      void min_(value::binary_kind, // binary => morphology on sets
+		const Image<I>& lhs, const Image<J>& rhs,
+		Image<O>& output)
+      {
+	return logical::and_(lhs, rhs, output);
+      }
+
+      template <typename K, typename I, typename J, typename O>
+      void min_(K, // otherwise => morphology on functions
+		const Image<I>& lhs, const Image<J>& rhs,
+		Image<O>& output)
+      {
+	return arith::min(lhs, rhs, output);
+      }
+
+      // in place
+
+      template <typename I, typename J>
+      void min_inplace_(value::binary_kind, // binary => morphology on sets
+			Image<I>& lhs, const Image<J>& rhs)
+      {
+	return logical::and_inplace(lhs, rhs);
+      }
+
+      template <typename K, typename I, typename J>
+      void min_inplace_(K, // otherwise => morphology on functions
+			Image<I>& lhs, const Image<J>& rhs)
+      {
+	return arith::min_inplace(lhs, rhs);
+      }
+
+    } // end of namespace mln::morpho::impl
+
+
+    // Facades.
+
+    template <typename I, typename J, typename O>
+    void min(const Image<I>& lhs, const Image<J>& rhs, Image<O>& output)
+    {
+      mln_precondition(exact(rhs).domain() = exact(lhs).domain());
+      mln_precondition(exact(output).domain() = exact(lhs).domain());
+      impl::min_(mln_value_kind(I)(), exact(lhs), exact(rhs), output);
+    }
+
+    template <typename I, typename J>
+    void min_inplace(Image<I>& lhs, const Image<J>& rhs)
+    {
+      mln_precondition(exact(rhs).domain() = exact(lhs).domain());
+      impl::min_inplace_(mln_value_kind(I)(), exact(lhs), exact(rhs));
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MORPHO_MIN_HH
Index: mln/morpho/includes.hh
--- mln/morpho/includes.hh	(revision 1062)
+++ mln/morpho/includes.hh	(working copy)
@@ -49,13 +49,15 @@
 # include <mln/border/fill.hh>
 
 # include <mln/geom/sym.hh>
+# include <mln/set/inter.hh>
 
 # include <mln/morpho/dilation.hh>
 # include <mln/morpho/erosion.hh>
 
+# include <mln/morpho/min.hh>
+# include <mln/morpho/complementation.hh>
 # include <mln/morpho/minus.hh>
 # include <mln/morpho/plus.hh>
-# include <mln/morpho/complementation.hh>
 
 
 #endif // ! MLN_MORPHO_INCLUDES_HH
Index: mln/morpho/hit_or_miss.hh
--- mln/morpho/hit_or_miss.hh	(revision 0)
+++ mln/morpho/hit_or_miss.hh	(revision 0)
@@ -0,0 +1,243 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_MORPHO_HIT_OR_MISS_HH
+# define MLN_MORPHO_HIT_OR_MISS_HH
+
+/*! \file mln/morpho/hit_or_miss.hh
+ *
+ * \brief Morphological hit-or-miss.
+ *
+ * \todo Save memory.
+ */
+
+# include <mln/morpho/includes.hh>
+# include <mln/pw/all.hh>
+# include <mln/fun/p2v/ternary.hh>
+
+
+namespace mln
+{
+
+  namespace morpho
+  {
+
+
+    bool constrained_hit_or_miss = true;
+
+
+    /*! Morphological hit-or-miss.
+     *
+     * This operator is HMT_(Bh,Bm) = e_Bh /\ (e_Bm o C). 
+     */
+    template <typename I, typename Wh, typename Wm, typename O>
+    void hit_or_miss(const Image<I>& input,
+		     const Window<Wh>& win_hit, const Window<Wm>& win_miss,
+		     Image<O>& output);
+
+    /*! Morphological hit-or-miss opening.
+     *
+     * This operator is d_(-Bh) o HMT_(Bh,Bm).
+     */
+    template <typename I, typename Wh, typename Wm, typename O>
+    void hit_or_miss_opening(const Image<I>& input,
+			     const Window<Wh>& win_hit, const Window<Wm>& win_miss,
+			     Image<O>& output);
+
+    /*! Morphological hit-or-miss opening of the background.
+     *
+     * This operator is FIXME.
+     */
+    template <typename I, typename Wh, typename Wm, typename O>
+    void hit_or_miss_background_opening(const Image<I>& input,
+					const Window<Wh>& win_hit, const Window<Wm>& win_miss,
+					Image<O>& output);
+
+    /*! Morphological hit-or-miss closing.
+     *
+     * This operator is FIXME.
+     */
+    template <typename I, typename Wh, typename Wm, typename O>
+    void hit_or_miss_closing(const Image<I>& input,
+			     const Window<Wh>& win_hit, const Window<Wm>& win_miss,
+			     Image<O>& output);
+
+    /*! Morphological hit-or-miss closing of the background.
+     *
+     * This operator is FIXME.
+     */
+    template <typename I, typename Wh, typename Wm, typename O>
+    void hit_or_miss_background_closing(const Image<I>& input,
+					const Window<Wh>& win_hit, const Window<Wm>& win_miss,
+					Image<O>& output);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    namespace impl
+    {
+
+      // Preconditions.
+
+      template <typename I, typename Wh, typename Wm, typename O>
+      void hit_or_miss_preconditions_(const Image<I>& input,
+				      const Window<Wh>& win_hit, const Window<Wm>& win_miss,
+				      Image<O>& output)
+      {
+	mln_precondition(exact(output).domain() = exact(input).domain());
+	mln_precondition(set::inter(exact(win_hit), exact(win_miss)).is_empty());
+      }
+
+      // On sets.
+
+      template <typename I, typename Wh, typename Wm, typename O>
+      void hit_or_miss_(value::binary_kind, // binary => morphology on sets
+			const Image<I>& input,
+			const Window<Wh>& win_hit, const Window<Wm>& win_miss,
+			Image<O>& output)
+      {
+	erosion(input, win_hit, output); // output = ero(input)_hit
+
+	O temp_1(exact(input).domain());
+	complementation(input, temp_1); // temp1 = C(input)
+
+	O temp_2(exact(input).domain());
+	erosion(temp_1, win_miss, temp_2); // temp_2 = ero(C(input))_miss
+
+	logical::and_inplace(output, temp_2); // output = ero(input)_hit /\ ero(C(input))_miss
+      }
+
+      // On functions.
+
+      template <typename K,
+		typename I, typename Wh, typename Wm, typename O>
+      void hit_or_miss_(K, // otherwise => morphology on functions
+			const Image<I>& input,
+			const Window<Wh>& win_hit, const Window<Wm>& win_miss,
+			Image<O>& output)
+      {
+	typedef mln_value(O)  V;
+
+	if (constrained_hit_or_miss) // CHMT.
+	  {
+	    if (exact(win_hit).is_centered())
+	      {
+		O ero_fg(exact(input).domain()), dil_bg(exact(input).domain());
+		erosion(input, win_hit,  ero_fg);
+		dilation(input, win_miss, dil_bg);
+		level::fill(output,
+			    fun::p2v::ternary(pw::value(input) = pw::value(ero_fg) && pw::value(dil_bg) < pw::value(input),
+					      pw::value(input) - pw::value(dil_bg),
+					      pw::cst(V::zero)));
+	      }
+	    else if (exact(win_miss).is_centered())
+	      {
+		O ero_bg(exact(input).domain()), dil_fg(exact(input).domain());
+		erosion(input, win_miss, ero_bg);
+		dilation(input, win_hit, dil_fg);
+		level::fill(output,
+			    fun::p2v::ternary(pw::value(input) = pw::value(dil_fg) && pw::value(ero_bg) > pw::value(input),
+					      pw::value(ero_bg) - pw::value(input),
+					      pw::cst(V::zero)));
+	      }
+	    else
+	      level::fill(output, pw::cst(V::zero));
+	  }
+	else // Unconstrained: UHMT.
+	  {
+	    O ero(exact(input).domain()), dil(exact(input).domain());
+	    erosion(input, win_hit, ero);
+	    dilation(input, win_miss, dil);
+	    level::fill(output,
+			fun::p2v::ternary(pw::value(dil) < pw::value(ero),
+					  pw::value(ero) - pw::value(dil),
+					  pw::cst(V::zero)));
+	  }
+      }
+
+    } // end of mln::morpho::impl
+
+
+    template <typename I, typename Wh, typename Wm, typename O>
+    void hit_or_miss(const Image<I>& input,
+		     const Window<Wh>& win_hit, const Window<Wm>& win_miss,
+		     Image<O>& output)
+    {
+      impl::hit_or_miss_preconditions_(input, win_hit, win_miss, output);
+      impl::hit_or_miss_(mln_value_kind(I)(), input, win_hit, win_miss, output);
+    }
+
+    template <typename I, typename Wh, typename Wm, typename O>
+    void hit_or_miss_opening(const Image<I>& input,
+			     const Window<Wh>& win_hit, const Window<Wm>& win_miss,
+			     Image<O>& output)
+    {
+      impl::hit_or_miss_preconditions_(input, win_hit, win_miss, output);
+
+      O temp(exact(input).domain());
+      hit_or_miss(input, win_hit, win_miss, temp);
+      dilation(temp, geom::sym(win_hit), output);
+    }
+
+    template <typename I, typename Wh, typename Wm, typename O>
+    void hit_or_miss_background_opening(const Image<I>& input,
+					const Window<Wh>& win_hit, const Window<Wm>& win_miss,
+					Image<O>& output)
+    {
+      impl::hit_or_miss_preconditions_(input, win_hit, win_miss, output);
+      hit_or_miss_opening(input, win_miss, win_hit, output);
+    }
+
+    template <typename I, typename Wh, typename Wm, typename O>
+    void hit_or_miss_closing(const Image<I>& input,
+			     const Window<Wh>& win_hit, const Window<Wm>& win_miss,
+			     Image<O>& output)
+    {
+      impl::hit_or_miss_preconditions_(input, win_hit, win_miss, output);
+      I temp(input.domain());
+      complementation(input, temp);
+      hit_or_miss_opening(temp, win_hit, win_miss, output);
+      complementation_inplace(output);
+    }
+
+    template <typename I, typename Wh, typename Wm, typename O>
+    void hit_or_miss_background_closing(const Image<I>& input,
+					const Window<Wh>& win_hit, const Window<Wm>& win_miss,
+					Image<O>& output)
+    {
+      impl::hit_or_miss_preconditions_(input, win_hit, win_miss, output);
+      hit_or_miss_closing(input, win_miss, win_hit, output);
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MORPHO_HIT_OR_MISS_HH
Index: mln/arith/min.hh
--- mln/arith/min.hh	(revision 0)
+++ mln/arith/min.hh	(revision 0)
@@ -0,0 +1,147 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_ARITH_MIN_HH
+# define MLN_ARITH_MIN_HH
+
+/*! \file mln/arith/min.hh
+ *
+ * \brief Point-wise min between images.
+ */
+
+# include <mln/core/concept/image.hh>
+
+
+namespace mln
+{
+
+  namespace arith
+  {
+
+    /*! Point-wise min of images \p lhs and \p rhs.
+     *
+     * \param[in] lhs First operand image.
+     * \param[in] rhs Second operand image.
+     * \param[out] output The result image.
+     *
+     * \pre \p output.domain = \p lhs.domain = \p rhs.domain
+     */
+    template <typename L, typename R, typename O>
+    void min(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output);
+
+
+    /*! Point-wise min of image \p lhs in image \p rhs.
+     *
+     * \param[in,out] lhs First operand image.
+     * \param[in] rhs Second operand image.
+     *
+     * This substraction performs: \n
+     *   for all p of rhs.domain \n
+     *     if rhs(p) < lhs(p) \n
+     *       lhs(p) = rhs(p)
+     *
+     * \pre \p rhs.domain <= \p lhs.domain
+     */
+    template <typename L, typename R>
+    void min_inplace(Image<L>& lhs, const Image<R>& rhs);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    namespace impl
+    {
+
+      template <typename L, typename R, typename O>
+      void min_(const Image<L>& lhs_, const Image<R>& rhs_, Image<O>& output_)
+      {
+	const L& lhs = exact(lhs_);
+	const R& rhs = exact(rhs_);
+	O& output = exact(output_);
+	mln_piter(L) p(lhs.domain());
+	for_all(p)
+	  output(p) = lhs(p) < rhs(p) ? lhs(p) : rhs(p);
+      }
+
+      template <typename L, typename R, typename O>
+      void min_(const Fast_Image<L>& lhs, const Fast_Image<R>& rhs, Fast_Image<O>& output)
+      {
+	mln_pixter(const L) lp(exact(lhs));
+	mln_pixter(const R) rp(exact(rhs));
+	mln_pixter(O)       op(exact(output));
+	for_all_3(lp, rp, op)
+	  op.val() = lp.val() < rp.val() ? lp.val() : rp.val();
+      }
+
+      template <typename L, typename R>
+      void min_inplace_(Image<L>& lhs_, const Image<R>& rhs_)
+      {
+	L& lhs = exact(lhs_);
+	const R& rhs = exact(rhs_);
+	mln_piter(R) p(rhs.domain());
+	for_all(p)
+	  if (rhs(p) < lhs(p))
+	    lhs(p) = rhs(p);
+      }
+
+      template <typename L, typename R>
+      void min_inplace_(Fast_Image<L>& lhs, const Fast_Image<R>& rhs)
+      {
+	mln_pixter(L) lp(exact(lhs));
+	mln_pixter(const R) rp(exact(rhs));
+	for_all_2(rp, lp)
+	  if (rp.val() < lp.val())
+	    lp.val() = rp.val();
+      }
+
+    } // end of namespace mln::arith::impl
+
+
+    // Facades.
+
+    template <typename L, typename R, typename O>
+    void min(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output)
+    {
+      mln_precondition(exact(rhs).domain() = exact(lhs).domain());
+      mln_precondition(exact(output).domain() = exact(lhs).domain());
+      impl::min_(exact(lhs), exact(rhs), exact(output));
+    }
+
+    template <typename L, typename R>
+    void min_inplace(Image<L>& lhs, const Image<R>& rhs)
+    {
+      mln_precondition(exact(rhs).domain() <= exact(lhs).domain());
+      impl::min_inplace_(exact(lhs), exact(rhs));
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::arith
+
+} // end of namespace mln
+
+
+#endif // ! MLN_ARITH_MIN_HH
Index: mln/arith/revert.hh
--- mln/arith/revert.hh	(revision 1062)
+++ mln/arith/revert.hh	(working copy)
@@ -95,7 +95,7 @@
 	mln_pixter(const I) ip(exact(input));
 	mln_pixter(O)       op(exact(output));
 	for_all_2(ip, op)
-	  op.val() = mln_min(V) + (mln_max(V) - op.val());
+	  op.val() = mln_min(V) + (mln_max(V) - ip.val());
       }
 
     } // end of namespace mln::arith::impl
Index: mln/value/int_u_sat.hh
--- mln/value/int_u_sat.hh	(revision 0)
+++ mln/value/int_u_sat.hh	(revision 0)
@@ -0,0 +1,191 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_VALUE_INT_U_SAT_HH
+# define MLN_VALUE_INT_U_SAT_HH
+
+/*! \file mln/value/int_u_sat.hh
+ *
+ * \brief Define a generic class for unsigned integers with saturation
+ * behavior.
+ */
+
+# include <mln/metal/math.hh>
+# include <mln/value/internal/value_like.hh>
+# include <mln/value/internal/encoding.hh>
+# include <mln/value/props.hh>
+# include <mln/debug/format.hh>
+
+
+namespace mln
+{
+
+  namespace value
+  {
+
+
+    /*! \brief Unsigned integer value class with saturation behavior.
+     *
+     * The parameter is \c n the number of encoding bits.
+     */
+    template <unsigned n>
+    struct int_u_sat
+      : public internal::value_like_< typename internal::encoding_unsigned_<n>::ret,
+				      int_u_sat<n> >
+    {
+    protected:
+      typedef internal::value_like_< typename internal::encoding_unsigned_<n>::ret,
+				     int_u_sat<n> > super;
+
+    public:
+
+      /// Encoding associated type.
+      typedef typename super::enc enc;
+
+      /// Constructor without argument.
+      int_u_sat();
+
+      /// Constructor from an integer.
+      int_u_sat(int i);
+
+      /// Assignment from an integer.
+      int_u_sat<n>& operator=(int i);
+
+      /// Zero value.
+      static const int_u_sat<n> zero;
+
+      /// Unit value.
+      static const int_u_sat<n> one;
+
+      /// Self addition.
+      int_u_sat<n>& operator+=(int i);
+
+      /// Self subtraction.
+      int_u_sat<n>& operator-=(int i);
+    };
+
+
+    // Safety.
+    template <> struct int_u_sat<0>;
+    template <> struct int_u_sat<1>;
+
+
+
+    template <unsigned n>
+    struct props< int_u_sat<n> >
+    {
+      static const std::size_t card_ = metal::pow<2, n>::value;
+      static const int_u_sat<n> min() { return 0; }
+      static const int_u_sat<n> max() { return card_ - 1; }
+      static const unsigned nbits = n;
+      typedef data_kind kind;
+      typedef float sum;
+    };
+
+
+
+    /*! \brief Print a saturated unsigned integer \p i into the output
+     *  stream \p ostr.
+     *
+     * \param[in,out] ostr An output stream.
+     * \param[in] i A saturated unsigned integer.
+     *
+     * \return The modified output stream \p ostr.
+     */
+    template <unsigned n>
+    std::ostream& operator<<(std::ostream& ostr, const int_u_sat<n>& i);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <unsigned n>
+    int_u_sat<n>::int_u_sat()
+    {
+    }
+
+    template <unsigned n>
+    int_u_sat<n>::int_u_sat(int i)
+    {
+      if (i < 0)
+	this->v_ = enc(0);
+      else if (i > mln_max(enc))
+	this->v_ = mln_max(enc);
+      else
+	this->v_ = enc(i);
+    }
+
+    template <unsigned n>
+    int_u_sat<n>&
+    int_u_sat<n>::operator=(int i)
+    {
+      if (i < 0)
+	this->v_ = enc(0);
+      else if (i > mln_max(enc))
+	this->v_ = mln_max(enc);
+      else
+	this->v_ = enc(i);
+      return *this;
+    }
+
+    template <unsigned n>
+    int_u_sat<n>&
+    int_u_sat<n>::operator+=(int i)
+    {
+      int v = int(this->v_) + i;
+      *this = v;
+      return *this;
+    }
+
+    template <unsigned n>
+    int_u_sat<n>&
+    int_u_sat<n>::operator-=(int i)
+    {
+      int v = int(this->v_) - i;
+      *this = v;
+      return *this;
+    }
+
+    template <unsigned n>
+    const int_u_sat<n> int_u_sat<n>::zero = 0;
+
+    template <unsigned n>
+    const int_u_sat<n> int_u_sat<n>::one = 1;
+
+    template <unsigned n>
+    std::ostream& operator<<(std::ostream& ostr, const int_u_sat<n>& i)
+    {
+      return ostr << debug::format(i.to_equiv());
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::value
+
+} // end of namespace mln
+
+
+#endif // ! MLN_VALUE_INT_U_SAT_HH
Index: img/picasso.pgm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: img/picasso.pgm
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from  Thierry Geraud  <thierry.geraud(a)lrde.epita.fr>
	Make operations on windows more explicit.
	* mln/convert/to_std_set.hh: New.
	* mln/geom/sym.hh: New.
	* mln/geom/shift.hh: New.
	* mln/set: New directory.
	* mln/set/inter.hh: New.
	* mln/set/diff.hh: New.
	* mln/set/union.hh: New.
	* mln/set/sym_diff.hh: New.
	* mln/convert/to_image.hh: Typo.
	* mln/convert/to_window.hh (to_window): New overload.
	* mln/convert/to_dpoint.hh: Typo.
	* mln/core/w_window.hh (sym_): Rename as...
	(sym): ...this and update.
	* mln/core/window.hh: Likewise.
	(operator-): Remove the unary version.
	(operator+, operator-): Remove; now handle by...
	* mln/geom/shift.hh (shift): ...this.
	* mln/core/concept/weighted_window.hh: Update.
	(operator-): Remove.
	* mln/core/concept/window.hh: Likewise.
	* mln/core/concept/doc/weighted_window.hh,
	* mln/core/concept/doc/window.hh,
	* mln/core/win/vline2d.hh,
	* mln/core/win/hline2d.hh,
	* mln/core/win/rectangle2d.hh,
	* mln/morpho/includes.hh,
	* mln/morpho/closing.hh,
	* mln/morpho/opening.hh,
	* mln/level/was.median.hh,
	* mln/level/median.hh,
	* mln/level/fast_median.hh,
	* tests/rectangle2d.cc: Update.
	* mln/core/concept/value.hh: Fix warning.
 mln/convert/to_dpoint.hh                |    2 
 mln/convert/to_image.hh                 |    2 
 mln/convert/to_std_set.hh               |   75 ++++++++++++++++++++++++++++
 mln/convert/to_window.hh                |   19 +++++++
 mln/core/concept/doc/weighted_window.hh |    4 -
 mln/core/concept/doc/window.hh          |    4 -
 mln/core/concept/value.hh               |    2 
 mln/core/concept/weighted_window.hh     |   10 ---
 mln/core/concept/window.hh              |   24 ++-------
 mln/core/w_window.hh                    |   14 +++--
 mln/core/win/hline2d.hh                 |    6 +-
 mln/core/win/rectangle2d.hh             |    6 +-
 mln/core/win/vline2d.hh                 |    6 +-
 mln/core/window.hh                      |   70 +++-----------------------
 mln/geom/shift.hh                       |   73 ++++++++++++++++++++++++++++
 mln/geom/sym.hh                         |   68 ++++++++++++++++++++++++++
 mln/level/fast_median.hh                |   14 +++--
 mln/level/median.hh                     |   14 +++--
 mln/level/was.median.hh                 |   12 ++--
 mln/morpho/closing.hh                   |    2 
 mln/morpho/includes.hh                  |    2 
 mln/morpho/opening.hh                   |    2 
 mln/set/diff.hh                         |   80 ++++++++++++++++++++++++++++++
 mln/set/inter.hh                        |   83 ++++++++++++++++++++++++++++++++
 mln/set/sym_diff.hh                     |   79 ++++++++++++++++++++++++++++++
 mln/set/union.hh                        |   82 +++++++++++++++++++++++++++++++
 tests/rectangle2d.cc                    |    3 -
 27 files changed, 630 insertions(+), 128 deletions(-)
Index: tests/rectangle2d.cc
--- tests/rectangle2d.cc	(revision 1061)
+++ tests/rectangle2d.cc	(working copy)
@@ -31,6 +31,7 @@
  */
 
 #include <mln/core/win/rectangle2d.hh>
+#include <mln/geom/sym.hh>
 
 
 
@@ -43,7 +44,7 @@
 
   mln_assertion(rec.is_centered());
   mln_assertion(rec.is_symmetric());
-  mln_assertion(rec = -rec);
+  mln_assertion(rec = geom::sym(rec));
   mln_assertion(rec.ndpoints() = h * w);
 }
 
Index: mln/convert/to_image.hh
--- mln/convert/to_image.hh	(revision 1061)
+++ mln/convert/to_image.hh	(working copy)
@@ -30,7 +30,7 @@
 
 /*! \file mln/convert/to_image.hh
  *
- * \brief Convertions to mln::Image.
+ * \brief Conversions to mln::Image.
  */
 
 # include <mln/core/image2d_b.hh>
Index: mln/convert/to_std_set.hh
--- mln/convert/to_std_set.hh	(revision 0)
+++ mln/convert/to_std_set.hh	(revision 0)
@@ -0,0 +1,75 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_CONVERT_TO_STD_SET_HH
+# define MLN_CONVERT_TO_STD_SET_HH
+
+/*! \file mln/convert/to_std_set.hh
+ *
+ * \brief Conversions to std::set.
+ */
+
+# include <set>
+# include <algorithm>
+# include <iterator>
+
+# include <mln/core/window.hh>
+
+
+namespace mln
+{
+
+  namespace convert
+  {
+
+    /// Convert a window \p win into a std::set of delta-points.
+    template <typename W>
+    std::set<mln_dpoint(W)> to_std_set(const Window<W>& win);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename W>
+    std::set<mln_dpoint(W)> to_std_set(const Window<W>& win)
+    {
+      typedef mln_dpoint(W) D;
+      typedef mln_point(D)  P;
+      std::set<D> s;
+      mln_qiter(W) q(exact(win), P::zero);
+      for_all(q)
+	s.insert(q - P::zero);
+      return s;
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::convert
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CONVERT_TO_STD_SET_HH
Index: mln/convert/to_window.hh
--- mln/convert/to_window.hh	(revision 1061)
+++ mln/convert/to_window.hh	(working copy)
@@ -33,10 +33,14 @@
  * \brief Conversions to mln::window.
  */
 
+# include <set>
+ 
+# include <mln/core/concept/dpoint.hh>
 # include <mln/core/concept/neighborhood.hh>
 # include <mln/core/window.hh>
 # include <mln/pw/image.hh>
 # include <mln/pw/cst.hh>
+# include <mln/metal/is_a.hh>
 
 
 namespace mln
@@ -57,6 +61,10 @@
     template <typename S, typename F>
     window<mln_dpoint(S)> to_window(const Point_Set<S>& pset);
 
+    /// Convert an std::set \p s of delta-points into a window.
+    template <typename D>
+    window<D> to_window(const std::set<D>& s);
+
 
 # ifndef MLN_INCLUDE_ONLY
 
@@ -95,6 +103,17 @@
       return to_window(pw::cst(true) | pset);
     }
 
+    template <typename D>
+    window<D> to_window(const std::set<D>& s)
+    {
+      mln::metal::is_a<D, Dpoint>::check();
+      window<D> win;
+      for (typename std::set<D>::const_iterator i = s.begin();
+	   i != s.end(); ++i)
+	win.insert(*i);
+      return win;
+    }
+
 # endif // ! MLN_INCLUDE_ONLY
 
   } // end of namespace mln::convert
Index: mln/convert/to_dpoint.hh
--- mln/convert/to_dpoint.hh	(revision 1061)
+++ mln/convert/to_dpoint.hh	(working copy)
@@ -30,7 +30,7 @@
 
 /*! \file mln/convert/to_dpoint.hh
  *
- * \brief Convertions to mln::Dpoint.
+ * \brief Conversions to mln::Dpoint.
  */
 
 # include <mln/core/concept/generalized_point.hh>
Index: mln/geom/sym.hh
--- mln/geom/sym.hh	(revision 0)
+++ mln/geom/sym.hh	(revision 0)
@@ -0,0 +1,68 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_GEOM_SYM_HH
+# define MLN_GEOM_SYM_HH
+
+/*! \file mln/geom/sym.hh
+ *
+ * \brief Give the symmetrical object.
+ */
+
+# include <mln/core/concept/window.hh>
+
+
+
+namespace mln
+{
+
+  namespace geom
+  {
+
+    /*! \brief Give the symmetrical window of \p win.
+     */
+    template <typename W>
+    W sym(const Window<W>& win);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename W>
+    W sym(const Window<W>& win)
+    {
+      W tmp = exact(win);
+      return tmp.sym();
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::geom
+
+} // end of namespace mln
+
+
+#endif // ! MLN_GEOM_SYM_HH
Index: mln/geom/shift.hh
--- mln/geom/shift.hh	(revision 0)
+++ mln/geom/shift.hh	(revision 0)
@@ -0,0 +1,73 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_GEOM_SHIFT_HH
+# define MLN_GEOM_SHIFT_HH
+
+/*! \file mln/geom/shift.hh
+ *
+ * \brief Shift.
+ */
+
+# include <mln/core/window.hh>
+
+
+
+namespace mln
+{
+
+  namespace geom
+  {
+
+    /// Shift a window \p win with a delta-point \p dp.
+    template <typename W>
+    window<mln_dpoint(W)>
+    shift(const Window<W>& win, const mln_dpoint(W)& dp);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename W>
+    window<mln_dpoint(W)>
+    shift(const Window<W>& win, const mln_dpoint(W)& dp)
+    {
+      typedef mln_point(W) P;
+      window<mln_dpoint(W)> tmp;
+      mln_qiter(W) q(win, P::zero);
+      for_all(q)
+	tmp.insert(convert::to_dpoint(q) + dp);
+      return tmp;
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::geom
+
+} // end of namespace mln
+
+
+#endif // ! MLN_GEOM_SHIFT_HH
Index: mln/core/w_window.hh
--- mln/core/w_window.hh	(revision 1061)
+++ mln/core/w_window.hh	(working copy)
@@ -104,8 +104,8 @@
     const mln::window<D>& win() const;
 
 
-    /// Give the symmetrical w_window.
-    w_window<D,W> sym_() const;
+    /// Apply a central symmetry to the target window.
+    w_window<D,W>& sym();
 
   protected:
     
@@ -252,11 +252,13 @@
   }
 
   template <typename D, typename W>
-  w_window<D,W>
-  w_window<D,W>::sym_() const
+  w_window<D,W>&
+  w_window<D,W>::sym()
   {
-    w_window<D,W> tmp(*this);
-    tmp.win_ = - this->win_;
+    w_window<D,W> tmp;
+    for (unsigned i = 0; i < this->ndpoints(); ++i)
+      tmp.insert(this->w(i), this->dp(i));
+    *this = tmp;
     return *this;
   }
 
Index: mln/core/window.hh
--- mln/core/window.hh	(revision 1061)
+++ mln/core/window.hh	(working copy)
@@ -40,6 +40,7 @@
 # include <mln/core/box.hh>
 
 # include <mln/convert/to_dpoint.hh>
+# include <mln/geom/sym.hh>
 
 
 namespace mln
@@ -87,8 +88,8 @@
     /// Insert a delta-point \p dp.
     window<D>& insert(const D& dp);
 
-    /// Give the symmetrical window.
-    window<D> sym_() const;
+    /// Apply a central symmetry to the target window.
+    window<D>& sym();
 
   protected:
     
@@ -96,24 +97,6 @@
   };
 
 
-  // FIXME: Move both ops below to mln/core/concept/window.hh
-
-  /// Shift a window \p win with a delta-point \p dp.
-  template <typename W>
-  window<mln_dpoint(W)> operator+(const Window<W>& win,
-				  const mln_dpoint(W)& dp);
-
-  /// Shift a window \p win with the delta-point (-\p dp).
-  template <typename W>
-  window<mln_dpoint(W)> operator-(const Window<W>& win,
-				  const mln_dpoint(W)& dp);
-
-  /// Substract \p rhs from \p lhs.
-  // FIXME: Give details!
-  template <typename Wl, typename Wr>
-  window<mln_dpoint(Wl)> operator-(const Window<Wl>& lhs,
-				   const Window<Wr>& rhs);
-
 
 
 # ifndef MLN_INCLUDE_ONLY
@@ -128,7 +111,7 @@
   template <typename D>
   bool window<D>::is_symmetric() const
   {
-    return this->sym_() = *this;
+    return geom::sym(*this) = *this;
   }
 
   template <typename D>
@@ -141,52 +124,15 @@
   }
 
   template <typename D>
-  window<D>
-  window<D>::sym_() const
+  window<D>&
+  window<D>::sym()
   {
     window<D> tmp;
     const unsigned n = this->ndpoints();
     for (unsigned i = 0; i < n; ++i)
       tmp.insert(- this->dp(i));
-    return tmp;
-  }
-
-
-  // operators
-
-  template <typename W>
-  window<mln_dpoint(W)> operator+(const Window<W>& win,
-				  const mln_dpoint(W)& dp)
-  {
-    typedef mln_point(W) P;
-    window<mln_dpoint(W)> tmp;
-    mln_qiter(W) q(win, P::zero);
-    for_all(q)
-      tmp.insert(convert::to_dpoint(q) + dp);
-    return tmp;
-  }
-
-  template <typename W>
-  window<mln_dpoint(W)> operator-(const Window<W>& win,
-				  const mln_dpoint(W)& dp)
-  {
-    return win + (-dp);
-  }
-
-  template <typename W, typename Wr>
-  window<mln_dpoint(W)> operator-(const Window<W>& lhs,
-				  const Window<Wr>& rhs)
-  {
-    typedef mln_point(W) P;
-    window<mln_dpoint(W)> tmp;
-    mln_qiter(W) q(lhs, P::zero);
-    for_all(q)
-      {
-	mln_dpoint(W) dp = convert::to_dpoint(q);
-	if (! exact(rhs).has(dp))
-	  tmp.insert(dp);
-      }
-    return tmp;
+    *this = tmp;
+    return *this;
   }
 
 # endif // ! MLN_INCLUDE_ONLY
Index: mln/core/concept/weighted_window.hh
--- mln/core/concept/weighted_window.hh	(revision 1061)
+++ mln/core/concept/weighted_window.hh	(working copy)
@@ -58,7 +58,7 @@
       typedef weight;
       typedef window;
 
-      E sym_() const;
+      E& sym();
     */
 
     /// Test if the weighted window is empty; final method.
@@ -107,19 +107,13 @@
     typedef mln_fwd_qiter(E) fwd_qiter;
     typedef mln_bkd_qiter(E) bkd_qiter;
 
-    E (E::*m1)() const = & E::sym_;
+    E& (E::*m1)() = & E::sym;
     m1 = 0;
 
     const window& (E::*m2)() const = & E::win;
     m2 = 0;
   }
 
-  template <typename W>
-  W operator-(const Weighted_Window<W>& rhs)
-  {
-    return exact(rhs).sym_();
-  }
-
 # endif // ! MLN_INCLUDE_ONLY
 
 } // end of namespace mln
Index: mln/core/concept/window.hh
--- mln/core/concept/window.hh	(revision 1061)
+++ mln/core/concept/window.hh	(working copy)
@@ -39,6 +39,7 @@
 namespace mln
 {
 
+
   /*! \brief Base class for implementation classes that are windows.
    *
    * \see mln::doc::Window for a complete documentation of this class
@@ -61,7 +62,7 @@
 
       unsigned delta() const;
 
-      E sym_() const;
+      E& sym();
     */
 
   protected:
@@ -69,22 +70,17 @@
   };
 
 
-  /*! \brief Compute the symmetrical window of \p rhs.
-   *
-   * \relates mln::Window
-   */
-  template <typename W>
-  W operator-(const Window<W>& rhs);
-
-
   /*! \brief Equality comparison between windows \p lhs and \p rhs.
    *
    * \relates mln::Window
+   *
+   * \todo Move into mln/set/compare.hh and delegate to replace this special impl.
    */
   template <typename Wl, typename Wr>
   bool operator=(const Window<Wl>& lhs, const Window<Wr>& rhs);
 
 
+
 # ifndef MLN_INCLUDE_ONLY
 
   template <typename E>
@@ -105,14 +101,8 @@
     m3 = 0;
     unsigned (E::*m4)() const = & E::delta;
     m4 = 0;
-    E (E::*m_)() const = & E::sym_;
-    m_ = 0;
-  }
-
-  template <typename W>
-  W operator-(const Window<W>& rhs)
-  {
-    return exact(rhs).sym_();
+    E& (E::*m5)() = & E::sym;
+    m5 = 0;
   }
 
   template <typename Wl, typename Wr>
Index: mln/core/concept/doc/weighted_window.hh
--- mln/core/concept/doc/weighted_window.hh	(revision 1061)
+++ mln/core/concept/doc/weighted_window.hh	(working copy)
@@ -89,9 +89,9 @@
        */
       const window& win() const;
 
-      /*! \brief Give the symmetrical weighted_window.
+      /*! \brief Apply a central symmetry to the target weighted window.
        */
-      E sym_() const;
+      E& sym();
     };
 
   } // end of namespace mln::doc
Index: mln/core/concept/doc/window.hh
--- mln/core/concept/doc/window.hh	(revision 1061)
+++ mln/core/concept/doc/window.hh	(working copy)
@@ -81,9 +81,9 @@
        */
       unsigned delta() const;
 
-      /*! \brief Give the symmetrical window.
+      /*! \brief Apply a central symmetry to the target window.
        */
-      E sym_() const;
+      E& sym();
     };
 
   } // end of namespace mln::doc
Index: mln/core/concept/value.hh
--- mln/core/concept/value.hh	(revision 1061)
+++ mln/core/concept/value.hh	(working copy)
@@ -115,7 +115,7 @@
 
       template <typename T, typename S>
       typename S::equiv
-      cast_(const T& dummy, const Value<S>& src)
+      cast_(const T&, const Value<S>& src)
       {
 	return exact(src);
       }
Index: mln/core/win/vline2d.hh
--- mln/core/win/vline2d.hh	(revision 1061)
+++ mln/core/win/vline2d.hh	(working copy)
@@ -108,8 +108,8 @@
        */
       unsigned delta() const;
 
-      /// Get the symmetrical window.
-      vline2d sym_() const;
+      /// Apply a central symmetry to the target window.
+      vline2d& sym();
 
     protected:
       unsigned length_;
@@ -161,7 +161,7 @@
       return length_ / 2;
     }
 
-    vline2d vline2d::sym_() const
+    vline2d& vline2d::sym()
     {
       return *this;
     }
Index: mln/core/win/hline2d.hh
--- mln/core/win/hline2d.hh	(revision 1061)
+++ mln/core/win/hline2d.hh	(working copy)
@@ -106,8 +106,8 @@
        */
       unsigned delta() const;
 
-      /// Get the symmetrical window.
-      hline2d sym_() const;
+      /// Apply a central symmetry to the target window.
+      hline2d& sym();
 
     protected:
       unsigned length_;
@@ -159,7 +159,7 @@
       return length_ / 2;
     }
 
-    hline2d hline2d::sym_() const
+    hline2d& hline2d::sym()
     {
       return *this;
     }
Index: mln/core/win/rectangle2d.hh
--- mln/core/win/rectangle2d.hh	(revision 1061)
+++ mln/core/win/rectangle2d.hh	(working copy)
@@ -111,8 +111,8 @@
        */
       unsigned delta() const;
 
-      /// Get the symmetrical window.
-      rectangle2d sym_() const;
+      /// Apply a central symmetry to the target window.
+      rectangle2d& sym();
 
     protected:
       unsigned height_, width_;
@@ -171,7 +171,7 @@
       return width_ > height_ ? width_ / 2 : height_ / 2;
     }
 
-    rectangle2d rectangle2d::sym_() const
+    rectangle2d& rectangle2d::sym()
     {
       return *this;
     }
Index: mln/set/inter.hh
--- mln/set/inter.hh	(revision 0)
+++ mln/set/inter.hh	(revision 0)
@@ -0,0 +1,83 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_SET_INTER_HH
+# define MLN_SET_INTER_HH
+
+/*! \file mln/set/inter.hh
+ *
+ * \brief Several routines to compute the intersection between a
+ * couple of sets.
+ */
+
+# include <mln/convert/to_std_set.hh>
+# include <mln/convert/to_window.hh>
+# include <mln/metal/equal.hh>
+
+
+
+namespace mln
+{
+
+  namespace set
+  {
+
+    /*! \brief Intersection between a couple of windows.
+     *
+     * \relates mln::Window
+     */
+    template <typename Wl, typename Wr>
+    window<mln_dpoint(Wl)>
+    inter(const Window<Wl>& lhs, const Window<Wr>& rhs);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename Wl, typename Wr>
+    window<mln_dpoint(Wl)>
+    inter(const Window<Wl>& lhs, const Window<Wr>& rhs)
+    {
+      mln::metal::equal<mln_dpoint(Wl), mln_dpoint(Wr)>::check();
+      typedef mln_dpoint(Wl) D;
+      std::set<D>
+	sl = convert::to_std_set(lhs),
+	sr = convert::to_std_set(rhs),
+	s;
+      std::set_intersection(sl.begin(), sl.end(),
+			    sr.begin(), sr.end(),
+			    std::inserter(s, s.begin()));
+      return convert::to_window(s);
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::set
+
+} // end of namespace mln
+
+
+#endif // ! MLN_SET_INTER_HH
Index: mln/set/diff.hh
--- mln/set/diff.hh	(revision 0)
+++ mln/set/diff.hh	(revision 0)
@@ -0,0 +1,80 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_SET_DIFF_HH
+# define MLN_SET_DIFF_HH
+
+/*! \file mln/set/diff.hh
+ *
+ * \brief Set theoretic difference (non-symmetrical) of a couple of
+ * sets.
+ */
+
+# include <mln/convert/to_std_set.hh>
+# include <mln/convert/to_window.hh>
+# include <mln/metal/equal.hh>
+
+
+
+namespace mln
+{
+
+  namespace set
+  {
+
+    /// Set theoretic difference of \p lhs and \p rhs.
+    template <typename Wl, typename Wr>
+    window<mln_dpoint(Wl)>
+    diff(const Window<Wl>& lhs, const Window<Wr>& rhs);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename Wl, typename Wr>
+    window<mln_dpoint(Wl)>
+    diff(const Window<Wl>& lhs, const Window<Wr>& rhs)
+    {
+      mln::metal::equal<mln_dpoint(Wl), mln_dpoint(Wr)>::check();
+      typedef mln_dpoint(Wl) D;
+      std::set<D>
+	sl = convert::to_std_set(lhs),
+	sr = convert::to_std_set(rhs),
+	s;
+      std::set_difference(sl.begin(), sl.end(),
+			  sr.begin(), sr.end(),
+			  std::inserter(s, s.begin()));
+      return convert::to_window(s);
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::set
+
+} // end of namespace mln
+
+
+#endif // ! MLN_SET_DIFF_HH
Index: mln/set/union.hh
--- mln/set/union.hh	(revision 0)
+++ mln/set/union.hh	(revision 0)
@@ -0,0 +1,82 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_SET_UNION_HH
+# define MLN_SET_UNION_HH
+
+/*! \file mln/set/union.hh
+ *
+ * \brief Several routines to compute the union of a couple of sets.
+ */
+
+# include <mln/convert/to_std_set.hh>
+# include <mln/convert/to_window.hh>
+# include <mln/metal/equal.hh>
+
+
+
+namespace mln
+{
+
+  namespace set
+  {
+
+    /*! \brief Union of a couple of windows.
+     *
+     * \relates mln::Window
+     */
+    template <typename Wl, typename Wr>
+    window<mln_dpoint(Wl)>
+    union(const Window<Wl>& lhs, const Window<Wr>& rhs);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename Wl, typename Wr>
+    window<mln_dpoint(Wl)>
+    union(const Window<Wl>& lhs, const Window<Wr>& rhs)
+    {
+      mln::metal::equal<mln_dpoint(Wl), mln_dpoint(Wr)>::check();
+      typedef mln_dpoint(Wl) D;
+      std::set<D>
+	sl = convert::to_std_set(lhs),
+	sr = convert::to_std_set(rhs),
+	s;
+      std::set_union(sl.begin(), sl.end(),
+		     sr.begin(), sr.end(),
+		     std::inserter(s, s.begin()));
+      return convert::to_window(s);
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::set
+
+} // end of namespace mln
+
+
+#endif // ! MLN_SET_UNION_HH
Index: mln/set/sym_diff.hh
--- mln/set/sym_diff.hh	(revision 0)
+++ mln/set/sym_diff.hh	(revision 0)
@@ -0,0 +1,79 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_SET_SYM_DIFF_HH
+# define MLN_SET_SYM_DIFF_HH
+
+/*! \file mln/set/sym_diff.hh
+ *
+ * \brief Set theoretic symmetrical difference of a couple of sets.
+ */
+
+# include <mln/convert/to_std_set.hh>
+# include <mln/convert/to_window.hh>
+# include <mln/metal/equal.hh>
+
+
+
+namespace mln
+{
+
+  namespace set
+  {
+
+    /// Set theoretic symmetrical difference of \p lhs and \p rhs.
+    template <typename Wl, typename Wr>
+    window<mln_dpoint(Wl)>
+    sym_diff(const Window<Wl>& lhs, const Window<Wr>& rhs);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename Wl, typename Wr>
+    window<mln_dpoint(Wl)>
+    sym_diff(const Window<Wl>& lhs, const Window<Wr>& rhs)
+    {
+      mln::metal::equal<mln_dpoint(Wl), mln_dpoint(Wr)>::check();
+      typedef mln_dpoint(Wl) D;
+      std::set<D>
+	sl = convert::to_std_set(lhs),
+	sr = convert::to_std_set(rhs),
+	s;
+      std::set_symmetric_difference(sl.begin(), sl.end(),
+				    sr.begin(), sr.end(),
+				    std::inserter(s, s.begin()));
+      return convert::to_window(s);
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::set
+
+} // end of namespace mln
+
+
+#endif // ! MLN_SET_SYM_DIFF_HH
Index: mln/morpho/includes.hh
--- mln/morpho/includes.hh	(revision 1061)
+++ mln/morpho/includes.hh	(working copy)
@@ -48,6 +48,8 @@
 # include <mln/border/resize.hh>
 # include <mln/border/fill.hh>
 
+# include <mln/geom/sym.hh>
+
 # include <mln/morpho/dilation.hh>
 # include <mln/morpho/erosion.hh>
 
Index: mln/morpho/closing.hh
--- mln/morpho/closing.hh	(revision 1061)
+++ mln/morpho/closing.hh	(working copy)
@@ -64,7 +64,7 @@
 
       O temp(input.domain());
       dilation(input, win, temp);
-      erosion(temp, -win, output);
+      erosion(temp, geom::sym(win), output);
 
       mln_postcondition(output >= input);
     }
Index: mln/morpho/opening.hh
--- mln/morpho/opening.hh	(revision 1061)
+++ mln/morpho/opening.hh	(working copy)
@@ -64,7 +64,7 @@
 
       O temp(input.domain());
       erosion(input, win, temp);
-      dilation(temp, -win, output);
+      dilation(temp, geom::sym(win), output);
 
       mln_postcondition(output <= input);
     }
Index: mln/level/was.median.hh
--- mln/level/was.median.hh	(revision 1061)
+++ mln/level/was.median.hh	(working copy)
@@ -59,12 +59,12 @@
 	  min_col = geom::min_col(input), max_col = geom::max_col(input);
 
 	window2d
-	  win_fwd_plus  = win - (win + left),
-	  win_fwd_minus = (win + left) - win,
-	  win_bkd_plus  = win - (win + right),
-	  win_bkd_minus = (win + right) - win,
-	  win_bot  = win - (win + up),
-	  win_top = (win + up) - win;
+	  win_fwd_plus  = set::diff(win, geom::shift(win, left)),
+	  win_fwd_minus = set::diff(geom::shift(win, left), win),
+	  win_bkd_plus  = set::diff(win, geom::shift(win, right)),
+	  win_bkd_minus = set::diff(geom::shift(win, right), win),
+	  win_bot  = set::diff(win, geom::shift(win, up)),
+	  win_top = set::diff(geom::shift(win, up), win);
 
 	point2d p;
 	mln_qiter(W)
Index: mln/level/median.hh
--- mln/level/median.hh	(revision 1061)
+++ mln/level/median.hh	(working copy)
@@ -38,11 +38,14 @@
 
 # include <mln/core/window2d.hh>
 # include <mln/core/win/hline2d.hh>
-
 # include <mln/core/t_image.hh>
+
 # include <mln/accu/median.hh>
 # include <mln/canvas/sbrowsing.hh>
 
+# include <mln/geom/shift.hh>
+# include <mln/set/diff.hh>
+
 
 namespace mln
 {
@@ -98,9 +101,12 @@
 	  // aux data
 	  med(input.values()),
 	  p(),
-	  win_fp(win - (win + left)),   win_fm((win + left)  - win),
-	  win_bp(win - (win + right)),  win_bm((win + right) - win),
-	  win_dp(win - (win + up)),     win_dm((win + up)    - win),
+	  win_fp(set::diff(win, geom::shift(win, left))),
+	  win_fm(set::diff(geom::shift(win, left),  win)),
+	  win_bp(set::diff(win, geom::shift(win, right))),
+	  win_bm(set::diff(geom::shift(win, right), win)),
+	  win_dp(set::diff(win, geom::shift(win, up))),
+	  win_dm(set::diff(geom::shift(win, up),    win)),
 	  q_fp(win_fp, p),  q_fm(win_fm, p),
 	  q_bp(win_bp, p),  q_bm(win_bm, p),
 	  q_dp(win_dp, p),  q_dm(win_dm, p)
Index: mln/level/fast_median.hh
--- mln/level/fast_median.hh	(revision 1061)
+++ mln/level/fast_median.hh	(working copy)
@@ -36,6 +36,8 @@
 # include <mln/core/concept/image.hh>
 # include <mln/core/window2d.hh>
 # include <mln/accu/median.hh>
+# include <mln/geom/shift.hh>
+# include <mln/set/diff.hh>
 
 
 namespace mln
@@ -77,12 +79,12 @@
 	  min_col = geom::min_col(input), max_col = geom::max_col(input);
 
 	window2d
-	  win_fwd_plus  = win - (win + left),
-	  win_fwd_minus = (win + left) - win,
-	  win_bkd_plus  = win - (win + right),
-	  win_bkd_minus = (win + right) - win,
-	  win_bot  = win - (win + up),
-	  win_top = (win + up) - win;
+	  win_fwd_plus  = set::diff(win, geom::shift(win, left)),
+	  win_fwd_minus = set::diff(geom::shift(win, left), win),
+	  win_bkd_plus  = set::diff(win, geom::shift(win, right)),
+	  win_bkd_minus = set::diff(geom::shift(win, right), win),
+	  win_bot  = set::diff(win, geom::shift(win, up)),
+	  win_top = set::diff(geom::shift(win, up), win);
 
 	accu::median<mln_vset(I)> med(input.values());
 
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from  Thierry Geraud  <thierry.geraud(a)lrde.epita.fr>
	Add morphological complementation.
	* tests/morpho_contrast.cc: Augment.
	* mln/core/concept/value.hh (cast): New.
	* mln/fun/v2v/saturate.hh: Update.
	* mln/morpho/minus.hh: Move assertions.
	* mln/logical/and.hh,
	* mln/logical/and_not.hh,
	* mln/logical/or.hh: Fix doc.
	* mln/value/int_s.hh (operator=): New.
	* mln/value/int_u.hh: Likewise.
	* mln/morpho/complementation.hh: New.
	* mln/morpho/includes.hh: Update.
	* mln/arith/revert.hh: New.
	* mln/logical/not.hh: New.
 mln/arith/revert.hh           |  127 ++++++++++++++++++++++++++++++++++++++++++
 mln/core/concept/value.hh     |   46 +++++++++++++++
 mln/fun/v2v/saturate.hh       |   10 +--
 mln/logical/and.hh            |    2 
 mln/logical/and_not.hh        |    2 
 mln/logical/not.hh            |  120 +++++++++++++++++++++++++++++++++++++++
 mln/logical/or.hh             |    2 
 mln/morpho/complementation.hh |  105 ++++++++++++++++++++++++++++++++++
 mln/morpho/includes.hh        |    1 
 mln/morpho/minus.hh           |    7 --
 mln/value/int_s.hh            |   13 ++++
 mln/value/int_u.hh            |   13 ++++
 tests/morpho_contrast.cc      |   22 ++++++-
 13 files changed, 455 insertions(+), 15 deletions(-)
Index: tests/morpho_contrast.cc
--- tests/morpho_contrast.cc	(revision 1060)
+++ tests/morpho_contrast.cc	(working copy)
@@ -37,7 +37,11 @@
 #include <mln/io/save_pgm.hh>
 
 #include <mln/value/int_u8.hh>
+#include <mln/value/int_s.hh>
+
 #include <mln/morpho/contrast.hh>
+
+#include <mln/level/fill.hh>
 #include <mln/level/saturate.hh>
 
 
@@ -53,9 +57,23 @@
     lena = io::load_pgm("../img/tiny.pgm"),
     out(lena.domain());
 
-  image2d_b<int> tmp(lena.domain());
-  morpho::contrast(lena, rect, tmp);
+  image2d_b< value::int_s<10> >
+    in(lena.domain()),
+    tmp(lena.domain());
+
+  level::fill(in, lena);
+  morpho::contrast(in, rect, tmp);
 
   level::saturate(tmp, out);
   io::save_pgm(out, "out.pgm");
+
+  {
+    // self-duality test: 
+    morpho::complementation_inplace(in);
+    image2d_b< value::int_s<10> > tmp_(lena.domain());
+    morpho::contrast(in, rect, tmp_);
+    morpho::complementation_inplace(tmp_);
+    mln_assertion(tmp_ = tmp);
+  }
+
 }
Index: mln/core/concept/value.hh
--- mln/core/concept/value.hh	(revision 1060)
+++ mln/core/concept/value.hh	(working copy)
@@ -62,6 +62,18 @@
   };
 
 
+
+  namespace value
+  {
+
+    /// Cast a value \p src from type \c Src to type \c Dest. 
+    template <typename Dest, typename Src>
+    Dest cast(const Src& src);
+
+  } // end of namespace mln::value
+
+
+
 # ifndef MLN_INCLUDE_ONLY
 
   template <typename E>
@@ -87,6 +99,40 @@
     return exact(*this);
   }
 
+
+  namespace value
+  {
+
+    namespace internal
+    {
+
+      template <typename S>
+      const S&
+      cast_(const S& src, ...)
+      {
+	return src;
+      }
+
+      template <typename T, typename S>
+      typename S::equiv
+      cast_(const T& dummy, const Value<S>& src)
+      {
+	return exact(src);
+      }
+
+    } // end of namespace mln::value::internal
+
+
+    template <typename Dest, typename Src>
+    Dest cast(const Src& src)
+    {
+      return internal::cast_(src, src);
+    }
+
+
+  } // end of namespace mln::value
+
+
 # endif // ! MLN_INCLUDE_ONLY
 
 } // end of namespace mln
Index: mln/fun/v2v/saturate.hh
--- mln/fun/v2v/saturate.hh	(revision 1060)
+++ mln/fun/v2v/saturate.hh	(working copy)
@@ -57,7 +57,7 @@
 	typedef V result;
 
 	template <typename W>
-	V operator()(const W& v) const;
+	V operator()(const W& w) const;
 
       protected:
 	V min_, max_;
@@ -84,13 +84,13 @@
       template <typename V>
       template <typename W>
       V
-      saturate<V>::operator()(const W& v) const
+      saturate<V>::operator()(const W& w) const
       {
-	if (v < min_)
+	if (w < min_)
 	  return min_;
-	if (v > max_)
+	if (w > max_)
 	  return max_;
-	return v;
+	return mln::value::cast<V>(w);
       }
 
 # endif // ! MLN_INCLUDE_ONLY
Index: mln/morpho/includes.hh
--- mln/morpho/includes.hh	(revision 1060)
+++ mln/morpho/includes.hh	(working copy)
@@ -53,6 +53,7 @@
 
 # include <mln/morpho/minus.hh>
 # include <mln/morpho/plus.hh>
+# include <mln/morpho/complementation.hh>
 
 
 #endif // ! MLN_MORPHO_INCLUDES_HH
Index: mln/morpho/minus.hh
--- mln/morpho/minus.hh	(revision 1060)
+++ mln/morpho/minus.hh	(working copy)
@@ -64,7 +64,9 @@
 		  const Image<I>& lhs, const Image<J>& rhs,
 		  Image<O>& output)
       {
+	// FIXME: mln_precondition(rhs <= lhs);
 	return logical::and_not(lhs, rhs, output);
+	// FIXME: mln_postcondition(output <= lhs);
       }
 
       template <typename K, typename I, typename J, typename O>
@@ -85,19 +87,14 @@
     {
       mln_precondition(exact(rhs).domain() = exact(lhs).domain());
       mln_precondition(exact(output).domain() = exact(lhs).domain());
-      mln_precondition(rhs <= lhs);
 
       impl::minus_(mln_value_kind(I)(), exact(lhs), exact(rhs), output);
-
-      mln_postcondition(output <= lhs);
     }
 
     template <typename I, typename J>
     void minus_inplace(Image<I>& lhs, const Image<J>& rhs)
     {
       mln_precondition(exact(rhs).domain() = exact(lhs).domain());
-      mln_precondition(rhs <= lhs);
-
       morpho::minus(lhs, rhs, lhs); // Calls the previous version.
     }
 
Index: mln/morpho/complementation.hh
--- mln/morpho/complementation.hh	(revision 0)
+++ mln/morpho/complementation.hh	(revision 0)
@@ -0,0 +1,105 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_MORPHO_COMPLEMENTATION_HH
+# define MLN_MORPHO_COMPLEMENTATION_HH
+
+# include <mln/level/compare.hh>
+# include <mln/logical/not.hh>
+# include <mln/arith/revert.hh>
+
+
+namespace mln
+{
+
+  namespace morpho
+  {
+
+    /*! Morphological complementation: either a logical "not" (if
+     *  morpho on sets) or an arithmetical complementation (if morpho
+     *  on functions).
+     */
+    template <typename I, typename O>
+    void complementation(const Image<I>& input, Image<O>& output);
+
+
+    /*! Morphological complementation, inplace version: either a
+     *  logical "not" (if morpho on sets) or an arithmetical
+     *  complementation (if morpho on functions).
+     */
+    template <typename I>
+    void complementation_inplace(Image<I>& input);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    namespace impl
+    {
+
+      template <typename I, typename O>
+      void complementation_(value::binary_kind, // binary => morphology on sets
+			    const Image<I>& input,
+			    Image<O>& output)
+      {
+	return logical::not_(input, output);
+      }
+
+      template <typename K, typename I, typename O>
+      void complementation_(K, // otherwise => morphology on functions
+			    const Image<I>& input,
+			    Image<O>& output)
+      {
+	return arith::revert(input, output);
+      }
+
+    } // end of namespace mln::morpho::impl
+
+
+    // Facades.
+
+    template <typename I, typename O>
+    void complementation(const Image<I>& input, Image<O>& output)
+    {
+      mln_precondition(exact(output).domain() = exact(input).domain());
+      impl::complementation_(mln_value_kind(I)(), exact(input), output);
+    }
+
+    template <typename I>
+    void complementation_inplace(Image<I>& input)
+    {
+      mln_precondition(exact(input).has_data());
+      morpho::complementation(input, input); // Calls the previous version.
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MORPHO_COMPLEMENTATION_HH
Index: mln/arith/revert.hh
--- mln/arith/revert.hh	(revision 0)
+++ mln/arith/revert.hh	(revision 0)
@@ -0,0 +1,127 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_ARITH_REVERT_HH
+# define MLN_ARITH_REVERT_HH
+
+/*! \file mln/arith/revert.hh
+ *
+ * \brief Point-wise revert (min -> max and max -> min) of images.
+ *
+ * \todo Add static assertion and save one iterator in in-place version.
+ */
+
+# include <mln/core/concept/image.hh>
+# include <mln/value/props.hh>
+
+// FIXME: Rely instead on mln/fun/v2v/revert.hh.
+// FIXME: Revert on int value 0 does not give 0 (since min != - max; idem for float etc.)
+
+
+
+namespace mln
+{
+
+  namespace arith
+  {
+
+    /*! Point-wise reversion of image \p input.
+     *
+     * \param[in] input the input image.
+     * \param[out] output The result image.
+     *
+     * \pre \p output.domain = \p input.domain
+     */
+    template <typename I, typename O>
+    void revert(const Image<I>& input, Image<O>& output);
+
+
+    /*! Point-wise in-place reversion of image \p input.
+     *
+     * \param[in,out] input The target image.
+     *
+     * It performs: \n
+     *   for all p of input.domain \n
+     *     input(p) = min + (max - input(p))
+     */
+    template <typename I>
+    void revert_inplace(Image<I>& input);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    namespace impl
+    {
+
+      template <typename I, typename O>
+      void revert_(const Image<I>& input_, Image<O>& output_)
+      {
+	const I& input = exact(input_);
+	O& output = exact(output_);
+	typedef mln_value(I) V;
+	mln_piter(I) p(input.domain());
+	for_all(p)
+	  output(p) = mln_min(V) + (mln_max(V) - input(p));
+      }
+
+      template <typename I, typename O>
+      void revert_(const Fast_Image<I>& input, Fast_Image<O>& output)
+      {
+	typedef mln_value(I) V;
+	mln_pixter(const I) ip(exact(input));
+	mln_pixter(O)       op(exact(output));
+	for_all_2(ip, op)
+	  op.val() = mln_min(V) + (mln_max(V) - op.val());
+      }
+
+    } // end of namespace mln::arith::impl
+
+
+    // Facades.
+
+    template <typename I, typename O>
+    void revert(const Image<I>& input, Image<O>& output)
+    {
+      mln_precondition(exact(output).domain() = exact(input).domain());
+      impl::revert_(exact(input), exact(output));
+    }
+
+    template <typename I>
+    void revert_inplace(Image<I>& input)
+    {
+      mln_precondition(exact(input).has_data());
+      impl::revert_(exact(input), exact(input));
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::arith
+
+} // end of namespace mln
+
+
+#endif // ! MLN_ARITH_REVERT_HH
Index: mln/logical/and.hh
--- mln/logical/and.hh	(revision 1060)
+++ mln/logical/and.hh	(working copy)
@@ -61,7 +61,7 @@
      * \param[in] lhs First operand image.
      * \param[in,out] rhs Second operand image.
      *
-     * This addition performs: \n
+     * It performs: \n
      *   for all p of rhs.domain \n
      *     lhs(p) = lhs(p) and rhs(p)
      *
Index: mln/logical/and_not.hh
--- mln/logical/and_not.hh	(revision 1060)
+++ mln/logical/and_not.hh	(working copy)
@@ -61,7 +61,7 @@
      * \param[in] lhs First operand image.
      * \param[in,out] rhs Second operand image.
      *
-     * This addition performs: \n
+     * It performs: \n
      *   for all p of rhs.domain \n
      *     lhs(p) = lhs(p) and not rhs(p)
      *
Index: mln/logical/or.hh
--- mln/logical/or.hh	(revision 1060)
+++ mln/logical/or.hh	(working copy)
@@ -61,7 +61,7 @@
      * \param[in] lhs First operand image.
      * \param[in,out] rhs Second operand image.
      *
-     * This addition performs: \n
+     * It performs: \n
      *   for all p of rhs.domain \n
      *     lhs(p) = lhs(p) or rhs(p)
      *
Index: mln/logical/not.hh
--- mln/logical/not.hh	(revision 0)
+++ mln/logical/not.hh	(revision 0)
@@ -0,0 +1,120 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_LOGICAL_NOT_HH
+# define MLN_LOGICAL_NOT_HH
+
+/*! \file mln/logical/not.hh
+ *
+ * \brief Point-wise "logical not" of a binary image.
+ *
+ * \todo Add static assertion and save one iterator in in-place version.
+ */
+
+# include <mln/core/concept/image.hh>
+
+
+namespace mln
+{
+
+  namespace logical
+  {
+
+    /*! Point-wise "logical not" of image \p input.
+     *
+     * \param[in] input the input image.
+     * \param[out] output The result image.
+     *
+     * \pre \p output.domain = \p input.domain
+     */
+    template <typename I, typename O>
+    void not_(const Image<I>& input, Image<O>& output);
+
+
+    /*! Point-wise in-place "logical not" of image \p input.
+     *
+     * \param[in,out] input The target image.
+     *
+     * It performs: \n
+     *   for all p of input.domain \n
+     *     input(p) = not input(p)
+     */
+    template <typename I>
+    void not_inplace(Image<I>& input);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    namespace impl
+    {
+
+      template <typename I, typename O>
+      void not__(const Image<I>& input_, Image<O>& output_)
+      {
+	const I& input = exact(input_);
+	O& output = exact(output_);
+	mln_piter(I) p(input.domain());
+	for_all(p)
+	  output(p) = ! input(p);
+      }
+
+      template <typename I, typename O>
+      void not__(const Fast_Image<I>& input, Fast_Image<O>& output)
+      {
+	mln_pixter(const I) ip(exact(input));
+	mln_pixter(O)       op(exact(output));
+	for_all_2(ip, op)
+	  op.val() = ! ip.val();
+      }
+
+    } // end of namespace mln::logical::impl
+
+
+    // Facades.
+
+    template <typename I, typename O>
+    void not_(const Image<I>& input, Image<O>& output)
+    {
+      mln_precondition(exact(output).domain() = exact(input).domain());
+      impl::not__(exact(input), exact(output));
+    }
+
+    template <typename I>
+    void not_inplace(Image<I>& input)
+    {
+      mln_precondition(exact(input).has_data());
+      impl::not__(exact(input), exact(input));
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::logical
+
+} // end of namespace mln
+
+
+#endif // ! MLN_LOGICAL_NOT_HH
Index: mln/value/int_s.hh
--- mln/value/int_s.hh	(revision 1060)
+++ mln/value/int_s.hh	(working copy)
@@ -71,6 +71,9 @@
       /// Constructor from an integer.
       int_s(int i);
 
+      /// Assignment from an integer.
+      int_s<n>& operator=(int i);
+
       /// Negation.
       int_s<n> operator-() const;
 
@@ -135,6 +138,16 @@
     }
 
     template <unsigned n>
+    int_s<n>&
+    int_s<n>::operator=(int i)
+    {
+      mln_precondition(i >= mln_min(enc));
+      mln_precondition(i <= mln_max(enc));
+      this->v_ = i;
+      return *this;
+    }
+
+    template <unsigned n>
     int_s<n>
     int_s<n>::operator-() const
     {
Index: mln/value/int_u.hh
--- mln/value/int_u.hh	(revision 1060)
+++ mln/value/int_u.hh	(working copy)
@@ -71,6 +71,9 @@
       /// Constructor from an integer.
       int_u(int i);
 
+      /// Assignment from an integer.
+      int_u<n>& operator=(int i);
+
       /// Zero value.
       static const int_u<n> zero;
 
@@ -132,6 +135,16 @@
 
     template <unsigned n>
     int_u<n>&
+    int_u<n>::operator=(int i)
+    {
+      mln_precondition(i >= 0);
+      mln_precondition(i <= mln_max(enc));
+      this->v_ = i;
+      return *this;
+    }
+
+    template <unsigned n>
+    int_u<n>&
     int_u<n>::operator+=(int i)
     {
       mln_precondition(long(this->v_) + i >= 0);
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from  Thierry Geraud  <thierry.geraud(a)lrde.epita.fr>
	Add morphology plus and minus.
	* tests/erosion.cc: Rename as...
	* tests/morpho_erosion.cc: ...this.
	* mln/geom/pmin_pmax.hh: Fix.
	* mln/morpho/plus.hh: New.
	* mln/morpho/minus.hh: New.
	* mln/logical: New.
	* mln/logical/and.hh: New.
	* mln/logical/and_not.hh: New.
	* mln/logical/or.hh: New.
	* mln/morpho/includes.hh,
	* mln/morpho/gradient.hh,
	* mln/morpho/contrast.hh,
	* mln/morpho/top_hat.hh: Update.
 mln/geom/pmin_pmax.hh   |    4 -
 mln/logical/and.hh      |  127 ++++++++++++++++++++++++++++++++++++++++++++++++
 mln/logical/and_not.hh  |  127 ++++++++++++++++++++++++++++++++++++++++++++++++
 mln/logical/or.hh       |  127 ++++++++++++++++++++++++++++++++++++++++++++++++
 mln/morpho/contrast.hh  |    4 -
 mln/morpho/gradient.hh  |    6 +-
 mln/morpho/includes.hh  |    5 -
 mln/morpho/minus.hh     |  111 +++++++++++++++++++++++++++++++++++++++++
 mln/morpho/plus.hh      |  108 ++++++++++++++++++++++++++++++++++++++++
 mln/morpho/top_hat.hh   |    6 +-
 tests/morpho_erosion.cc |    2 
 11 files changed, 613 insertions(+), 14 deletions(-)
Index: tests/morpho_erosion.cc
--- tests/morpho_erosion.cc	(revision 1059)
+++ tests/morpho_erosion.cc	(working copy)
@@ -25,7 +25,7 @@
 // reasons why the executable file might be covered by the GNU General
 // Public License.
 
-/*! \file tests/erosion.cc
+/*! \file tests/morpho_erosion.cc
  *
  * \brief Test on mln::morpho::erosion.
  */
Index: mln/geom/pmin_pmax.hh
--- mln/geom/pmin_pmax.hh	(revision 1059)
+++ mln/geom/pmin_pmax.hh	(working copy)
@@ -108,7 +108,7 @@
     {
       typedef mln_point(I) P;
       std::pair<P, P> tmp;
-      pmin_pmax(p, tmp.first, tmp.second); // calls the previous version
+      pmin_pmax(p, tmp.first, tmp.second); // Calls the previous version.
       return tmp;
     }
 
@@ -156,7 +156,7 @@
       mln_precondition(exact(s).npoints() != 0);
       typedef mln_point(S) P;
       std::pair<P, P> tmp;
-      pmin_pmax(p_, tmp.first, tmp.second); // calls the previous version
+      pmin_pmax(s, tmp.first, tmp.second); // Calls the previous version.
       return tmp;
     }
 
Index: mln/morpho/plus.hh
--- mln/morpho/plus.hh	(revision 0)
+++ mln/morpho/plus.hh	(revision 0)
@@ -0,0 +1,108 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_MORPHO_PLUS_HH
+# define MLN_MORPHO_PLUS_HH
+
+# include <mln/level/compare.hh>
+# include <mln/logical/or.hh>
+# include <mln/arith/plus.hh>
+
+
+namespace mln
+{
+
+  namespace morpho
+  {
+
+    /*! Morphological plus: either a "logical or" (if morpho on sets)
+     *  or an "arithmetical plus" (if morpho on functions).
+     */
+    template <typename I, typename J, typename O>
+    void plus(const Image<I>& lhs, const Image<J>& rhs,
+	       Image<O>& output);
+
+    /*! Morphological plus, inplace version: either a "logical or" (if
+     *  morpho on sets) or an "arithmetical plus" (if morpho on
+     *  functions).
+     */
+    template <typename I, typename J>
+    void plus_inplace(Image<I>& lhs, const Image<J>& rhs);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    namespace impl
+    {
+
+      template <typename I, typename J, typename O>
+      void plus_(value::binary_kind, // binary => morphology on sets
+		 const Image<I>& lhs, const Image<J>& rhs,
+		 Image<O>& output)
+      {
+	return logical::or_(lhs, rhs, output);
+      }
+
+      template <typename K, typename I, typename J, typename O>
+      void plus_(K, // otherwise => morphology on functions
+		 const Image<I>& lhs, const Image<J>& rhs,
+		 Image<O>& output)
+      {
+	return arith::plus(lhs, rhs, output);
+      }
+
+    } // end of namespace mln::morpho::impl
+
+
+    // Facades.
+
+    template <typename I, typename J, typename O>
+    void plus(const Image<I>& lhs, const Image<J>& rhs, Image<O>& output)
+    {
+      mln_precondition(exact(rhs).domain() = exact(lhs).domain());
+      mln_precondition(exact(output).domain() = exact(lhs).domain());
+
+      impl::plus_(mln_value_kind(I)(), exact(lhs), exact(rhs), output);
+
+      mln_postcondition(output <= lhs);
+    }
+
+    template <typename I, typename J>
+    void plus_inplace(Image<I>& lhs, const Image<J>& rhs)
+    {
+      mln_precondition(exact(rhs).domain() = exact(lhs).domain());
+      morpho::plus(lhs, rhs, lhs); // Calls the previous version.
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MORPHO_PLUS_HH
Index: mln/morpho/includes.hh
--- mln/morpho/includes.hh	(revision 1059)
+++ mln/morpho/includes.hh	(working copy)
@@ -40,9 +40,6 @@
 # include <mln/accu/min.hh>
 # include <mln/accu/max.hh>
 
-# include <mln/arith/plus.hh>
-# include <mln/arith/minus.hh>
-
 # include <mln/level/compare.hh>
 # include <mln/level/fill.hh>
 
@@ -54,6 +51,8 @@
 # include <mln/morpho/dilation.hh>
 # include <mln/morpho/erosion.hh>
 
+# include <mln/morpho/minus.hh>
+# include <mln/morpho/plus.hh>
 
 
 #endif // ! MLN_MORPHO_INCLUDES_HH
Index: mln/morpho/minus.hh
--- mln/morpho/minus.hh	(revision 0)
+++ mln/morpho/minus.hh	(revision 0)
@@ -0,0 +1,111 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_MORPHO_MINUS_HH
+# define MLN_MORPHO_MINUS_HH
+
+# include <mln/level/compare.hh>
+# include <mln/logical/and_not.hh>
+# include <mln/arith/minus.hh>
+
+
+namespace mln
+{
+
+  namespace morpho
+  {
+
+    /*! Morphological minus: either a logical "and not" (if morpho on
+     *  sets) or an arithmetical minus (if morpho on functions).
+     */
+    template <typename I, typename J, typename O>
+    void minus(const Image<I>& lhs, const Image<J>& rhs,
+	       Image<O>& output);
+
+    /*! Morphological minus, inplace version: either a logical "and
+     *  not" (if morpho on sets) or an arithmetical minus (if morpho
+     *  on functions).
+     */
+    template <typename I, typename J>
+    void minus_inplace(Image<I>& lhs, const Image<J>& rhs);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    namespace impl
+    {
+
+      template <typename I, typename J, typename O>
+      void minus_(value::binary_kind, // binary => morphology on sets
+		  const Image<I>& lhs, const Image<J>& rhs,
+		  Image<O>& output)
+      {
+	return logical::and_not(lhs, rhs, output);
+      }
+
+      template <typename K, typename I, typename J, typename O>
+      void minus_(K, // otherwise => morphology on functions
+		  const Image<I>& lhs, const Image<J>& rhs,
+		  Image<O>& output)
+      {
+	return arith::minus(lhs, rhs, output);
+      }
+
+    } // end of namespace mln::morpho::impl
+
+
+    // Facades.
+
+    template <typename I, typename J, typename O>
+    void minus(const Image<I>& lhs, const Image<J>& rhs, Image<O>& output)
+    {
+      mln_precondition(exact(rhs).domain() = exact(lhs).domain());
+      mln_precondition(exact(output).domain() = exact(lhs).domain());
+      mln_precondition(rhs <= lhs);
+
+      impl::minus_(mln_value_kind(I)(), exact(lhs), exact(rhs), output);
+
+      mln_postcondition(output <= lhs);
+    }
+
+    template <typename I, typename J>
+    void minus_inplace(Image<I>& lhs, const Image<J>& rhs)
+    {
+      mln_precondition(exact(rhs).domain() = exact(lhs).domain());
+      mln_precondition(rhs <= lhs);
+
+      morpho::minus(lhs, rhs, lhs); // Calls the previous version.
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MORPHO_MINUS_HH
Index: mln/morpho/gradient.hh
--- mln/morpho/gradient.hh	(revision 1059)
+++ mln/morpho/gradient.hh	(working copy)
@@ -86,7 +86,7 @@
       dilation(input, win, output); // output = dilation
       O temp(input.domain());
       erosion(input, win, temp); // temp = erosion
-      arith::minus_inplace(output, temp); // now output = dilation - erosion
+      morpho::minus_inplace(output, temp); // now output = dilation - erosion
 
       mln_postcondition(test::positive(output));
     }
@@ -104,7 +104,7 @@
 
       O temp(input.domain());
       erosion(input, win, temp); // temp = erosion
-      arith::minus(input, temp, output); // output = input - erosion
+      morpho::minus(input, temp, output); // output = input - erosion
 
       mln_postcondition(test::positive(output));
     }
@@ -121,7 +121,7 @@
       mln_precondition(! win.is_empty());
 
       dilation(input, win, output); // output = dilation
-      arith::minus_inplace(output, input); // now output = dilation - input
+      morpho::minus_inplace(output, input); // now output = dilation - input
 
       mln_postcondition(test::positive(output));
     }
Index: mln/morpho/contrast.hh
--- mln/morpho/contrast.hh	(revision 1059)
+++ mln/morpho/contrast.hh	(working copy)
@@ -66,10 +66,10 @@
       mln_precondition(! win.is_empty());
 
       top_hat_white(input, win, output); // output = wth
-      arith::plus_inplace(output, input); // now output = wth + input
+      morpho::plus_inplace(output, input); // now output = wth + input
       O temp(input.domain());
       top_hat_black(input, win, temp); // temp = bth
-      arith::minus_inplace(output, temp); // now output = wth + input - bth
+      morpho::minus_inplace(output, temp); // now output = wth + input - bth
     }
 
 # endif // ! MLN_INCLUDE_ONLY
Index: mln/morpho/top_hat.hh
--- mln/morpho/top_hat.hh	(revision 1059)
+++ mln/morpho/top_hat.hh	(working copy)
@@ -89,7 +89,7 @@
 
       O temp(input.domain());
       opening(input, win, temp); // temp = opening
-      arith::minus(input, temp, output); // output = input - opening
+      morpho::minus(input, temp, output); // output = input - opening
 
       mln_postcondition(test::positive(output));
     }
@@ -105,7 +105,7 @@
       mln_precondition(! win.is_empty());
 
       closing(input, win, output); // output = closing
-      arith::minus_inplace(output, input); // now output = closing - input
+      morpho::minus_inplace(output, input); // now output = closing - input
 
       mln_postcondition(test::positive(output));
     }
@@ -123,7 +123,7 @@
       closing(input, win, output); // output = closing
       O temp(input.domain());
       opening(input, win, temp); // temp = opening
-      arith::minus_inplace(output, temp); // now output = closing - opening
+      morpho::minus_inplace(output, temp); // now output = closing - opening
 
       mln_postcondition(test::positive(output));
     }
Index: mln/logical/and.hh
--- mln/logical/and.hh	(revision 0)
+++ mln/logical/and.hh	(revision 0)
@@ -0,0 +1,127 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_LOGICAL_AND_HH
+# define MLN_LOGICAL_AND_HH
+
+/*! \file mln/logical/and.hh
+ *
+ * \brief Point-wise "logical and" between binary images.
+ *
+ * \todo Add static assertion and save one iterator in in-place version.
+ */
+
+# include <mln/core/concept/image.hh>
+
+
+namespace mln
+{
+
+  namespace logical
+  {
+
+    /*! Point-wise "logical and" between images \p lhs and \p rhs.
+     *
+     * \param[in] lhs First operand image.
+     * \param[in] rhs Second operand image.
+     * \param[out] output The result image.
+     *
+     * \pre \p output.domain = \p lhs.domain = \p rhs.domain
+     */
+    template <typename L, typename R, typename O>
+    void and_(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output);
+
+
+    /*! Point-wise in-place "logical and" of image \p rhs in image \p lhs.
+     *
+     * \param[in] lhs First operand image.
+     * \param[in,out] rhs Second operand image.
+     *
+     * This addition performs: \n
+     *   for all p of rhs.domain \n
+     *     lhs(p) = lhs(p) and rhs(p)
+     *
+     * \pre \p rhs.domain <= \p lhs.domain
+     */
+    template <typename L, typename R>
+    void and_inplace(Image<L>& lhs, const Image<R>& rhs);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    namespace impl
+    {
+
+      template <typename L, typename R, typename O>
+      void and__(const Image<L>& lhs_, const Image<R>& rhs_, Image<O>& output_)
+      {
+	const L& lhs = exact(lhs_);
+	const R& rhs = exact(rhs_);
+	O& output = exact(output_);
+	mln_piter(L) p(lhs.domain());
+	for_all(p)
+	  output(p) = lhs(p) && rhs(p);
+      }
+
+      template <typename L, typename R, typename O>
+      void and__(const Fast_Image<L>& lhs, const Fast_Image<R>& rhs, Fast_Image<O>& output)
+      {
+	mln_pixter(const L) lp(exact(lhs));
+	mln_pixter(const R) rp(exact(rhs));
+	mln_pixter(O)       op(exact(output));
+	for_all_3(lp, rp, op)
+	  op.val() = lp.val() && rp.val();
+      }
+
+    } // end of namespace mln::logical::impl
+
+
+    // Facades.
+
+    template <typename L, typename R, typename O>
+    void and_(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output)
+    {
+      mln_precondition(exact(rhs).domain() = exact(lhs).domain());
+      mln_precondition(exact(output).domain() = exact(lhs).domain());
+      impl::and__(exact(lhs), exact(rhs), exact(output));
+    }
+
+    template <typename L, typename R>
+    void and_inplace(Image<L>& lhs, const Image<R>& rhs)
+    {
+      mln_precondition(exact(rhs).domain() <= exact(lhs).domain());
+      impl::and__(exact(lhs), exact(rhs), exact(lhs));
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::logical
+
+} // end of namespace mln
+
+
+#endif // ! MLN_LOGICAL_AND_HH
Index: mln/logical/and_not.hh
--- mln/logical/and_not.hh	(revision 0)
+++ mln/logical/and_not.hh	(revision 0)
@@ -0,0 +1,127 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_LOGICAL_AND_NOT_HH
+# define MLN_LOGICAL_AND_NOT_HH
+
+/*! \file mln/logical/and_not.hh
+ *
+ * \brief Point-wise logical "and not" between binary images.
+ *
+ * \todo Add static assertion and save one iterator in in-place version.
+ */
+
+# include <mln/core/concept/image.hh>
+
+
+namespace mln
+{
+
+  namespace logical
+  {
+
+    /*! Point-wise logical "and not" between images \p lhs and \p rhs.
+     *
+     * \param[in] lhs First operand image.
+     * \param[in] rhs Second operand image.
+     * \param[out] output The result image.
+     *
+     * \pre \p output.domain = \p lhs.domain = \p rhs.domain
+     */
+    template <typename L, typename R, typename O>
+    void and_not(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output);
+
+
+    /*! Point-wise in-place logical "and not" of image \p rhs in image \p lhs.
+     *
+     * \param[in] lhs First operand image.
+     * \param[in,out] rhs Second operand image.
+     *
+     * This addition performs: \n
+     *   for all p of rhs.domain \n
+     *     lhs(p) = lhs(p) and not rhs(p)
+     *
+     * \pre \p rhs.domain <= \p lhs.domain
+     */
+    template <typename L, typename R>
+    void and_not_inplace(Image<L>& lhs, const Image<R>& rhs);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    namespace impl
+    {
+
+      template <typename L, typename R, typename O>
+      void and_not_(const Image<L>& lhs_, const Image<R>& rhs_, Image<O>& output_)
+      {
+	const L& lhs = exact(lhs_);
+	const R& rhs = exact(rhs_);
+	O& output = exact(output_);
+	mln_piter(L) p(lhs.domain());
+	for_all(p)
+	  output(p) = lhs(p) && ! rhs(p);
+      }
+
+      template <typename L, typename R, typename O>
+      void and_not_(const Fast_Image<L>& lhs, const Fast_Image<R>& rhs, Fast_Image<O>& output)
+      {
+	mln_pixter(const L) lp(exact(lhs));
+	mln_pixter(const R) rp(exact(rhs));
+	mln_pixter(O)       op(exact(output));
+	for_all_3(lp, rp, op)
+	  op.val() = lp.val() && ! rp.val();
+      }
+
+    } // end of namespace mln::logical::impl
+
+
+    // Facades.
+
+    template <typename L, typename R, typename O>
+    void and_not(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output)
+    {
+      mln_precondition(exact(rhs).domain() = exact(lhs).domain());
+      mln_precondition(exact(output).domain() = exact(lhs).domain());
+      impl::and_not_(exact(lhs), exact(rhs), exact(output));
+    }
+
+    template <typename L, typename R>
+    void and_not_inplace(Image<L>& lhs, const Image<R>& rhs)
+    {
+      mln_precondition(exact(rhs).domain() <= exact(lhs).domain());
+      impl::and_not_(exact(lhs), exact(rhs), exact(lhs));
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::logical
+
+} // end of namespace mln
+
+
+#endif // ! MLN_LOGICAL_AND_NOT_HH
Index: mln/logical/or.hh
--- mln/logical/or.hh	(revision 0)
+++ mln/logical/or.hh	(revision 0)
@@ -0,0 +1,127 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_LOGICAL_OR_HH
+# define MLN_LOGICAL_OR_HH
+
+/*! \file mln/logical/or.hh
+ *
+ * \brief Point-wise "logical or" between binary images.
+ *
+ * \todo Add static assertion and save one iterator in in-place version.
+ */
+
+# include <mln/core/concept/image.hh>
+
+
+namespace mln
+{
+
+  namespace logical
+  {
+
+    /*! Point-wise "logical or" between images \p lhs and \p rhs.
+     *
+     * \param[in] lhs First operand image.
+     * \param[in] rhs Second operand image.
+     * \param[out] output The result image.
+     *
+     * \pre \p output.domain = \p lhs.domain = \p rhs.domain
+     */
+    template <typename L, typename R, typename O>
+    void or_(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output);
+
+
+    /*! Point-wise in-place "logical or" of image \p rhs in image \p lhs.
+     *
+     * \param[in] lhs First operand image.
+     * \param[in,out] rhs Second operand image.
+     *
+     * This addition performs: \n
+     *   for all p of rhs.domain \n
+     *     lhs(p) = lhs(p) or rhs(p)
+     *
+     * \pre \p rhs.domain <= \p lhs.domain
+     */
+    template <typename L, typename R>
+    void or_inplace(Image<L>& lhs, const Image<R>& rhs);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    namespace impl
+    {
+
+      template <typename L, typename R, typename O>
+      void or__(const Image<L>& lhs_, const Image<R>& rhs_, Image<O>& output_)
+      {
+	const L& lhs = exact(lhs_);
+	const R& rhs = exact(rhs_);
+	O& output = exact(output_);
+	mln_piter(L) p(lhs.domain());
+	for_all(p)
+	  output(p) = lhs(p) || rhs(p);
+      }
+
+      template <typename L, typename R, typename O>
+      void or__(const Fast_Image<L>& lhs, const Fast_Image<R>& rhs, Fast_Image<O>& output)
+      {
+	mln_pixter(const L) lp(exact(lhs));
+	mln_pixter(const R) rp(exact(rhs));
+	mln_pixter(O)       op(exact(output));
+	for_all_3(lp, rp, op)
+	  op.val() = lp.val() || rp.val();
+      }
+
+    } // end of namespace mln::logical::impl
+
+
+    // Facades.
+
+    template <typename L, typename R, typename O>
+    void or_(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output)
+    {
+      mln_precondition(exact(rhs).domain() = exact(lhs).domain());
+      mln_precondition(exact(output).domain() = exact(lhs).domain());
+      impl::or__(exact(lhs), exact(rhs), exact(output));
+    }
+
+    template <typename L, typename R>
+    void or_inplace(Image<L>& lhs, const Image<R>& rhs)
+    {
+      mln_precondition(exact(rhs).domain() <= exact(lhs).domain());
+      impl::or__(exact(lhs), exact(rhs), exact(lhs));
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::logical
+
+} // end of namespace mln
+
+
+#endif // ! MLN_LOGICAL_OR_HH
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from  Thierry Geraud  <thierry.geraud(a)lrde.epita.fr>
	Add morphological top-hats and contrast.
	* tests/morpho_gradient.cc: Fix doc.
	* mln/geom/pmin_pmax.hh (pmin_pmax): Overload for point set.
	* mln/geom/bbox.hh: Update.
	* mln/morpho/includes.hh (include): Add mln/test/positive.hh
	and mln/arith/plus.hh.
	* mln/morpho/gradient.hh: Add commentaries.
	* tests/morpho_contrast.cc: New.
	* mln/morpho/contrast.hh: New.
	* mln/morpho/top_hat.hh: New.
 mln/geom/bbox.hh         |    3 -
 mln/geom/pmin_pmax.hh    |   91 ++++++++++++++++++++++++++----
 mln/morpho/contrast.hh   |   82 +++++++++++++++++++++++++++
 mln/morpho/gradient.hh   |   21 +++----
 mln/morpho/includes.hh   |    3 +
 mln/morpho/top_hat.hh    |  138 +++++++++++++++++++++++++++++++++++++++++++++++
 tests/morpho_contrast.cc |   61 ++++++++++++++++++++
 tests/morpho_gradient.cc |    4 -
 8 files changed, 373 insertions(+), 30 deletions(-)
Index: tests/morpho_gradient.cc
--- tests/morpho_gradient.cc	(revision 1058)
+++ tests/morpho_gradient.cc	(working copy)
@@ -25,9 +25,9 @@
 // reasons why the executable file might be covered by the GNU General
 // Public License.
 
-/*! \file tests/erosion.cc
+/*! \file tests/morpho_gradient.cc
  *
- * \brief Test on mln::morpho::erosion.
+ * \brief Test on mln::morpho::gradient.
  */
 
 #include <mln/core/image2d_b.hh>
Index: tests/morpho_contrast.cc
--- tests/morpho_contrast.cc	(revision 0)
+++ tests/morpho_contrast.cc	(revision 0)
@@ -0,0 +1,61 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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 tests/morpho_contrast.cc
+ *
+ * \brief Test on mln::morpho::contrast.
+ */
+
+#include <mln/core/image2d_b.hh>
+#include <mln/core/win/rectangle2d.hh>
+
+#include <mln/io/load_pgm.hh>
+#include <mln/io/save_pgm.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/morpho/contrast.hh>
+#include <mln/level/saturate.hh>
+
+
+int main()
+{
+  using namespace mln;
+  using value::int_u8;
+
+  win::rectangle2d rect(5, 5);
+  border::thickness = 2;
+
+  image2d_b<int_u8>
+    lena = io::load_pgm("../img/tiny.pgm"),
+    out(lena.domain());
+
+  image2d_b<int> tmp(lena.domain());
+  morpho::contrast(lena, rect, tmp);
+
+  level::saturate(tmp, out);
+  io::save_pgm(out, "out.pgm");
+}
Index: mln/geom/pmin_pmax.hh
--- mln/geom/pmin_pmax.hh	(revision 1058)
+++ mln/geom/pmin_pmax.hh	(working copy)
@@ -36,6 +36,10 @@
 
 # include <utility>
 
+# include <mln/core/concept/point_set.hh>
+# include <mln/core/concept/box.hh>
+
+
 
 namespace mln
 {
@@ -44,6 +48,19 @@
   {
 
 
+    /// Compute the minimum and maximum points of point set \p s.
+    template <typename S>
+    std::pair<mln_point(S), mln_point(S)>
+    pmin_pmax(const Point_Set<S>& s);
+
+
+    /// Compute the minimum and maximum points, \p pmin and \p max,
+    /// of point set \p s.
+    template <typename S>
+    void
+    pmin_pmax(const Point_Set<S>& s,  mln_point(S)& pmin, mln_point(S)& pmax);
+
+
     /// Compute the minimum and maximum points when browsing with
     /// iterator \p p.
     template <typename I>
@@ -61,40 +78,86 @@
 
 # ifndef MLN_INCLUDE_ONLY
 
+
+    // Versions with point iterator. 
+
     template <typename I>
-    std::pair<mln_point(I), mln_point(I)>
-    pmin_pmax(Point_Iterator<I>& p_)
+    void
+    pmin_pmax(const Point_Iterator<I>& p_, mln_point(I)& pmin, mln_point(I)& pmax)
     {
-      I& p = exact(p_);
-
-      typedef mln_point(I) P;
-      std::pair<P, P> tmp;
-      P& pmin = tmp.first;
-      P& pmax = tmp.second;
+      I p = exact(p_); // a copy of p_
 
       // init with first point
       p.start();
+      mln_precondition(p.is_valid());
       pmin = pmax = p;
 
       // update with remaining points
+      typedef mln_point(I) P;
       for_all_remaining(p)
 	for (unsigned i = 0; i < P::dim; ++i)
 	  if (p[i] < pmin[i])
 	    pmin[i] = p[i];
 	  else if (p[i] > pmax[i])
 	    pmax[i] = p[i];
+    }
 
+    template <typename I>
+    std::pair<mln_point(I), mln_point(I)>
+    pmin_pmax(const Point_Iterator<I>& p)
+    {
+      typedef mln_point(I) P;
+      std::pair<P, P> tmp;
+      pmin_pmax(p, tmp.first, tmp.second); // calls the previous version
       return tmp;
     }
 
-    template <typename I>
+
+    // Versions with point set. 
+
+    namespace impl
+    {
+
+      // General case.
+
+      template <typename S>
     void
-    pmin_pmax(const Point_Iterator<I>& p, mln_point(I)& pmin, mln_point(I)& pmax)
+      pmin_pmax_(const Point_Set<S>& s, mln_point(S)& pmin, mln_point(S)& pmax)
     {
-      typedef mln_point(I) P;
-      std::pair<P, P> tmp = pmin_pmax(p);
-      pmin = tmp.first;
-      pmax = tmp.second;
+	mln_piter(S) it(exact(s));
+	pmin_pmax(it, pmin, pmax);
+      }
+
+      // Box.
+
+      template <typename B>
+      void
+      pmin_pmax_(const Box<B>& b, mln_point(B)& pmin, mln_point(B)& pmax)
+      {
+	pmin = exact(b).pmin();
+	pmax = exact(b).pmax();
+      }
+
+    } // end of namespace mln::geom::impl
+
+
+    template <typename S>
+    void
+    pmin_pmax(const Point_Set<S>& s, mln_point(S)& pmin, mln_point(S)& pmax)
+    {
+      mln_precondition(exact(s).npoints() != 0);
+      impl::pmin_pmax_(exact(s), pmin, pmax);
+    }
+
+    template <typename S>
+    std::pair<mln_point(S), mln_point(S)>
+    pmin_pmax(const Point_Set<S>& s)
+    {
+      mln_precondition(exact(s).npoints() != 0);
+      typedef mln_point(S) P;
+      std::pair<P, P> tmp;
+      pmin_pmax(p_, tmp.first, tmp.second); // calls the previous version
+      return tmp;
     }
 
 # endif // ! MLN_INCLUDE_ONLY
Index: mln/geom/bbox.hh
--- mln/geom/bbox.hh	(revision 1058)
+++ mln/geom/bbox.hh	(working copy)
@@ -100,8 +100,7 @@
       mln_precondition(pset.npoints() != 0);
 
       typedef mln_point(S) P;
-      mln_piter(S) p(pset);
-      std::pair<P, P> pp = geom::pmin_pmax(p);
+      std::pair<P, P> pp = geom::pmin_pmax(pset);
 
       box_<P> tmp(pp.first, pp.second);
       // FIXME: mln_postcondition(tmp <= pset.bbox());
Index: mln/morpho/includes.hh
--- mln/morpho/includes.hh	(revision 1058)
+++ mln/morpho/includes.hh	(working copy)
@@ -40,11 +40,14 @@
 # include <mln/accu/min.hh>
 # include <mln/accu/max.hh>
 
+# include <mln/arith/plus.hh>
 # include <mln/arith/minus.hh>
 
 # include <mln/level/compare.hh>
 # include <mln/level/fill.hh>
 
+# include <mln/test/positive.hh>
+
 # include <mln/border/resize.hh>
 # include <mln/border/fill.hh>
 
Index: mln/morpho/gradient.hh
--- mln/morpho/gradient.hh	(revision 1058)
+++ mln/morpho/gradient.hh	(working copy)
@@ -31,10 +31,11 @@
 /*! \file mln/morpho/gradient.hh
  *
  * \brief Morphological gradient.
+ *
+ * \todo Save memory.
  */
 
 # include <mln/morpho/includes.hh>
-# include <mln/test/positive.hh>
 
 
 namespace mln
@@ -82,11 +83,10 @@
       mln_precondition(output.domain() = input.domain());
       mln_precondition(! win.is_empty());
 
+      dilation(input, win, output); // output = dilation
       O temp(input.domain());
-      erosion(input, win, temp);
-
-      dilation(input, win, output);
-      arith::minus_inplace(output, temp);
+      erosion(input, win, temp); // temp = erosion
+      arith::minus_inplace(output, temp); // now output = dilation - erosion
 
       mln_postcondition(test::positive(output));
     }
@@ -103,9 +103,8 @@
       mln_precondition(! win.is_empty());
 
       O temp(input.domain());
-      erosion(input, win, temp);
-
-      arith::minus(input, temp, output);
+      erosion(input, win, temp); // temp = erosion
+      arith::minus(input, temp, output); // output = input - erosion
 
       mln_postcondition(test::positive(output));
     }
@@ -121,10 +120,8 @@
       mln_precondition(output.domain() = input.domain());
       mln_precondition(! win.is_empty());
 
-      O temp(input.domain());
-      dilation(input, win, temp);
-
-      arith::minus(temp, input, output);
+      dilation(input, win, output); // output = dilation
+      arith::minus_inplace(output, input); // now output = dilation - input
 
       mln_postcondition(test::positive(output));
     }
Index: mln/morpho/contrast.hh
--- mln/morpho/contrast.hh	(revision 0)
+++ mln/morpho/contrast.hh	(revision 0)
@@ -0,0 +1,82 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_MORPHO_CONTRAST_HH
+# define MLN_MORPHO_CONTRAST_HH
+
+/*! \file mln/morpho/contrast.hh
+ *
+ * \brief Morphological contrast operator (based on top-hats).
+ *
+ * \todo Save memory.
+ */
+
+# include <mln/morpho/top_hat.hh>
+
+
+namespace mln
+{
+
+  namespace morpho
+  {
+
+    /*! Morphological contrast operator (based on top-hats).
+     *
+     * This operator is Id + wth_B - bth_B. 
+     */
+    template <typename I, typename W, typename O>
+    void contrast(const Image<I>& input, const Window<W>& win,
+		  Image<O>& output);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I, typename W, typename O>
+    void contrast(const Image<I>& input_, const Window<W>& win_, Image<O>& output_)
+    {
+      const I& input = exact(input_);
+      const W& win = exact(win_);
+      O& output = exact(output_);
+
+      mln_precondition(output.domain() = input.domain());
+      mln_precondition(! win.is_empty());
+
+      top_hat_white(input, win, output); // output = wth
+      arith::plus_inplace(output, input); // now output = wth + input
+      O temp(input.domain());
+      top_hat_black(input, win, temp); // temp = bth
+      arith::minus_inplace(output, temp); // now output = wth + input - bth
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MORPHO_CONTRAST_HH
Index: mln/morpho/top_hat.hh
--- mln/morpho/top_hat.hh	(revision 0)
+++ mln/morpho/top_hat.hh	(revision 0)
@@ -0,0 +1,138 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_MORPHO_TOP_HAT_HH
+# define MLN_MORPHO_TOP_HAT_HH
+
+/*! \file mln/morpho/top_hat.hh
+ *
+ * \brief Morphological top-hats.
+ *
+ * \todo Save memory.
+ */
+
+# include <mln/morpho/opening.hh>
+# include <mln/morpho/closing.hh>
+
+
+namespace mln
+{
+
+  namespace morpho
+  {
+
+    /*! Morphological white top-hat (for object / light objects).
+     *
+     * This operator is Id - ope_B. 
+     */
+    template <typename I, typename W, typename O>
+    void top_hat_white(const Image<I>& input, const Window<W>& win,
+		       Image<O>& output);
+
+
+    /*! Morphological black top-hat (for background / dark objects).
+     *
+     * This operator is clo_B - Id.
+     */
+    template <typename I, typename W, typename O>
+    void top_hat_black(const Image<I>& input, const Window<W>& win,
+		       Image<O>& output);
+
+
+    /*! Morphological self-complementary top-hat.
+     *
+     * This operator is \n
+     *   = top_hat_white + top_hat_black \n
+     *   = (input - opening) + (closing - input) \n
+     *   = closing - opening. \n
+     */
+    template <typename I, typename W, typename O>
+    void top_hat_self_complementary(const Image<I>& input, const Window<W>& win,
+				    Image<O>& output);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I, typename W, typename O>
+    void top_hat_white(const Image<I>& input_, const Window<W>& win_, Image<O>& output_)
+    {
+      const I& input = exact(input_);
+      const W& win = exact(win_);
+      O& output = exact(output_);
+
+      mln_precondition(output.domain() = input.domain());
+      mln_precondition(! win.is_empty());
+
+      O temp(input.domain());
+      opening(input, win, temp); // temp = opening
+      arith::minus(input, temp, output); // output = input - opening
+
+      mln_postcondition(test::positive(output));
+    }
+
+    template <typename I, typename W, typename O>
+    void top_hat_black(const Image<I>& input_, const Window<W>& win_, Image<O>& output_)
+    {
+      const I& input = exact(input_);
+      const W& win = exact(win_);
+      O& output = exact(output_);
+
+      mln_precondition(output.domain() = input.domain());
+      mln_precondition(! win.is_empty());
+
+      closing(input, win, output); // output = closing
+      arith::minus_inplace(output, input); // now output = closing - input
+
+      mln_postcondition(test::positive(output));
+    }
+
+    template <typename I, typename W, typename O>
+    void top_hat_self_complementary(const Image<I>& input_, const Window<W>& win_, Image<O>& output_)
+    {
+      const I& input = exact(input_);
+      const W& win = exact(win_);
+      O& output = exact(output_);
+
+      mln_precondition(output.domain() = input.domain());
+      mln_precondition(! win.is_empty());
+
+      closing(input, win, output); // output = closing
+      O temp(input.domain());
+      opening(input, win, temp); // temp = opening
+      arith::minus_inplace(output, temp); // now output = closing - opening
+
+      mln_postcondition(test::positive(output));
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MORPHO_TOP_HAT_HH
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from  Thierry Geraud  <thierry.geraud(a)lrde.epita.fr>
	Replace 2D specific methods in 2D images by routines.
	* mln/geom/max_col.hh: New.
	* mln/geom/nrows.hh: New.
	* mln/geom/min_row.hh: New.
	* mln/geom/max_row.hh: New.
	* mln/geom/ncols.hh: New.
	* mln/geom/size2d.hh: New.
	* mln/geom/min_col.hh: New.
	* mln/core/image2d_b.hh (image2d_b): Remove inheritance to
	box_impl.
	* tests/image2d_b.cc,
	* mln/core/pixter2d_b.hh,
	* mln/io/save_pgm.hh,
	* mln/io/load_pgm.hh,
	* mln/level/was.median.hh,
	* mln/level/median.hh,
	* mln/level/fast_median.hh,
	* mln/canvas/sbrowsing.hh: Update.
 mln/canvas/sbrowsing.hh  |    7 ++--
 mln/core/image2d_b.hh    |    4 --
 mln/core/pixter2d_b.hh   |    5 ++-
 mln/geom/max_col.hh      |   66 ++++++++++++++++++++++++++++++++++++++++++++++
 mln/geom/max_row.hh      |   66 ++++++++++++++++++++++++++++++++++++++++++++++
 mln/geom/min_col.hh      |   66 ++++++++++++++++++++++++++++++++++++++++++++++
 mln/geom/min_row.hh      |   66 ++++++++++++++++++++++++++++++++++++++++++++++
 mln/geom/ncols.hh        |   67 +++++++++++++++++++++++++++++++++++++++++++++++
 mln/geom/nrows.hh        |   67 +++++++++++++++++++++++++++++++++++++++++++++++
 mln/geom/size2d.hh       |   40 ++++++++++++++++++++++++++++
 mln/io/load_pgm.hh       |   10 +++----
 mln/io/save_pgm.hh       |   17 +++++------
 mln/level/fast_median.hh |    4 +-
 mln/level/median.hh      |   10 ++++---
 mln/level/was.median.hh  |   13 ++++-----
 tests/image2d_b.cc       |    3 +-
 16 files changed, 475 insertions(+), 36 deletions(-)
Index: tests/image2d_b.cc
--- tests/image2d_b.cc	(revision 1057)
+++ tests/image2d_b.cc	(working copy)
@@ -31,6 +31,7 @@
  */
 
 #include <mln/core/image2d_b.hh>
+#include <mln/geom/size2d.hh>
 
 
 int main()
@@ -43,6 +44,6 @@
 
   image2d_b<int> f(nrows, ncols, border);
 
-  mln_assertion(f.npoints() = f.nrows() * f.ncols());
+  mln_assertion(f.npoints() = geom::nrows(f) * geom::ncols(f));
   mln_assertion(f.ncells()  = (nrows + 2 * border) * (ncols + 2 * border));
 }
Index: mln/geom/max_col.hh
--- mln/geom/max_col.hh	(revision 0)
+++ mln/geom/max_col.hh	(revision 0)
@@ -0,0 +1,66 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_GEOM_MAX_COL_HH
+# define MLN_GEOM_MAX_COL_HH
+
+/*! \file mln/geom/max_col.hh
+ *
+ * \brief Give the maximum column of an image.
+ */
+
+# include <mln/core/concept/image.hh>
+
+
+namespace mln
+{
+
+  namespace geom
+  {
+
+    /// Give the maximum column of an image.
+    template <typename I>
+    mln_coord(I) max_col(const Image<I>& ima);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I>
+    mln_coord(I) max_col(const Image<I>& ima)
+    {
+      mln_precondition(exact(ima).has_data());
+      return exact(ima).bbox().pmax().col();
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::geom
+
+} // end of namespace mln
+
+
+#endif // ! MLN_GEOM_MAX_COL_HH
Index: mln/geom/nrows.hh
--- mln/geom/nrows.hh	(revision 0)
+++ mln/geom/nrows.hh	(revision 0)
@@ -0,0 +1,67 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_GEOM_NROWS_HH
+# define MLN_GEOM_NROWS_HH
+
+/*! \file mln/geom/nrows.hh
+ *
+ * \brief Give the number of rows of an image.
+ */
+
+# include <mln/geom/min_row.hh>
+# include <mln/geom/max_row.hh>
+
+
+namespace mln
+{
+
+  namespace geom
+  {
+
+    /// Give the number of rows of an image.
+    template <typename I>
+    unsigned nrows(const Image<I>& ima);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I>
+    unsigned nrows(const Image<I>& ima)
+    {
+      mln_precondition(exact(ima).has_data());
+      return geom::max_row(ima) - geom::min_row(ima) + 1;
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::geom
+
+} // end of namespace mln
+
+
+#endif // ! MLN_GEOM_NROWS_HH
Index: mln/geom/min_row.hh
--- mln/geom/min_row.hh	(revision 0)
+++ mln/geom/min_row.hh	(revision 0)
@@ -0,0 +1,66 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_GEOM_MIN_ROW_HH
+# define MLN_GEOM_MIN_ROW_HH
+
+/*! \file mln/geom/min_row.hh
+ *
+ * \brief Give the minimum row of an image.
+ */
+
+# include <mln/core/concept/image.hh>
+
+
+namespace mln
+{
+
+  namespace geom
+  {
+
+    /// Give the minimum row of an image.
+    template <typename I>
+    mln_coord(I) min_row(const Image<I>& ima);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I>
+    mln_coord(I) min_row(const Image<I>& ima)
+    {
+      mln_precondition(exact(ima).has_data());
+      return exact(ima).bbox().pmin().row();
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::geom
+
+} // end of namespace mln
+
+
+#endif // ! MLN_GEOM_MIN_ROW_HH
Index: mln/geom/max_row.hh
--- mln/geom/max_row.hh	(revision 0)
+++ mln/geom/max_row.hh	(revision 0)
@@ -0,0 +1,66 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_GEOM_MAX_ROW_HH
+# define MLN_GEOM_MAX_ROW_HH
+
+/*! \file mln/geom/max_row.hh
+ *
+ * \brief Give the maximum row of an image.
+ */
+
+# include <mln/core/concept/image.hh>
+
+
+namespace mln
+{
+
+  namespace geom
+  {
+
+    /// Give the maximum row of an image.
+    template <typename I>
+    mln_coord(I) max_row(const Image<I>& ima);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I>
+    mln_coord(I) max_row(const Image<I>& ima)
+    {
+      mln_precondition(exact(ima).has_data());
+      return exact(ima).bbox().pmax().row();
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::geom
+
+} // end of namespace mln
+
+
+#endif // ! MLN_GEOM_MAX_ROW_HH
Index: mln/geom/ncols.hh
--- mln/geom/ncols.hh	(revision 0)
+++ mln/geom/ncols.hh	(revision 0)
@@ -0,0 +1,67 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_GEOM_NCOLS_HH
+# define MLN_GEOM_NCOLS_HH
+
+/*! \file mln/geom/ncols.hh
+ *
+ * \brief Give the number of columns of an image.
+ */
+
+# include <mln/geom/min_col.hh>
+# include <mln/geom/max_col.hh>
+
+
+namespace mln
+{
+
+  namespace geom
+  {
+
+    /// Give the number of columns of an image.
+    template <typename I>
+    unsigned ncols(const Image<I>& ima);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I>
+    unsigned ncols(const Image<I>& ima)
+    {
+      mln_precondition(exact(ima).has_data());
+      return geom::max_col(ima) - geom::min_col(ima) + 1;
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::geom
+
+} // end of namespace mln
+
+
+#endif // ! MLN_GEOM_NCOLS_HH
Index: mln/geom/size2d.hh
--- mln/geom/size2d.hh	(revision 0)
+++ mln/geom/size2d.hh	(revision 0)
@@ -0,0 +1,40 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_GEOM_SIZE2D_HH
+# define MLN_GEOM_SIZE2D_HH
+
+/*! \file mln/geom/size2d.hh
+ *
+ * \brief Facade to include 2D size access routines.
+ */
+
+# include <mln/geom/nrows.hh>
+# include <mln/geom/ncols.hh>
+
+
+#endif // ! MLN_GEOM_SIZE2D_HH
Index: mln/geom/min_col.hh
--- mln/geom/min_col.hh	(revision 0)
+++ mln/geom/min_col.hh	(revision 0)
@@ -0,0 +1,66 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_GEOM_MIN_COL_HH
+# define MLN_GEOM_MIN_COL_HH
+
+/*! \file mln/geom/min_col.hh
+ *
+ * \brief Give the minimum column of an image.
+ */
+
+# include <mln/core/concept/image.hh>
+
+
+namespace mln
+{
+
+  namespace geom
+  {
+
+    /// Give the minimum column of an image.
+    template <typename I>
+    mln_coord(I) min_col(const Image<I>& ima);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I>
+    mln_coord(I) min_col(const Image<I>& ima)
+    {
+      mln_precondition(exact(ima).has_data());
+      return exact(ima).bbox().pmin().col();
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::geom
+
+} // end of namespace mln
+
+
+#endif // ! MLN_GEOM_MIN_COL_HH
Index: mln/core/pixter2d_b.hh
--- mln/core/pixter2d_b.hh	(revision 1057)
+++ mln/core/pixter2d_b.hh	(working copy)
@@ -35,6 +35,7 @@
 
 # include <mln/core/internal/pixel_iterator_base.hh>
 # include <mln/core/point2d.hh>
+# include <mln/geom/size2d.hh>
 
 
 
@@ -84,8 +85,8 @@
   {
     mln_precondition(image.has_data());
     border_x2_ = 2 * image.border();
-    row_offset_ = image.max_col() - image.min_col() + 1 + border_x2_;
-    eor_ = & image.at(image.min_row(), image.max_col()) + 1;
+    row_offset_ = geom::max_col(image) - geom::min_col(image) + 1 + border_x2_;
+    eor_ = & image.at(geom::min_row(image), geom::max_col(image)) + 1;
   }
 
   template <typename I>
Index: mln/core/image2d_b.hh
--- mln/core/image2d_b.hh	(revision 1057)
+++ mln/core/image2d_b.hh	(working copy)
@@ -34,7 +34,6 @@
  */
 
 # include <mln/core/internal/image_base.hh>
-# include <mln/core/internal/box_impl.hh>
 # include <mln/core/box2d.hh>
 
 # include <mln/border/thickness.hh>
@@ -75,8 +74,7 @@
    * thickness around data.
    */
   template <typename T>
-  struct image2d_b : public internal::image_base_< box2d, image2d_b<T> >,
-		     public internal::box_impl_< 2, int, image2d_b<T> >
+  struct image2d_b : public internal::image_base_< box2d, image2d_b<T> >
   {
     // Warning: just to make effective types appear in Doxygen:
     typedef box2d   pset;
Index: mln/io/save_pgm.hh
--- mln/io/save_pgm.hh	(revision 1057)
+++ mln/io/save_pgm.hh	(working copy)
@@ -33,6 +33,7 @@
 # include <fstream>
 
 # include <mln/core/image2d_b.hh>
+# include <mln/geom/size2d.hh>
 # include <mln/value/int_u8.hh>
 
 
@@ -53,16 +54,16 @@
 	}
       file << "P5" << std::endl;
       file << "# olena" << std::endl;
-      file << ima.ncols() << ' ' << ima.nrows() << std::endl;
+      file << geom::ncols(ima) << ' ' << geom::nrows(ima) << std::endl;
       file << "255" << std::endl;
       const int
-	min_row = ima.domain().pmin().row(),
-	max_row = ima.domain().pmax().row();
+	min_row = geom::min_row(ima),
+	max_row = geom::max_row(ima);
       point2d p;
       if (sizeof(value::int_u8) = 1)
 	{
-	  p.col() = ima.domain().pmin().col();
-	  size_t len = ima.ncols();
+	  p.col() = geom::min_col(ima);
+	  size_t len = geom::ncols(ima);
 	  for (p.row() = min_row; p.row() <= max_row; ++p.row())
 	    file.write((char*)(& ima(p)), len);
 	}
@@ -70,10 +71,8 @@
 	{
 	  // FIXME: code for g++-2.95 when sizeof(int_u8) = 2!!!
 	  const int
-	    min_col = ima.domain().pmin().col(),
-	    max_col = ima.domain().pmax().col();
-	  std::cout << min_row << ' ' << max_row << std::endl;
-	  std::cout << min_col << ' ' << max_col << std::endl;
+	    min_col = geom::min_col(ima),
+	    max_col = geom::max_col(ima);
 	  for (p.row() = min_row; p.row() <= max_row; ++p.row())
 	    for (p.col() = min_col; p.col() <= max_col; ++p.col())
 	      {
Index: mln/io/load_pgm.hh
--- mln/io/load_pgm.hh	(revision 1057)
+++ mln/io/load_pgm.hh	(working copy)
@@ -137,11 +137,11 @@
 	point2d p = make::point2d(0, ima.domain().pmin().col());
 	typedef mln_value(I) V;
 	const mln_coord(I)
-	  min_row = ima.domain().pmin().row(),
-	  max_row = ima.domain().pmax().row();
+	  min_row = geom::min_row(ima),
+	  max_row = geom::max_row(ima);
 	if (sizeof(V) = 1)
 	  {
-	    size_t len = ima.ncols() * sizeof(mln_enc(V));
+	    size_t len = geom::ncols(ima) * sizeof(mln_enc(V));
 	    for (p.row() = min_row; p.row() <= max_row; ++p.row())
 	      file.read((char*)(& ima(p)), len);
 	  }
@@ -149,8 +149,8 @@
 	  {
 	    // FIXME: code for g++-2.95 when sizeof(int_u8) = 2!!!
 	    const mln_coord(I)
-	      min_col = ima.domain().pmin().col(),
-	      max_col = ima.domain().pmax().col();
+	      min_col = geom::min_col(ima),
+	      max_col = geom::max_col(ima);
 	    for (p.row()  = min_row; p.row() <= max_row; ++p.row())
 	      for (p.col()  = min_col; p.col() <= max_col; ++p.col())
 		{
Index: mln/level/was.median.hh
--- mln/level/was.median.hh	(revision 1057)
+++ mln/level/was.median.hh	(working copy)
@@ -55,8 +55,8 @@
 	mln_precondition(output.has_data());
 
 	int
-	  min_row = input.min_row(), max_row = input.max_row(),
-	  min_col = input.min_col(), max_col = input.max_col();
+	  min_row = geom::min_row(input), max_row = geom::max_row(input),
+	  min_col = geom::min_col(input), max_col = geom::max_col(input);
 
 	window2d
 	  win_fwd_plus  = win - (win + left),
@@ -76,7 +76,7 @@
 
 	// initialization
 
-	p = input.domain().pmin() + up;
+	p = input.bbox().pmin() + up;
 	med.init();
 	{
 	  mln_qiter(W) q(win, p);
@@ -137,9 +137,8 @@
       {
 
 	const int
-	  max_row = input.max_row(),
-	  min_col = input.min_col(),
-	  max_col = input.max_col();
+	  min_row = geom::min_row(input), max_row = geom::max_row(input),
+	  min_col = geom::min_col(input), max_col = geom::max_col(input);
 	const unsigned half = win.length() / 2;
 
 	point2d p;
@@ -148,7 +147,7 @@
 
 	accu::median<mln_vset(I)> med(input.values());
 
-	for (row = input.min_row(); row <= max_row; ++row)
+	for (row = min_row; row <= max_row; ++row)
 	  {
 	    int ct, cu;
 
Index: mln/level/median.hh
--- mln/level/median.hh	(revision 1057)
+++ mln/level/median.hh	(working copy)
@@ -34,6 +34,7 @@
  */
 
 # include <mln/core/concept/image.hh>
+# include <mln/geom/size2d.hh>
 
 # include <mln/core/window2d.hh>
 # include <mln/core/win/hline2d.hh>
@@ -162,9 +163,10 @@
       {
 	typedef mln_coord(I) coord;
 	const coord
-	  max_row = input.bbox().max_row(),
-	  min_col = input.bbox().min_col(),
-	  max_col = input.bbox().max_col();
+	  min_row = geom::min_row(input),
+	  max_row = geom::max_row(input),
+	  min_col = geom::min_col(input),
+	  max_col = geom::max_col(input);
 	const coord half = win.length() / 2;
 
 	point2d p;
@@ -179,7 +181,7 @@
 
 	accu::median<mln_vset(I)> med(input.values());
 
-	for (row = input.bbox().min_row(); row <= max_row; ++row)
+	for (row = min_row; row <= max_row; ++row)
 	  {
 	    pt.row() = pu.row() = row;
 
Index: mln/level/fast_median.hh
--- mln/level/fast_median.hh	(revision 1057)
+++ mln/level/fast_median.hh	(working copy)
@@ -73,8 +73,8 @@
 	mln_precondition(output.has_data());
 
 	int
-	  min_row = input.min_row(), max_row = input.max_row(),
-	  min_col = input.min_col(), max_col = input.max_col();
+	  min_row = geom::min_row(input), max_row = geom::max_row(input),
+	  min_col = geom::min_col(input), max_col = geom::max_col(input);
 
 	window2d
 	  win_fwd_plus  = win - (win + left),
Index: mln/canvas/sbrowsing.hh
--- mln/canvas/sbrowsing.hh	(revision 1057)
+++ mln/canvas/sbrowsing.hh	(working copy)
@@ -34,6 +34,7 @@
  */
 
 # include <mln/core/dpoint2d.hh> // for "up"
+# include <mln/geom/size2d.hh>
 
 
 namespace mln
@@ -69,11 +70,11 @@
     {
       mln_precondition(f.input.has_data());
       int
-	min_row = f.input.min_row(), max_row = f.input.max_row(),
-	min_col = f.input.min_col(), max_col = f.input.max_col();
+	min_row = geom::min_row(f.input), max_row = geom::max_row(f.input),
+	min_col = geom::min_col(f.input), max_col = geom::max_col(f.input);
 
       // p
-      f.p = f.input.domain().pmin() + up;
+      f.p = f.input.bbox().pmin() + up;
       int& row = f.p.row();
       int& col = f.p.col();
 
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from  Thierry Geraud  <thierry.geraud(a)lrde.epita.fr>
	Fix compilation errors.
	* tests/run_pset.cc: Fix and clean.
	* tests/README: Augment.
	* tests/erosion.cc: Clean.
	* mln/core/internal/run_pset.hh: Fix.
	* mln/core/concept/function.hh: Add explicit calls to cpy
	ctors.
 mln/core/concept/function.hh  |   23 ++++++++----
 mln/core/internal/run_pset.hh |    2 -
 tests/README                  |   16 ++++++++
 tests/erosion.cc              |    7 ++-
 tests/run_pset.cc             |   77 ++++++++++++++++++++++++++----------------
 5 files changed, 85 insertions(+), 40 deletions(-)
Index: tests/run_pset.cc
--- tests/run_pset.cc	(revision 1056)
+++ tests/run_pset.cc	(working copy)
@@ -1,58 +1,79 @@
-#include <mln/core/internal/run_pset.hh>
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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 tests/run_pset.cc
+ *
+ * \brief Test on mln::internal::run_pset_ and related tools.
+ */
+
 #include <mln/core/image2d_b.hh>
-#include <iostream>
+#include <mln/core/internal/run_pset.hh>
 
-using namespace mln;
 
 template <typename Pset>
-void
-parc(const Pset& pset)
+void parc(const Pset& pset)
 {
-  typename Pset::fwd_piter it_(pset);
-
+  mln_fwd_piter(Pset) it_(pset);
   for_all(it_)
-  {
-    std::cout << (typename Pset::point) it_ << std::endl;
-  }
-
-  typename Pset::bkd_piter rit_(pset);
+    std::cout << it_ << std::endl;
 
+  mln_bkd_piter(Pset) rit_(pset);
   for_all(rit_)
-  {
-    std::cout << (typename Pset::point) rit_ << std::endl;
-  }
+    std::cout << rit_ << std::endl;
 }
 
 
-int
-main()
+int main()
 {
+  using namespace mln;
+
   point2d p, q, r;
   p = make::point2d(2, 4);
   q = make::point2d(18, 42);
   r = make::point2d(50, 76);
 
   // Psite declaration
-  run_psite<point2d>  site(p, 5, 0);
-  run_psite<point2d>  site2(r, 40, 0);
+  internal::run_psite<point2d>  site(p, 5, 0);
+  internal::run_psite<point2d>  site2(r, 40, 0);
 
   // Pset test
   internal::run_pset_<point2d> ps;
 
   ps.insert(p, 7);
-  assert(ps.npoints() = 7);
+  mln_assertion(ps.npoints() = 7);
 
   ps.insert(q, 42);
-  assert(ps.npoints() = 49);
+  mln_assertion(ps.npoints() = 49);
 
-  assert(ps.has(site));
-  assert(!ps.has(site2));
+  mln_assertion(ps.has(site));
+  mln_assertion(!ps.has(site2));
 
   ps.insert(r, 14);
-  assert(!ps.has(site2));
-
-  // FIXME bbox test
+  mln_assertion(!ps.has(site2));
 
-  parc(ps);
-  return 0;
+  // parc(ps);
 }
Index: tests/README
--- tests/README	(revision 1056)
+++ tests/README	(working copy)
@@ -4,14 +4,28 @@
 
 * compilation
 
+** g++-4.1
+*** options
+-ansi -pedantic -W -Wall -Wextra -Wconversion
+*** sample
 g++-4.1 -ansi -pedantic -W -Wall -Wextra -Wconversion  -I..  sample.cc
 
+** g++-2.95
+*** options
+-ansi -pedantic -W -Wall -Wconversion -ftemplate-depth-51
+*** sample
 g++-2.95 -ansi -pedantic -W -Wall -Wconversion -ftemplate-depth-51  -I..  sample.cc
 
+** icpc-9.1
+*** options
+-w1 -Wcheck -Werror -ansi
+*** sample
+icpc-9.1 -w1 -Wcheck -Werror -ansi -I.. sample.cc
+
 
 * bench
 
+** median
 naive: 18s
 median: 1s
 approx: 0.05s
-
Index: tests/erosion.cc
--- tests/erosion.cc	(revision 1056)
+++ tests/erosion.cc	(working copy)
@@ -54,12 +54,13 @@
   win::rectangle2d rec(21, 21);
   border::thickness = 66;
 
-  image2d_b<int_u8>
-    lena = io::load_pgm("../img/lena.pgm"),
-    out(lena.domain());
+  image2d_b<int_u8> lena = io::load_pgm("../img/lena.pgm");
 
+  { 
+    image2d_b<int_u8> out(lena.domain());
   morpho::erosion(lena, rec, out);
   io::save_pgm(out, "out.pgm");
+  }
 
   {
     image2d_b<bool> bin(lena.domain()), out(lena.domain());
Index: mln/core/internal/run_pset.hh
--- mln/core/internal/run_pset.hh	(revision 1056)
+++ mln/core/internal/run_pset.hh	(working copy)
@@ -217,7 +217,7 @@
     }
 
     template <typename P, typename E>
-    run_piter_<P, E>::operator typename run_piter_<P, E>::psite () const
+    run_piter_<P, E>::operator internal::run_psite<P> () const
     {
       return site_;
     }
Index: mln/core/concept/function.hh
--- mln/core/concept/function.hh	(revision 1056)
+++ mln/core/concept/function.hh	(working copy)
@@ -148,7 +148,8 @@
   }
 
   template <typename E>
-  Function<E>::Function(const Function<E>&)
+  Function<E>::Function(const Function<E>& rhs)
+    : Object<E>(rhs)
   {
   }
 
@@ -158,7 +159,8 @@
   }
 
   template <typename E>
-  Function_v2v<E>::Function_v2v(const Function_v2v<E>&)
+  Function_v2v<E>::Function_v2v(const Function_v2v<E>& rhs)
+    : Function<E>(rhs)
   {
   }
 
@@ -168,7 +170,8 @@
   }
 
   template <typename E>
-  Function_i2v<E>::Function_i2v(const Function_i2v<E>&)
+  Function_i2v<E>::Function_i2v(const Function_i2v<E>& rhs)
+    : Function_v2v<E>(rhs)
   {
   }
 
@@ -178,7 +181,8 @@
   }
 
   template <typename E>
-  Function_p2v<E>::Function_p2v(const Function_p2v<E>&)
+  Function_p2v<E>::Function_p2v(const Function_p2v<E>& rhs)
+    : Function_v2v<E>(rhs)
   {
   }
 
@@ -188,7 +192,8 @@
   }
 
   template <typename E>
-  Function_v2b<E>::Function_v2b(const Function_v2b<E>&)
+  Function_v2b<E>::Function_v2b(const Function_v2b<E>& rhs)
+    : Function_v2v<E>(rhs)
   {
   }
 
@@ -198,7 +203,10 @@
   }
 
   template <typename E>
-  Function_p2b<E>::Function_p2b(const Function_p2b<E>&)
+  Function_p2b<E>::Function_p2b(const Function_p2b<E>& rhs)
+    : Function_v2v<E>(rhs),
+      Function_p2v<E>(rhs),
+      Function_v2b<E>(rhs)
   {
   }
 
@@ -208,7 +216,8 @@
   }
 
   template <typename E>
-  Function_p2p<E>::Function_p2p(const Function_p2p<E>&)
+  Function_p2p<E>::Function_p2p(const Function_p2p<E>& rhs)
+    : Function_p2v<E>(rhs)
   {
   }
 
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from  Thierry Geraud  <thierry.geraud(a)lrde.epita.fr>
	Augment morpho and add saturation for int-like types.
	* mln/arith/minus.hh (minus_inplace): New.
	* mln/arith/plus.hh (plus_inplace): New.
	* mln/fun/v2v/saturate.hh: New.
	* mln/level/abs.hh: New.
	* mln/level/saturate.hh: New.
	* mln/linear/sobel.hh: Update.
	* mln/math/round.hh (round_): Rename as...
	(round): ...this.
	* tests/convolve.cc,
	* tests/line_convolve.cc,
	* tests/sobel.cc: Update.
	* mln/linear/line_convolve.hh,
	* mln/linear/line_x2_convolve.hh,
	* mln/make/w_window_line.hh: Unconst array literals to help
	g++-2.95.
	* mln/core/concept/function.hh (Function_v2b): New.
	* mln/core/macros.hh (mln_value_): New.
	* mln/fun/ops.hh (l_, r_, f_): Add const.
	(mln_decl_binary_expr_): Use 'Out' part of fun type name.
	(mln_decl_unary_expr_): Likewise.
	New overload for "v2v -> v2b" operators.
	* mln/fun/v2v/id.hh: New.
	* mln/level/assign.hh,
	* mln/level/fill.hh: Add todo.
	* mln/morpho/erosion.hh: Update.
	* mln/morpho/includes.hh,
	* mln/morpho/closing.hh,
	* mln/morpho/dilation.hh
	* mln/morpho/gradient.hh
	* mln/morpho/opening.hh: New.
	* mln/test: New directory.
	* mln/test/positive.hh,
	* mln/test/predicate.hh,
	* tests/morpho_gradient.cc: New.
 mln/arith/minus.hh             |   72 +++++++++++++++++++--
 mln/arith/plus.hh              |   42 ++++++++++++
 mln/core/concept/function.hh   |   70 ++++++++++++++++++++
 mln/core/macros.hh             |    1 
 mln/fun/internal/selector.hh   |   22 +++---
 mln/fun/ops.hh                 |   42 +++++++++---
 mln/fun/v2v/id.hh              |   77 ++++++++++++++++++++++
 mln/fun/v2v/saturate.hh        |  105 ++++++++++++++++++++++++++++++
 mln/level/abs.hh               |   89 ++++++++++++++++++++++++++
 mln/level/assign.hh            |    2 
 mln/level/fill.hh              |    2 
 mln/level/saturate.hh          |  121 +++++++++++++++++++++++++++++++++++
 mln/linear/line_convolve.hh    |    4 -
 mln/linear/line_x2_convolve.hh |    4 -
 mln/linear/sobel.hh            |   16 ++--
 mln/make/w_window_line.hh      |    4 -
 mln/math/round.hh              |    4 -
 mln/morpho/closing.hh          |   79 +++++++++++++++++++++++
 mln/morpho/dilation.hh         |  102 ++++++++++++++++++++++++++++++
 mln/morpho/erosion.hh          |   32 ++++-----
 mln/morpho/gradient.hh         |  139 +++++++++++++++++++++++++++++++++++++++++
 mln/morpho/includes.hh         |   56 ++++++++++++++++
 mln/morpho/opening.hh          |   79 +++++++++++++++++++++++
 mln/test/positive.hh           |   73 +++++++++++++++++++++
 mln/test/predicate.hh          |  128 +++++++++++++++++++++++++++++++++++++
 tests/convolve.cc              |    2 
 tests/line_convolve.cc         |    3 
 tests/morpho_gradient.cc       |   58 +++++++++++++++++
 tests/sobel.cc                 |    6 -
 tests/test_positive.cc         |   64 ++++++++++++++++++
 30 files changed, 1431 insertions(+), 67 deletions(-)
Index: tests/convolve.cc
--- tests/convolve.cc	(revision 1055)
+++ tests/convolve.cc	(working copy)
@@ -63,7 +63,7 @@
 
   image2d_b<float> tmp(lena.domain());
   linear::convolve(lena, w, tmp);
-  level::transform(tmp, math::round_<int_u8>(), out);
+  level::transform(tmp, math::round<int_u8>(), out);
 
   io::save_pgm(out, "out.pgm");
 }
Index: tests/sobel.cc
--- tests/sobel.cc	(revision 1055)
+++ tests/sobel.cc	(working copy)
@@ -32,13 +32,11 @@
 
 #include <mln/core/image2d_b.hh>
 #include <mln/value/int_u8.hh>
+#include <mln/level/saturate.hh>
 
 #include <mln/io/load_pgm.hh>
 #include <mln/io/save_pgm.hh>
 
-#include <mln/math/round_sat.hh>
-#include <mln/level/transform.hh>
-
 #include <mln/border/thickness.hh>
 #include <mln/linear/sobel.hh>
 
@@ -57,6 +55,6 @@
   image2d_b<int> tmp(lena.domain());
   linear::sobel(lena, tmp);
 
-  level::transform(tmp, math::round_sat_<int_u8>(), out);
+  level::saturate(tmp, out);
   io::save_pgm(out, "out.pgm");
 }
Index: tests/test_positive.cc
--- tests/test_positive.cc	(revision 0)
+++ tests/test_positive.cc	(revision 0)
@@ -0,0 +1,64 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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 tests/test_positive.cc
+ *
+ * \brief Tests on mln::test::positive.
+ */
+
+#include <mln/core/image2d_b.hh>
+#include <mln/level/fill.hh>
+#include <mln/test/positive.hh>
+
+
+// both test routines can be called with a p2b function
+
+template <typename F>
+void test_p2v(const mln::Function_p2v<F>&)
+{
+}
+
+template <typename F>
+void test_v2b(const mln::Function_v2b<F>&)
+{
+}
+
+
+
+int main()
+{
+  using namespace mln;
+  typedef image2d_b<int> I;
+
+  I ima(1,1);
+  level::fill(ima, 0);
+
+  test_v2b(fun::v2v::id<mln_value_(I)>() >= pw::cst(0));
+
+  // test2(fun::v2v::id<mln_value_(I)>() >= pw::cst(0));
+  // test::positive(ima);
+}
Index: tests/line_convolve.cc
--- tests/line_convolve.cc	(revision 1055)
+++ tests/line_convolve.cc	(working copy)
@@ -36,7 +36,6 @@
 #include <mln/io/load_pgm.hh>
 #include <mln/io/save_pgm.hh>
 #include <mln/math/round.hh>
-#include <mln/math/round_sat.hh>
 #include <mln/level/transform.hh>
 
 #include <mln/core/w_window2d_float.hh>
@@ -59,6 +58,6 @@
   float ws[] = { .11, .11, .11, .11, .11, .11, .11, .11, .11 };
   linear::line_convolve(lena, ws, tmp);
   
-  level::transform(tmp, math::round_<int_u8>(), out);
+  level::transform(tmp, math::round<int_u8>(), out);
   io::save_pgm(out, "out.pgm");
 }
Index: tests/morpho_gradient.cc
--- tests/morpho_gradient.cc	(revision 0)
+++ tests/morpho_gradient.cc	(revision 0)
@@ -0,0 +1,58 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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 tests/erosion.cc
+ *
+ * \brief Test on mln::morpho::erosion.
+ */
+
+#include <mln/core/image2d_b.hh>
+#include <mln/core/win/rectangle2d.hh>
+
+#include <mln/io/load_pgm.hh>
+#include <mln/io/save_pgm.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/morpho/gradient.hh>
+
+
+
+int main()
+{
+  using namespace mln;
+  using value::int_u8;
+
+  win::rectangle2d rect(5, 5);
+  border::thickness = 2;
+
+  image2d_b<int_u8>
+    lena = io::load_pgm("../img/tiny.pgm"),
+    out(lena.domain());
+
+  morpho::gradient(lena, rect, out);
+  io::save_pgm(out, "out.pgm");
+}
Index: mln/test/positive.hh
--- mln/test/positive.hh	(revision 0)
+++ mln/test/positive.hh	(revision 0)
@@ -0,0 +1,73 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_TEST_POSITIVE_HH
+# define MLN_TEST_POSITIVE_HH
+
+/*! \file mln/test/positive.hh
+ *
+ * \brief Test if an image only contains positive values.
+ */
+
+# include <mln/test/predicate.hh>
+# include <mln/pw/all.hh>
+# include <mln/fun/v2v/id.hh>
+
+
+namespace mln
+{
+
+  namespace test
+  {
+
+    /// Test if an image only contains positive values.
+    template <typename I>
+    bool positive(const Image<I>& input);
+
+  
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I>
+    bool positive(const Image<I>& input_)
+    {
+      const I& input = exact(input_);
+      mln_precondition(input.has_data());
+      return test::predicate(input.domain(),
+			     pw::value(input) >= pw::cst(0));
+      // FIXME: test the version below.
+//       return test::predicate(input,
+// 			     fun::v2v::id<mln_value(I)>() >= pw::cst(0));
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::test
+
+} // end of namespace mln
+
+
+#endif // ! MLN_TEST_POSITIVE_HH
Index: mln/test/predicate.hh
--- mln/test/predicate.hh	(revision 0)
+++ mln/test/predicate.hh	(revision 0)
@@ -0,0 +1,128 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_TEST_PREDICATE_HH
+# define MLN_TEST_PREDICATE_HH
+
+/*! \file mln/test/predicate.hh
+ *
+ * \brief Test a predicate on the pixel values of an image.
+ */
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/function.hh>
+# include <mln/core/concept/point_set.hh>
+
+
+namespace mln
+{
+
+  namespace test
+  {
+
+    /*! Test if all pixel values of \p ima verify the predicate \p
+     *  f.
+     *
+     * \param[in] ima The image.
+     * \param[in] f The predicate.
+     */
+    template <typename I, typename F>
+    bool predicate(const Image<I>& ima, const Function_v2b<F>& f);
+
+
+    /*! Test if all points of \p pset verify the predicate \p f.
+     *
+     * \param[in] pset The point set.
+     * \param[in] f The predicate.
+     */
+    template <typename S, typename F>
+    bool predicate(const Point_Set<S>& pset, const Function_p2b<F>& f);
+
+  
+# ifndef MLN_INCLUDE_ONLY
+
+    namespace impl
+    {
+
+      template <typename I, typename F>
+      bool predicate_(const Image<I>& ima_, const F& f)
+      {
+	const I& ima = exact(ima_);
+	mln_piter(I) p(ima.domain());
+	for_all(p)
+	  if (! f(ima(p)))
+	    return false;
+	return true;
+      }
+
+      template <typename I, typename F>
+      bool predicate_(const Fast_Image<I>& ima_, const F& f)
+      {
+	const I& ima = exact(ima_);
+	mln_pixter(const I) pxl(ima);
+	for_all(pxl)
+	  if (! f(pxl.val()))
+	    return false;
+	return true;
+      }
+
+      template <typename S, typename F>
+      bool predicate_(const Point_Set<S>& pset, const F& f)
+      {
+	mln_piter(S) p(exact(pset));
+	for_all(p)
+	  if (! f(p))
+	    return false;
+	return true;
+      }
+
+    } // end of namespace mln::test::impl
+
+
+    // Facades.
+
+    template <typename I, typename F>
+    bool predicate(const Image<I>& ima, const Function_v2b<F>& f)
+    {
+      mln_precondition(exact(ima).has_data());
+      return impl::predicate_(exact(ima), exact(f));
+    }
+
+    template <typename S, typename F>
+    bool predicate(const Point_Set<S>& pset, const Function_p2b<F>& f)
+    {
+      return impl::predicate_(exact(pset), exact(f));
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::test
+
+} // end of namespace mln
+
+
+#endif // ! MLN_TEST_PREDICATE_HH
Index: mln/pw/value.hh
Index: mln/core/macros.hh
--- mln/core/macros.hh	(revision 1055)
+++ mln/core/macros.hh	(working copy)
@@ -148,6 +148,7 @@
 
 /// Shortcut to access the value type associated to T.
 # define mln_value(T)      typename T::value
+# define mln_value_(T)     T::value
 
 /// Shortcut to the kind of values for an image with type \c I.
 # define mln_value_kind(I) typename mln::value::props< mln_value(I) >::kind
Index: mln/core/concept/function.hh
--- mln/core/concept/function.hh	(revision 1055)
+++ mln/core/concept/function.hh	(working copy)
@@ -53,6 +53,7 @@
      */
   protected:
     Function();
+    Function(const Function&);
   };
 
 
@@ -65,6 +66,7 @@
   {
   protected:
     Function_v2v();
+    Function_v2v(const Function_v2v&);
   };
 
 
@@ -77,6 +79,7 @@
   {
   protected:
     Function_i2v();
+    Function_i2v(const Function_i2v&);
   };
 
 
@@ -85,10 +88,25 @@
   /// Base class for implementation of function-objects from point to
   /// value.
   template <typename E>
-  struct Function_p2v : public Function_v2v<E>
+  struct Function_p2v : public virtual Function_v2v<E>
   {
   protected:
     Function_p2v();
+    Function_p2v(const Function_p2v&);
+  };
+
+
+  // Value -> bool.
+
+  /// Base class for implementation of function-objects from value to
+  /// bool.
+  template <typename E>
+  struct Function_v2b : public virtual Function_v2v<E>
+  {
+    typedef bool result;
+  protected:
+    Function_v2b();
+    Function_v2b(const Function_v2b&);
   };
 
 
@@ -97,11 +115,13 @@
   /// Base class for implementation of function-objects from point to
   /// bool.
   template <typename E>
-  struct Function_p2b : public Function_p2v<E>
+  struct Function_p2b : public Function_p2v<E>,
+			public Function_v2b<E>
   {
     typedef bool result;
   protected:
     Function_p2b();
+    Function_p2b(const Function_p2b&);
   };
 
 
@@ -114,6 +134,7 @@
   {
   protected:
     Function_p2p();
+    Function_p2p(const Function_p2p&);
   };
 
 
@@ -127,25 +148,70 @@
   }
 
   template <typename E>
+  Function<E>::Function(const Function<E>&)
+  {
+  }
+
+  template <typename E>
   Function_v2v<E>::Function_v2v()
   {
   }
 
   template <typename E>
+  Function_v2v<E>::Function_v2v(const Function_v2v<E>&)
+  {
+  }
+
+  template <typename E>
   Function_i2v<E>::Function_i2v()
   {
   }
 
   template <typename E>
+  Function_i2v<E>::Function_i2v(const Function_i2v<E>&)
+  {
+  }
+
+  template <typename E>
   Function_p2v<E>::Function_p2v()
   {
   }
 
   template <typename E>
+  Function_p2v<E>::Function_p2v(const Function_p2v<E>&)
+  {
+  }
+
+  template <typename E>
+  Function_v2b<E>::Function_v2b()
+  {
+  }
+
+  template <typename E>
+  Function_v2b<E>::Function_v2b(const Function_v2b<E>&)
+  {
+  }
+
+  template <typename E>
   Function_p2b<E>::Function_p2b()
   {
   }
 
+  template <typename E>
+  Function_p2b<E>::Function_p2b(const Function_p2b<E>&)
+  {
+  }
+
+  template <typename E>
+  Function_p2p<E>::Function_p2p()
+  {
+  }
+
+  template <typename E>
+  Function_p2p<E>::Function_p2p(const Function_p2p<E>&)
+  {
+  }
+
 # endif // ! MLN_INCLUDE_ONLY
 
 } // end of namespace mln
Index: mln/fun/ops.hh
--- mln/fun/ops.hh	(revision 1055)
+++ mln/fun/ops.hh	(working copy)
@@ -34,6 +34,7 @@
  */
 
 # include <mln/core/concept/function.hh>
+# include <mln/fun/internal/selector.hh>
 
 
 
@@ -43,11 +44,12 @@
   {										\
 										\
     template <typename L, typename R>						\
-    struct Name##_expr_ : public Function_##Out < Name##_expr_<L,R> >		\
+    struct Name##_##Out##_expr_							\
+      : public Function_##Out < Name##_##Out##_expr_<L,R> >			\
     {										\
       typedef mln_result(L) result;						\
 										\
-      Name##_expr_(const L& l, const R& r)					\
+      Name##_##Out##_expr_(const L& l, const R& r)				\
 	: l_(l), r_(r)								\
       {										\
       }										\
@@ -59,17 +61,17 @@
       }										\
 										\
     protected:									\
-      L l_;									\
-      R r_;									\
+      const L l_;								\
+      const R r_;								\
     };										\
 										\
   }										\
 										\
   template <typename L, typename R>						\
-  fun::Name##_expr_<L,R>							\
+  fun::Name##_##Out##_expr_<L,R>						\
   operator Symbol (const Function_##In<L>& lhs, const Function_##In<R>& rhs)	\
   {										\
-    fun::Name##_expr_<L,R> tmp(exact(lhs), exact(rhs));				\
+    fun::Name##_##Out##_expr_<L,R> tmp(exact(lhs), exact(rhs));			\
     return tmp;									\
   }										\
 										\
@@ -82,11 +84,12 @@
   {									\
 									\
     template <typename F>						\
-    struct Name##_expr_ : public Function_##Out< Name##_expr_<F> >	\
+    struct Name##_##Out##_expr_					\
+      : public Function_##Out< Name##_##Out##_expr_<F> >	\
     {									\
       typedef mln_result(F) result;					\
 									\
-      Name##_expr_(const F& f)						\
+      Name##_##Out##_expr_(const F& f)				\
 	: f_(f)								\
       {									\
       }									\
@@ -98,16 +101,16 @@
       }									\
 									\
     protected:								\
-      F f_;								\
+      const F f_;						\
     };									\
 									\
   }									\
 									\
   template <typename F>							\
-  fun::Name##_expr_<F>							\
+  fun::Name##_##Out##_expr_<F>					\
   operator Symbol (const Function_##In<F>& f)				\
   {									\
-    fun::Name##_expr_<F> tmp(exact(f));					\
+    fun::Name##_##Out##_expr_<F> tmp(exact(f));			\
     return tmp;								\
   }									\
 									\
@@ -117,6 +120,7 @@
 
 namespace mln
 {
+  // -> p2v
 
   mln_decl_binary_expr_(p2v, p2b, equal, =);
   mln_decl_binary_expr_(p2v, p2b, not_equal, !=);
@@ -141,6 +145,22 @@
   mln_decl_unary_expr_(p2v, p2v, uplus, +);
   mln_decl_unary_expr_(p2v, p2v, uminus, -);
 
+  // -> v2b
+
+  mln_decl_binary_expr_(v2v, v2b, equal, =);
+  mln_decl_binary_expr_(v2v, v2b, not_equal, !=);
+
+  mln_decl_binary_expr_(v2v, v2b, less, <);
+  mln_decl_binary_expr_(v2v, v2b, less_or_equal, <=);
+  mln_decl_binary_expr_(v2v, v2b, greater_or_equal, >=);
+  mln_decl_binary_expr_(v2v, v2b, greater, >);
+
+  mln_decl_binary_expr_(v2b, v2b, and, &&);
+  mln_decl_binary_expr_(v2b, v2b, or, ||);
+  mln_decl_binary_expr_(v2b, v2b, xor, ^);
+
+  mln_decl_unary_expr_(v2b, v2b, not, !);
+
 } // end of namespace mln
 
 
Index: mln/fun/internal/selector.hh
--- mln/fun/internal/selector.hh	(revision 1055)
+++ mln/fun/internal/selector.hh	(working copy)
@@ -51,11 +51,13 @@
 
       //       Function_v2v
       //         |
-      //         + -- Function_i2v
-      //         |
-      //         + -- Function_p2v
-      //                |
-      //                + -- Function_p2b
+      //         + ---------------------- Function_v2b
+      //         |                           |
+      //         + -- Function_i2v           |
+      //         |                           |
+      //         + -- Function_p2v           |
+      //                |                    |
+      //                + -- Function_p2b -- +
       //                |
       //                + -- Function_p2p
 
@@ -69,9 +71,9 @@
 
       template <int arg, int res, typename E> struct helper_selector_;
 
-      // no b2* type => v2v type
+      // b2* => v2v type, except for v2b
       template <typename E>
-      struct helper_selector_< b_, b_, E > { typedef Function_v2v<E> ret; };
+      struct helper_selector_< b_, b_, E > { typedef Function_v2b<E> ret; };
       template <typename E>
       struct helper_selector_< b_, i_, E > { typedef Function_v2v<E> ret; };
       template <typename E>
@@ -79,7 +81,7 @@
       template <typename E>
       struct helper_selector_< b_, v_, E > { typedef Function_v2v<E> ret; };
 
-      // i2* => only i2v type
+      // i2* => i2v type
       template <typename E>
       struct helper_selector_< i_, b_, E > { typedef Function_i2v<E> ret; };
       template <typename E>
@@ -99,9 +101,9 @@
       template <typename E>
       struct helper_selector_< p_, v_, E > { typedef Function_p2v<E> ret; };
 
-      // v2* => only v2v type
+      // v2* => v2v type, except for v2b
       template <typename E>
-      struct helper_selector_< v_, b_, E > { typedef Function_v2v<E> ret; };
+      struct helper_selector_< v_, b_, E > { typedef Function_v2b<E> ret; };
       template <typename E>
       struct helper_selector_< v_, i_, E > { typedef Function_v2v<E> ret; };
       template <typename E>
Index: mln/fun/v2v/saturate.hh
--- mln/fun/v2v/saturate.hh	(revision 0)
+++ mln/fun/v2v/saturate.hh	(revision 0)
@@ -0,0 +1,105 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_FUN_V2V_SATURATE_HH
+# define MLN_FUN_V2V_SATURATE_HH
+
+/*! \file mln/fun/v2v/saturate.hh
+ *
+ * \brief FIXME.
+ */
+
+# include <mln/core/concept/function.hh>
+# include <mln/value/props.hh>
+
+
+namespace mln
+{
+
+  namespace fun
+  {
+
+    namespace v2v
+    {
+
+      // FIXME: Doc!
+
+      template <typename V>
+      struct saturate : public Function_v2v< saturate<V> >
+      {
+	saturate();
+	saturate(const V& min, const V& max);
+
+	typedef V result;
+
+	template <typename W>
+	V operator()(const W& v) const;
+
+      protected:
+	V min_, max_;
+      };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+      template <typename V>
+      saturate<V>::saturate()
+	: min_(mln_min(V)),
+	  max_(mln_max(V))
+      {
+      }
+
+      template <typename V>
+      saturate<V>::saturate(const V& min, const V& max)
+	: min_(min),
+	  max_(max)
+      {
+	mln_precondition(max > min);
+      }
+
+      template <typename V>
+      template <typename W>
+      V
+      saturate<V>::operator()(const W& v) const
+      {
+	if (v < min_)
+	  return min_;
+	if (v > max_)
+	  return max_;
+	return v;
+      }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+    } // end of namespace mln::fun::v2v
+
+  } // end of namespace mln::fun
+
+} // end of namespace mln
+
+
+#endif // ! MLN_FUN_V2V_SATURATE_HH
Index: mln/fun/v2v/id.hh
--- mln/fun/v2v/id.hh	(revision 0)
+++ mln/fun/v2v/id.hh	(revision 0)
@@ -0,0 +1,77 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_FUN_V2V_ID_HH
+# define MLN_FUN_V2V_ID_HH
+
+/*! \file mln/fun/id.hh
+ *
+ * \brief FIXME.
+ */
+
+# include <mln/fun/internal/selector.hh>
+
+
+namespace mln
+{
+
+  namespace fun
+  {
+
+    namespace v2v
+    {
+
+      // FIXME: Doc!
+
+      template <typename T>
+      struct id
+	: fun::internal::selector_<T, T, id<T> >::ret
+      {
+	typedef T result;
+	T operator()(const T& t) const;
+      };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+      template <typename T>
+      T
+      id<T>::operator()(const T& t) const
+      {
+	return t;
+      }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+    } // end of namespace mln::fun::v2v
+
+  } // end of namespace mln::fun
+
+} // end of namespace mln
+
+
+#endif // ! MLN_FUN_V2V_ID_HH
Index: mln/math/round.hh
--- mln/math/round.hh	(revision 1055)
+++ mln/math/round.hh	(working copy)
@@ -47,7 +47,7 @@
 
 
     template <typename R>
-    struct round_ : public Function_v2v< round_<R> >
+    struct round : public Function_v2v< round<R> >
     {
       typedef R result;
 
@@ -61,7 +61,7 @@
 
     template <typename R>
     template <typename T>
-    R round_<R>::operator()(const T& v) const
+    R round<R>::operator()(const T& v) const
     {
       return (long int)(v + 0.49999); // FIXME: !!!
     }
Index: mln/morpho/dilation.hh
--- mln/morpho/dilation.hh	(revision 0)
+++ mln/morpho/dilation.hh	(revision 0)
@@ -0,0 +1,102 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_MORPHO_DILATION_HH
+# define MLN_MORPHO_DILATION_HH
+
+/*! \file mln/morpho/dilation.hh
+ *
+ * \brief Morphological dilation.
+ *
+ * \todo Mimic erosion.hh when completed.
+ */
+
+# include <mln/morpho/includes.hh>
+
+
+namespace mln
+{
+
+  namespace morpho
+  {
+
+    /*! Morphological dilation.
+     */
+    template <typename I, typename W, typename O>
+    void dilation(const Image<I>& input, const Window<W>& win, Image<O>& output);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    namespace impl
+    {
+
+      template <typename I, typename W, typename O>
+      void dilation_on_function(const Image<I>& input_, const Window<W>& win_, Image<O>& output_)
+      {
+	const I& input = exact(input_);
+	const W& win   = exact(win_);
+	O& output      = exact(output_);
+
+	accu::max<mln_value(I)> max;
+
+	mln_piter(I) p(input.domain());
+	mln_qiter(W) q(win, p);
+	for_all(p)
+	  {
+	    max.init();
+	    for_all(q) if (input.has(q))
+	      max.take(input(q));
+	    output(p) = max.to_value();
+	  }
+      }
+
+    } // end of namespace mln::morpho::impl
+
+
+    // Facade.
+
+    template <typename I, typename W, typename O>
+    void dilation(const Image<I>& input, const Window<W>& win, Image<O>& output)
+    {
+      mln_precondition(exact(output).domain() = exact(input).domain());
+      mln_precondition(! exact(win).is_empty());
+
+      impl::dilation_on_function(input, win, output);
+
+      if (exact(win).is_centered())
+	mln_postcondition(output >= input);
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MORPHO_DILATION_HH
Index: mln/morpho/includes.hh
--- mln/morpho/includes.hh	(revision 0)
+++ mln/morpho/includes.hh	(revision 0)
@@ -0,0 +1,56 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_MORPHO_INCLUDES_HH
+# define MLN_MORPHO_INCLUDES_HH
+
+/*! \file mln/morpho/includes.hh
+ *
+ * \brief Basic list of includes for all files in mln/morpho/.
+ */
+
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/window.hh>
+
+# include <mln/accu/min.hh>
+# include <mln/accu/max.hh>
+
+# include <mln/arith/minus.hh>
+
+# include <mln/level/compare.hh>
+# include <mln/level/fill.hh>
+
+# include <mln/border/resize.hh>
+# include <mln/border/fill.hh>
+
+# include <mln/morpho/dilation.hh>
+# include <mln/morpho/erosion.hh>
+
+
+
+#endif // ! MLN_MORPHO_INCLUDES_HH
Index: mln/morpho/gradient.hh
--- mln/morpho/gradient.hh	(revision 0)
+++ mln/morpho/gradient.hh	(revision 0)
@@ -0,0 +1,139 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_MORPHO_GRADIENT_HH
+# define MLN_MORPHO_GRADIENT_HH
+
+/*! \file mln/morpho/gradient.hh
+ *
+ * \brief Morphological gradient.
+ */
+
+# include <mln/morpho/includes.hh>
+# include <mln/test/positive.hh>
+
+
+namespace mln
+{
+
+  namespace morpho
+  {
+
+    /*! Morphological gradient.
+     *
+     * This operator is d_B - e_B. 
+     */
+    template <typename I, typename W, typename O>
+    void gradient(const Image<I>& input, const Window<W>& win,
+		  Image<O>& output);
+
+
+    /*! Morphological internal gradient.
+     *
+     * This operator is Id - e_B. 
+     */
+    template <typename I, typename W, typename O>
+    void gradient_internal(const Image<I>& input, const Window<W>& win,
+			   Image<O>& output);
+
+
+    /*! Morphological external gradient.
+     *
+     * This operator is d_B - Id. 
+     */
+    template <typename I, typename W, typename O>
+    void gradient_external(const Image<I>& input, const Window<W>& win,
+			   Image<O>& output);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I, typename W, typename O>
+    void gradient(const Image<I>& input_, const Window<W>& win_, Image<O>& output_)
+    {
+      const I& input = exact(input_);
+      const W& win = exact(win_);
+      O& output = exact(output_);
+
+      mln_precondition(output.domain() = input.domain());
+      mln_precondition(! win.is_empty());
+
+      O temp(input.domain());
+      erosion(input, win, temp);
+
+      dilation(input, win, output);
+      arith::minus_inplace(output, temp);
+
+      mln_postcondition(test::positive(output));
+    }
+
+    template <typename I, typename W, typename O>
+    void gradient_internal(const Image<I>& input_, const Window<W>& win_,
+			   Image<O>& output_)
+    {
+      const I& input = exact(input_);
+      const W& win = exact(win_);
+      O& output = exact(output_);
+
+      mln_precondition(output.domain() = input.domain());
+      mln_precondition(! win.is_empty());
+
+      O temp(input.domain());
+      erosion(input, win, temp);
+
+      arith::minus(input, temp, output);
+
+      mln_postcondition(test::positive(output));
+    }
+
+    template <typename I, typename W, typename O>
+    void gradient_external(const Image<I>& input_, const Window<W>& win_,
+			   Image<O>& output_)
+    {
+      const I& input = exact(input_);
+      const W& win = exact(win_);
+      O& output = exact(output_);
+
+      mln_precondition(output.domain() = input.domain());
+      mln_precondition(! win.is_empty());
+
+      O temp(input.domain());
+      dilation(input, win, temp);
+
+      arith::minus(temp, input, output);
+
+      mln_postcondition(test::positive(output));
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MORPHO_GRADIENT_HH
Index: mln/morpho/erosion.hh
--- mln/morpho/erosion.hh	(revision 1055)
+++ mln/morpho/erosion.hh	(working copy)
@@ -28,13 +28,7 @@
 #ifndef MLN_MORPHO_EROSION_HH
 # define MLN_MORPHO_EROSION_HH
 
-# include <mln/core/concept/image.hh>
-# include <mln/core/concept/window.hh>
-# include <mln/accu/min.hh>
-# include <mln/value/props.hh>
-# include <mln/level/compare.hh>
-# include <mln/level/fill.hh>
-// FIXME: # include <mln/border/assign.hh>
+# include <mln/morpho/includes.hh>
 
 
 namespace mln
@@ -43,6 +37,11 @@
   namespace morpho
   {
 
+    /*! Morphological erosion.
+     *
+     * \todo Overload erosion_wrt_win for hline and vline and for fast
+     * images.
+     */
     template <typename I, typename W, typename O>
     void erosion(const Image<I>& input, const Window<W>& win, Image<O>& output);
 
@@ -52,7 +51,7 @@
     namespace impl
     {
 
-      // on function
+      // On function.
 
       template <typename I, typename W, typename O>
       void erosion_on_function(const Image<I>& input_, const Window<W>& win_, Image<O>& output_)
@@ -75,7 +74,7 @@
       }
 
 
-      // on set
+      // On set.
 
       template <typename I, typename W, typename O>
       void erosion_on_set(const Image<I>& input_, const Window<W>& win_, Image<O>& output_)
@@ -104,10 +103,10 @@
 
 
 
-      // FIXME: stage 3: dispatch w.r.t. fast property
+      // FIXME: Stage 3: dispatch w.r.t. fast property
 
 
-      // stage 2: dispatch w.r.t. the value kind
+      // Stage 2: dispatch w.r.t. the value kind.
 
       template <typename I, typename W, typename O>
       void erosion_wrt_value(value::binary_kind, // binary => morphology on sets
@@ -125,7 +124,7 @@
 
 
 
-      // stage 1: dispatch w.r.t. the window type
+      // Stage 1: dispatch w.r.t. the window type.
       //   |
       //   V
 
@@ -142,9 +141,9 @@
       template <typename I, typename O>
       void erosion_wrt_win(const Image<I>& input, const win::rectangle2d& win, Image<O>& output)
       {
-	O tmp(exact(output).domain());
-	morpho::erosion(input, win::hline2d(win.width()),  tmp);
-	morpho::erosion(tmp,   win::vline2d(win.height()), output);
+	O temp(exact(output).domain());
+	morpho::erosion(input, win::hline2d(win.width()),  temp);
+	morpho::erosion(temp,  win::vline2d(win.height()), output);
       }
 
 #  endif // MLN_CORE_WIN_RECTANGLE2D_HH
@@ -157,7 +156,7 @@
     } // end of namespace mln::morpho::impl
 
 
-    // facade
+    // Facade.
 
     template <typename I, typename W, typename O>
     void erosion(const Image<I>& input, const Window<W>& win, Image<O>& output)
@@ -166,6 +165,7 @@
       mln_precondition(! exact(win).is_empty());
 
       impl::erosion_wrt_win(input, exact(win), output);
+
       if (exact(win).is_centered())
 	mln_postcondition(output <= input);
     }
Index: mln/morpho/closing.hh
--- mln/morpho/closing.hh	(revision 0)
+++ mln/morpho/closing.hh	(revision 0)
@@ -0,0 +1,79 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_MORPHO_CLOSING_HH
+# define MLN_MORPHO_CLOSING_HH
+
+/*! \file mln/morpho/closing.hh
+ *
+ * \brief Morphological closing.
+ */
+
+# include <mln/morpho/includes.hh>
+
+
+namespace mln
+{
+
+  namespace morpho
+  {
+
+    /*! Morphological closing.
+     *
+     * This operator is e_{-B} o d_B. 
+     */
+    template <typename I, typename W, typename O>
+    void closing(const Image<I>& input, const Window<W>& win, Image<O>& output);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I, typename W, typename O>
+    void closing(const Image<I>& input_, const Window<W>& win_, Image<O>& output_)
+    {
+      const I& input = exact(input_);
+      const W& win = exact(win_);
+      O& output = exact(output_);
+
+      mln_precondition(output.domain() = input.domain());
+      mln_precondition(! win.is_empty());
+
+      O temp(input.domain());
+      dilation(input, win, temp);
+      erosion(temp, -win, output);
+
+      mln_postcondition(output >= input);
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MORPHO_CLOSING_HH
Index: mln/morpho/opening.hh
--- mln/morpho/opening.hh	(revision 0)
+++ mln/morpho/opening.hh	(revision 0)
@@ -0,0 +1,79 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_MORPHO_OPENING_HH
+# define MLN_MORPHO_OPENING_HH
+
+/*! \file mln/morpho/opening.hh
+ *
+ * \brief Morphological opening.
+ */
+
+# include <mln/morpho/includes.hh>
+
+
+namespace mln
+{
+
+  namespace morpho
+  {
+
+    /*! Morphological opening.
+     *
+     * This operator is d_{-B} o e_B. 
+     */
+    template <typename I, typename W, typename O>
+    void opening(const Image<I>& input, const Window<W>& win, Image<O>& output);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I, typename W, typename O>
+    void opening(const Image<I>& input_, const Window<W>& win_, Image<O>& output_)
+    {
+      const I& input = exact(input_);
+      const W& win = exact(win_);
+      O& output = exact(output_);
+
+      mln_precondition(output.domain() = input.domain());
+      mln_precondition(! win.is_empty());
+
+      O temp(input.domain());
+      erosion(input, win, temp);
+      dilation(temp, -win, output);
+
+      mln_postcondition(output <= input);
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MORPHO_OPENING_HH
Index: mln/level/assign.hh
--- mln/level/assign.hh	(revision 1055)
+++ mln/level/assign.hh	(working copy)
@@ -31,6 +31,8 @@
 /*! \file mln/level/assign.hh
  *
  * \brief Assignment between a couple of images.
+ *
+ * \todo Assign should be a precondition then a call to level::fill.
  */
 
 # include <mln/core/concept/image.hh>
Index: mln/level/fill.hh
--- mln/level/fill.hh	(revision 1055)
+++ mln/level/fill.hh	(working copy)
@@ -31,6 +31,8 @@
 /*! \file mln/level/fill.hh
  *
  * \brief Fill an image, that is, set pixel values.
+ *
+ * \todo Overload for fast images.
  */
 
 # include <cstring>
Index: mln/level/saturate.hh
--- mln/level/saturate.hh	(revision 0)
+++ mln/level/saturate.hh	(revision 0)
@@ -0,0 +1,121 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_LEVEL_SATURATE_HH
+# define MLN_LEVEL_SATURATE_HH
+
+/*! \file mln/level/saturate.hh
+ *
+ * \brief Apply a saturation function to image pixel values.
+ */
+
+# include <mln/fun/v2v/saturate.hh>
+# include <mln/level/apply.hh>
+# include <mln/level/transform.hh>
+
+
+namespace mln
+{
+
+  namespace level
+  {
+
+
+    /*! Apply the saturate function to image pixel values.
+     *
+     * \param[in] input The input image.
+     * \param[out] output The output image.
+     *
+     * The saturation is based on the min and max values of the output
+     * value type.  This assumes that the range of values in the input
+     * image is larger than the one of the output image.
+     */
+    template <typename I, typename O>
+    void saturate(const Image<I>& input, Image<O>& output);
+
+
+    /*! Apply the saturate function to image pixel values.
+     *
+     * \param[in] input The input image.
+     * \param[in] min The minimum output value.
+     * \param[in] max The maximum output value.
+     * \param[out] output The output image.
+     */
+    template <typename I, typename O>
+    void saturate(const Image<I>& input,
+		  const mln_value(O)& min, const mln_value(O)& max,
+		  Image<O>& output);
+
+
+    /*! Apply the saturate function to image pixel values.
+     *
+     * \param[in,out] input The input image.
+     * \param[in] min The minimum output value.
+     * \param[in] max The maximum output value.
+     */
+    template <typename I>
+    void saturate_inplace(Image<I>& input,
+			  const mln_value(I)& min, const mln_value(I)& max);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I, typename O>
+    void saturate(const Image<I>& input, Image<O>& output)
+    {
+      mln_precondition(exact(input).domain() = exact(output).domain());
+      fun::v2v::saturate<mln_value(O)> f;
+      level::transform(input, f, output);
+    }
+
+    template <typename I, typename O>
+    void saturate(const Image<I>& input,
+		  const mln_value(O)& min, const mln_value(O)& max,
+		  Image<O>& output)
+    {
+      mln_precondition(exact(input).domain() = exact(output).domain());
+      fun::v2v::saturate<mln_value(O)> f(min, max);
+      level::transform(input, f, output);
+    }
+
+    template <typename I>
+    void saturate_inplace(Image<I>& input,
+			  const mln_value(I)& min, const mln_value(I)& max)
+    {
+      mln_precondition(exact(input).has_data());
+      fun::v2v::saturate<mln_value(I)> f(min, max);
+      level::apply(input, f);
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::level
+
+} // end of namespace mln
+
+
+#endif // ! MLN_LEVEL_SATURATE_HH
Index: mln/level/abs.hh
--- mln/level/abs.hh	(revision 0)
+++ mln/level/abs.hh	(revision 0)
@@ -0,0 +1,89 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_LEVEL_ABS_HH
+# define MLN_LEVEL_ABS_HH
+
+/*! \file mln/level/abs.hh
+ *
+ * \brief Apply the absolute value (abs) function to image pixel
+ * values.
+ */
+
+# include <mln/fun/v2v/abs.hh>
+# include <mln/level/apply.hh>
+# include <mln/level/transform.hh>
+
+
+namespace mln
+{
+
+  namespace level
+  {
+
+
+    /*! Apply the absolute value (abs) function to image pixel values.
+     *
+     * \param[in] input The input image.
+     * \param[out] output The output image.
+     */
+    template <typename I, typename O>
+    void abs(const Image<I>& input, Image<O>& output);
+
+
+    /*! Apply the absolute value (abs) function to image pixel values.
+     *
+     * \param[in,out] input The input image.
+     */
+    template <typename I>
+    void abs_inplace(Image<I>& input);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I, typename O>
+    void abs(const Image<I>& input, Image<O>& output)
+    {
+      mln_precondition(exact(input).domain() = exact(output).domain());
+      level::transform(input, fun::v2v::abs<mln_value(I)>(), output);
+    }
+
+    template <typename I>
+    void abs_inplace(Image<I>& input)
+    {
+      mln_precondition(exact(input).has_data());
+      level::apply(input, fun::v2v::abs<mln_value(I)>());
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::level
+
+} // end of namespace mln
+
+
+#endif // ! MLN_LEVEL_ABS_HH
Index: mln/arith/plus.hh
--- mln/arith/plus.hh	(revision 1055)
+++ mln/arith/plus.hh	(working copy)
@@ -54,6 +54,20 @@
     void plus(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output);
 
 
+    /*! Point-wise addition of image \p rhs in image \p lhs.
+     *
+     * \param[in] lhs First operand image (subject to addition).
+     * \param[in,out] rhs Second operand image (to be added to \p lhs).
+     *
+     * This addition performs: \n
+     *   for all p of rhs.domain \n
+     *     lhs(p) += rhs(p)
+     *
+     * \pre \p rhs.domain <= \p lhs.domain
+     */
+    template <typename L, typename R>
+    void plus_inplace(Image<L>& lhs, const Image<R>& rhs);
+
 
 # ifndef MLN_INCLUDE_ONLY
 
@@ -81,10 +95,29 @@
 	  op.val() = lp.val() + rp.val();
       }
 
+      template <typename L, typename R>
+      void plus_inplace_(Image<L>& lhs_, const Image<R>& rhs_)
+      {
+	L& lhs = exact(lhs_);
+	const R& rhs = exact(rhs_);
+	mln_piter(R) p(rhs.domain());
+	for_all(p)
+	  lhs(p) += rhs(p);
+      }
+
+      template <typename L, typename R>
+      void plus_inplace_(Fast_Image<L>& lhs, const Fast_Image<R>& rhs)
+      {
+	mln_pixter(L) lp(exact(lhs));
+	mln_pixter(const R) rp(exact(rhs));
+	for_all_2(rp, lp)
+	  lp.val() += rp.val();
+      }
+
     } // end of namespace mln::arith::impl
 
 
-    // Facade.
+    // Facades.
 
     template <typename L, typename R, typename O>
     void plus(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output)
@@ -94,6 +127,13 @@
       impl::plus_(exact(lhs), exact(rhs), exact(output));
     }
 
+    template <typename L, typename R>
+    void plus_inplace(Image<L>& lhs, const Image<R>& rhs)
+    {
+      mln_precondition(exact(rhs).domain() <= exact(lhs).domain());
+      impl::plus_inplace_(exact(lhs), exact(rhs));
+    }
+
 # endif // ! MLN_INCLUDE_ONLY
 
   } // end of namespace mln::arith
Index: mln/arith/minus.hh
--- mln/arith/minus.hh	(revision 1055)
+++ mln/arith/minus.hh	(working copy)
@@ -54,22 +54,84 @@
     void minus(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output);
 
 
+    /*! Point-wise substraction of image \p lhs in image \p rhs.
+     *
+     * \param[in,out] lhs First operand image (subject to substraction).
+     * \param[in] rhs Second operand image (to be substracted to \p lhs).
+     *
+     * This substraction performs: \n
+     *   for all p of rhs.domain \n
+     *     lhs(p) -= rhs(p)
+     *
+     * \pre \p rhs.domain <= \p lhs.domain
+     */
+    template <typename L, typename R>
+    void minus_inplace(Image<L>& lhs, const Image<R>& rhs);
+
 
 # ifndef MLN_INCLUDE_ONLY
 
+    namespace impl
+    {
+
     template <typename L, typename R, typename O>
-    void minus(const Image<L>& lhs_, const Image<R>& rhs_, Image<O>& output_)
+      void minus_(const Image<L>& lhs_, const Image<R>& rhs_, Image<O>& output_)
     {
       const L& lhs = exact(lhs_);
       const R& rhs = exact(rhs_);
       O& output = exact(output_);
+	mln_piter(L) p(lhs.domain());
+	for_all(p)
+	  output(p) = lhs(p) - rhs(p);
+      }
 
-      mln_precondition(rhs.domain() = lhs.domain());
-      mln_precondition(output.domain() = lhs.domain());
+      template <typename L, typename R, typename O>
+      void minus_(const Fast_Image<L>& lhs, const Fast_Image<R>& rhs, Fast_Image<O>& output)
+      {
+	mln_pixter(const L) lp(exact(lhs));
+	mln_pixter(const R) rp(exact(rhs));
+	mln_pixter(O)       op(exact(output));
+	for_all_3(lp, rp, op)
+	  op.val() = lp.val() - rp.val();
+      }
 
-      mln_piter(I) p(output.domain());
+      template <typename L, typename R>
+      void minus_inplace_(Image<L>& lhs_, const Image<R>& rhs_)
+      {
+	L& lhs = exact(lhs_);
+	const R& rhs = exact(rhs_);
+	mln_piter(R) p(rhs.domain());
       for_all(p)
-	output(p) = lhs(p) - rhs(p);
+	  lhs(p) -= rhs(p);
+      }
+
+      template <typename L, typename R>
+      void minus_inplace_(Fast_Image<L>& lhs, const Fast_Image<R>& rhs)
+      {
+	mln_pixter(L) lp(exact(lhs));
+	mln_pixter(const R) rp(exact(rhs));
+	for_all_2(rp, lp)
+	  lp.val() -= rp.val();
+      }
+
+    } // end of namespace mln::arith::impl
+
+
+    // Facades.
+
+    template <typename L, typename R, typename O>
+    void minus(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output)
+    {
+      mln_precondition(exact(rhs).domain() = exact(lhs).domain());
+      mln_precondition(exact(output).domain() = exact(lhs).domain());
+      impl::minus_(exact(lhs), exact(rhs), exact(output));
+    }
+
+    template <typename L, typename R>
+    void minus_inplace(Image<L>& lhs, const Image<R>& rhs)
+    {
+      mln_precondition(exact(rhs).domain() <= exact(lhs).domain());
+      impl::minus_inplace_(exact(lhs), exact(rhs));
     }
 
 # endif // ! MLN_INCLUDE_ONLY
Index: mln/linear/line_convolve.hh
--- mln/linear/line_convolve.hh	(revision 1055)
+++ mln/linear/line_convolve.hh	(working copy)
@@ -56,14 +56,14 @@
      * \pre output.domain = input.domain
      */
     template <typename I, typename W, unsigned N, typename O>
-    void line_convolve(const Image<I>& input, const W (&weights)[N],
+    void line_convolve(const Image<I>& input, W (&weights)[N],
 		   Image<O>& output);
 
 
 # ifndef MLN_INCLUDE_ONLY
 
     template <typename I, typename W, unsigned N, typename O>
-    void line_convolve(const Image<I>& input, const W (&weights)[N],
+    void line_convolve(const Image<I>& input, W (&weights)[N],
 		   Image<O>& output)
     {
       mln_precondition(exact(output).domain() = exact(input).domain());
Index: mln/linear/sobel.hh
--- mln/linear/sobel.hh	(revision 1055)
+++ mln/linear/sobel.hh	(working copy)
@@ -34,8 +34,7 @@
  */
 
 # include <mln/arith/plus.hh>
-# include <mln/fun/v2v/abs.hh>
-# include <mln/level/apply.hh>
+# include <mln/level/abs.hh>
 # include <mln/linear/line_x2_convolve.hh>
 
 
@@ -97,11 +96,14 @@
       template <typename I, typename O>
       void sobel_(const Image<I>& input, Image<O>& output)
       {
-	O temp_h(exact(input).domain()), temp_v(exact(input).domain());
-	sobel_h(input, temp_h);
-	sobel_v(input, temp_v);
-	arith::plus(temp_h, temp_v, output);
-	level::apply(exact(output), fun::v2v::abs<mln_value(O)>());
+	// h
+	sobel_h(input, output);
+	// v
+	O temp(exact(input).domain());
+	sobel_v(input, temp);
+	// output
+	arith::plus_inplace(output, temp);
+	level::abs_inplace(output);
       }
 
     } // end of namespace mln::linear::impl
Index: mln/linear/line_x2_convolve.hh
--- mln/linear/line_x2_convolve.hh	(revision 1055)
+++ mln/linear/line_x2_convolve.hh	(working copy)
@@ -59,7 +59,7 @@
 	      typename W, unsigned Nr, unsigned Nc,
 	      typename O>
     void line_x2_convolve(const Image<I>& input,
-			  const W (&row_weights)[Nr], const W (&col_weights)[Nc],
+			  W (&row_weights)[Nr], W (&col_weights)[Nc],
 			  Image<O>& output);
 
 
@@ -69,7 +69,7 @@
 	      typename W, unsigned Nr, unsigned Nc,
 	      typename O>
     void line_x2_convolve(const Image<I>& input,
-			  const W (&row_weights)[Nr], const W (&col_weights)[Nc],
+			  W (&row_weights)[Nr], W (&col_weights)[Nc],
 			  Image<O>& output)
     {
       // FIXME: Check 2D.
Index: mln/make/w_window_line.hh
--- mln/make/w_window_line.hh	(revision 1055)
+++ mln/make/w_window_line.hh	(working copy)
@@ -52,13 +52,13 @@
      * \return A window.
      */
     template <typename D, typename W, unsigned L>
-    mln::w_window<D,W> w_window_line(const W (&w)[L]);
+    mln::w_window<D,W> w_window_line(W (&w)[L]);
 
 
 # ifndef MLN_INCLUDE_ONLY
 
     template <typename D, typename W, unsigned L>
-    mln::w_window<D,W> w_window_line(const W (&w)[L])
+    mln::w_window<D,W> w_window_line(W (&w)[L])
     {
       mln_precondition(L % 2 = 1);
       mln::w_window<D,W> w_win;
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                     
                        
                    27 Aug '07
                    
                        https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from  Thierry Geraud  <thierry.geraud(a)lrde.epita.fr>
	Augment tools for linear filtering; add sobel.
	* mln/core/decorated_image.hh
	(helper_decorated_image_write_): Replace by...
	(decorated_image_impl_): ...this.
	(impl_): New.
	(lvalue): Update.
	(write_): Remove; now in impl_.
	* mln/value/all.hh: Update.
	* mln/value/props.hh,
	* mln/value/int_u.hh,
	* mln/value/int_s.hh (min, max): Change to proc.
	* mln/value/props.hh (mln_min, mln_max): Update.
	(epsilon): Change to proc.
	* mln/value/aliases.hh: New.
	* mln/level/stretch.hh: Update.
	* mln/arith/abs.hh: New.
	* mln/arith/plus.hh: Overload.
	* mln/fun/v2v/abs.hh: New.
	* mln/level/apply.hh: Fix meaning; add todo.
	* mln/math/abs.hh: Overload.
	* mln/core/concept/iterator.hh (for_all_3): New.
	* mln/math/round_sat.hh: New.
	* mln/make/w_window_line.hh: New.
	* mln/metal/abort.hh: New.
	* mln/linear/line_convolve.hh: New.
	* mln/linear/line_x2_convolve.hh: New.
	* mln/linear/sobel.hh: New.
	* tests/line_convolve.cc: New.
	* tests/sobel.cc: New.
 mln/arith/plus.hh              |   34 ++++++++-
 mln/core/concept/iterator.hh   |    9 ++
 mln/core/decorated_image.hh    |   55 +++++++++-------
 mln/fun/v2v/abs.hh             |   77 ++++++++++++++++++++++
 mln/level/apply.hh             |   42 +++++-------
 mln/level/stretch.hh           |    2 
 mln/linear/convolve.hh         |    8 +-
 mln/linear/hconvolve.hh        |  109 +++++++++++++++++++++++++++++++
 mln/linear/line_convolve.hh    |   82 ++++++++++++++++++++++++
 mln/linear/line_x2_convolve.hh |   92 ++++++++++++++++++++++++++
 mln/linear/sobel.hh            |  140 +++++++++++++++++++++++++++++++++++++++++
 mln/make/w_window_line.hh      |   81 +++++++++++++++++++++++
 mln/math/abs.hh                |   13 +++
 mln/math/round_sat.hh          |   83 ++++++++++++++++++++++++
 mln/metal/abort.hh             |   50 ++++++++++++++
 mln/value/aliases.hh           |   43 ++++++++++++
 mln/value/all.hh               |    9 ++
 mln/value/int_s.hh             |   23 ++----
 mln/value/int_u.hh             |   13 ---
 mln/value/props.hh             |   52 +++++++--------
 tests/line_convolve.cc         |   64 ++++++++++++++++++
 tests/sobel.cc                 |   62 ++++++++++++++++++
 22 files changed, 1034 insertions(+), 109 deletions(-)
Index: tests/sobel.cc
--- tests/sobel.cc	(revision 0)
+++ tests/sobel.cc	(revision 0)
@@ -0,0 +1,62 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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 tests/sobel.cc
+ *
+ * \brief Tests on mln::linear::sobel.
+ */
+
+#include <mln/core/image2d_b.hh>
+#include <mln/value/int_u8.hh>
+
+#include <mln/io/load_pgm.hh>
+#include <mln/io/save_pgm.hh>
+
+#include <mln/math/round_sat.hh>
+#include <mln/level/transform.hh>
+
+#include <mln/border/thickness.hh>
+#include <mln/linear/sobel.hh>
+
+
+int main()
+{
+  using namespace mln;
+  using value::int_u8;
+
+  border::thickness = 1;
+
+  image2d_b<int_u8>
+    lena = io::load_pgm("../img/lena.pgm"),
+    out(lena.domain());
+
+  image2d_b<int> tmp(lena.domain());
+  linear::sobel(lena, tmp);
+
+  level::transform(tmp, math::round_sat_<int_u8>(), out);
+  io::save_pgm(out, "out.pgm");
+}
Index: tests/line_convolve.cc
--- tests/line_convolve.cc	(revision 0)
+++ tests/line_convolve.cc	(revision 0)
@@ -0,0 +1,64 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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 tests/line_convolve.cc
+ *
+ * \brief Tests on mln::linear::line_convolve.
+ */
+
+#include <mln/core/image2d_b.hh>
+#include <mln/value/int_u8.hh>
+
+#include <mln/io/load_pgm.hh>
+#include <mln/io/save_pgm.hh>
+#include <mln/math/round.hh>
+#include <mln/math/round_sat.hh>
+#include <mln/level/transform.hh>
+
+#include <mln/core/w_window2d_float.hh>
+#include <mln/border/thickness.hh>
+#include <mln/linear/line_convolve.hh>
+
+
+int main()
+{
+  using namespace mln;
+  using value::int_u8;
+
+  border::thickness = 4;
+
+  image2d_b<int_u8>
+    lena = io::load_pgm("../img/lena.pgm"),
+    out(lena.domain());
+
+  image2d_b<float> tmp(lena.domain());
+  float ws[] = { .11, .11, .11, .11, .11, .11, .11, .11, .11 };
+  linear::line_convolve(lena, ws, tmp);
+  
+  level::transform(tmp, math::round_<int_u8>(), out);
+  io::save_pgm(out, "out.pgm");
+}
Index: mln/core/decorated_image.hh
--- mln/core/decorated_image.hh	(revision 1054)
+++ mln/core/decorated_image.hh	(working copy)
@@ -35,13 +35,39 @@
 namespace mln
 {
 
+  // Fwd decl.
+  template <typename I, typename D> class decorated_image;
+
+
+  namespace internal
+  {
+
+    template <typename I, typename E>
+    struct decorated_image_impl_
+    {
+      typedef mln::value::proxy<E> lvalue;
+      void write_(const mln_psite(I)& p, const mln_value(I)& v);
+    };
+
+    template <typename I, typename E>
+    struct decorated_image_impl_< const I, E >
+    {
+      typedef mln::value::proxy<const E> lvalue;
+    };
+
+  } // end of namespace::internal
+
+
+
   // FIXME: Doc!
 
   template <typename I, typename D>
-  class decorated_image : public internal::image_adaptor_< I, decorated_image<I,D> >
+  class decorated_image : public internal::image_adaptor_< I, decorated_image<I,D> >,
+			  public internal::decorated_image_impl_< I, decorated_image<I,D> >
   {
     typedef decorated_image<I, D> self_;
     typedef internal::image_adaptor_< I, self_ > super_;
+    typedef internal::decorated_image_impl_< I, self_ > impl_;
   public:
 
     decorated_image(I& ima, const D& deco);
@@ -49,13 +75,12 @@
 
     typedef mln_value(I)                    value;
     typedef mln::value::proxy<const self_> rvalue;
-    typedef mln::value::proxy<self_>       lvalue;
+    typedef typename impl_::lvalue         lvalue;
 
     rvalue operator()(const mln_psite(I)& p) const;
     lvalue operator()(const mln_psite(I)& p);
 
     mln_value(I) read_(const mln_psite(I)& p) const;
-    void write_(const mln_psite(I)& p, const mln_value(I)& v);
 
     template <typename V>
     struct change_value
@@ -110,7 +135,7 @@
   }
 
   template <typename I, typename D>
-  mln::value::proxy< const decorated_image<I,D> >
+  typename decorated_image<I,D>::rvalue
   decorated_image<I,D>::operator()(const mln_psite(I)& p) const
   {
     rvalue tmp(*this, p);
@@ -118,7 +143,7 @@
   }
 
   template <typename I, typename D>
-  mln::value::proxy< decorated_image<I,D> >
+  typename decorated_image<I,D>::lvalue
   decorated_image<I,D>::operator()(const mln_psite(I)& p)
   {
     lvalue tmp(*this, p);
@@ -128,32 +153,18 @@
   namespace internal
   {
 
-    template <typename I, typename D>
+    template <typename I, typename E>
     void
-    helper_decorated_image_write_(decorated_image<I,D>& ima,
-				  const mln_psite(I)& p, const mln_value(I)& v)
+    decorated_image_impl_<I,E>::write_(const mln_psite(I)& p, const mln_value(I)& v)
     {
+      E& ima = internal::force_exact<E>(*this);
       ima.decoration().writing(ima.adaptee(), p, v);
       ima.adaptee()(p) = v;
     }
 
-    template <typename I, typename D>
-    void
-    helper_decorated_image_write_(decorated_image<const I,D>&,
-				  const mln_psite(I)&, const mln_value(I)&)
-      // FIXME: Static assertion instead.
-      ;
-
   } // end of namespace mln::internal
 
   template <typename I, typename D>
-  void
-  decorated_image<I,D>::write_(const mln_psite(I)& p, const mln_value(I)& v)
-  {
-    internal::helper_decorated_image_write_(*this, p, v);
-  }
-
-  template <typename I, typename D>
   mln_value(I)
   decorated_image<I,D>::read_(const mln_psite(I)& p) const
   {
Index: mln/core/concept/iterator.hh
--- mln/core/concept/iterator.hh	(revision 1054)
+++ mln/core/concept/iterator.hh	(working copy)
@@ -46,6 +46,15 @@
 # define for_all_2(x1, x2) for(x1.start(),x2.start(); x1.is_valid(); x1.next(),x2.next())
 
 
+/*! \brief Loop to browse all the elements targetted by the triplet of
+ * iterators \p x1, \p x2, and \p x3.
+ */
+# define for_all_3(x1, x2, x3)			\
+  for(x1.start(), x2.start(), x3.start();	\
+      x1.is_valid();				\
+      x1.next(), x2.next(), x3.next())
+
+
 /*! \brief Loop to browse all the remaining elements targetted by the
  * iterator \p x.
  */
Index: mln/fun/v2v/abs.hh
--- mln/fun/v2v/abs.hh	(revision 0)
+++ mln/fun/v2v/abs.hh	(revision 0)
@@ -0,0 +1,77 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_FUN_V2V_ABS_HH
+# define MLN_FUN_V2V_ABS_HH
+
+/*! \file mln/fun/v2v/abs.hh
+ *
+ * \brief FIXME.
+ */
+
+# include <mln/core/concept/function.hh>
+# include <mln/math/abs.hh>
+
+
+namespace mln
+{
+
+  namespace fun
+  {
+
+    namespace v2v
+    {
+
+      // FIXME: Doc!
+
+      template <typename V>
+      struct abs : public Function_v2v< abs<V> >
+      {
+	typedef V result;
+	V operator()(const V& v) const;
+      };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+      template <typename V>
+      V
+      abs<V>::operator()(const V& v) const
+      {
+	return mln::math::abs(v);
+      }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+    } // end of namespace mln::fun::v2v
+
+  } // end of namespace mln::fun
+
+} // end of namespace mln
+
+
+#endif // ! MLN_FUN_V2V_ABS_HH
Index: mln/math/abs.hh
--- mln/math/abs.hh	(revision 1054)
+++ mln/math/abs.hh	(working copy)
@@ -34,6 +34,7 @@
  */
 
 # include <cmath>
+# include <mln/value/all.hh>
 
 
 
@@ -55,6 +56,18 @@
       return std::abs(v);
     }
 
+    template <unsigned n>
+    value::int_u<n> abs(const value::int_u<n>& v)
+    {
+      return v;
+    }
+
+    template <unsigned n>
+    value::int_s<n> abs(const value::int_s<n>& v)
+    {
+      return std::abs(v.to_enc());
+    }
+
 # endif // ! MLN_INCLUDE_ONLY
 
   } // end of namespace mln::math
Index: mln/math/round_sat.hh
--- mln/math/round_sat.hh	(revision 0)
+++ mln/math/round_sat.hh	(revision 0)
@@ -0,0 +1,83 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_MATH_ROUND_SAT_HH
+# define MLN_MATH_ROUND_SAT_HH
+
+/*! \file mln/math/round_sat.hh
+ *
+ * \brief Define round_sat routine.
+ */
+
+# include <cmath>
+
+# include <mln/core/concept/function.hh>
+# include <mln/value/props.hh>
+
+
+
+namespace mln
+{
+
+  namespace math
+  {
+
+
+    template <typename R>
+    struct round_sat_ : public Function_v2v< round_sat_<R> >
+    {
+      typedef R result;
+
+      template <typename T>
+      result operator()(const T& v) const;
+
+    };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename R>
+    template <typename T>
+    R round_sat_<R>::operator()(const T& v) const
+    {
+      long int l = (long int)(v + 0.49999); // FIXME: !!!
+      return
+	l < mln_min(R)
+	? mln_min(R)
+	: (l > mln_max(R)
+	   ? mln_max(R)
+	   : R(l));
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::math
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MATH_ROUND_SAT_HH
Index: mln/metal/abort.hh
--- mln/metal/abort.hh	(revision 0)
+++ mln/metal/abort.hh	(revision 0)
@@ -0,0 +1,50 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_METAL_ABORT_HH
+# define MLN_METAL_ABORT_HH
+
+# include <mln/metal/bool.hh>
+
+
+namespace mln
+{
+
+  namespace metal
+  {
+
+    template <typename T>
+    struct abort : false_
+    {};
+
+
+  } // end of namespace mln::metal
+
+} // end of namespace mln
+
+
+#endif // ! MLN_METAL_ABORT_HH
Index: mln/level/apply.hh
--- mln/level/apply.hh	(revision 1054)
+++ mln/level/apply.hh	(working copy)
@@ -34,7 +34,7 @@
  */
 
 # include <mln/core/concept/image.hh>
-# include <mln/core/concept/accumulator.hh>
+# include <mln/core/concept/function.hh>
 
 
 namespace mln
@@ -45,19 +45,19 @@
 
     /*! Apply a function-object to the image \p input.
      *
-     * \param[in] input The input image.
+     * \param[in,out] input The input image.
      * \param[in] f The function-object.
-     * \result A copy of the function-object.
      *
      * This routine runs: \n
-     *   for all p of \p input, \p f( \p input(p) ) \n
-     *   return \p f
+     *   for all p of \p input, \p input(p) = \p f( \p input(p) ) \n
      *
-     * \todo Find a meaning for this routine! (Clue: f is mutable
-     * and/or same for input?)
+     * This routine is equivalent to level::tranform(input, f, input)
+     * but it is faster since a single iterator is required.
+     *
+     * \todo Add versions for lowq images.
      */
     template <typename I, typename F>
-    F apply(const Image<I>& input, const Function<F>& f);
+    void apply(Image<I>& input, const Function_v2v<F>& f);
 
 
 
@@ -67,39 +67,33 @@
     {
 
       template <typename I, typename F>
-      F apply(const Image<I>& input_, const Function<F>& f_)
+      void apply_(Image<I>& input_, const F& f)
       {
-	const I& input  = exact(input_);
-	F f = exact(f_);
-	
+	I& input   = exact(input_);
 	mln_piter(I) p(input.domain());
 	for_all(p)
-	  f(input(p));
-	return f;
+	  input(p) = f(input(p));
       }
 
       template <typename I, typename F>
-      F apply(const Fast_Image<I>& input_, const Function<F>& f_)
+      void apply_(Fast_Image<I>& input_, const F& f)
       {
-	const I& input  = exact(input_);
-	F f = exact(f_);
-	
-	mln_pixter(const I) pxl(input);
+	I& input   = exact(input_);
+	mln_pixter(I) pxl(input);
 	for_all(pxl)
-	  f(pxl.val());
-	return f;
+	  pxl.val() = f(pxl.val());
       }
 
     } // end of namespace mln::level::impl
 
 
-    // Facades.
+    // Facade.
 
     template <typename I, typename F>
-    F apply(const Image<I>& input, const Function<F>& f)
+    void apply(Image<I>& input, const Function_v2v<F>& f)
     {
       mln_precondition(exact(input).has_data());
-      return impl::apply(exact(input), f);
+      impl::apply_(exact(input), exact(f));
     }
 
 # endif // ! MLN_INCLUDE_ONLY
Index: mln/level/stretch.hh
--- mln/level/stretch.hh	(revision 1054)
+++ mln/level/stretch.hh	(working copy)
@@ -71,7 +71,7 @@
 	if (max_ = min_)
 	  return; // FIXME
 	float min = float(min_), max = float(max_);
-	const float epsilon = value::props<float>::epsilon;
+	const float epsilon = value::props<float>::epsilon();
  	float m = 0.0f - 0.5f + epsilon;
  	float M = mln_max(value::int_u<n>) + 0.5f - epsilon;
 	float a = (M - m) / (max - min);
Index: mln/arith/plus.hh
--- mln/arith/plus.hh	(revision 1054)
+++ mln/arith/plus.hh	(working copy)
@@ -57,21 +57,43 @@
 
 # ifndef MLN_INCLUDE_ONLY
 
+    namespace impl
+    {
+
     template <typename L, typename R, typename O>
-    void plus(const Image<L>& lhs_, const Image<R>& rhs_, Image<O>& output_)
+      void plus_(const Image<L>& lhs_, const Image<R>& rhs_, Image<O>& output_)
     {
       const L& lhs = exact(lhs_);
       const R& rhs = exact(rhs_);
       O& output = exact(output_);
-
-      mln_precondition(rhs.domain() = lhs.domain());
-      mln_precondition(output.domain() = lhs.domain());
-
-      mln_piter(I) p(output.domain());
+	mln_piter(L) p(lhs.domain());
       for_all(p)
 	output(p) = lhs(p) + rhs(p);
     }
 
+      template <typename L, typename R, typename O>
+      void plus_(const Fast_Image<L>& lhs, const Fast_Image<R>& rhs, Fast_Image<O>& output)
+      {
+	mln_pixter(const L) lp(exact(lhs));
+	mln_pixter(const R) rp(exact(rhs));
+	mln_pixter(O)       op(exact(output));
+	for_all_3(lp, rp, op)
+	  op.val() = lp.val() + rp.val();
+      }
+
+    } // end of namespace mln::arith::impl
+
+
+    // Facade.
+
+    template <typename L, typename R, typename O>
+    void plus(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output)
+    {
+      mln_precondition(exact(rhs).domain() = exact(lhs).domain());
+      mln_precondition(exact(output).domain() = exact(lhs).domain());
+      impl::plus_(exact(lhs), exact(rhs), exact(output));
+    }
+
 # endif // ! MLN_INCLUDE_ONLY
 
   } // end of namespace mln::arith
Index: mln/linear/line_convolve.hh
--- mln/linear/line_convolve.hh	(revision 0)
+++ mln/linear/line_convolve.hh	(revision 0)
@@ -0,0 +1,82 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_LINEAR_LINE_CONVOLVE_HH
+# define MLN_LINEAR_LINE_CONVOLVE_HH
+
+/*! \file mln/linear/line_convolve.hh
+ *
+ * \brief Convolution by a line-shaped kernel.
+ */
+
+# include <mln/linear/convolve.hh>
+# include <mln/make/w_window_line.hh>
+
+
+
+namespace mln
+{
+
+  namespace linear
+  {
+
+    /*! Convolution of an image \p input by a line-shaped weighted
+     *  window defined by the array of \p weights.
+     *
+     * \warning Computation of \p output(p) is performed with the
+     * value type of \p output.
+     *
+     * \warning The weighted window is used as-is, considering that
+     * its symmetrization is handled by the client.
+     *
+     * \pre output.domain = input.domain
+     */
+    template <typename I, typename W, unsigned N, typename O>
+    void line_convolve(const Image<I>& input, const W (&weights)[N],
+		   Image<O>& output);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I, typename W, unsigned N, typename O>
+    void line_convolve(const Image<I>& input, const W (&weights)[N],
+		   Image<O>& output)
+    {
+      mln_precondition(exact(output).domain() = exact(input).domain());
+      linear::convolve(input,
+		       make::w_window_line<mln_dpoint(I)>(weights),
+		       output);
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::linear
+
+} // end of namespace mln
+
+
+#endif // ! MLN_LINEAR_LINE_CONVOLVE_HH
Index: mln/linear/hconvolve.hh
--- mln/linear/hconvolve.hh	(revision 0)
+++ mln/linear/hconvolve.hh	(revision 0)
@@ -0,0 +1,109 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_LINEAR_LINE_CONVOLVE_HH
+# define MLN_LINEAR_LINE_CONVOLVE_HH
+
+/*! \file mln/linear/line_convolve.hh
+ *
+ * \brief Convolution by an horizontal kernel.
+ */
+
+# include <vector>
+
+# include <mln/linear/convolve.hh>
+# include <mln/make/w_window_line.hh>
+# include <mln/core/t_image.hh>
+
+
+
+namespace mln
+{
+
+  namespace linear
+  {
+
+    /*! Convolution of an image \p input by an horizontal weighted
+     *  window defined by the array of \p weights.
+     *
+     * \warning Computation of \p output(p) is performed with the
+     * value type of \p output.
+     *
+     * \warning The weighted window is used as-is, considering that
+     * its symmetrization is handled by the client.
+     *
+     * \pre output.domain = input.domain
+     */
+    template <typename I, typename W, unsigned N, typename O>
+    void line_convolve(const Image<I>& input, const W (&weights)[N],
+		   Image<O>& output);
+
+    // FIXME: Doc!
+    template <typename I, typename W, unsigned Nr, unsigned Nc, typename O>
+    void line_convolve(const Image<I>& input,
+		   const W (&row_weights)[Nr], const W (&col_weights)[Nc],
+		   Image<O>& output);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I, typename W, unsigned N, typename O>
+    void line_convolve(const Image<I>& input, const W (&weights)[N],
+		   Image<O>& output)
+    {
+      mln_precondition(exact(output).domain() = exact(input).domain());
+      linear::convolve(input,
+		       make::w_window_line<mln_dpoint(I)>(weights),
+		       output);
+    }
+
+
+    template <typename I, typename W, unsigned Nr, unsigned Nc, typename O>
+    void line_convolve(const Image<I>& input,
+		   const W (&row_weights)[Nr], const W (&col_weights)[Nc],
+		   Image<O>& output)
+    {
+      // FIXME: Check 2D.
+      mln_precondition(exact(output).domain() = exact(input).domain());
+      O tmp(exact(output).domain());
+      linear::convolve(input,
+		       make::w_window_line<mln_dpoint(I)>(row_weights),
+		       tmp);
+      t_image<O> swap_output = swap_coords(output, 0, 1);
+      linear::convolve(swap_coords(tmp, 0, 1),
+		       make::w_window_line<mln_dpoint(I)>(col_weights),
+		       swap_output);
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::linear
+
+} // end of namespace mln
+
+
+#endif // ! MLN_LINEAR_LINE_CONVOLVE_HH
Index: mln/linear/sobel.hh
--- mln/linear/sobel.hh	(revision 0)
+++ mln/linear/sobel.hh	(revision 0)
@@ -0,0 +1,140 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_LINEAR_SOBEL_HH
+# define MLN_LINEAR_SOBEL_HH
+
+/*! \file mln/linear/sobel.hh
+ *
+ * \brief Sobel filter.
+ */
+
+# include <mln/arith/plus.hh>
+# include <mln/fun/v2v/abs.hh>
+# include <mln/level/apply.hh>
+# include <mln/linear/line_x2_convolve.hh>
+
+
+
+namespace mln
+{
+
+  namespace linear
+  {
+
+    /*! Convolution of an image \p input by the weighted window \p w_win.
+     *
+     * \warning Computation of \p output(p) is performed with the
+     * value type of \p output.
+     *
+     * \warning The weighted window is used as-is, considering that
+     * its symmetrization is handled by the client.
+     *
+     * \pre output.domain = input.domain
+     *
+     * \todo Only for 2D so check + generalize.
+     *
+     * \todo Suboptimal since it is not point-wise and it costs temp
+     * images.
+     */
+    template <typename I, typename O>
+    void sobel_v(const Image<I>& input, Image<O>& output);
+
+    template <typename I, typename O>
+    void sobel_h(const Image<I>& input, Image<O>& output);
+
+    template <typename I, typename O>
+    void sobel(const Image<I>& input, Image<O>& output);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    namespace impl
+    {
+
+      template <typename I, typename O>
+      void sobel_h_(const Image<I>& input, Image<O>& output)
+      {
+	int wrow[] = { -1, 0, 1 }, wcol[] = { 1,
+					      2,
+					      1 };
+	linear::line_x2_convolve(input, wrow, wcol, output);
+      }
+
+      template <typename I, typename O>
+      void sobel_v_(const Image<I>& input, Image<O>& output)
+      {
+	int wrow[] = { 1, 2, 1 }, wcol[] = { -1,
+					      0,
+					     +1 };
+	linear::line_x2_convolve(input, wrow, wcol, output);
+      }
+
+      template <typename I, typename O>
+      void sobel_(const Image<I>& input, Image<O>& output)
+      {
+	O temp_h(exact(input).domain()), temp_v(exact(input).domain());
+	sobel_h(input, temp_h);
+	sobel_v(input, temp_v);
+	arith::plus(temp_h, temp_v, output);
+	level::apply(exact(output), fun::v2v::abs<mln_value(O)>());
+      }
+
+    } // end of namespace mln::linear::impl
+
+
+    // Facades.
+
+    template <typename I, typename O>
+    void sobel_h(const Image<I>& input, Image<O>& output)
+    {
+      mln_precondition(exact(output).domain() = exact(input).domain());
+      impl::sobel_h_(exact(input), exact(output));
+    }
+
+    template <typename I, typename O>
+    void sobel_v(const Image<I>& input, Image<O>& output)
+    {
+      mln_precondition(exact(output).domain() = exact(input).domain());
+      impl::sobel_v_(exact(input), exact(output));
+    }
+
+    template <typename I, typename O>
+    void sobel(const Image<I>& input, Image<O>& output)
+    {
+      mln_precondition(exact(output).domain() = exact(input).domain());
+      impl::sobel_(exact(input), exact(output));
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::linear
+
+} // end of namespace mln
+
+
+#endif // ! MLN_LINEAR_SOBEL_HH
Index: mln/linear/convolve.hh
--- mln/linear/convolve.hh	(revision 1054)
+++ mln/linear/convolve.hh	(working copy)
@@ -46,7 +46,7 @@
   namespace linear
   {
 
-    /*! Convolution of image \p input by the weighted window \p w_win.
+    /*! Convolution of an image \p input by the weighted window \p w_win.
      *
      * \warning Computation of \p output(p) is performed with the
      * value type of \p output.
@@ -67,7 +67,7 @@
     {
 
       template <typename I, typename W, typename O>
-      void convolve(const Image<I>& input_, const Weighted_Window<W>& w_win_,
+      void convolve_(const Image<I>& input_, const Weighted_Window<W>& w_win_,
 		    Image<O>& output_)
       {
 	const I& input = exact(input_);
@@ -87,7 +87,7 @@
       }
 
       template <typename I, typename W, typename O>
-      void convolve(const Fast_Image<I>& input_, const Weighted_Window<W>& w_win_,
+      void convolve_(const Fast_Image<I>& input_, const Weighted_Window<W>& w_win_,
 		    Fast_Image<O>& output_)
       {
 	const I& input = exact(input_);
@@ -122,7 +122,7 @@
 		  Image<O>& output)
     {
       mln_precondition(exact(output).domain() = exact(input).domain());
-      impl::convolve(exact(input), exact(w_win), exact(output));
+      impl::convolve_(exact(input), exact(w_win), exact(output));
     }
 
 # endif // ! MLN_INCLUDE_ONLY
Index: mln/linear/line_x2_convolve.hh
--- mln/linear/line_x2_convolve.hh	(revision 0)
+++ mln/linear/line_x2_convolve.hh	(revision 0)
@@ -0,0 +1,92 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_LINEAR_LINE_X2_CONVOLVE_HH
+# define MLN_LINEAR_LINE_X2_CONVOLVE_HH
+
+/*! \file mln/linear/line_x2_convolve.hh
+ *
+ * \brief 2D convolution by a couple of line kernels.
+ */
+
+# include <mln/linear/line_convolve.hh>
+# include <mln/core/t_image.hh>
+
+
+
+namespace mln
+{
+
+  namespace linear
+  {
+
+    /*! Convolution of an image \p input by two weighted line-shapes
+     *  windows.
+     *
+     * \warning Computation of \p output(p) is performed with the
+     * value type of \p output.
+     *
+     * \warning The weighted window is used as-is, considering that
+     * its symmetrization is handled by the client.
+     *
+     * \pre output.domain = input.domain
+     */
+    template <typename I,
+	      typename W, unsigned Nr, unsigned Nc,
+	      typename O>
+    void line_x2_convolve(const Image<I>& input,
+			  const W (&row_weights)[Nr], const W (&col_weights)[Nc],
+			  Image<O>& output);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I,
+	      typename W, unsigned Nr, unsigned Nc,
+	      typename O>
+    void line_x2_convolve(const Image<I>& input,
+			  const W (&row_weights)[Nr], const W (&col_weights)[Nc],
+			  Image<O>& output)
+    {
+      // FIXME: Check 2D.
+      mln_precondition(exact(output).domain() = exact(input).domain());
+
+      O tmp(exact(output).domain());
+      linear::line_convolve(input, row_weights, tmp);
+
+      t_image<O> swap_output = swap_coords(output, 0, 1);
+      linear::line_convolve(swap_coords(tmp, 0, 1), col_weights, swap_output);
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::linear
+
+} // end of namespace mln
+
+
+#endif // ! MLN_LINEAR_LINE_X2_CONVOLVE_HH
Index: mln/value/aliases.hh
--- mln/value/aliases.hh	(revision 0)
+++ mln/value/aliases.hh	(revision 0)
@@ -0,0 +1,43 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_VALUE_ALIASES_HH
+# define MLN_VALUE_ALIASES_HH
+
+/*! \file mln/value/aliases.hh
+ *
+ * \brief File that includes all aliases of value types.
+ */
+
+
+# include <mln/value/int_u8.hh>
+# include <mln/value/int_u16.hh>
+
+# include <mln/value/int_s8.hh>
+
+
+#endif // ! MLN_VALUE_ALIASES_HH
Index: mln/value/props.hh
--- mln/value/props.hh	(revision 1054)
+++ mln/value/props.hh	(working copy)
@@ -42,11 +42,11 @@
 
 
 /// Get the minimum value of type \c T.
-# define mln_min(T) mln::value::props< T >::min
+# define mln_min(T) mln::value::props< T >::min()
 
 
 /// Get the maximum value of type \c T.
-# define mln_max(T) mln::value::props< T >::max
+# define mln_max(T) mln::value::props< T >::max()
 
 
 /// Get the number of values for value type \c T.
@@ -108,8 +108,8 @@
     template <>
     struct props<bool>
     {
-      static const bool min = false;
-      static const bool max = true;
+      static const bool min() { return false; }
+      static const bool max() { return true; }
       static const std::size_t card_ = 2;
       typedef binary_kind kind;
     };
@@ -120,8 +120,8 @@
     template <>
     struct props<unsigned char>
     {
-      static const unsigned char min =   0;
-      static const unsigned char max = 255;
+      static const unsigned char min() { return   0; }
+      static const unsigned char max() { return 255; }
       static const std::size_t  card_ = 256;
       typedef data_kind kind;
       typedef float sum;
@@ -130,8 +130,8 @@
     template <>
     struct props<signed char>
     {
-      static const signed char  min = -128;
-      static const signed char  max =  127;
+      static const signed char  min() { return -128; }
+      static const signed char  max() { return  127; }
       static const std::size_t card_ =  256;
       typedef data_kind kind;
       typedef float sum;
@@ -140,8 +140,8 @@
     template <>
     struct props<unsigned short>
     {
-      static const unsigned short min =     0;
-      static const unsigned short max = 65535;
+      static const unsigned short min() { return     0; }
+      static const unsigned short max() { return 65535; }
       static const std::size_t   card_ = 65536;
       typedef data_kind kind;
       typedef float sum;
@@ -150,8 +150,8 @@
     template <>
     struct props<signed short>
     {
-      static const signed short min = -32768;
-      static const signed short max =  32767;
+      static const signed short min() { return -32768; }
+      static const signed short max() { return  32767; }
       static const std::size_t card_ = 655356;
       typedef data_kind kind;
       typedef float sum;
@@ -160,8 +160,8 @@
     template <>
     struct props<unsigned int>
     {
-      static const unsigned int min = 0;
-      static const unsigned int max = UINT_MAX;
+      static const unsigned int min() { return 0; }
+      static const unsigned int max() { return UINT_MAX; }
       typedef data_kind kind;
       static const std::size_t card_ = 0;
       typedef float sum;
@@ -170,8 +170,8 @@
     template <>
     struct props<signed int>
     {
-      static const signed int  min = INT_MIN;
-      static const signed int  max = INT_MAX;
+      static const signed int  min() { return INT_MIN; }
+      static const signed int  max() { return INT_MAX; }
       typedef data_kind kind;
       static const std::size_t card_ = 0;
       typedef float sum;
@@ -180,8 +180,8 @@
     template <>
     struct props<unsigned long int>
     {
-      static const unsigned long int min = 0;
-      static const unsigned long int max = ULONG_MAX;
+      static const unsigned long int min() { return 0; }
+      static const unsigned long int max() { return ULONG_MAX; }
       typedef data_kind kind;
       static const std::size_t card_ = 0;
       typedef float sum;
@@ -190,8 +190,8 @@
     template <>
     struct props<signed long int>
     {
-      static const signed long int min = LONG_MIN;
-      static const signed long int max = LONG_MAX;
+      static const signed long int min() { return LONG_MIN; }
+      static const signed long int max() { return LONG_MAX; }
       typedef data_kind kind;
       static const std::size_t card_ = 0;
       typedef float sum;
@@ -203,9 +203,9 @@
     template <>
     struct props<float>
     {
-      static const float min = FLT_MIN;
-      static const float max = FLT_MAX;
-      static const float epsilon = 0.00001f;
+      static const float min() { return FLT_MIN; }
+      static const float max() { return FLT_MAX; }
+      static const float epsilon() { return 0.00001f; }
       typedef data_kind kind;
       static const std::size_t card_ = 0;
       typedef float sum;
@@ -214,9 +214,9 @@
     template <>
     struct props<double>
     {
-      static const double min = DBL_MIN;
-      static const double max = DBL_MAX;
-      static const double epsilon = 0.0000001;
+      static const double min() { return DBL_MIN; }
+      static const double max() { return DBL_MAX; }
+      static const double epsilon() { return 0.0000001; }
       typedef data_kind kind;
       static const std::size_t card_ = 0;
       typedef double sum;
Index: mln/value/all.hh
--- mln/value/all.hh	(revision 1054)
+++ mln/value/all.hh	(working copy)
@@ -44,7 +44,16 @@
 }
 
 
+# include <mln/value/aliases.hh>
+# include <mln/value/label.hh>
 # include <mln/value/props.hh>
+# include <mln/value/proxy.hh>
+
+
+// FIXME: that includes concept/image.hh!
+
+// # include <mln/value/cast.hh>
+// # include <mln/value/stack.hh>
 
 
 
Index: mln/value/int_s.hh
--- mln/value/int_s.hh	(revision 1054)
+++ mln/value/int_s.hh	(working copy)
@@ -89,23 +89,24 @@
 
 
 
+    // Safety.
+    template <> struct int_s<0>;
+    template <> struct int_s<1>;
+
+
+
     template <unsigned n>
     struct props< int_s<n> >
     {
-      static const int_s<n> max; // = 2^(n-1) - 1
-      static const int_s<n> min; // = - max
       static const std::size_t card_ = metal::pow<2, n>::value;
+      static const int_s<n> max() { return metal::pow<2, n-1>::value - 1; }
+      static const int_s<n> min() { return - max(); }
       static const unsigned nbits = n;
       typedef data_kind kind;
       typedef float sum;
     };
 
 
-    // Safety.
-    template <> struct int_s<0>;
-    template <> struct int_s<1>;
-
-
 
     /*! \brief Print an signed integer \p i into the output stream \p ostr.
      *
@@ -167,14 +168,6 @@
     const int_s<n> int_s<n>::one = 1;
 
     template <unsigned n>
-    const int_s<n>
-    props< int_s<n> >::min = 1 - metal::pow<2, n - 1>::value;
-
-    template <unsigned n>
-    const int_s<n>
-    props< int_s<n> >::max = metal::pow<2, n - 1>::value - 1;
-
-    template <unsigned n>
     std::ostream& operator<<(std::ostream& ostr, const int_s<n>& i)
     {
       return ostr << debug::format(i.to_equiv());
Index: mln/value/int_u.hh
--- mln/value/int_u.hh	(revision 1054)
+++ mln/value/int_u.hh	(working copy)
@@ -95,8 +95,8 @@
     struct props< int_u<n> >
     {
       static const std::size_t card_ = metal::pow<2, n>::value;
-      static const int_u<n> min; // = 0
-      static const int_u<n> max; // = card_ - 1
+      static const int_u<n> min() { return 0; }
+      static const int_u<n> max() { return card_ - 1; }
       static const unsigned nbits = n;
       typedef data_kind kind;
       typedef float sum;
@@ -156,15 +156,6 @@
     template <unsigned n>
     const int_u<n> int_u<n>::one = 1;
 
-
-    template <unsigned n>
-    const int_u<n>
-    props< int_u<n> >::min = 0;
-
-    template <unsigned n>
-    const int_u<n>
-    props< int_u<n> >::max = metal::pow<2, n>::value - 1;
-
     template <unsigned n>
     std::ostream& operator<<(std::ostream& ostr, const int_u<n>& i)
     {
Index: mln/make/w_window_line.hh
--- mln/make/w_window_line.hh	(revision 0)
+++ mln/make/w_window_line.hh	(revision 0)
@@ -0,0 +1,81 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+#ifndef MLN_MAKE_W_WINDOW_LINE_HH
+# define MLN_MAKE_W_WINDOW_LINE_HH
+
+/*! \file mln/make/w_window_line.hh
+ *
+ * \brief Routine to create an horizontal mln::w_window.
+ */
+
+# include <mln/core/w_window.hh>
+
+
+namespace mln
+{
+
+  namespace make
+  {
+
+    /*! \brief Create an horizontal centered and symmetrical
+     *  mln::w_window.
+     *
+     * The free parameter \c D is a type of delta-point. 
+     *
+     * \pre The window length \c L has to be odd.
+     *
+     * \return A window.
+     */
+    template <typename D, typename W, unsigned L>
+    mln::w_window<D,W> w_window_line(const W (&w)[L]);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename D, typename W, unsigned L>
+    mln::w_window<D,W> w_window_line(const W (&w)[L])
+    {
+      mln_precondition(L % 2 = 1);
+      mln::w_window<D,W> w_win;
+      D dp = D::zero;
+      for (unsigned i = 0; i < L; ++i)
+	{
+	  dp[D::dim - 1] = i - L / 2;
+	  w_win.insert(w[i], dp);
+	}
+      return w_win;
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::make
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MAKE_W_WINDOW_LINE_HH
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0