Olena-patches
  Threads by month 
                
            - ----- 2025 -----
 - November
 - 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
 
September 2007
- 7 participants
 - 135 discussions
 
                        
                            
                                
                            
                            milena r1159: Change image_adaptor inheritance to	morphers inheritance
                        
                        
by Matthieu Garrigues 24 Sep '07
                    by Matthieu Garrigues 24 Sep '07
24 Sep '07
                    
                          URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2007-09-24  Matthieu Garrigues  <garrigues(a)lrde.epita.fr>
	Change image_adaptor inheritance to morphers inheritance.
	* mln/core/decorated_image.hh: Inherit from identity morpher.
	* mln/core/image_if.hh: Inherit from domain morpher.
	Move destroy method to the super class image_base.
	* mln/core/image2d_b.hh,
	* mln/core/image3d_b.hh,
	* mln/core/internal/image_base.hh: Update.
---
 decorated_image.hh     |   63 +++++-----------------------
 image2d_b.hh           |    5 --
 image3d_b.hh           |    6 +-
 image_if.hh            |  109 +++++++++++++------------------------------------
 internal/image_base.hh |   11 ++++
 5 files changed, 57 insertions(+), 137 deletions(-)
Index: trunk/milena/mln/core/decorated_image.hh
===================================================================
--- trunk/milena/mln/core/decorated_image.hh	(revision 1158)
+++ trunk/milena/mln/core/decorated_image.hh	(revision 1159)
@@ -28,7 +28,7 @@
 #ifndef MLN_CORE_DECORATED_IMAGE_HH
 # define MLN_CORE_DECORATED_IMAGE_HH
 
-# include <mln/core/internal/image_base.hh>
+# include <mln/core/internal/image_identity_morpher.hh>
 
 # include <mln/value/proxy.hh>
 
@@ -37,7 +37,7 @@
 {
 
   // Fwd decl.
-  template <typename I, typename D> class decorated_image;
+  template <typename I, typename D> struct decorated_image;
 
 
   namespace internal
@@ -72,23 +72,26 @@
   // FIXME: Doc!
 
   template <typename I, typename D>
-  class decorated_image : public internal::image_base_< mln_pset(I), decorated_image<I,D> >,
-			  public internal::decorated_image_impl_< I, decorated_image<I,D> >
+  struct decorated_image :
+    public internal::decorated_image_impl_< I, decorated_image<I,D> >,
+    public internal::image_identity_morpher_< I, mln_pset(I), decorated_image<I,D> >
   {
     typedef decorated_image<I, D> self_;
     typedef internal::decorated_image_impl_< I, self_ > impl_;
-    typedef internal::image_base_< mln_pset(I), decorated_image<I,D> > super_;
+    typedef internal::image_identity_morpher_< I, mln_pset(I), self_ > super_;
+
+    /// Return type of read-write access.
+    typedef typename internal::morpher_lvalue_<I>::ret lvalue;
+
   public:
 
+
     /// Ctors
     decorated_image();
     decorated_image(I& ima, const D& deco);
     /// Dtor
     ~decorated_image();
 
-    typedef mln_value(I)                    value;
-    typedef mln::value::proxy<const self_> rvalue;
-    typedef typename impl_::lvalue         lvalue;
 
     /// Value_Set associated type.
     typedef mln_vset(I) vset;
@@ -96,10 +99,6 @@
     /// Skeleton.
     typedef decorated_image< tag::image<I>, tag::data<D> > skeleton;
 
-
-    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;
 
     /// Const promotion via convertion.
@@ -111,13 +110,7 @@
     /// Give the decoration.
     D& decoration();
 
-    /// FIXME : to put into a identity morpher
-    /// Give the definition domain.
-    const mln_pset(I)& domain() const;
-
-    /// Give the set of values.
-    const mln_vset(I)& values() const;
-
+  protected:
     using super_::data_;
   };
 
@@ -172,22 +165,6 @@
     mw = 0;
   }
 
-  template <typename I, typename D>
-  typename decorated_image<I,D>::rvalue
-  decorated_image<I,D>::operator()(const mln_psite(I)& p) const
-  {
-    rvalue tmp(*this, p);
-    return tmp;
-  }
-
-  template <typename I, typename D>
-  typename decorated_image<I,D>::lvalue
-  decorated_image<I,D>::operator()(const mln_psite(I)& p)
-  {
-    lvalue tmp(*this, p);
-    return tmp;
-  }
-
   namespace internal
   {
 
@@ -232,22 +209,6 @@
     return this->data_->deco_;
   }
 
-  template <typename I, typename D>
-  const mln_pset(I)&
-  decorated_image<I,D>::domain() const
-  {
-    mln_precondition(exact(this)->has_data());
-    return  this->data_->ima_.domain();
-  }
-
-  template <typename I, typename D>
-  const mln_vset(I)&
-  decorated_image<I,D>::values() const
-  {
-    return this->data_->ima_.values();
-  }
-
-
   // decorate
 
   template <typename I, typename D>
Index: trunk/milena/mln/core/image_if.hh
===================================================================
--- trunk/milena/mln/core/image_if.hh	(revision 1158)
+++ trunk/milena/mln/core/image_if.hh	(revision 1159)
@@ -33,7 +33,7 @@
  * \brief Definition of a image_if image.
  */
 
-# include <mln/core/internal/image_base.hh>
+# include <mln/core/internal/image_domain_morpher.hh>
 # include <mln/core/pset_if.hh>
 # include <mln/pw/all.hh>
 
@@ -51,13 +51,10 @@
     struct data_< image_if<I,F> >
     {
       data_(I& ima, const F& f);
+      data_(I& ima, const pset_if<mln_pset(I), F>& pset);
 
-      pset_if<mln_pset(I), F> pset_;
-      F f_;
       I ima_;
-      // FIXME for matthieu: f_ is *also* in pset_; pb: redundancy!!!
-      // FIXME for matthieu: ctor arg list and attr list should be the *same*!
-      // FIXME for matthieu: do *not* change order of those lists elements!
+      pset_if<mln_pset(I), F> pset_;
     };
 
   } // end of namespace mln::internal
@@ -67,25 +64,21 @@
    *
    */
   template <typename I, typename F>
-  struct image_if
-    : public internal::image_base_< pset_if<mln_pset(I), F>, image_if<I,F> >
-  // FIXME for matthieu: *not* image_base_ *but* image_domain_morpher_
+  struct image_if : public internal::image_domain_morpher_< I,
+							    pset_if<mln_pset(I),F>,
+							    image_if<I,F> >
   {
 
-    // Parent
-    typedef internal::image_base_< pset_if<mln_pset(I), F>, image_if<I,F> > super_;
-    // FIXME for matthieu: this should *not* be public!
-    // FIXME for matthieu: comments end with a '.'
-    // FIXME for matthieu: we do not say "parent" but "super".
-
 
     /// Skeleton.
     typedef image_if< tag::image<I>, tag::function<F> > skeleton;
 
-
-    /// Point_Set associated type.
+    /// Point_Site associated type.
     typedef pset_if<mln_pset(I), F> pset;
 
+    /// Psite type.
+    typedef mln_psite(pset) psite;
+
     /// Constructor from an image \p ima and a predicate \p f.
     image_if(I& ima, const F& f);
 
@@ -101,40 +94,16 @@
     /// Const promotion via convertion.
     operator image_if<const I, F>() const;
 
-    using super_::data_;
-    // FIXME for matthieu: this should *not* be public!
-
-    typedef image_if<I,F> self_;
-
-    // FIXME : to put into an identity morpher
-    // FIXME for matthieu: nope...
-
 
-    // FIXME for matthieu: most of those typedefs and methods are useless...
+  protected:
 
-    /// Point_Site associated type.
-    typedef mln_point(I) point;
-    typedef mln_psite(pset) psite;
-
-    /// Value_Set associated type.
-    typedef mln_vset(I) vset;
-
-    /// Value associated type.
-    typedef mln_value(I)   value;
-
-    /// Return type of read-only access.
-    typedef mln_rvalue(I) rvalue;
-
-    typedef typename internal::morpher_lvalue_<I>::ret lvalue;
-
-    /// Read-only access of pixel value at point site \p p.
-    rvalue operator()(const psite& p) const;
+    /// Self type.
+    typedef image_if<I,F> self_;
 
-    /// Read-write access of pixel value at point site \p p.
-    lvalue operator()(const psite& p);
+    /// Super type.
+    typedef internal::image_base_< pset_if<mln_pset(I), F>, image_if<I,F> > super_;
 
-    /// Give the set of values.
-    const vset& values() const;
+    using super_::data_;
   };
 
 
@@ -176,8 +145,14 @@
     template <typename I, typename F>
     data_< image_if<I,F> >::data_(I& ima, const F& f)
       : ima_(ima),
-	pset_(ima.domain() | f),
-	f_(f)
+	pset_(ima.domain() | f)
+    {
+    }
+
+    template <typename I, typename F>
+    data_< image_if<I,F> >::data_(I& ima, const pset_if<mln_pset(I), F>& pset)
+      : ima_(ima),
+	pset_(pset)
     {
     }
 
@@ -197,6 +172,13 @@
   }
 
   template <typename I, typename F>
+  image_if<I,F>::operator image_if<const I, F>() const
+  {
+    image_if<const I, F> tmp(this->data_->ima_, this->data_->pset_);
+    return tmp;
+  }
+
+  template <typename I, typename F>
   bool
   image_if<I,F>::owns_(const mln_psite(I)& p) const
   {
@@ -210,37 +192,8 @@
     return data_->pset_;
   }
 
-  template <typename I, typename F>
-  image_if<I,F>::operator image_if<const I, F>() const
-  {
-    image_if<const I, F> tmp(this->data_->ima_, this->data_->f_);
-    return tmp;
-  }
 
 
-  template <typename I, typename F>
-  typename image_if<I,F>::rvalue
-  image_if<I,F>::operator()(const psite& p) const
-  {
-    mln_precondition(exact(this)->owns_(p));
-    return data_->ima_(p);
-  }
-
-  template <typename I, typename F>
-  typename image_if<I,F>::lvalue
-  image_if<I,F>::operator()(const psite& p)
-  {
-    mln_precondition(exact(this)->owns_(p));
-    return data_->ima_(p);
-  }
-
-  template <typename I, typename F>
-  const mln_vset(I)&
-  image_if<I,F>::values() const
-  {
-    return data_->ima_.values();
-  }
-
 
   // Operators.
 
Index: trunk/milena/mln/core/internal/image_base.hh
===================================================================
--- trunk/milena/mln/core/internal/image_base.hh	(revision 1158)
+++ trunk/milena/mln/core/internal/image_base.hh	(revision 1159)
@@ -171,6 +171,8 @@
       /// Copy constructor.
       image_base_(const image_base_& rhs);
 
+      /// Detach data from an image (free it if nobody else hold it).
+      void destroy();
 
       const util::tracked_ptr< internal::data_<E> >& hook_data_() const { return data_; }
 
@@ -192,6 +194,8 @@
 
     template <typename S, typename E>
     image_base_<S,E>::image_base_(const image_base_& rhs)
+      : select_image_concept_< typename trait::is_fast<E>::ret,
+			       E >()
     {
       mln_precondition(exact(rhs).has_data()); // FIXME: Is-it too restrictive?
       this->data_ = rhs.data_;
@@ -247,6 +251,13 @@
       return exact(this)->domain().npoints();      
     }
 
+    template <typename S, typename E>
+    void
+    image_base_<S,E>::destroy()
+    {
+      data_.clean_();
+    }
+
 # endif // ! MLN_INCLUDE_ONLY
 
   } // end of namespace mln::internal
Index: trunk/milena/mln/core/image2d_b.hh
===================================================================
--- trunk/milena/mln/core/image2d_b.hh	(revision 1158)
+++ trunk/milena/mln/core/image2d_b.hh	(revision 1159)
@@ -145,11 +145,6 @@
     /// 3).
     image2d_b(const box2d& b, unsigned bdr = border::thickness);
 
-
-    /// Detach data from an image (free it if nobody else hold it).
-    void destroy();
-
-
     /// Initialize an empty image.
     void init_(const box2d& b, unsigned bdr = border::thickness);
 
Index: trunk/milena/mln/core/image3d_b.hh
===================================================================
--- trunk/milena/mln/core/image3d_b.hh	(revision 1158)
+++ trunk/milena/mln/core/image3d_b.hh	(revision 1159)
@@ -113,8 +113,8 @@
     // End of warning.
 
 
-    /// Parent type
-    typedef internal::image_primary_< box3d, image3d_b<T> > parent;
+    /// Super type
+    typedef internal::image_primary_< box3d, image3d_b<T> > super_;
 
     /// Value associated type.
     typedef T         value;
@@ -199,7 +199,7 @@
     T* buffer();
 
     /// To use the track pointer inherited.
-    using parent::data_;
+    using super_::data_;
   };
 
 
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from  Thierry Geraud  <thierry.geraud(a)lrde.epita.fr>
	Rename init_with_ as init_.
	* mln/core/internal/image_base.hh
	(init_with_): Rename as...
	(init_): ...this.
	* mln/core/image2d_b.hh,
	* mln/core/sub_image.hh,
	* mln/core/clone.hh,
	* mln/io/internal/pnm/load.hh: Update.
 core/clone.hh               |    2 +-
 core/image2d_b.hh           |   29 +++++++++++++++++++++--------
 core/internal/image_base.hh |    2 +-
 core/sub_image.hh           |   16 ++++++++--------
 io/internal/pnm/load.hh     |    2 +-
 5 files changed, 32 insertions(+), 19 deletions(-)
Index: mln/core/internal/image_base.hh
--- mln/core/internal/image_base.hh	(revision 1157)
+++ mln/core/internal/image_base.hh	(working copy)
@@ -60,7 +60,7 @@
 
     /// Declaration of the general image initialization routine.
     template <typename I, typename J>
-    void init_with_(Image<I>& target, const Image<J>& model);
+    void init_(Image<I>& target, const Image<J>& model);
 
     // FIXME: Say more about it!
 
Index: mln/core/image2d_b.hh
--- mln/core/image2d_b.hh	(revision 1157)
+++ mln/core/image2d_b.hh	(working copy)
@@ -151,7 +151,7 @@
 
 
     /// Initialize an empty image.
-    void init_with_(const box2d& b, unsigned bdr = border::thickness);
+    void init_(const box2d& b, unsigned bdr = border::thickness);
 
 
     /// Test if \p p is valid.
@@ -208,7 +208,7 @@
   {
 
     template <typename T, typename J>
-    void init_with_(image2d_b<T>& target, const J& model);
+    void init_(image2d_b<T>& target, const J& model);
     
   } // end of namespace mln::impl
 
@@ -217,17 +217,30 @@
 # ifndef MLN_INCLUDE_ONLY
 
 
-  // impl::init_with_
+  // impl::init_
 
   namespace impl
   {
 
+//     void init(tag::border, unsigned b, const image2d_b<T>& model)
+//     {
+//       b = model.border();
+//     }
+
     template <typename T, typename J>
-    void init_with_(image2d_b<T>& target, const J& model)
+    void init_(image2d_b<T>& target, const J& model)
     {
       box2d b = geom::bbox(model);
       unsigned bdr = border::get(model);
-      target.init_with_(b, bdr);
+
+      // FIXME
+
+//       box2d b;
+//       init(tag::bbox, b, model);
+//       unsigned bdr;
+//       init(tag::border, bdr, model);
+
+      target.init_(b, bdr);
     }
     
   } // end of namespace mln::impl
@@ -313,18 +326,18 @@
   template <typename T>
   image2d_b<T>::image2d_b(int nrows, int ncols, unsigned bdr)
   {
-    init_with_(make::box2d(nrows, ncols), bdr);
+    init_(make::box2d(nrows, ncols), bdr);
   }
 
   template <typename T>
   image2d_b<T>::image2d_b(const box2d& b, unsigned bdr)
   {
-    init_with_(b, bdr);
+    init_(b, bdr);
   }
 
   template <typename T>
   void
-  image2d_b<T>::init_with_(const box2d& b, unsigned bdr)
+  image2d_b<T>::init_(const box2d& b, unsigned bdr)
   {
     mln_precondition(! this->has_data());
     this->data_ = new internal::data_< image2d_b<T> >(b, bdr);
Index: mln/core/sub_image.hh
--- mln/core/sub_image.hh	(revision 1157)
+++ mln/core/sub_image.hh	(working copy)
@@ -71,7 +71,7 @@
     sub_image(I& ima, const S& pset);
 
     /// Initialization.
-    void init_with_(I& ima, const S& pset);
+    void init_(I& ima, const S& pset);
 
     /// Give the definition domain.
     const S& domain() const;
@@ -95,7 +95,7 @@
   {
 
     template <typename I, typename S, typename J>
-    void init_with_(sub_image<I,S>& target, const J& model);
+    void init_(sub_image<I,S>& target, const J& model);
     
   } // end of namespace mln::impl
 
@@ -103,18 +103,18 @@
 
 # ifndef MLN_INCLUDE_ONLY
 
-  // impl::init_with_
+  // impl::init_
 
   namespace impl
   {
 
     template <typename I, typename S, typename J>
-    void init_with_(sub_image<I,S>& target, const J& model)
+    void init_(sub_image<I,S>& target, const J& model)
     {
       I ima;
-      init_with_(ima, model); // rec
+      init_(ima, model); // rec
       S pset = model.domain();
-      target.init_with_(ima, pset);
+      target.init_(ima, pset);
     }
     
   } // end of namespace mln::impl
@@ -145,12 +145,12 @@
   template <typename I, typename S>
   sub_image<I,S>::sub_image(I& ima, const S& pset)
   {
-    init_with_(ima, pset);
+    init_(ima, pset);
   }
 
   template <typename I, typename S>
   void
-  sub_image<I,S>::init_with_(I& ima, const S& pset)
+  sub_image<I,S>::init_(I& ima, const S& pset)
   {
     mln_precondition(! this->has_data());
     this->data_ = new internal::data_< sub_image<I,S> >(ima, pset);
Index: mln/core/clone.hh
--- mln/core/clone.hh	(revision 1157)
+++ mln/core/clone.hh	(working copy)
@@ -58,7 +58,7 @@
   {
     // FIXME: Add a static check that mln_concrete(I) actually *is* concrete...
     mln_concrete(I) tmp;
-    impl::init_with_(tmp, exact(model));
+    impl::init_(tmp, exact(model));
     level::fill(tmp, model);
     return tmp;
   }
Index: mln/io/internal/pnm/load.hh
--- mln/io/internal/pnm/load.hh	(revision 1157)
+++ mln/io/internal/pnm/load.hh	(working copy)
@@ -208,7 +208,7 @@
 	    abort();
 	  }
 
-	  ima.init_with(nrows, ncols);
+	  ima.init_(make::box2d(nrows, ncols));
 	  if (type = type_)
 	    load_raw_2d(file, ima);
 	  else
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from  Thierry Geraud  <thierry.geraud(a)lrde.epita.fr>
	introduce meta accumulators and better accumulators.
	New material for accumulators.
	* tests/accu_nil.cc: New.
	* tests/labeling_estimate.cc: New.
	* tests/accu_min.cc: New.
	* tests/accu_all.cc: New.
	* mln/accu/nil.hh: New.
	* mln/accu/take.hh: New.
	* mln/accu/pair.hh: New.
	* mln/accu/p.hh: New.
	* mln/accu/v.hh: New.
	* mln/accu/all.hh: New.
	* mln/accu/compute.hh: New.
	* mln/make/pix.hh: New.
	* mln/labeling/estimate.hh: New.
	* mln/util/ignore.hh: New.
	* mln/util/eat.hh: New.
	Renaming to disambiguate.
	* mln/core/concept/accumulator.hh
	(value, to_value): Rename as...
	(result, to_result): ...these.
	Introduce meta accumulators.
	* mln/core/concept/meta_accumulator.hh: New.
	* mln/accu/min.hh,
	* mln/accu/max.hh,
	* mln/accu/min_max.hh,
	* mln/accu/count.hh,
	* mln/accu/sum.hh,
	* mln/accu/mean.hh (<name>): Rename accumulators as...
	(<name_>): ...these.
	(<name>): New meta accumulators.
	Propagate updates.
	* mln/accu/bbox.hh,
	* mln/accu/histo.hh,
	* mln/accu/max_h.hh,
	* mln/accu/median_alt.hh,
	* mln/accu/median.hh,
	* mln/accu/min_h.hh,
	* mln/estim/sum.hh,
	* mln/estim/min_max.hh,
	* mln/estim/mean.hh,
	* mln/core/internal/run_pset.hh,
	* mln/core/queue_p.hh,
	* mln/core/vec_p.hh,
	* mln/core/set_p.hh,
	* mln/morpho/opening_attribute.hh,
	* mln/morpho/opening_area.hh,
	* mln/morpho/erosion_fast.hh,
	* mln/morpho/dilation.hh,
	* mln/morpho/erosion.hh,
	* mln/morpho/dilation_fast.hh,
	* mln/level/take.hh,
	* mln/level/median.hh,
	* mln/level/naive/median.hh,
	* mln/level/fast_median.hh,
	* mln/level/compute.hh,
	* mln/canvas/morpho/algebraic_union_find.hh: Update.
	Misc.
	* tests/core_clone.cc: Augment.
	* mln/geom/bbox.hh (bbox): New overload for Box.
	* mln/core/image_if.hh: Add FIXMEs.
	(operator |): New overloads.
	* mln/core/image2d_b.hh: Remove dead code.
	* mln/util/pix.hh (p_of): New.
	Clean interface.
 mln/accu/all.hh                           |   65 ++++++++++++
 mln/accu/bbox.hh                          |   31 +++--
 mln/accu/compute.hh                       |  101 ++++++++++++++++++
 mln/accu/count.hh                         |   44 +++++---
 mln/accu/histo.hh                         |   11 ++
 mln/accu/max.hh                           |   54 +++++++---
 mln/accu/max_h.hh                         |    7 -
 mln/accu/mean.hh                          |   45 ++++++--
 mln/accu/median.hh                        |    7 -
 mln/accu/median_alt.hh                    |    6 -
 mln/accu/min.hh                           |   44 ++++++--
 mln/accu/min_h.hh                         |    7 -
 mln/accu/min_max.hh                       |   90 +---------------
 mln/accu/nil.hh                           |  126 +++++++++++++++++++++++
 mln/accu/p.hh                             |  144 ++++++++++++++++++++++++++
 mln/accu/pair.hh                          |  162 ++++++++++++++++++++++++++++++
 mln/accu/sum.hh                           |   47 +++++---
 mln/accu/take.hh                          |   99 ++++++++++++++++++
 mln/accu/v.hh                             |  154 ++++++++++++++++++++++++++++
 mln/canvas/morpho/algebraic_union_find.hh |    2 
 mln/core/concept/accumulator.hh           |   29 +----
 mln/core/concept/meta_accumulator.hh      |   82 +++++++++++++++
 mln/core/image2d_b.hh                     |   14 --
 mln/core/image_if.hh                      |   89 +++++++++++++++-
 mln/core/internal/run_pset.hh             |    2 
 mln/core/queue_p.hh                       |    2 
 mln/core/set_p.hh                         |    2 
 mln/core/vec_p.hh                         |    2 
 mln/estim/mean.hh                         |    7 -
 mln/estim/min_max.hh                      |   11 --
 mln/estim/sum.hh                          |    8 -
 mln/geom/bbox.hh                          |   28 ++++-
 mln/labeling/estimate.hh                  |   73 +++++++++++++
 mln/level/compute.hh                      |   51 +++++++--
 mln/level/fast_median.hh                  |    6 -
 mln/level/median.hh                       |   12 +-
 mln/level/naive/median.hh                 |    2 
 mln/level/take.hh                         |   12 +-
 mln/make/pix.hh                           |   66 ++++++++++++
 mln/morpho/dilation.hh                    |    4 
 mln/morpho/dilation_fast.hh               |    6 -
 mln/morpho/erosion.hh                     |    4 
 mln/morpho/erosion_fast.hh                |    6 -
 mln/morpho/opening_area.hh                |    5 
 mln/morpho/opening_attribute.hh           |    5 
 mln/util/eat.hh                           |   84 +++++++++++++++
 mln/util/ignore.hh                        |   75 +++++++++++++
 mln/util/pix.hh                           |   59 +++++-----
 tests/accu_all.cc                         |   56 ++++++++++
 tests/accu_min.cc                         |   62 +++++++++++
 tests/accu_nil.cc                         |   46 ++++++++
 tests/core_clone.cc                       |    3 
 tests/labeling_estimate.cc                |   62 +++++++++++
 53 files changed, 1914 insertions(+), 307 deletions(-)
Index: tests/core_clone.cc
--- tests/core_clone.cc	(revision 1156)
+++ tests/core_clone.cc	(working copy)
@@ -49,6 +49,9 @@
   {
     box2d b = make::box2d(2,2);
     std::cout << border::get( clone(ima | b) ) << std::endl;
+
+    debug::println(ima | b);
+    debug::println(clone(ima | b));
   }
 
 //   {
Index: tests/accu_nil.cc
--- tests/accu_nil.cc	(revision 0)
+++ tests/accu_nil.cc	(revision 0)
@@ -0,0 +1,46 @@
+// 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/accu_nil.cc
+ *
+ * \brief Tests on mln::accu::nil.
+ */
+
+#include <mln/core/image2d_b.hh>
+#include <mln/value/int_u8.hh>
+
+#include <mln/accu/nil.hh>
+#include <mln/level/compute.hh>
+
+
+int main()
+{
+  using namespace mln;
+  image2d_b<value::int_u8> ima(3, 3);
+  accu::nil a;
+  level::compute<accu::nil>(ima);
+}
Index: tests/labeling_estimate.cc
--- tests/labeling_estimate.cc	(revision 0)
+++ tests/labeling_estimate.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/labeling_foreground.cc
+ *
+ * \brief Test on mln::labeling::foreground.
+ */
+
+#include <mln/core/image2d_b.hh>
+#include <mln/core/neighb2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/pw/all.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/labeling/foreground.hh>
+#include <mln/labeling/estimate.hh>
+#include <mln/accu/count.hh>
+
+
+int main()
+{
+  using namespace mln;
+  using value::int_u8;
+
+  image2d_b<int_u8> lena = io::pgm::load("../img/tiny.pgm"),
+    out(lena.domain());
+
+  unsigned n;
+  labeling::foreground((pw::value(lena) > pw::cst(127)) | lena.domain(),
+		       c4(), out, n);
+  mln_assertion(n = 14);
+
+  unsigned sum = 0;
+  for (int_u8 i = 0; i <= n; ++i)
+    sum += labeling::estimate< accu::count >(out, i);
+  // FIXME: use of pix so that (center, mean) etc.
+  mln_assertion(sum = lena.npoints());
+}
Index: tests/accu_min.cc
--- tests/accu_min.cc	(revision 0)
+++ tests/accu_min.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/accu_min.cc
+ *
+ * \brief Tests on mln::accu::min.
+ */
+
+#include <mln/core/image2d_b.hh>
+#include <mln/debug/iota.hh>
+
+#include <mln/accu/nil.hh>
+#include <mln/accu/min.hh>
+#include <mln/accu/p.hh>
+#include <mln/accu/v.hh>
+#include <mln/accu/compute.hh>
+
+#include <mln/level/compute.hh>
+
+
+int main()
+{
+  using namespace mln;
+  image2d_b<int> ima(3, 3);
+  debug::iota(ima);
+  mln_assertion(level::compute< accu::min >(ima) = 1);
+  mln_assertion(level::compute< accu::min_<int> >(ima) = 1);
+
+//   accu::compute< accu::nil >(ima); // No-op.
+
+//   accu::compute< accu::min >(ima);
+
+  std::cout << accu::compute< accu::val<accu::min> >(ima)
+	    << std::endl;
+
+//   std::cout << accu::compute< accu::min >(ima)
+// 	    << std::endl;
+}
Index: tests/accu_all.cc
--- tests/accu_all.cc	(revision 0)
+++ tests/accu_all.cc	(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.
+
+/*! \file tests/accu_all.cc
+ *
+ * \brief Tests on all files in mln/accu.
+ */
+
+#include <mln/accu/all.hh>
+#include <mln/core/point2d.hh>
+#include <mln/value/set.hh>
+
+
+int main()
+{
+  using namespace mln;
+  using namespace mln::accu;
+
+
+  bbox<point2d> b;
+  count_<int> c;
+  histo< value::set<bool> > h;
+  max_<int> ma;
+  mean_<int> me;
+  median< value::set<bool> > med;
+  min_<int> mi;
+  min_h< value::set<bool> > mh;
+  min_max_<int> mm;
+  nil n;
+  pair_< min_<int>, max_<int> > p;
+  sum_<int> s;
+}
Index: mln/estim/sum.hh
--- mln/estim/sum.hh	(revision 1156)
+++ mln/estim/sum.hh	(working copy)
@@ -31,6 +31,8 @@
 /*! \file mln/estim/sum.hh
  *
  * \brief Compute the sum pixel value.
+ *
+ * \todo Sum works on level so move into mln/level; otherwise on pix then ambiguous.
  */
 
 # include <mln/accu/sum.hh>
@@ -67,15 +69,15 @@
     mln_sum(mln_value(I)) sum(const Image<I>& input)
     {
       mln_precondition(exact(input).has_data());
-      return level::compute(input, accu::sum<mln_value(I)>()).to_value();
+      return level::compute<accu::sum>(input);
     }
 
     template <typename I, typename S>
     void sum(const Image<I>& input, S& result)
     {
       mln_precondition(exact(input).has_data());
-      result = level::compute(input,
-			      accu::sum<mln_value(I), S>()).to_value();
+      typedef accu::sum_<mln_value(I), S> A;
+      result = level::compute(input, A());
     }
 
 # endif // ! MLN_INCLUDE_ONLY
Index: mln/estim/min_max.hh
--- mln/estim/min_max.hh	(revision 1156)
+++ mln/estim/min_max.hh	(working copy)
@@ -34,7 +34,7 @@
  */
 
 # include <mln/accu/min_max.hh>
-# include <mln/level/take.hh>
+# include <mln/level/compute.hh>
 
 
 namespace mln
@@ -61,11 +61,10 @@
 		 mln_value(I)& min, mln_value(I)& max)
     {
       mln_precondition(exact(input).has_data());
-      accu::min_max<mln_value(I)> a;
-      a.init();
-      level::take(a, input);
-      min = a.min();
-      max = a.max();
+      typedef accu::min_max_<mln_value(I)> A;
+      mln_result(A) mm = level::compute<A>(input);
+      min = mm.first;
+      max = mm.second;
     }
 
 # endif // ! MLN_INCLUDE_ONLY
Index: mln/estim/mean.hh
--- mln/estim/mean.hh	(revision 1156)
+++ mln/estim/mean.hh	(working copy)
@@ -70,16 +70,15 @@
     mln_sum(mln_value(I)) mean(const Image<I>& input)
     {
       mln_precondition(exact(input).has_data());
-      return level::compute(input,
-			    accu::mean<mln_value(I)>()).to_value();
+      return level::compute<accu::mean>(input);
     }
 
     template <typename S, typename I, typename M>
     void mean(const Image<I>& input, M& result)
     {
       mln_precondition(exact(input).has_data());
-      result = level::compute(input,
-			      accu::mean<mln_value(I), S, M>()).to_value();
+      typedef accu::mean_<mln_value(I), S, M> A;
+      result = level::compute(input, A());
     }
 
 # endif // ! MLN_INCLUDE_ONLY
Index: mln/geom/bbox.hh
--- mln/geom/bbox.hh	(revision 1156)
+++ mln/geom/bbox.hh	(working copy)
@@ -35,7 +35,7 @@
  */
 
 # include <mln/core/concept/image.hh>
-# include <mln/core/concept/point_set.hh>
+# include <mln/core/concept/box.hh>
 # include <mln/core/concept/window.hh>
 # include <mln/core/concept/weighted_window.hh>
 # include <mln/geom/pmin_pmax.hh>
@@ -93,20 +93,38 @@
       return bbox(exact(w_win).win());
     }
 
+
+    namespace impl
+    {
+
     template <typename S>
-    box_<mln_point(S)> bbox(const Point_Set<S>& pset_)
+      box_<mln_point(S)> bbox_(const Point_Set<S>& pset_)
     {
       const S& pset = exact(pset_);
-      mln_precondition(pset.npoints() != 0);
-
       typedef mln_point(S) P;
       std::pair<P, P> pp = geom::pmin_pmax(pset);
-
       box_<P> tmp(pp.first, pp.second);
+	return tmp;
+      }
+
+      template <typename B>
+      box_<mln_point(B)> bbox_(const Box<B>& pset_)
+      {
+	return exact(pset_);
+      }
+
+    } // end of namespace mln::geom::impl
+
+    template <typename S>
+    box_<mln_point(S)> bbox(const Point_Set<S>& pset)
+    {
+      mln_precondition(exact(pset).npoints() != 0);
+      box_<mln_point(S)> tmp = impl::bbox_(exact(pset));
       // FIXME: mln_postcondition(tmp <= pset.bbox());
       return tmp;
     }
 
+
     template <typename I>
     box_<mln_point(I)> bbox(const Image<I>& ima_)
     {
Index: mln/core/image_if.hh
--- mln/core/image_if.hh	(revision 1156)
+++ mln/core/image_if.hh	(working copy)
@@ -35,6 +35,7 @@
 
 # include <mln/core/internal/image_base.hh>
 # include <mln/core/pset_if.hh>
+# include <mln/pw/all.hh>
 
 
 namespace mln
@@ -54,6 +55,9 @@
       pset_if<mln_pset(I), F> pset_;
       F f_;
       I ima_;
+      // FIXME for matthieu: f_ is *also* in pset_; pb: redundancy!!!
+      // FIXME for matthieu: ctor arg list and attr list should be the *same*!
+      // FIXME for matthieu: do *not* change order of those lists elements!
     };
 
   } // end of namespace mln::internal
@@ -63,11 +67,17 @@
    *
    */
   template <typename I, typename F>
-  struct image_if : public internal::image_base_< pset_if<mln_pset(I), F>, image_if<I,F> >
+  struct image_if
+    : public internal::image_base_< pset_if<mln_pset(I), F>, image_if<I,F> >
+  // FIXME for matthieu: *not* image_base_ *but* image_domain_morpher_
   {
 
     // Parent
     typedef internal::image_base_< pset_if<mln_pset(I), F>, image_if<I,F> > super_;
+    // FIXME for matthieu: this should *not* be public!
+    // FIXME for matthieu: comments end with a '.'
+    // FIXME for matthieu: we do not say "parent" but "super".
+
 
     /// Skeleton.
     typedef image_if< tag::image<I>, tag::function<F> > skeleton;
@@ -76,9 +86,10 @@
     /// Point_Set associated type.
     typedef pset_if<mln_pset(I), F> pset;
 
-    /// Constructor from an \p image.
+    /// Constructor from an image \p ima and a predicate \p f.
     image_if(I& ima, const F& f);
 
+    /// Constructor without argument.
     image_if();
 
     /// Test if a pixel value is accessible at \p p.
@@ -91,10 +102,15 @@
     operator image_if<const I, F>() const;
 
     using super_::data_;
+    // FIXME for matthieu: this should *not* be public!
 
     typedef image_if<I,F> self_;
 
-    /// FIXME : to put into an identity morpher
+    // FIXME : to put into an identity morpher
+    // FIXME for matthieu: nope...
+
+
+    // FIXME for matthieu: most of those typedefs and methods are useless...
 
     /// Point_Site associated type.
     typedef mln_point(I) point;
@@ -123,13 +139,30 @@
 
 
 
+  // Operators.
+
   template <typename I, typename F>
   image_if<I, F>
-  operator | (Image<I>& ima, const Function_p2b<F>& f)
-  {
-    image_if<I, F> tmp(exact(ima), exact(f));
-    return tmp;
-  }
+  operator | (Image<I>& ima, const Function_p2b<F>& f);
+
+  template <typename I, typename F>
+  image_if<const I, F>
+  operator | (const Image<I>& ima, const Function_p2b<F>& f);
+
+  template <typename I>
+  image_if< I,
+	    fun::equal_p2b_expr_< pw::value_<I>,
+				  pw::cst_<mln_value(I)> > >
+  operator | (Image<I>& ima, const mln_value(I)& v);
+
+  template <typename I>
+  image_if< const I,
+	    fun::equal_p2b_expr_< pw::value_<I>,
+				  pw::cst_<mln_value(I)> > >
+  operator | (Image<I>& ima, const mln_value(I)& v);
+
+  // FIXME: Add the notion of "interval of values"...
+  // FIXME: so we can write:  ima | from_to(v1, v2)
 
 
 
@@ -150,6 +183,8 @@
 
   } // end of namespace mln::internal
 
+  // image_if<I,F>
+
   template <typename I, typename F>
   image_if<I,F>::image_if()
   {
@@ -205,6 +240,44 @@
   {
     return data_->ima_.values();
   }
+
+
+  // Operators.
+
+  template <typename I, typename F>
+  image_if<I, F>
+  operator | (Image<I>& ima, const Function_p2b<F>& f)
+  {
+    image_if<I, F> tmp(exact(ima), exact(f));
+    return tmp;
+  }
+
+  template <typename I, typename F>
+  image_if<const I, F>
+  operator | (const Image<I>& ima, const Function_p2b<F>& f)
+  {
+    image_if<const I, F> tmp(exact(ima), exact(f));
+    return tmp;
+  }
+
+  template <typename I>
+  image_if< I,
+	    fun::equal_p2b_expr_< pw::value_<I>,
+				  pw::cst_<mln_value(I)> > >
+  operator | (Image<I>& ima, const mln_value(I)& v)
+  {
+    return ima | (pw::value(ima) = pw::cst(v));
+  }
+
+  template <typename I>
+  image_if< const I,
+	    fun::equal_p2b_expr_< pw::value_<I>,
+				  pw::cst_<mln_value(I)> > >
+  operator | (const Image<I>& ima, const mln_value(I)& v)
+  {
+    return ima | (pw::value(ima) = pw::cst(v));
+  }
+
 # endif // ! MLN_INCLUDE_ONLY
 
 } // end of namespace mln
Index: mln/core/internal/run_pset.hh
--- mln/core/internal/run_pset.hh	(revision 1156)
+++ mln/core/internal/run_pset.hh	(working copy)
@@ -117,7 +117,7 @@
     const box_<P>&
     run_pset_<P>::bbox() const
     {
-      return fb_.to_value();
+      return fb_.to_result();
     }
 
     template <typename P>
Index: mln/core/image2d_b.hh
--- mln/core/image2d_b.hh	(revision 1156)
+++ mln/core/image2d_b.hh	(working copy)
@@ -42,6 +42,7 @@
 # include <mln/core/line_piter.hh>
 # include <mln/border/get.hh>
 # include <mln/debug/println.hh>
+# include <mln/geom/bbox.hh>
 
 // FIXME:
 
@@ -153,17 +154,6 @@
     void init_with_(const box2d& b, unsigned bdr = border::thickness);
 
 
-//     /// Initialize an empty image.
-//     template <typename I>
-//     void init_with_(const Image<I>& other) // FIXME: Remove this soon obsolete code!
-//     {
-//       mln_precondition(this->data_ = 0);
-//       mln_precondition(exact(other).has_data());
-//       this->data_ = new internal::data_< image2d_b<T> >(exact(other).bbox(),
-// 							exact(other).border());
-//     }
-
-
     /// Test if \p p is valid.
     bool owns_(const point2d& p) const;
 
@@ -235,7 +225,7 @@
     template <typename T, typename J>
     void init_with_(image2d_b<T>& target, const J& model)
     {
-      box2d b = model.bbox();
+      box2d b = geom::bbox(model);
       unsigned bdr = border::get(model);
       target.init_with_(b, bdr);
     }
Index: mln/core/queue_p.hh
--- mln/core/queue_p.hh	(revision 1156)
+++ mln/core/queue_p.hh	(working copy)
@@ -175,7 +175,7 @@
     mln_precondition(npoints() != 0);
     if (bb_needs_update_)
       bb_update_();
-    return bb_.to_value();
+    return bb_.to_result();
   }
 
   template <typename P>
Index: mln/core/vec_p.hh
--- mln/core/vec_p.hh	(revision 1156)
+++ mln/core/vec_p.hh	(working copy)
@@ -175,7 +175,7 @@
     mln_precondition(npoints() != 0);
     if (bb_needs_update_)
       update_bb_();
-    return bb_.to_value();
+    return bb_.to_result();
   }
 
   template <typename P>
Index: mln/core/concept/meta_accumulator.hh
--- mln/core/concept/meta_accumulator.hh	(revision 0)
+++ mln/core/concept/meta_accumulator.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_CORE_CONCEPT_META_ACCUMULATOR_HH
+# define MLN_CORE_CONCEPT_META_ACCUMULATOR_HH
+
+/*! \file mln/core/concept/meta_accumulator.hh
+ *
+ * \brief Definition of the concept of mln::Meta_Accumulator.
+ */
+
+# include <mln/core/concept/object.hh>
+# include <mln/core/concept/accumulator.hh>
+
+
+# define mln_accu_with(A, T) \
+typename A::template with< T >::ret
+
+
+# define mln_accu_result(A, T) \
+typename A::template with< T >::ret::result
+
+
+
+namespace mln
+{
+
+
+  /*! \brief Base class for implementation of meta accumulators.
+   *
+   * The parameter \a E is the exact type.
+   *
+   * \see mln::doc::Meta_Accumulator for a complete documentation of
+   * this class contents.
+   */
+  template <typename E>
+  struct Meta_Accumulator : public Object<E>
+  {
+  protected:
+    Meta_Accumulator();
+  };
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+  template <typename E>
+  Meta_Accumulator<E>::Meta_Accumulator()
+  {
+    // FIXME: Check "with" on E.
+  }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_CONCEPT_META_ACCUMULATOR_HH
Index: mln/core/concept/accumulator.hh
--- mln/core/concept/accumulator.hh	(revision 1156)
+++ mln/core/concept/accumulator.hh	(working copy)
@@ -31,6 +31,8 @@
 /*! \file mln/core/concept/accumulator.hh
  *
  * \brief Definition of the concept of mln::Accumulator.
+ *
+ * \todo Rename value as argument.
  */
 
 # include <mln/core/concept/object.hh>
@@ -52,9 +54,11 @@
   {
     /*
       typedef value;
+      typedef result;
       void init();
       void take(const value& v);
       void take(const E& other);
+      result to_result() const;
      */
 
     // Default impl.
@@ -66,19 +70,6 @@
   };
 
 
-  /*! \brief Merge two accumulators.
-   *
-   * The parameter \a E is the accumulator exact type.
-   *
-   * \param[in] lhs An accumulator.
-   * \param[in] rhs Another accumulator.
-   * \result A temporary accumulator.
-   *
-   * \see relates mln::Accumulator
-   */
-  template <typename E>
-  E merge(const Accumulator<E>& lhs, const Accumulator<E>& rhs);
-
 
 # ifndef MLN_INCLUDE_ONLY
 
@@ -86,12 +77,16 @@
   Accumulator<E>::Accumulator()
   {
     typedef mln_value(E) value;
+    typedef mln_result(E) result;
+
     void (E::*m1)() = & E::init;
     m1 = 0;
     void (E::*m2)(const value&) = & E::take;
     m2 = 0;
     void (E::*m3)(const E&) = & E::take;
     m3 = 0;
+    result (E::*m4)() const = & E::to_result;
+    m4 = 0;
   }
 
   template <typename E>
@@ -103,14 +98,6 @@
     exact(this)->take(t);
   }
 
-  template <typename E>
-  E merge(const Accumulator<E>& lhs, const Accumulator<E>& rhs)
-  {
-    E tmp(exact(lhs));
-    tmp.take(exact(rhs));
-    return tmp;
-  }
-
 # endif // ! MLN_INCLUDE_ONLY
 
 } // end of namespace mln
Index: mln/core/set_p.hh
--- mln/core/set_p.hh	(revision 1156)
+++ mln/core/set_p.hh	(working copy)
@@ -145,7 +145,7 @@
   set_p<P>::bbox() const
   {
     mln_precondition(npoints() != 0);
-    return bb_.to_value();
+    return bb_.to_result();
   }
 
 # endif // ! MLN_INCLUDE_ONLY
Index: mln/morpho/opening_attribute.hh
--- mln/morpho/opening_attribute.hh	(revision 1156)
+++ mln/morpho/opening_attribute.hh	(working copy)
@@ -36,6 +36,7 @@
 # include <mln/morpho/includes.hh>
 # include <mln/canvas/morpho/algebraic_union_find.hh>
 # include <mln/level/sort_points.hh>
+# include <mln/util/pix.hh>
 
 
 namespace mln
@@ -70,7 +71,7 @@
 	typedef N_ N;
 	typedef O_ O;
 	typedef vec_p<P> S;
-	typedef util::pix_<I> pix_t;
+	typedef util::pix<I> pix_t;
       
 	const I& input;
 	const N& nbh;
@@ -86,7 +87,7 @@
 
 	bool is_active(const A& attr) const
 	{
-	  return attr.to_value() < lambda;
+	  return attr.to_result() < lambda;
 	}
 
 	void inactivate(A& attr)
Index: mln/morpho/opening_area.hh
--- mln/morpho/opening_area.hh	(revision 1156)
+++ mln/morpho/opening_area.hh	(working copy)
@@ -57,8 +57,9 @@
 		      Image<O>& output)
     {
       mln_precondition(exact(output).domain() = exact(input).domain());
-      typedef util::pix_<I> pix_t;
-      opening_attribute< accu::count<pix_t> >(input, nbh, lambda, output);
+      typedef util::pix<I> pix_t;
+      // FIXME: Change sig of opening_attribute!
+      opening_attribute< accu::count_<pix_t> >(input, nbh, lambda, output);
     }
 
 # endif // ! MLN_INCLUDE_ONLY
Index: mln/morpho/erosion_fast.hh
--- mln/morpho/erosion_fast.hh	(revision 1156)
+++ mln/morpho/erosion_fast.hh	(working copy)
@@ -133,7 +133,7 @@
 	    min.untake(input(q_dm));
 	  for_all(q_dp) if (input.has(q_dp))
 	    min.take(input(q_dp));
-	  output(p) = min.to_value();
+	  output(p) = min.to_result();
 	}
 
 	void fwd()
@@ -142,7 +142,7 @@
 	    min.untake(input(q_fm));
 	  for_all(q_fp) if (input.has(q_fp))
 	    min.take(input(q_fp));
-	  output(p) = min.to_value();
+	  output(p) = min.to_result();
 	}
 
 	void bkd()
@@ -151,7 +151,7 @@
 	    min.untake(input(q_bm));
 	  for_all(q_bp) if (input.has(q_bp))
 	    min.take(input(q_bp));
-	  output(p) = min.to_value();
+	  output(p) = min.to_result();
 	}
 
       }; // end of erosion_fast_t
Index: mln/morpho/dilation.hh
--- mln/morpho/dilation.hh	(revision 1156)
+++ mln/morpho/dilation.hh	(working copy)
@@ -66,7 +66,7 @@
 	const W& win   = exact(win_);
 	O& output      = exact(output_);
 
-	accu::max<mln_value(I)> max;
+	accu::max_<mln_value(I)> max;
 
 	mln_piter(I) p(input.domain());
 	mln_qiter(W) q(win, p);
@@ -75,7 +75,7 @@
 	    max.init();
 	    for_all(q) if (input.has(q))
 	      max.take(input(q));
-	    output(p) = max.to_value();
+	    output(p) = max.to_result();
 	  }
       }
 
Index: mln/morpho/erosion.hh
--- mln/morpho/erosion.hh	(revision 1156)
+++ mln/morpho/erosion.hh	(working copy)
@@ -66,7 +66,7 @@
 	const W& win   = exact(win_);
 	O& output      = exact(output_);
 
-	accu::min<mln_value(I)> min;
+	accu::min_<mln_value(I)> min;
 
 	mln_piter(I) p(input.domain());
 	mln_qiter(W) q(win, p);
@@ -75,7 +75,7 @@
 	    min.init();
 	    for_all(q) if (input.has(q))
 	      min.take(input(q));
-	    output(p) = min.to_value();
+	    output(p) = min.to_result();
 	  }
       }
 
Index: mln/morpho/dilation_fast.hh
--- mln/morpho/dilation_fast.hh	(revision 1156)
+++ mln/morpho/dilation_fast.hh	(working copy)
@@ -133,7 +133,7 @@
 	    max.untake(input(q_dm));
 	  for_all(q_dp) if (input.has(q_dp))
 	    max.take(input(q_dp));
-	  output(p) = max.to_value();
+	  output(p) = max.to_result();
 	}
 
 	void fwd()
@@ -142,7 +142,7 @@
 	    max.untake(input(q_fm));
 	  for_all(q_fp) if (input.has(q_fp))
 	    max.take(input(q_fp));
-	  output(p) = max.to_value();
+	  output(p) = max.to_result();
 	}
 
 	void bkd()
@@ -151,7 +151,7 @@
 	    max.untake(input(q_bm));
 	  for_all(q_bp) if (input.has(q_bp))
 	    max.take(input(q_bp));
-	  output(p) = max.to_value();
+	  output(p) = max.to_result();
 	}
 
       }; // end of dilation_fast_t
Index: mln/level/take.hh
--- mln/level/take.hh	(revision 1156)
+++ mln/level/take.hh	(working copy)
@@ -45,8 +45,8 @@
 
     /*! Make an accumulator take the values of the image \p input.
      *
-     * \param[in,out] a The accumulator.
      * \param[in] input The input image.
+     * \param[in,out] a The accumulator.
      *
      * This routine runs: \n
      *   for all p of \p input, \p a.take( \p input(p) ) \n
@@ -54,7 +54,7 @@
      * \warning This routine does not perform a.init().
      */
     template <typename A, typename I>
-    void take(Accumulator<A>& a, const Image<I>& input);
+    void take(const Image<I>& input, Accumulator<A>& a);
 
 
 # ifndef MLN_INCLUDE_ONLY
@@ -63,7 +63,7 @@
     {
 
       template <typename A, typename I>
-      void take(A& a, const Image<I>& input_)
+      void take(const Image<I>& input_, A& a)
       {
 	const I& input = exact(input_);
 	mln_piter(I) p(input.domain());
@@ -72,7 +72,7 @@
       }
 
       template <typename A, typename I>
-      void take(A& a, const Fast_Image<I>& input_)
+      void take(const Fast_Image<I>& input_, A& a)
       {
 	const I& input = exact(input_);
 	mln_pixter(const I) pxl(input);
@@ -86,10 +86,10 @@
     // Facade.
 
     template <typename A, typename I>
-    void take(Accumulator<A>& a, const Image<I>& input)
+    void take(const Image<I>& input, Accumulator<A>& a)
     {
       mln_precondition(exact(input).has_data());
-      impl::take(exact(a), exact(input));
+      impl::take(exact(input), exact(a));
     }
 
 # endif // ! MLN_INCLUDE_ONLY
Index: mln/level/median.hh
--- mln/level/median.hh	(revision 1156)
+++ mln/level/median.hh	(working copy)
@@ -151,7 +151,7 @@
 	    med.untake(input(q_dm));
 	  for_all(q_dp) if (input.has(q_dp))
 	    med.take(input(q_dp));
-	  output(p) = med.to_value();
+	  output(p) = med.to_result();
 	}
 
 	void fwd()
@@ -160,7 +160,7 @@
 	    med.untake(input(q_fm));
 	  for_all(q_fp) if (input.has(q_fp))
 	    med.take(input(q_fp));
-	  output(p) = med.to_value();
+	  output(p) = med.to_result();
 	}
 
 	void bkd()
@@ -169,7 +169,7 @@
 	    med.untake(input(q_bm));
 	  for_all(q_bp) if (input.has(q_bp))
 	    med.take(input(q_bp));
-	  output(p) = med.to_value();
+	  output(p) = med.to_result();
 	}
 
       }; // end of median_t
@@ -243,7 +243,7 @@
 	      if (input.has(pt))
 		med.take(input(pt));
 	      if (output.has(p))
-		output(p) = med.to_value();
+		output(p) = med.to_result();
 	    }
 
 	  // middle columns (both take and untake)
@@ -255,7 +255,7 @@
 	      if (input.has(pu))
 		med.untake(input(pu));
 	      if (output.has(p))
-		output(p) = med.to_value();
+		output(p) = med.to_result();
 	    }
 
 	  // right columns (now just untake old points)
@@ -264,7 +264,7 @@
 	      if (input.has(pu))
 		med.untake(input(pu));
 	      if (output.has(p))
-		output(p) = med.to_value();
+		output(p) = med.to_result();
 	    }
 	}
 
Index: mln/level/naive/median.hh
--- mln/level/naive/median.hh	(revision 1156)
+++ mln/level/naive/median.hh	(working copy)
@@ -85,7 +85,7 @@
 	      med.init();
 	      for_all(q) if (input.has(q))
 		med.take(input(q));
-	      output(p) = med.to_value();
+	      output(p) = med.to_result();
 	    }
 	}
 
Index: mln/level/fast_median.hh
--- mln/level/fast_median.hh	(revision 1156)
+++ mln/level/fast_median.hh	(working copy)
@@ -121,7 +121,7 @@
 	    for_all(q_bot)
 	      med.take(q_bot.val());
 
-	    output(p) = med.to_value();
+	    output(p) = med.to_result();
 
 	    if (fwd)
 	      // browse line fwd
@@ -132,7 +132,7 @@
 		    med.untake(q_fm.val());
 		  for_all(q_fp)
 		    med.take(q_fp.val());
-		  output(p) = med.to_value();
+		  output(p) = med.to_result();
 		}
 	    else
 	      // browse line bkd
@@ -143,7 +143,7 @@
 		    med.untake(q_bm.val());
 		  for_all(q_bp)
 		    med.take(q_bp.val());
-		  output(p) = med.to_value();
+		  output(p) = med.to_result();
 		}
 	    // change browsing
 	    fwd = ! fwd;
Index: mln/level/compute.hh
--- mln/level/compute.hh	(revision 1156)
+++ mln/level/compute.hh	(working copy)
@@ -33,7 +33,10 @@
  * \brief Compute an accumulator onto image pixel values.
  */
 
+# include <mln/core/concept/meta_accumulator.hh>
 # include <mln/level/take.hh>
+# include <mln/metal/is_a.hh>
+
 
 
 namespace mln
@@ -46,27 +49,51 @@
      *
      * \param[in] input The input image.
      * \param[in] a The accumulator.
-     * \return A resulting accumulator.
+     * \return The accumulator result.
      *
-     * This routine computes: \n
-     *   res = \p a \n
-     *   res.init() \n
-     *   level::take(res, \p input) \n
-     *   return res \n
+     * This routine runs: \n
+     *   tmp = \p a \n
+     *   tmp.init() \n
+     *   level::take(\p input, tmp) \n
+     *   return tmp.to_result() \n
      */
     template <typename I, typename A>
-    A compute(const Image<I>& input, const Accumulator<A>& a);
+    mln_result(A)
+    compute(const Image<I>& input, const Accumulator<A>& a);
+
+    template <typename A, typename I>
+    mln_accu_with(A, mln_value(I))::result
+    compute(const Image<I>& input);
 
 
 # ifndef MLN_INCLUDE_ONLY
 
     template <typename I, typename A>
-    A compute(const Image<I>& input, const Accumulator<A>& a)
+    mln_result(A)
+    compute(const Image<I>& input, const Accumulator<A>& a_)
+    {
+      mln_precondition(exact(input).has_data());
+      A a = exact(a_); // Cpy.
+      a.init();
+      level::take(input, a);
+      return a.to_result();
+    }
+
+    template <typename A, typename I>
+    mln_result(A)
+    compute(const Image<I>& input)
+    {
+      mln_precondition(exact(input).has_data());
+      return level::compute(input, A());
+    }
+
+    template <typename A, typename I>
+    mln_accu_with(A, mln_value(I))::result
+    compute(const Image<I>& input)
     {
-      A res = exact(a);
-      res.init();
-      level::take(res, input);
-      return res;
+      mlc_is_a(A, Meta_Accumulator)::check();
+      return compute(input,
+		     mln_accu_with(A, mln_value(I))());
     }
 
 # endif // ! MLN_INCLUDE_ONLY
Index: mln/canvas/morpho/algebraic_union_find.hh
--- mln/canvas/morpho/algebraic_union_find.hh	(revision 1156)
+++ mln/canvas/morpho/algebraic_union_find.hh	(working copy)
@@ -119,7 +119,7 @@
 	void make_set(const point& p)
 	{
 	  parent(p) = p;
-	  data(p).take_as_init(util::pix(f.input, p));
+	  data(p).take_as_init(make::pix(f.input, p));
 	}
 
 	bool is_root(const point& p) const
Index: mln/accu/nil.hh
--- mln/accu/nil.hh	(revision 0)
+++ mln/accu/nil.hh	(revision 0)
@@ -0,0 +1,126 @@
+// 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_ACCU_NIL_HH
+# define MLN_ACCU_NIL_HH
+
+/*! \file mln/accu/nil.hh
+ *
+ * \brief Define an accumulator that does nothing.
+ *
+ * \todo A macro to generate the meta version. 
+ */
+
+# include <mln/core/concept/meta_accumulator.hh>
+# include <mln/core/concept/accumulator.hh>
+# include <mln/util/eat.hh>
+# include <mln/util/ignore.hh>
+
+
+namespace mln
+{
+
+  namespace accu
+  {
+
+    /*! Define an accumulator that does nothing.
+     */
+    template <typename T>
+    struct nil_ : public Accumulator< nil_<T> >
+    {
+      typedef util::eat    value;
+      typedef util::ignore result;
+
+      nil_();
+
+      void init();
+      void take_as_init(const value&);
+      void take(const value&);
+      void take(const nil_<T>&);
+
+      util::ignore to_result() const;
+    };
+
+
+
+    // FIXME: Doc!
+    struct nil : public Meta_Accumulator< nil >
+    {
+      template <typename V>
+      struct with
+      {
+	typedef nil_<V> ret;
+      };
+    };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename T>
+    nil_<T>::nil_()
+    {
+    }
+
+    template <typename T>
+    void
+    nil_<T>::init()
+    {
+    }
+
+    template <typename T>
+    void
+    nil_<T>::take(const value&)
+    {
+    }
+
+    template <typename T>
+    void
+    nil_<T>::take_as_init(const value&)
+    {
+    }
+
+    template <typename T>
+    void
+    nil_<T>::take(const nil_<T>&)
+    {
+    }
+
+    template <typename T>
+    util::ignore
+    nil_<T>::to_result() const
+    {
+      return util::ignore();
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::accu
+
+} // end of namespace mln
+
+
+#endif // ! MLN_ACCU_NIL_HH
Index: mln/accu/min.hh
--- mln/accu/min.hh	(revision 1156)
+++ mln/accu/min.hh	(working copy)
@@ -33,8 +33,9 @@
  * \brief Define an accumulator that computes a min.
  */
 
-# include <mln/core/concept/accumulator.hh>
+# include <mln/core/concept/meta_accumulator.hh>
 # include <mln/value/props.hh>
+# include <mln/util/pix.hh>
 
 
 namespace mln
@@ -49,17 +50,19 @@
      * The parameter \c V is the type of values.
      */
     template <typename V>
-    struct min : public Accumulator< min<V> >
+    struct min_ : public Accumulator< min_<V> >
     {
       typedef V value;
+      typedef V result;
 
-      min();
+      min_();
 
-      void take(const value& v);
-      void take(const min<V>& other);
       void init();
+      void take_as_init(const value& v);
+      void take(const value& v);
+      void take(const min_<V>& other);
 
-      V to_value() const;
+      V to_result() const;
       
     protected:
 
@@ -67,24 +70,43 @@
     };
 
 
+    template <typename I> struct min_< util::pix<I> >;
+
+
+    // FIXME: Doc!
+    struct min : public Meta_Accumulator< min >
+    {
+      template <typename V>
+      struct with
+      {
+	typedef min_<V> ret;
+      };
+    };
+
 
 # ifndef MLN_INCLUDE_ONLY
 
     template <typename V>
-    min<V>::min()
+    min_<V>::min_()
     {
       init();
     }
 
     template <typename V>
     void
-    min<V>::init()
+    min_<V>::init()
     {
       v_ = mln_max(V);
     }
 
     template <typename V>
-    void min<V>::take(const value& v)
+    void min_<V>::take_as_init(const value& v)
+    {
+      v_ = v;
+    }
+
+    template <typename V>
+    void min_<V>::take(const value& v)
     {
       if (v < v_)
 	v_ = v;
@@ -92,7 +114,7 @@
     
     template <typename V>
     void
-    min<V>::take(const min<V>& other)
+    min_<V>::take(const min_<V>& other)
     {
       if (other.v_ < v_)
 	v_ = other.v_;
@@ -100,7 +122,7 @@
 
     template <typename V>
     V
-    min<V>::to_value() const
+    min_<V>::to_result() const
     {
       return v_;
     }
Index: mln/accu/take.hh
--- mln/accu/take.hh	(revision 0)
+++ mln/accu/take.hh	(revision 0)
@@ -0,0 +1,99 @@
+// 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_ACCU_TAKE_HH
+# define MLN_ACCU_TAKE_HH
+
+/*! \file mln/accu/take.hh
+ *
+ * \brief Make an accumulator take image pixels.
+ */
+
+# include <mln/core/concept/accumulator.hh>
+# include <mln/core/concept/image.hh>
+# include <mln/util/pix.hh>
+
+
+namespace mln
+{
+
+  namespace accu
+  {
+
+    /*! Make an accumulator take the pixels of the image \p input.
+     *
+     * \param[in] input The input image.
+     * \param[in,out] a The accumulator.
+     *
+     * This routine runs: \n
+     *   for all p of \p input, \p a.take( pix(\p input, p) ) \n
+     *
+     * \warning This routine does not perform a.init().
+     */
+    template <typename A, typename I>
+    void take(const Image<I>& input, Accumulator<A>& a);
+
+
+    // FIXME: Overload for point sets.
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    namespace impl
+    {
+
+      template <typename A, typename I>
+      void take(const Image<I>& input_, A& a)
+      {
+	const I& input = exact(input_);
+	mln_piter(I) p(input.domain());
+	for_all(p)
+	  a.take(make::pix(input, p));
+      }
+
+      // FIXME: We need an impl for pixels of fast images.
+
+    } // end of namespace mln::accu::impl
+
+
+    // Facade.
+
+    template <typename A, typename I>
+    void take(const Image<I>& input, Accumulator<A>& a)
+    {
+      mln_precondition(exact(input).has_data());
+      impl::take(exact(input), exact(a));
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::accu
+
+} // end of namespace mln
+
+
+#endif // ! MLN_ACCU_TAKE_HH
Index: mln/accu/max.hh
--- mln/accu/max.hh	(revision 1156)
+++ mln/accu/max.hh	(working copy)
@@ -33,8 +33,9 @@
  * \brief Define an accumulator that computes a max.
  */
 
-# include <mln/core/concept/accumulator.hh>
+# include <mln/core/concept/meta_accumulator.hh>
 # include <mln/value/props.hh>
+# include <mln/util/pix.hh>
 
 
 namespace mln
@@ -49,17 +50,19 @@
      * The parameter \c V is the type of values.
      */
     template <typename V>
-    struct max : public Accumulator< max<V> >
+    struct max_ : public Accumulator< max_<V> >
     {
       typedef V value;
+      typedef V result;
 
-      max();
+      max_();
 
-      void take(const value& v);
-      void take(const max<V>& other);
       void init();
+      void take_as_init(const value& v);
+      void take(const value& v);
+      void take(const max_<V>& other);
 
-      V to_value() const;
+      V to_result() const;
       
     protected:
 
@@ -67,41 +70,62 @@
     };
 
 
+    template <typename I> struct max_< util::pix<I> >;
+
+
+    // FIXME: Doc!
+    struct max : public Meta_Accumulator< max >
+    {
+      template <typename V>
+      struct with
+      {
+	typedef max_<V> ret;
+      };
+    };
+
+
 
 # ifndef MLN_INCLUDE_ONLY
 
     template <typename V>
-    max<V>::max()
+    max_<V>::max_()
     {
       init();
     }
 
     template <typename V>
     void
-    max<V>::take(const value& v)
+    max_<V>::init()
+    {
+      v_ = mln_min(V);
+    }
+
+    template <typename V>
+    void
+    max_<V>::take_as_init(const value& v)
     {
-      if (v > v_)
 	v_ = v;
     }
 
     template <typename V>
     void
-    max<V>::take(const max<V>& other)
+    max_<V>::take(const value& v)
     {
-      if (other.v_ > v_)
-	v_ = other.v_;
+      if (v > v_)
+	v_ = v;
     }
 
     template <typename V>
     void
-    max<V>::init()
+    max_<V>::take(const max_<V>& other)
     {
-      v_ = mln_min(V);
+      if (other.v_ > v_)
+	v_ = other.v_;
     }
 
     template <typename V>
     V
-    max<V>::to_value() const
+    max_<V>::to_result() const
     {
       return v_;
     }
Index: mln/accu/histo.hh
--- mln/accu/histo.hh	(revision 1156)
+++ mln/accu/histo.hh	(working copy)
@@ -31,6 +31,8 @@
 /*! \file mln/accu/histo.hh
  *
  * \brief Define a generic histogram accumulator class.
+ *
+ * \todo Use histo::data instead of std::vector!
  */
 
 # include <vector>
@@ -57,6 +59,7 @@
       histo();
 
       typedef mln_value(S) value;
+      typedef const std::vector<std::size_t>& result;
 
       void   take(const value& v);
       void   take(const histo<S>& other);
@@ -69,6 +72,7 @@
       std::size_t sum() const;
 
       const std::vector<std::size_t>& vect() const;
+      const std::vector<std::size_t>& to_result() const;
 
       const S& vset() const;
       
@@ -176,6 +180,13 @@
     }
     
     template <typename S>
+    const std::vector<std::size_t>&
+    histo<S>::to_result() const
+    {
+      return h_;
+    }
+    
+    template <typename S>
     const S&
     histo<S>::vset() const
     {
Index: mln/accu/min_max.hh
--- mln/accu/min_max.hh	(revision 1156)
+++ mln/accu/min_max.hh	(working copy)
@@ -31,12 +31,17 @@
 /*! \file mln/accu/min_max.hh
  *
  * \brief Define an accumulator that computes a min and a max.
+ *
+ * \todo A macro to create such accumulators.
  */
 
 # include <utility>
 
+# include <mln/accu/pair.hh>
 # include <mln/accu/min.hh>
 # include <mln/accu/max.hh>
+# include <mln/value/props.hh>
+# include <mln/util/pix.hh>
 
 
 namespace mln
@@ -45,99 +50,22 @@
   namespace accu
   {
 
-
     /*! Generic min and max accumulator class.
      *
      * The parameter \c V is the type of values.
      */
     template <typename V>
-    struct min_max : public Accumulator< min_max<V> >
+    struct min_max_ : public pair_< min_<V>, max_<V> >
     {
-      typedef V value;
-
-      min_max();
-
-      void take(const value& v);
-      void take(const min_max<V>& other);
-      void init();
-
-      V min() const;
-      V max() const;
-
-      std::pair<V,V> to_value() const;
-      void values(V& min, V& max) const;
-
-    protected:
-
-      accu::min<V> min_;
-      accu::max<V> max_;
     };
 
 
+    template <typename I> struct min_max_< util::pix<I> >;
 
-# ifndef MLN_INCLUDE_ONLY
 
-    template <typename V>
-    min_max<V>::min_max()
-    {
-      init();
-    }
-
-    template <typename V>
-    void
-    min_max<V>::init()
-    {
-      min_.init();
-      max_.init();
-    }
-
-    template <typename V>
-    void min_max<V>::take(const value& v)
-    {
-      min_.take(v);
-      max_.take(v);
-    }
-    
-    template <typename V>
-    void
-    min_max<V>::take(const min_max<V>& other)
-    {
-      min_.take(other.min_);
-      max_.take(other.max_);
-    }
-
-    template <typename V>
-    V
-    min_max<V>::min() const
-    {
-      return min_.to_value();
-    }
-
-    template <typename V>
-    V
-    min_max<V>::max() const
-    {
-      return max_.to_value();
-    }
-
-    template <typename V>
-    std::pair<V,V>
-    min_max<V>::to_value() const
-    {
-      std::pair<V,V> tmp(min_.to_value(),
-			 max_.to_value());
-      return tmp;
-    }
-
-    template <typename V>
-    void
-    min_max<V>::values(V& min, V& max) const
-    {
-      min = min_.to_value();
-      max = max_.to_value();
-    }
+    // FIXME: Doc!
+    typedef pair<min,max> min_max;
 
-# endif // ! MLN_INCLUDE_ONLY
 
   } // end of namespace mln::accu
 
Index: mln/accu/count.hh
--- mln/accu/count.hh	(revision 1156)
+++ mln/accu/count.hh	(working copy)
@@ -33,7 +33,7 @@
  * \brief Define an accumulator that counts.
  */
 
-# include <mln/core/concept/accumulator.hh>
+# include <mln/core/concept/meta_accumulator.hh>
 
 
 namespace mln
@@ -46,68 +46,78 @@
     /*! Generic counter accumulator class.
      */
     template <typename V>
-    struct count : public Accumulator< count<V> >
+    struct count_ : public Accumulator< count_<V> >
     {
       typedef V value;
       typedef std::size_t result; // FIXME: Up in Accumulator.
 
-      count();
+      count_();
 
       void init();
       void take(const value&);
-      void take(const count<V>& other);
+      void take(const count_<V>& other);
 
-      std::size_t to_value() const;
+      std::size_t to_result() const;
       void set_value(std::size_t c);
 
     protected:
 
-      std::size_t count_;
+      std::size_t count__;
     };
 
 
+    // FIXME: Doc!
+    struct count : public Meta_Accumulator< count >
+    {
+      template <typename V>
+      struct with
+      {
+	typedef count_<V> ret;
+      };
+    };
+
 
 # ifndef MLN_INCLUDE_ONLY
 
     template <typename V>
-    count<V>::count()
+    count_<V>::count_()
     {
       init();
     }
 
     template <typename V>
     void
-    count<V>::init()
+    count_<V>::init()
     {
-      count_ = 0;
+      count__ = 0;
     }
 
     template <typename V>
     void
-    count<V>::take(const value&)
+    count_<V>::take(const value&)
     {
-      ++count_;
+      ++count__;
     }
 
     template <typename V>
     void
-    count<V>::take(const count<V>& other)
+    count_<V>::take(const count_<V>& other)
     {
-      count_ += other.count_;
+      count__ += other.count__;
     }
 
     template <typename V>
     std::size_t
-    count<V>::to_value() const
+    count_<V>::to_result() const
     {
-      return count_;
+      return count__;
     }
 
     template <typename V>
     void
-    count<V>::set_value(std::size_t c)
+    count_<V>::set_value(std::size_t c)
     {
-      count_ = c;
+      count__ = c;
     }
 
 # endif // ! MLN_INCLUDE_ONLY
Index: mln/accu/min_h.hh
--- mln/accu/min_h.hh	(revision 1156)
+++ mln/accu/min_h.hh	(working copy)
@@ -51,6 +51,7 @@
     struct min_h : public Accumulator< min_h<S> >
     {
       typedef mln_value(S) value;
+      typedef value result;
 
       min_h(const Value_Set<S>& s);
       min_h();
@@ -63,7 +64,7 @@
 
       unsigned card() const { return h_.sum(); }
 
-      value to_value() const;
+      value to_result() const;
 
       const accu::histo<S>& histo() const;
 
@@ -213,7 +214,7 @@
 
     template <typename S>
     typename min_h<S>::value
-    min_h<S>::to_value() const
+    min_h<S>::to_result() const
     {
       if (! valid_)
 	update_();
@@ -230,7 +231,7 @@
     template <typename S>
     std::ostream& operator<<(std::ostream& ostr, const min_h<S>& m)
     {
-      return ostr << m.to_value();
+      return ostr << m.to_result();
     }
 
 # endif // ! MLN_INCLUDE_ONLY
Index: mln/accu/bbox.hh
--- mln/accu/bbox.hh	(revision 1156)
+++ mln/accu/bbox.hh	(working copy)
@@ -52,14 +52,16 @@
     struct bbox : public Accumulator< bbox<P> >
     {
       typedef P value;
+      typedef const box_<P>& result;
 
       bbox();
 
+      void init();
+      void take_as_init(const P& p);
       void take(const P& p);
       void take(const bbox<P>& other);
-      void init();
 
-      const box_<P>& to_value() const;
+      const box_<P>& to_result() const;
 
       bool is_valid() const;
 
@@ -81,6 +83,22 @@
 
     template <typename P>
     void
+    bbox<P>::init()
+    {
+      is_valid_ = false;
+    }
+
+    template <typename P>
+    void
+    bbox<P>::take_as_init(const P& p)
+    {
+      b_.pmin() = p;
+      b_.pmax() = p;
+      is_valid_ = true;
+    }
+
+    template <typename P>
+    void
     bbox<P>::take(const P& p)
     {
       if (! is_valid_)
@@ -122,15 +140,8 @@
     }
 
     template <typename P>
-    void
-    bbox<P>::init()
-    {
-      is_valid_ = false;
-    }
-
-    template <typename P>
     const box_<P>&
-    bbox<P>::to_value() const
+    bbox<P>::to_result() const
     {
       mln_precondition(is_valid_);
       return b_;
Index: mln/accu/pair.hh
--- mln/accu/pair.hh	(revision 0)
+++ mln/accu/pair.hh	(revision 0)
@@ -0,0 +1,162 @@
+// 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_ACCU_PAIR_HH
+# define MLN_ACCU_PAIR_HH
+
+/*! \file mln/accu/pair.hh
+ *
+ * \brief Define a pair of accumulators.
+ */
+
+# include <utility>
+
+# include <mln/core/concept/meta_accumulator.hh>
+# include <mln/metal/is_a.hh>
+# include <mln/metal/unqualif.hh>
+
+
+namespace mln
+{
+
+  namespace accu
+  {
+
+
+    /*! Generic pair of accumulators.
+     *
+     * The parameter \c V is the type of values.
+     *
+     * \todo Check that, when V is not provided, A1 and A2 have the same value.
+     */
+    template <typename A1, typename A2, typename V = mln_value(A1)>
+    struct pair_ : public Accumulator< pair_<A1,A2,V> >
+    {
+      typedef V value;
+
+      typedef mlc_unqualif(mln_result(A1))  result_1;
+      typedef mlc_unqualif(mln_result(A2))  result_2;
+      typedef std::pair<result_1, result_2> result;
+
+      pair_();
+      pair_(const A1& a1, const A2& a2);
+
+      void init();
+      void take_as_init(const value& v);
+      void take(const value& v);
+      void take(const pair_<A1,A2,V>& other);
+
+      result to_result() const;
+      void get_result(result_1& r1, result_2& r2) const;
+
+    protected:
+
+      A1 a1_;
+      A2 a2_;
+    };
+
+
+
+    // FIXME: Doc!
+    template <typename A1, typename A2>
+    struct pair : public Meta_Accumulator< pair<A1,A2> >
+    {
+      template <typename V>
+      struct with
+      {
+	typedef mln_accu_with(A1, V) A1_V;
+	typedef mln_accu_with(A2, V) A2_V;
+	typedef pair_<A1_V, A2_V, V> ret;
+      };
+    };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename A1, typename A2, typename V>
+    pair_<A1,A2,V>::pair_()
+    {
+      init();
+    }
+
+    template <typename A1, typename A2, typename V>
+    void
+    pair_<A1,A2,V>::init()
+    {
+      a1_.init();
+      a2_.init();
+    }
+
+    template <typename A1, typename A2, typename V>
+    void
+    pair_<A1,A2,V>::take_as_init(const value& v)
+    {
+      a1_.take_as_init(v);
+      a2_.take_as_init(v);
+    }
+
+    template <typename A1, typename A2, typename V>
+    void
+    pair_<A1,A2,V>::take(const value& v)
+    {
+      a1_.take(v);
+      a2_.take(v);
+    }
+    
+    template <typename A1, typename A2, typename V>
+    void
+    pair_<A1,A2,V>::take(const pair_<A1,A2,V>& other)
+    {
+      a1_.take(other.a1_);
+      a2_.take(other.a2_);
+    }
+
+    template <typename A1, typename A2, typename V>
+    typename pair_<A1,A2,V>::result
+    pair_<A1,A2,V>::to_result() const
+    {
+      result tmp(a1_.to_result(), a2_.to_result());
+      return tmp;
+    }
+
+    template <typename A1, typename A2, typename V>
+    void
+    pair_<A1,A2,V>::get_result(result_1& r1,
+			    result_2& r2) const
+    {
+      r1 = a1_.to_result();
+      r2 = a2_.to_result();
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::accu
+
+} // end of namespace mln
+
+
+#endif // ! MLN_ACCU_PAIR_HH
Index: mln/accu/max_h.hh
--- mln/accu/max_h.hh	(revision 1156)
+++ mln/accu/max_h.hh	(working copy)
@@ -51,6 +51,7 @@
     struct max_h : public Accumulator< max_h<S> >
     {
       typedef mln_value(S) value;
+      typedef value result;
 
       max_h(const Value_Set<S>& s);
       max_h();
@@ -63,7 +64,7 @@
 
       unsigned card() const { return h_.sum(); }
 
-      value to_value() const;
+      value to_result() const;
 
       const accu::histo<S>& histo() const;
 
@@ -212,7 +213,7 @@
 
     template <typename S>
     typename max_h<S>::value
-    max_h<S>::to_value() const
+    max_h<S>::to_result() const
     {
       if (! valid_)
 	update_();
@@ -229,7 +230,7 @@
     template <typename S>
     std::ostream& operator<<(std::ostream& ostr, const max_h<S>& m)
     {
-      return ostr << m.to_value();
+      return ostr << m.to_result();
     }
 
 # endif // ! MLN_INCLUDE_ONLY
Index: mln/accu/median_alt.hh
--- mln/accu/median_alt.hh	(revision 1156)
+++ mln/accu/median_alt.hh	(working copy)
@@ -58,7 +58,7 @@
       void init();
 
       operator mln_value(S) () const;
-      value to_value() const;
+      value to_result() const;
 
       // FIXME: remove
       void debug__() const
@@ -256,7 +256,7 @@
 
     template <typename S>
     typename median_alt<S>::value
-    median_alt<S>::to_value() const
+    median_alt<S>::to_result() const
     {
       return v_;
     }
@@ -265,7 +265,7 @@
     std::ostream& operator<<(std::ostream& ostr, const median_alt<S>& m)
     {
       m.debug__();
-      return ostr << m.to_value();
+      return ostr << m.to_result();
     }
 
 
Index: mln/accu/median.hh
--- mln/accu/median.hh	(revision 1156)
+++ mln/accu/median.hh	(working copy)
@@ -51,6 +51,7 @@
     struct median : public Accumulator< median<S> >
     {
       typedef mln_value(S) value;
+      typedef value result;
 
       median(const Value_Set<S>& s);
       median();
@@ -62,7 +63,7 @@
 
       unsigned card() const { return h_.sum(); }
 
-      value to_value() const;
+      value to_result() const;
 
       const accu::histo<S>& histo() const;
 
@@ -223,7 +224,7 @@
 
     template <typename S>
     typename median<S>::value
-    median<S>::to_value() const
+    median<S>::to_result() const
     {
       if (! valid_)
 	update_();
@@ -240,7 +241,7 @@
     template <typename S>
     std::ostream& operator<<(std::ostream& ostr, const median<S>& m)
     {
-      return ostr << m.to_value();
+      return ostr << m.to_result();
     }
 
 # endif // ! MLN_INCLUDE_ONLY
Index: mln/accu/p.hh
--- mln/accu/p.hh	(revision 0)
+++ mln/accu/p.hh	(revision 0)
@@ -0,0 +1,144 @@
+// 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_ACCU_P_HH
+# define MLN_ACCU_P_HH
+
+/*! \file mln/accu/p.hh
+ *
+ * \brief Define an accumulator that computes a min and a max.
+ */
+
+# include <mln/core/concept/meta_accumulator.hh>
+# include <mln/core/concept/accumulator.hh>
+# include <mln/metal/is_a.hh>
+
+
+namespace mln
+{
+
+  namespace accu
+  {
+
+
+    /*! Generic p of accumulators.
+     *
+     * The parameter \c V is the type of values.
+     */
+    template <typename A>
+    struct p_ : public Accumulator< p_<A> >
+    {
+      typedef mln_value(A)  value;
+      typedef mln_result(A) result;
+
+
+      p_();
+      p_(const A& a);
+
+      void init();
+      void take_as_init(const value& v);
+      void take(const value& v);
+      void take(const p_<A>& other);
+
+      result to_result() const;
+
+    protected:
+      A a_;
+    };
+
+
+
+    // FIXME: Doc!
+    template <typename mA>
+    struct p : public Meta_Accumulator< p<mA> >
+    {
+      template <typename V>
+      struct with
+      {
+	typedef mln_accu_with(mA, mln_psite(V)) ret;
+      };
+    };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename A>
+    p_<A>::p_()
+    {
+      init();
+    }
+
+    template <typename A>
+    p_<A>::p_(const A& a)
+      : a_(a)
+    {
+      init();
+    }
+
+    template <typename A>
+    void
+    p_<A>::init()
+    {
+      a_.init();
+    }
+
+    template <typename A>
+    void
+    p_<A>::take_as_init(const value& v)
+    {
+      a_.take_as_init(v.p()); // FIXME: Generalize with "psite(v)".
+    }
+
+    template <typename A>
+    void
+    p_<A>::take(const value& v)
+    {
+      a_.take(v.p());
+    }
+    
+    template <typename A>
+    void
+    p_<A>::take(const p_<A>& other)
+    {
+      a_.take(other.a_);
+    }
+
+    template <typename A>
+    typename p_<A>::result
+    p_<A>::to_result() const
+    {
+      return a_.to_result();
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::accu
+
+} // end of namespace mln
+
+
+#endif // ! MLN_ACCU_P_HH
Index: mln/accu/sum.hh
--- mln/accu/sum.hh	(revision 1156)
+++ mln/accu/sum.hh	(working copy)
@@ -33,8 +33,9 @@
  * \brief Define an accumulator that computes a sum.
  */
 
-# include <mln/core/concept/accumulator.hh>
+# include <mln/core/concept/meta_accumulator.hh>
 # include <mln/value/props.hh>
+# include <mln/util/pix.hh>
 
 
 namespace mln
@@ -51,21 +52,37 @@
      * \c S is the summation type (property) of \c V.
      */
     template <typename V, typename S = mln_sum(V)>
-    struct sum : public Accumulator< sum<V,S> >
+    struct sum_ : public Accumulator< sum_<V,S> >
     {
       typedef V value;
+      typedef S result;
 
-      sum();
+      sum_();
 
       void init();
       void take(const value& v);
-      void take(const sum<V,S>& other);
+      void take(const sum_<V,S>& other);
 
-      S to_value() const;
+      S to_result() const;
       
     protected:
 
-      S sum_;
+      S s_;
+    };
+
+
+    template <typename I, typename S>
+    struct sum_< util::pix<I>, S >;
+
+
+    // FIXME: Doc!
+    struct sum : public Meta_Accumulator< sum >
+    {
+      template <typename V, typename S = mln_sum(V)>
+      struct with
+      {
+	typedef sum_<V, S> ret;
+      };
     };
 
 
@@ -73,36 +90,36 @@
 # ifndef MLN_INCLUDE_ONLY
 
     template <typename V, typename S>
-    sum<V,S>::sum()
+    sum_<V,S>::sum_()
     {
       init();
     }
 
     template <typename V, typename S>
     void
-    sum<V,S>::init()
+    sum_<V,S>::init()
     {
-      sum_ = 0;
+      s_ = 0;
     }
 
     template <typename V, typename S>
-    void sum<V,S>::take(const value& v)
+    void sum_<V,S>::take(const value& v)
     {
-      sum_ += v;
+      s_ += v;
     }
 
     template <typename V, typename S>
     void
-    sum<V,S>::take(const sum<V,S>& other)
+    sum_<V,S>::take(const sum_<V,S>& other)
     {
-      sum_ += other.sum_;
+      s_ += other.s_;
     }
 
     template <typename V, typename S>
     S
-    sum<V,S>::to_value() const
+    sum_<V,S>::to_result() const
     {
-      return sum_;
+      return s_;
     }
 
 # endif // ! MLN_INCLUDE_ONLY
Index: mln/accu/v.hh
--- mln/accu/v.hh	(revision 0)
+++ mln/accu/v.hh	(revision 0)
@@ -0,0 +1,154 @@
+// 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_ACCU_V_HH
+# define MLN_ACCU_V_HH
+
+/*! \file mln/accu/v.hh
+ *
+ * \brief Define an accumulator that computes a min and a max.
+ */
+
+# include <mln/core/concept/meta_accumulator.hh>
+# include <mln/core/concept/accumulator.hh>
+# include <mln/metal/is_a.hh>
+
+
+namespace mln
+{
+
+  namespace accu
+  {
+
+
+    /*! Generic v of accumulators.
+     */
+    template <typename A>
+    struct val_ : public Accumulator< val_<A> >
+    {
+      typedef mln_value(A)  value;
+      typedef mln_result(A) result;
+
+      val_();
+      val_(const A& a);
+
+      void init();
+      void take_as_init(const value& v);
+      void take(const value& v);
+      void take(const val_<A>& other);
+
+      template <typename I>
+      void take_as_init(const util::pix<I>& pix)
+      {
+	a_.take_as_init(pix.v()); // FIXME: Generalize with "value(pix)".
+      }
+
+      template <typename I>
+      void take(const util::pix<I>& pix)
+      {
+	a_.take(pix.v());
+      }
+
+      result to_result() const;
+
+    protected:
+      A a_;
+    };
+
+
+
+    // FIXME: Doc!
+    template <typename mA>
+    struct val : public Meta_Accumulator< val<mA> >
+    {
+      template <typename V>
+      struct with
+      {
+	typedef mln_accu_with(mA, mln_value(V)) A;
+	typedef val_<A> ret;
+      };
+    };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename A>
+    val_<A>::val_()
+    {
+      init();
+    }
+
+    template <typename A>
+    val_<A>::val_(const A& a)
+      : a_(a)
+    {
+      init();
+    }
+
+    template <typename A>
+    void
+    val_<A>::init()
+    {
+      a_.init();
+    }
+
+    template <typename A>
+    void
+    val_<A>::take_as_init(const value& v)
+    {
+      a_.take_as_init(v);
+    }
+
+    template <typename A>
+    void
+    val_<A>::take(const value& v)
+    {
+      a_.take(v);
+    }
+    
+    template <typename A>
+    void
+    val_<A>::take(const val_<A>& other)
+    {
+      a_.take(other.a_);
+    }
+
+    template <typename A>
+    typename val_<A>::result
+    val_<A>::to_result() const
+    {
+      return a_.to_result();
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::accu
+
+} // end of namespace mln
+
+
+#endif // ! MLN_ACCU_VAL_HH
Index: mln/accu/all.hh
--- mln/accu/all.hh	(revision 0)
+++ mln/accu/all.hh	(revision 0)
@@ -0,0 +1,65 @@
+// 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_ACCU_ALL_HH
+# define MLN_ACCU_ALL_HH
+
+/*! \file mln/accu/all.hh
+ *
+ * \brief File that includes all accumulator types.
+ *
+ * \todo Update accumulators s.a. count so that they are like min_/min.
+ *
+ * \todo Propagate those updates to mln/estim/.
+ */
+
+
+namespace mln
+{
+
+  /*! Namespace of accumulators.
+   */
+  namespace accu {}
+
+}
+
+
+# include <mln/accu/bbox.hh>
+# include <mln/accu/count.hh>
+# include <mln/accu/histo.hh>
+# include <mln/accu/max.hh>
+# include <mln/accu/mean.hh>
+# include <mln/accu/median.hh>
+# include <mln/accu/min.hh>
+# include <mln/accu/min_h.hh>
+# include <mln/accu/min_max.hh>
+# include <mln/accu/nil.hh>
+# include <mln/accu/pair.hh>
+# include <mln/accu/sum.hh>
+
+
+#endif // ! MLN_ACCU_ALL_HH
Index: mln/accu/compute.hh
--- mln/accu/compute.hh	(revision 0)
+++ mln/accu/compute.hh	(revision 0)
@@ -0,0 +1,101 @@
+// 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_ACCU_COMPUTE_HH
+# define MLN_ACCU_COMPUTE_HH
+
+/*! \file mln/accu/compute.hh
+ *
+ * \brief Make an accumulator compute image pixels.
+ */
+
+# include <mln/core/concept/meta_accumulator.hh>
+# include <mln/core/concept/accumulator.hh>
+# include <mln/core/concept/image.hh>
+# include <mln/metal/is_a.hh>
+# include <mln/util/pix.hh>
+
+
+namespace mln
+{
+
+  namespace accu
+  {
+
+    /*! Make an accumulator compute the pixels of the image \p input.
+     *
+     * \param[in] input The input image.
+     *
+     * This routine runs: \n
+     *   FIXME
+     *
+     * \warning This routine does not perform a.init().
+     */
+    template <typename A, typename I>
+    mln_result(A)
+    compute(const Image<I>& input);
+
+
+    // FIXME: Doc!
+    template <typename A, typename I>
+    mln_accu_with(A, util::pix<I>)::result
+    compute(const Image<I>& input);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename A, typename I>
+    mln_result(A)
+    compute(const Image<I>& input_)
+    {
+      mlc_is_a(A, Accumulator)::check();
+      const I& input = exact(input_);
+      A a;
+      mln_piter(I) p(input.domain());
+      for_all(p)
+	a.take(make::pix(input, p));
+      return a.to_result();
+    }
+
+    template <typename A, typename I>
+    mln_accu_with(A, util::pix<I>)::result
+    compute(const Image<I>& input)
+    {
+      mlc_is_a(A, Meta_Accumulator)::check();
+      typedef mln_accu_with(A, util::pix<I>) A_;
+      return compute<A_>(input);
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::accu
+
+} // end of namespace mln
+
+
+#endif // ! MLN_ACCU_COMPUTE_HH
Index: mln/accu/mean.hh
--- mln/accu/mean.hh	(revision 1156)
+++ mln/accu/mean.hh	(working copy)
@@ -31,6 +31,8 @@
 /*! \file mln/accu/mean.hh
  *
  * \brief Define an accumulator that computes a mean.
+ *
+ * \todo Use accu::pair just like in accu::min_max.
  */
 
 # include <mln/accu/count.hh>
@@ -55,44 +57,63 @@
     template <typename V,
 	      typename S = mln_sum(V),
 	      typename M = S>
-    struct mean : public Accumulator< mean<V,S,M> >
+    struct mean_ : public Accumulator< mean_<V,S,M> >
     {
       typedef V value;
+      typedef M result;
 
-      mean();
+      mean_();
 
       void init();
       void take(const value& v);
-      void take(const mean<V,S,M>& other);
+      void take(const mean_<V,S,M>& other);
 
-      M to_value() const;
+      M to_result() const;
 
     protected:
 
-      accu::count<V> count_;
-      accu::sum<V,S>   sum_;
+      accu::count_<V> count_;
+      accu::sum_<V,S>   sum_;
     };
 
 
 
+    template <typename I, typename S, typename M>
+    struct mean_< util::pix<I>, S,M >;
+
+
+
+    // FIXME: Doc!
+    struct mean : public Meta_Accumulator< mean >
+    {
+      template < typename V,
+		 typename S = mln_sum(V),
+		 typename M = S >
+      struct with
+      {
+	typedef mean_<V,S,M> ret;
+      };
+    };
+
+
 # ifndef MLN_INCLUDE_ONLY
 
     template <typename V, typename S, typename M>
-    mean<V,S,M>::mean()
+    mean_<V,S,M>::mean_()
     {
       init();
     }
 
     template <typename V, typename S, typename M>
     void
-    mean<V,S,M>::init()
+    mean_<V,S,M>::init()
     {
       count_.init();
       sum_.init();
     }
 
     template <typename V, typename S, typename M>
-    void mean<V,S,M>::take(const value& v)
+    void mean_<V,S,M>::take(const value& v)
     {
       count_.take(v);
       sum_.take(v);
@@ -100,7 +121,7 @@
 
     template <typename V, typename S, typename M>
     void
-    mean<V,S,M>::take(const mean<V,S,M>& other)
+    mean_<V,S,M>::take(const mean_<V,S,M>& other)
     {
       count_.take(other.count_);
       sum_.take(other.sum_);
@@ -108,9 +129,9 @@
 
     template <typename V, typename S, typename M>
     M
-    mean<V,S,M>::to_value() const
+    mean_<V,S,M>::to_result() const
     {
-      return sum_.to_value() / count_.to_value();
+      return sum_.to_result() / count_.to_result();
     }
 
 # endif // ! MLN_INCLUDE_ONLY
Index: mln/make/pix.hh
--- mln/make/pix.hh	(revision 0)
+++ mln/make/pix.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_MAKE_PIX_HH
+# define MLN_MAKE_PIX_HH
+
+/*! \file mln/make/pix.hh
+ *
+ * \brief Routine to construct an mln::util::pix.
+ */
+
+# include <mln/util/pix.hh>
+
+
+namespace mln
+{
+
+  namespace make
+  {
+
+    /// Create an mln::pix from an image \p ima and a psite \p p.
+    template <typename I>
+    mln::util::pix<I> pix(const Image<I>& ima, const mln_psite(I)& p);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename I>
+    mln::util::pix<I> pix(const Image<I>& ima, const mln_psite(I)& p)
+    {
+      mln::util::pix<I> tmp(ima, p);
+      return tmp;
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::make
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MAKE_PIX_HH
Index: mln/labeling/estimate.hh
--- mln/labeling/estimate.hh	(revision 0)
+++ mln/labeling/estimate.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_LABELING_ESTIMATE_HH
+# define MLN_LABELING_ESTIMATE_HH
+
+/*! \file mln/labeling/estimate.hh
+ *
+ * \brief Compute the estimate pixel value.
+ */
+
+# include <mln/core/image_if.hh>
+# include <mln/accu/compute.hh>
+
+
+namespace mln
+{
+
+  namespace labeling
+  {
+
+    /*! \brief FIXME: Compute an estimate over the pixels of image \p
+     *  input with value \p val.
+     *
+     * \param[in] input The image.
+     * \result The estimate value.
+     */
+    template <typename A, typename I>
+    mln_accu_with(A, util::pix<I>)::result
+    estimate(const Image<I>& input, const mln_value(I)& val);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename A, typename I>
+    mln_accu_with(A, util::pix<I>)::result
+    estimate(const Image<I>& input, const mln_value(I)& val)
+    {
+      return accu::compute<A>(input | val);
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::labeling
+
+} // end of namespace mln
+
+
+#endif // ! MLN_LABELING_ESTIMATE_HH
Index: mln/util/ignore.hh
--- mln/util/ignore.hh	(revision 0)
+++ mln/util/ignore.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_UTIL_IGNORE_HH
+# define MLN_UTIL_IGNORE_HH
+
+/*! \file mln/util/ignore.hh
+ *
+ * \brief Definition of an "ignorer" object.
+ */
+
+# include <mln/core/concept/object.hh>
+
+
+namespace mln
+{
+
+  namespace util
+  {
+
+    /// Ignore structure.
+    struct ignore
+    {
+      ignore();
+
+      template <typename T>
+      operator T() const;
+    };
+
+# ifndef MLN_INCLUDE_ONLY
+
+    // ignore
+
+    ignore::ignore()
+    {
+    }
+
+    template <typename T>
+    ignore::operator T() const
+    {
+      return T();
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::util
+
+} // end of namespace mln
+
+
+#endif // ! MLN_UTIL_IGNORE_HH
Index: mln/util/eat.hh
--- mln/util/eat.hh	(revision 0)
+++ mln/util/eat.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_UTIL_EAT_HH
+# define MLN_UTIL_EAT_HH
+
+/*! \file mln/util/eat.hh
+ *
+ * \brief Definition of an "eater" object.
+ */
+
+# include <mln/core/concept/object.hh>
+
+
+namespace mln
+{
+
+  namespace util
+  {
+
+    /// Eat structure.
+    struct eat
+    {
+      eat();
+
+      template <typename T>
+      eat(const T&);
+
+      template <typename T>
+      eat& operator=(const T&);
+    };
+
+# ifndef MLN_INCLUDE_ONLY
+
+    // eat
+
+    eat::eat()
+    {
+    }
+
+    template <typename T>
+    eat::eat(const T&)
+    {
+    }
+
+    template <typename T>
+    eat&
+    eat::operator=(const T&)
+    {
+      return *this;
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::util
+
+} // end of namespace mln
+
+
+#endif // ! MLN_UTIL_EAT_HH
Index: mln/util/pix.hh
--- mln/util/pix.hh	(revision 1156)
+++ mln/util/pix.hh	(working copy)
@@ -39,35 +39,44 @@
 namespace mln
 {
 
+  namespace select
+  {
+
+    template <typename P>
+    struct p_of : P
+    {
+      operator typename P::psite() const
+      {
+	return this->p();
+      }
+    };
+    
+  }
+
   namespace util
   {
 
     /// Pix structure.
     template <typename I>
-    struct pix_
+    struct pix
     {
-      pix_(const Image<I>& ima, const mln_point(I)& p);
+      typedef mln_psite(I) psite;
+      typedef mln_value(I) value;
+
+      pix(const Image<I>& ima, const mln_psite(I)& p);
       const I& ima() const;
-      const mln_point(I)& p() const;
-      operator mln_rvalue(I)() const;
+      const mln_psite(I)& p() const;
+      mln_rvalue(I)       v() const;
     private:
       const I& ima_;
-      const mln_point(I)& p_;
+      const mln_psite(I)& p_;
     };
     
 
-    /// Routine to construct a pix on the fly.
-    template <typename I>
-    pix_<I>
-    pix(const Image<I>& ima, const mln_point(I)& p);
-
-
 # ifndef MLN_INCLUDE_ONLY
 
-    // pix_<I>
-
     template <typename I>
-    pix_<I>::pix_(const Image<I>& ima, const mln_point(I)& p)
+    pix<I>::pix(const Image<I>& ima, const mln_psite(I)& p)
       : ima_(exact(ima)),
 	p_(p)
     {
@@ -75,34 +84,25 @@
 
     template <typename I>
     const I&
-    pix_<I>::ima() const
+    pix<I>::ima() const
     {
       return ima_;
     }
 
     template <typename I>
-    const mln_point(I)&
-    pix_<I>::p() const
+    const mln_psite(I)&
+    pix<I>::p() const
     {
       return p_;
     }
 
     template <typename I>
-    pix_<I>::operator mln_rvalue(I)() const
+    mln_rvalue(I)
+    pix<I>::v() const
     {
       return ima_(p_);
     }
 
-    // pix
-
-    template <typename I>
-    pix_<I>
-    pix(const Image<I>& ima, const mln_point(I)& p)
-    {
-      pix_<I> tmp(ima, p);
-      return tmp;
-    }
-
 # endif // ! MLN_INCLUDE_ONLY
 
   } // end of namespace mln::util
@@ -110,4 +110,7 @@
 } // end of namespace mln
 
 
+# include <mln/make/pix.hh>
+
+
 #endif // ! MLN_UTIL_PIX_HH
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                          URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2007-09-24  Simon Nivault  <simon.nivault(a)lrde.epita.fr>
	Add test of rotation and fix.
	* mln/core/interpolated.hh: Fix.
	* mln/core/point.hh: Fix and add constructor for filling.
	* mln/fun/internal/selector.hh: Add tag x for vectors.
	* mln/io/internal/pnm/save.hh: Fix.
	* mln/io/internal/pnm/save_header.hh: Fix.
	* sandbox/nivault/rotation.cc: Experimentation on rotation.
---
 mln/core/interpolated.hh           |   12 ++++++
 mln/core/point.hh                  |   16 ++++++--
 mln/fun/internal/selector.hh       |   33 +++++++++++++++-
 mln/io/internal/pnm/save.hh        |    2 +
 mln/io/internal/pnm/save_header.hh |    2 +
 sandbox/nivault/rotation.cc        |   72 +++++++++++++++++++++++++++++++++++++
 6 files changed, 130 insertions(+), 7 deletions(-)
Index: trunk/milena/mln/core/point.hh
===================================================================
--- trunk/milena/mln/core/point.hh	(revision 1155)
+++ trunk/milena/mln/core/point.hh	(revision 1156)
@@ -85,6 +85,9 @@
     /// Constructor without argument.
     point_();
 
+    /// Constructor with filling.
+    point_(C c);
+
     /// Constructor; coordinates are set by function \p f.
     template <typename F>
     point_(const Function_i2v<F>& f);
@@ -99,13 +102,13 @@
     point_<M,C>& operator+=(const dpoint& dp);
 
     /// Type of the array of coordinates.
-    typedef metal::vec<dim, C> vec_t;
+    typedef metal::vec<M::dim, C> vec_t;
 
     /// Hook to coordinates.
     operator metal::vec<M::dim, C>() const;
 
   protected:
-    metal::vec<dim, C> coord_;
+    metal::vec<M::dim, C> coord_;
   };
 
 
@@ -131,6 +134,12 @@
   }
 
   template <typename M, typename C>
+  point_<M,C>::point_(C c)
+  {
+    set_all(c);
+  }
+
+  template <typename M, typename C>
   template <typename F>
   point_<M,C>::point_(const Function_i2v<F>& f_)
   {
@@ -142,8 +151,7 @@
   template <typename M, typename C>
   void point_<M,C>::set_all(C c)
   {
-    for (unsigned i = 0; i < dim; ++i)
-      coord_[i] = c;
+    coord_.set_all(c);
   }
 
   template <typename M, typename C>
Index: trunk/milena/mln/core/interpolated.hh
===================================================================
--- trunk/milena/mln/core/interpolated.hh	(revision 1155)
+++ trunk/milena/mln/core/interpolated.hh	(revision 1156)
@@ -78,6 +78,9 @@
     /// Test if a pixel value is accessible at \p p.
     bool owns_(const psite& p) const;
 
+    /// Test if a pixel value is accessible at \p v.
+    bool owns_(const mln::metal::vec<I::point::dim, float>& v) const;
+
     /// Give the definition domain.
     const mln_pset(I)& domain() const;
 
@@ -123,6 +126,15 @@
   }
 
   template <typename I>
+  bool interpolated<I>::owns_(const mln::metal::vec<I::point::dim, float>& v) const
+  {
+    mln_point(I) p;
+    for (unsigned i = 0; i < I::point::dim; ++i)
+      p[i] = static_cast<int>(round(v[i]));
+    return ima_.owns_(p);
+  }
+
+  template <typename I>
   const mln_pset(I)&
   interpolated<I>::domain() const
   {
Index: trunk/milena/mln/fun/internal/selector.hh
===================================================================
--- trunk/milena/mln/fun/internal/selector.hh	(revision 1155)
+++ trunk/milena/mln/fun/internal/selector.hh	(revision 1156)
@@ -34,10 +34,11 @@
  */
 
 # include <mln/core/concept/function.hh>
-# include <mln/core/concept/point.hh>
+# include <mln/core/concept/point_site.hh>
 # include <mln/metal/unqualif.hh>
 # include <mln/metal/if.hh>
 # include <mln/metal/is_a.hh>
+# include <mln/metal/vec.hh>
 
 
 namespace mln
@@ -66,7 +67,8 @@
 	  b_,
 	  i_,
 	  p_,
-	  v_
+	  v_,
+	  x_
 	};
 
       template <int arg, int res, typename E> struct helper_selector_;
@@ -80,6 +82,8 @@
       struct helper_selector_< b_, p_, E > { typedef Function_v2v<E> ret; };
       template <typename E>
       struct helper_selector_< b_, v_, E > { typedef Function_v2v<E> ret; };
+      template <typename E>
+      struct helper_selector_< b_, x_, E > { typedef Function_v2v<E> ret; };
 
       // i2* => i2v type
       template <typename E>
@@ -90,6 +94,8 @@
       struct helper_selector_< i_, p_, E > { typedef Function_i2v<E> ret; };
       template <typename E>
       struct helper_selector_< i_, v_, E > { typedef Function_i2v<E> ret; };
+      template <typename E>
+      struct helper_selector_< i_, x_, E > { typedef Function_i2v<E> ret; };
 
       // p2*
       template <typename E>
@@ -100,6 +106,8 @@
       struct helper_selector_< p_, p_, E > { typedef Function_p2p<E> ret; };
       template <typename E>
       struct helper_selector_< p_, v_, E > { typedef Function_p2v<E> ret; };
+      template <typename E>
+      struct helper_selector_< p_, x_, E > { typedef Function_p2v<E> ret; };
 
       // v2* => v2v type, except for v2b
       template <typename E>
@@ -110,7 +118,20 @@
       struct helper_selector_< v_, p_, E > { typedef Function_v2v<E> ret; };
       template <typename E>
       struct helper_selector_< v_, v_, E > { typedef Function_v2v<E> ret; };
+      template <typename E>
+      struct helper_selector_< v_, x_, E > { typedef Function_v2v<E> ret; };
 
+      // x2* => v2v type
+      template <typename E>
+      struct helper_selector_< x_, b_, E > { typedef Function_v2b<E> ret; };
+      template <typename E>
+      struct helper_selector_< x_, i_, E > { typedef Function_v2v<E> ret; };
+      template <typename E>
+      struct helper_selector_< x_, p_, E > { typedef Function_v2v<E> ret; };
+      template <typename E>
+      struct helper_selector_< x_, v_, E > { typedef Function_v2v<E> ret; };
+      template <typename E>
+      struct helper_selector_< x_, x_, E > { typedef Function_v2v<E> ret; };
 
       // tag_
 
@@ -128,10 +149,16 @@
 	enum { value = i_ };
       };
 
+      template <unsigned n, typename T>
+      struct tag_< metal::vec<n,T> >
+      {
+	enum { value = x_ };
+      };
+
       template <typename T>
       struct tag_
       {
-	enum { value = mlc_is_a(T, Point)::to_bool
+	enum { value = mlc_is_a(T, Point_Site)::to_bool
 	       ? p_
 	       : v_ };
       };
Index: trunk/milena/mln/io/internal/pnm/save_header.hh
===================================================================
--- trunk/milena/mln/io/internal/pnm/save_header.hh	(revision 1155)
+++ trunk/milena/mln/io/internal/pnm/save_header.hh	(revision 1156)
@@ -33,6 +33,8 @@
 # include <fstream>
 
 # include <mln/value/rgb.hh>
+# include <mln/geom/nrows.hh>
+# include <mln/geom/ncols.hh>
 
 namespace mln
 {
Index: trunk/milena/mln/io/internal/pnm/save.hh
===================================================================
--- trunk/milena/mln/io/internal/pnm/save.hh	(revision 1155)
+++ trunk/milena/mln/io/internal/pnm/save.hh	(revision 1156)
@@ -39,6 +39,7 @@
 # include <fstream>
 
 # include <mln/core/concept/image.hh>
+# include <mln/core/point2d.hh>
 
 # include <mln/value/rgb.hh>
 # include <mln/value/rgb8.hh>
@@ -51,6 +52,7 @@
 
 # include <mln/geom/size2d.hh>
 
+
 namespace mln
 {
 
Index: trunk/milena/sandbox/nivault/rotation.cc
===================================================================
--- trunk/milena/sandbox/nivault/rotation.cc	(revision 0)
+++ trunk/milena/sandbox/nivault/rotation.cc	(revision 1156)
@@ -0,0 +1,72 @@
+// 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/image2d_b.cc
+ *
+ * \brief Tests on mln::image2d_b.
+ */
+
+#include <cmath>
+#include <iostream>
+
+#include <mln/io/pgm/save.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/core/image2d_b.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/core/interpolated.hh>
+
+
+int main()
+{
+  using namespace mln;
+  using value::int_u8;
+
+  image2d_b<int_u8> lena = io::pgm::load("../img/lena.pgm");
+  image2d_b<int_u8> out(lena.domain());
+
+  interpolated<image2d_b<int_u8> > inter(lena);
+
+  image2d_b<int_u8>::fwd_piter p(out.domain());
+  float q0, q1;
+
+  float cos10 = cos(0.15);
+  float sin10 = sin(0.15);
+
+  for_all(p)
+    {
+      q0 = cos10 * p[0] - sin10 * p[1];
+      q1 = sin10 * p[0] + cos10 * p[1];
+      if (inter.owns_(make::vec(q0, q1)))
+      {
+	out(p) = inter(make::vec(q0, q1));
+//	std::cout << "GOOD" << std::endl;
+      }
+      else
+	out(p) = 0;
+    }
+  io::pgm::save(out, "out.pgm");
+}
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                          URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2007-09-21  Matthieu Garrigues  <garrigues(a)lrde.epita.fr>
	Remove image_adaptor inheritance
	* mln/core/decorated_image.hh:
	* mln/core/image_if.hh:
	* mln/value/stack.hh: Change image_adpator inheritance to image_base.
	* mln/core/image3d_b.hh: Add a using super_::data_
---
 core/decorated_image.hh |   86 ++++++++++++++++++++++++++++------
 core/image3d_b.hh       |    6 ++
 core/image_if.hh        |  121 ++++++++++++++++++++++++++++++++++++++++--------
 value/stack.hh          |   66 +++++++++++++++-----------
 4 files changed, 220 insertions(+), 59 deletions(-)
Index: trunk/milena/mln/core/decorated_image.hh
===================================================================
--- trunk/milena/mln/core/decorated_image.hh	(revision 1154)
+++ trunk/milena/mln/core/decorated_image.hh	(revision 1155)
@@ -28,7 +28,8 @@
 #ifndef MLN_CORE_DECORATED_IMAGE_HH
 # define MLN_CORE_DECORATED_IMAGE_HH
 
-# include <mln/core/internal/image_adaptor.hh>
+# include <mln/core/internal/image_base.hh>
+
 # include <mln/value/proxy.hh>
 
 
@@ -55,28 +56,42 @@
       typedef mln::value::proxy<const E> lvalue;
     };
 
-  } // end of namespace::internal
+    template <typename I, typename D>
+    struct data_< decorated_image<I,D> >
+    {
+      data_(I& ima, const D& deco);
+
+      I ima_;
+      D deco_;
+    };
+
+  } // end of namespace mln::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_base_< mln_pset(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_;
+    typedef internal::image_base_< mln_pset(I), decorated_image<I,D> > super_;
   public:
 
+    /// Ctors
+    decorated_image();
     decorated_image(I& ima, const D& deco);
+    /// Dtor
     ~decorated_image();
 
     typedef mln_value(I)                    value;
     typedef mln::value::proxy<const self_> rvalue;
     typedef typename impl_::lvalue         lvalue;
 
+    /// Value_Set associated type.
+    typedef mln_vset(I) vset;
 
     /// Skeleton.
     typedef decorated_image< tag::image<I>, tag::data<D> > skeleton;
@@ -96,8 +111,14 @@
     /// Give the decoration.
     D& decoration();
 
-  protected:
-    D deco_;
+    /// FIXME : to put into a identity morpher
+    /// Give the definition domain.
+    const mln_pset(I)& domain() const;
+
+    /// Give the set of values.
+    const mln_vset(I)& values() const;
+
+    using super_::data_;
   };
 
 
@@ -114,13 +135,31 @@
 
 # ifndef MLN_INCLUDE_ONLY
 
+  namespace internal
+  {
+
+    // internal::data_< decorated_image<I,S> >
+
+    template <typename I, typename D>
+    data_< decorated_image<I,D> >::data_(I& ima, const D& deco)
+      : ima_(ima),
+	deco_(deco)
+    {
+    }
+
+  } // end of namespace mln::internal
+
   // decorated_image<I,D>
 
   template <typename I, typename D>
+  decorated_image<I,D>::decorated_image()
+  {
+  }
+
+  template <typename I, typename D>
   decorated_image<I,D>::decorated_image(I& ima, const D& deco)
-    : super_(ima),
-      deco_(deco)
   {
+    this->data_ = new internal::data_< decorated_image<I,D> >(ima, deco);
   }
 
   template <typename I, typename D>
@@ -157,8 +196,8 @@
     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;
+      ima.decoration().writing(ima.data_->ima_, p, v);
+      ima.data_->ima_(p) = v;
     }
 
   } // end of namespace mln::internal
@@ -167,31 +206,48 @@
   mln_value(I)
   decorated_image<I,D>::read_(const mln_psite(I)& p) const
   {
-    deco_.reading(this->adaptee_, p);
-    return this->adaptee_(p);
+    this->data_->deco_.reading(this->data_->ima_, p);
+    return this->data_->ima_(p);
   }
 
   template <typename I, typename D>
   decorated_image<I,D>::operator decorated_image<const I, D>() const
   {
-    decorated_image<const I, D> tmp(this->adaptee_, deco_);
+    decorated_image<const I, D> tmp(this->data_->ima_, this->data_->deco_);
     return tmp;
   }
 
+
   template <typename I, typename D>
   const D&
   decorated_image<I,D>::decoration() const
   {
-    return deco_;
+    return this->data_->deco_;
   }
 
   template <typename I, typename D>
   D&
   decorated_image<I,D>::decoration()
   {
-    return deco_;
+    return this->data_->deco_;
   }
 
+  template <typename I, typename D>
+  const mln_pset(I)&
+  decorated_image<I,D>::domain() const
+  {
+    mln_precondition(exact(this)->has_data());
+    return  this->data_->ima_.domain();
+  }
+
+  template <typename I, typename D>
+  const mln_vset(I)&
+  decorated_image<I,D>::values() const
+  {
+    return this->data_->ima_.values();
+  }
+
+
   // decorate
 
   template <typename I, typename D>
Index: trunk/milena/mln/core/image_if.hh
===================================================================
--- trunk/milena/mln/core/image_if.hh	(revision 1154)
+++ trunk/milena/mln/core/image_if.hh	(revision 1155)
@@ -30,25 +30,45 @@
 
 /*! \file mln/core/image_if.hh
  *
- * \brief Definition of a base class for image adaptors.
+ * \brief Definition of a image_if image.
  */
 
-# include <mln/core/internal/image_adaptor.hh>
+# include <mln/core/internal/image_base.hh>
 # include <mln/core/pset_if.hh>
 
 
 namespace mln
 {
 
+  // Fwd decl.
+  template <typename I, typename F> struct image_if;
+
+
+  namespace internal
+  {
+    template <typename I, typename F>
+    struct data_< image_if<I,F> >
+    {
+      data_(I& ima, const F& f);
+
+      pset_if<mln_pset(I), F> pset_;
+      F f_;
+      I ima_;
+    };
+
+  } // end of namespace mln::internal
+
+
   /*! \brief A base class for image adaptors.
    *
    */
   template <typename I, typename F>
-  struct image_if : public internal::image_adaptor_< I,
-						     image_if<I,F>,
-						     pset_if<mln_pset(I),F>  >
+  struct image_if : public internal::image_base_< pset_if<mln_pset(I), F>, image_if<I,F> >
   {
 
+    // Parent
+    typedef internal::image_base_< pset_if<mln_pset(I), F>, image_if<I,F> > super_;
+
     /// Skeleton.
     typedef image_if< tag::image<I>, tag::function<F> > skeleton;
 
@@ -56,8 +76,10 @@
     /// Point_Set associated type.
     typedef pset_if<mln_pset(I), F> pset;
 
-    /// Constructor from an \p adaptee image.
-    image_if(I& adaptee, const F& f);
+    /// Constructor from an \p image.
+    image_if(I& ima, const F& f);
+
+    image_if();
 
     /// Test if a pixel value is accessible at \p p.
     bool owns_(const mln_psite(I)& p) const;
@@ -68,13 +90,35 @@
     /// Const promotion via convertion.
     operator image_if<const I, F>() const;
 
-  protected:
-
-    pset pset_;
-    F f_;
+    using super_::data_;
 
     typedef image_if<I,F> self_;
-    typedef internal::image_adaptor_< I, self_, pset > super_;
+
+    /// FIXME : to put into an identity morpher
+
+    /// Point_Site associated type.
+    typedef mln_point(I) point;
+    typedef mln_psite(pset) psite;
+
+    /// Value_Set associated type.
+    typedef mln_vset(I) vset;
+
+    /// Value associated type.
+    typedef mln_value(I)   value;
+
+    /// Return type of read-only access.
+    typedef mln_rvalue(I) rvalue;
+
+    typedef typename internal::morpher_lvalue_<I>::ret lvalue;
+
+    /// Read-only access of pixel value at point site \p p.
+    rvalue operator()(const psite& p) const;
+
+    /// Read-write access of pixel value at point site \p p.
+    lvalue operator()(const psite& p);
+
+    /// Give the set of values.
+    const vset& values() const;
   };
 
 
@@ -91,35 +135,76 @@
 
 # ifndef MLN_INCLUDE_ONLY
 
+  namespace internal
+  {
+
+    // internal::data_< image_if<I,S> >
+
   template <typename I, typename F>
-  image_if<I,F>::image_if(I& adaptee, const F& f)
-    : super_(adaptee),
-      pset_(adaptee.domain() | f),
+    data_< image_if<I,F> >::data_(I& ima, const F& f)
+      : ima_(ima),
+	pset_(ima.domain() | f),
       f_(f)
   {
   }
 
+  } // end of namespace mln::internal
+
+  template <typename I, typename F>
+  image_if<I,F>::image_if()
+  {
+  }
+
+  template <typename I, typename F>
+  image_if<I,F>::image_if(I& ima, const F& f)
+  {
+    this->data_ = new internal::data_< image_if<I,F> >(ima, f);
+  }
+
   template <typename I, typename F>
   bool
   image_if<I,F>::owns_(const mln_psite(I)& p) const
   {
-    return pset_.has(p);
+    return data_->pset_.has(p);
   }
 
   template <typename I, typename F>
   const pset_if<mln_pset(I), F>&
   image_if<I,F>::domain() const
   {
-    return pset_;
+    return data_->pset_;
   }
 
   template <typename I, typename F>
   image_if<I,F>::operator image_if<const I, F>() const
   {
-    image_if<const I, F> tmp(this->adaptee_, this->f_);
+    image_if<const I, F> tmp(this->data_->ima_, this->data_->f_);
     return tmp;
   }
 
+
+  template <typename I, typename F>
+  typename image_if<I,F>::rvalue
+  image_if<I,F>::operator()(const psite& p) const
+  {
+    mln_precondition(exact(this)->owns_(p));
+    return data_->ima_(p);
+  }
+
+  template <typename I, typename F>
+  typename image_if<I,F>::lvalue
+  image_if<I,F>::operator()(const psite& p)
+  {
+    mln_precondition(exact(this)->owns_(p));
+    return data_->ima_(p);
+  }
+
+  template <typename I, typename F>
+  const mln_vset(I)&
+  image_if<I,F>::values() const
+  {
+    return data_->ima_.values();
+  }
 # endif // ! MLN_INCLUDE_ONLY
 
 } // end of namespace mln
Index: trunk/milena/mln/core/image3d_b.hh
===================================================================
--- trunk/milena/mln/core/image3d_b.hh	(revision 1154)
+++ trunk/milena/mln/core/image3d_b.hh	(revision 1155)
@@ -113,6 +113,9 @@
     // End of warning.
 
 
+    /// Parent type
+    typedef internal::image_primary_< box3d, image3d_b<T> > parent;
+
     /// Value associated type.
     typedef T         value;
 
@@ -194,6 +197,9 @@
 
     /// Give a hook to the value buffer.
     T* buffer();
+
+    /// To use the track pointer inherited.
+    using parent::data_;
   };
 
 
Index: trunk/milena/mln/value/stack.hh
===================================================================
--- trunk/milena/mln/value/stack.hh	(revision 1154)
+++ trunk/milena/mln/value/stack.hh	(revision 1155)
@@ -34,7 +34,6 @@
  */
 
 # include <mln/core/internal/image_base.hh>
-# include <mln/core/internal/tracked_ptr.hh>
 
 # include <mln/metal/vec.hh>
 # include <mln/value/set.hh>
@@ -44,16 +43,31 @@
 namespace mln
 {
 
-  namespace value
+  // Fwd decl.
+  namespace value { template <unsigned n, typename I> struct stack_image; }
+
+  namespace internal
   {
 
-    // Fwd decl.
-    template <unsigned n, typename I> struct stack_image;
 
+    /*! \brief data structure for stack_image
+     *
+     */
+    template <unsigned n, typename I>
+    struct data_< value::stack_image<n, I> >
+    {
+    public:
+      data_(const metal::vec<n,I>& imas);
+      metal::vec<n,I> imas_;
+    };
 
-    namespace internal
+  }
+
+  namespace value
     {
 
+    namespace internal
+    {
       template <unsigned n, typename I>
       struct helper_stack_image_lvalue_
       {
@@ -75,25 +89,9 @@
 	}
       };
 
-    } // end of namespace mln::value::internal
-
 
-    /*! \brief data structure for stack_image
-     *
-     */
-    template <unsigned n, typename I>
-    struct stack_image_data
-    {
-    public:
-      stack_image_data(const metal::vec<n,I>& imas);
-      metal::vec<n,I> imas_;
-    };
+    } // end of namespace mln::value::internal
 
-    template <unsigned n, typename I>
-    stack_image_data<n,I>::stack_image_data(const metal::vec<n,I>& imas)
-      : imas_(imas)
-    {
-    }
 
     /*! \brief FIXME
      *
@@ -101,6 +99,8 @@
     template <unsigned n, typename I>
     struct stack_image : public mln::internal::image_base_< mln_pset(I), stack_image<n,I> >
     {
+      typedef mln::internal::image_base_< mln_pset(I), stack_image<n,I> > parent;
+
       /// Point_Site associated type.
       typedef mln_psite(I) psite;
 
@@ -149,8 +149,7 @@
       /// Give the set of values of the image.
       const vset& values() const;
 
-    protected:
-      tracked_ptr< stack_image_data<n, I> > data_;
+      using parent::data_;
     };
 
 
@@ -164,10 +163,25 @@
     stack_image<2, I>
     stack(Image<I>& ima1, Image<I>& ima2);
 
-
+  } // end of namespace mln::value
 
 # ifndef MLN_INCLUDE_ONLY
 
+  namespace internal
+  {
+    // internal::data_< cast_image_<T,I> >
+
+    template <unsigned n, typename I>
+    data_< value::stack_image<n,I> >::data_(const metal::vec<n,I>& imas)
+      : imas_(imas)
+    {
+    }
+
+  } // end of namespace mln::internal
+
+
+  namespace value
+  {
     // stack_image<n, I>
 
     template <unsigned n, typename I>
@@ -178,7 +192,7 @@
     template <unsigned n, typename I>
     stack_image<n,I>::stack_image(const metal::vec<n,I>& imas)
     {
-      data_ = new stack_image_data<n,I>(imas);
+      data_ = new mln::internal::data_< stack_image<n, I> >(imas);
       for (unsigned i = 0; i < n; ++i)
       {
 	mln_precondition(imas[i].has_data());
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    21 Sep '07
                    
                        https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from  Thierry Geraud  <thierry.geraud(a)lrde.epita.fr>
	Fixes and add impl::init_with_ for two image2d_b and sub_image.
	* tests/core_clone.cc: New.
	* mln/core/point.hh: Fix.
	* mln/core/internal/image_base.hh (hook_data_): New.
	* mln/core/internal/image_morpher.hh: Fix typo.
	* mln/core/image2d_b.hh (init_with): Rename as...
	(init_with_): ...this.
	(init_with_): Inactivate version with image.
	(init_with_): New in impl.
	* mln/core/sub_image.hh (init_with_): New in impl.
	Update ctors.
	* mln/border/get.hh: Fix.
 mln/border/get.hh                  |    2 -
 mln/core/image2d_b.hh              |   51 +++++++++++++++++-----------
 mln/core/internal/image_base.hh    |    3 +
 mln/core/internal/image_morpher.hh |    2 -
 mln/core/point.hh                  |    4 +-
 mln/core/sub_image.hh              |   48 ++++++++++++++++++++++++--
 tests/core_clone.cc                |   67 +++++++++++++++++++++++++++++++++++++
 7 files changed, 149 insertions(+), 28 deletions(-)
Index: tests/core_clone.cc
--- tests/core_clone.cc	(revision 0)
+++ tests/core_clone.cc	(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.
+
+/*! \file tests/core_clone.cc
+ *
+ * \brief Tests on mln::clone.
+ */
+
+#include <mln/core/image2d_b.hh>
+#include <mln/core/sub_image.hh>
+
+#include <mln/debug/iota.hh>
+#include <mln/debug/println.hh>
+
+#include <mln/core/clone.hh>
+
+
+
+int main()
+{
+  using namespace mln;
+  image2d_b<int> ima(3, 3, 51);
+  debug::iota(ima);
+
+  {
+    box2d b = make::box2d(2,2);
+    std::cout << border::get( clone(ima | b) ) << std::endl;
+  }
+
+//   {
+//     image2d_b<int> ima_ = clone(ima);
+//     std::cout << ima_.border() << std::endl;
+//     ima_(make::point2d(1,1)) = 51;
+//     debug::println(ima);
+//   }
+  
+//   {
+//     image2d_b<int> ima_( ima );
+//     ima_(make::point2d(1,1)) = 51;
+//     debug::println(ima);
+//   }
+
+}
Index: mln/core/point.hh
--- mln/core/point.hh	(revision 1153)
+++ mln/core/point.hh	(working copy)
@@ -102,7 +102,7 @@
     typedef metal::vec<dim, C> vec_t;
 
     /// Hook to coordinates.
-    operator metal::vec<dim, C>() const;
+    operator metal::vec<M::dim, C>() const;
 
   protected:
     metal::vec<dim, C> coord_;
@@ -159,7 +159,7 @@
   }
 
   template <typename M, typename C>
-  point_<M,C>::operator metal::vec<dim, C>() const
+  point_<M,C>::operator metal::vec<M::dim, C>() const
   {
     return coord_;
   }
Index: mln/core/internal/image_base.hh
--- mln/core/internal/image_base.hh	(revision 1153)
+++ mln/core/internal/image_base.hh	(working copy)
@@ -171,6 +171,9 @@
       /// Copy constructor.
       image_base_(const image_base_& rhs);
 
+
+      const util::tracked_ptr< internal::data_<E> >& hook_data_() const { return data_; }
+
     protected:
       image_base_();
 
Index: mln/core/internal/image_morpher.hh
--- mln/core/internal/image_morpher.hh	(revision 1153)
+++ mln/core/internal/image_morpher.hh	(working copy)
@@ -110,7 +110,7 @@
     image_morpher_<I,S,E>::has_data() const
     {
       return
-	this->data != 0 &&
+	this->data_ != 0 &&
 	this->delegatee_() != 0 &&
 	this->delegatee_()->has_data();
     }
Index: mln/core/image2d_b.hh
--- mln/core/image2d_b.hh	(revision 1153)
+++ mln/core/image2d_b.hh	(working copy)
@@ -150,18 +150,18 @@
 
 
     /// Initialize an empty image.
-    void init_with(const box2d& b, unsigned bdr = border::thickness);
+    void init_with_(const box2d& b, unsigned bdr = border::thickness);
 
 
-    /// Initialize an empty image.
-    template <typename I>
-    void init_with(const Image<I>& other) // FIXME: Remove this soon obsolete code!
-    {
-      mln_precondition(this->data_ = 0);
-      mln_precondition(exact(other).has_data());
-      this->data_ = new internal::data_< image2d_b<T> >(exact(other).bbox(),
-							exact(other).border());
-    }
+//     /// Initialize an empty image.
+//     template <typename I>
+//     void init_with_(const Image<I>& other) // FIXME: Remove this soon obsolete code!
+//     {
+//       mln_precondition(this->data_ = 0);
+//       mln_precondition(exact(other).has_data());
+//       this->data_ = new internal::data_< image2d_b<T> >(exact(other).bbox(),
+// 							exact(other).border());
+//     }
 
 
     /// Test if \p p is valid.
@@ -217,13 +217,8 @@
   namespace impl
   {
 
-    template <typename T, typename I>
-    void init_with_(image2d_b<T>& target, const I& model)
-    {
-      box2d b = model.domain();
-      unsigned bdr = border::get(model);
-      target = image2d_b<T>(b, bdr);
-    }
+    template <typename T, typename J>
+    void init_with_(image2d_b<T>& target, const J& model);
     
   } // end of namespace mln::impl
 
@@ -232,6 +227,22 @@
 # ifndef MLN_INCLUDE_ONLY
 
 
+  // impl::init_with_
+
+  namespace impl
+  {
+
+    template <typename T, typename J>
+    void init_with_(image2d_b<T>& target, const J& model)
+    {
+      box2d b = model.bbox();
+      unsigned bdr = border::get(model);
+      target.init_with_(b, bdr);
+    }
+    
+  } // end of namespace mln::impl
+
+
   // internal::data_< image2d_b<T> >
 
   namespace internal
@@ -312,18 +323,18 @@
   template <typename T>
   image2d_b<T>::image2d_b(int nrows, int ncols, unsigned bdr)
   {
-    init_with(make::box2d(nrows, ncols), bdr);
+    init_with_(make::box2d(nrows, ncols), bdr);
   }
 
   template <typename T>
   image2d_b<T>::image2d_b(const box2d& b, unsigned bdr)
   {
-    init_with(b, bdr);
+    init_with_(b, bdr);
   }
 
   template <typename T>
   void
-  image2d_b<T>::init_with(const box2d& b, unsigned bdr)
+  image2d_b<T>::init_with_(const box2d& b, unsigned bdr)
   {
     mln_precondition(! this->has_data());
     this->data_ = new internal::data_< image2d_b<T> >(b, bdr);
Index: mln/core/sub_image.hh
--- mln/core/sub_image.hh	(revision 1153)
+++ mln/core/sub_image.hh	(working copy)
@@ -47,14 +47,15 @@
     {
       data_(I& ima, const S& pset);
 
-      I& ima_;
-      const S& pset_;
+      I ima_;
+      S pset_;
     };
 
   } // end of namespace mln::internal
 
 
 
+
   // FIXME: Doc!
 
   template <typename I, typename S>
@@ -69,6 +70,9 @@
     /// Constructor.
     sub_image(I& ima, const S& pset);
 
+    /// Initialization.
+    void init_with_(I& ima, const S& pset);
+
     /// Give the definition domain.
     const S& domain() const;
 
@@ -78,6 +82,7 @@
 
 
 
+
   template <typename I, typename S>
   sub_image<const I, S> operator|(const Image<I>& ima, const Point_Set<S>& pset);
 
@@ -86,8 +91,35 @@
 
 
 
+  namespace impl
+  {
+
+    template <typename I, typename S, typename J>
+    void init_with_(sub_image<I,S>& target, const J& model);
+    
+  } // end of namespace mln::impl
+
+
+
 # ifndef MLN_INCLUDE_ONLY
 
+  // impl::init_with_
+
+  namespace impl
+  {
+
+    template <typename I, typename S, typename J>
+    void init_with_(sub_image<I,S>& target, const J& model)
+    {
+      I ima;
+      init_with_(ima, model); // rec
+      S pset = model.domain();
+      target.init_with_(ima, pset);
+    }
+    
+  } // end of namespace mln::impl
+
+
   // internal::data_< sub_image<I,S> >
 
   namespace internal
@@ -106,14 +138,22 @@
   // sub_image<I,S>
 
   template <typename I, typename S>
+  sub_image<I,S>::sub_image()
+  {
+  }
+
+  template <typename I, typename S>
   sub_image<I,S>::sub_image(I& ima, const S& pset)
   {
-    this->data_ = new internal::data_< sub_image<I,S> >(ima, pset);
+    init_with_(ima, pset);
   }
 
   template <typename I, typename S>
-  sub_image<I,S>::sub_image()
+  void
+  sub_image<I,S>::init_with_(I& ima, const S& pset)
   {
+    mln_precondition(! this->has_data());
+    this->data_ = new internal::data_< sub_image<I,S> >(ima, pset);
   }
 
   template <typename I, typename S>
Index: mln/border/get.hh
--- mln/border/get.hh	(revision 1153)
+++ mln/border/get.hh	(working copy)
@@ -59,7 +59,7 @@
       template <typename I, typename S, typename E>
       unsigned get__(const mln::internal::image_morpher_<I,S,E>& ima)
       {
-	return border::get(ima.delegatee_());
+	return border::get(*ima.delegatee_());
       }
 
       template <typename S, typename E>
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from  Thierry Geraud  <thierry.geraud(a)lrde.epita.fr>
	Update of clone and impl::init_with_ mechanism.
	* mln/core/internal/image_base.hh (init_with_): New.
	(operator=, image_base_): New.
	* mln/core/image2d_b.hh: Remove op=, dtor, and cpy ctor.
	(init_with_): New overload.
	(init_with): Remove overload with nrows-ncols.
	* mln/core/sub_image.hh: New ctor.
	* mln/core/clone.hh: Update.
	* mln/border/get.hh: New.
 border/get.hh               |  102 ++++++++++++++++++++++++++++++++++++++++++++
 core/clone.hh               |   33 +++-----------
 core/image2d_b.hh           |   66 ++++++----------------------
 core/internal/image_base.hh |   40 ++++++++++++++++-
 core/sub_image.hh           |    8 +++
 5 files changed, 174 insertions(+), 75 deletions(-)
Index: mln/core/internal/image_base.hh
--- mln/core/internal/image_base.hh	(revision 1152)
+++ mln/core/internal/image_base.hh	(working copy)
@@ -55,11 +55,22 @@
   } // end of namespace mln::internal
 
 
+  namespace impl
+  {
+
+    /// Declaration of the general image initialization routine.
+    template <typename I, typename J>
+    void init_with_(Image<I>& target, const Image<J>& model);
+
+    // FIXME: Say more about it!
+
+  } // end of namespace mln::impl
+
+
 
   namespace internal
   {
 
-
     /*! \brief Return the lvalue type when an image with type \c I is
      *  morphed.
      *
@@ -153,13 +164,22 @@
 
       // FIXME: Add void init_data(..);
 
+
+      /// Assignment operator.
+      image_base_& operator=(const image_base_& rhs);
+
+      /// Copy constructor.
+      image_base_(const image_base_& rhs);
+
     protected:
       image_base_();
 
+      // Internal data, sharable by several images.
       util::tracked_ptr< internal::data_<E> > data_;
     };
 
 
+
 # ifndef MLN_INCLUDE_ONLY
 
     template <typename S, typename E>
@@ -168,6 +188,24 @@
     }
 
     template <typename S, typename E>
+    image_base_<S,E>::image_base_(const image_base_& rhs)
+    {
+      mln_precondition(exact(rhs).has_data()); // FIXME: Is-it too restrictive?
+      this->data_ = rhs.data_;
+    }
+
+    template <typename S, typename E>
+    image_base_<S,E>&
+    image_base_<S,E>::operator=(const image_base_<S,E>& rhs)
+    {
+      mln_precondition(exact(rhs).has_data()); // FIXME: Is-it too restrictive?
+      if (& rhs = this) // || ! exact(rhs).has_data())
+	return *this;
+      this->data_ = rhs.data_;
+      return *this;
+    }
+
+    template <typename S, typename E>
     bool
     image_base_<S,E>::has_data() const
     {
Index: mln/core/image2d_b.hh
--- mln/core/image2d_b.hh	(revision 1152)
+++ mln/core/image2d_b.hh	(working copy)
@@ -40,6 +40,8 @@
 # include <mln/value/set.hh>
 # include <mln/fun/i2v/all.hh>
 # include <mln/core/line_piter.hh>
+# include <mln/border/get.hh>
+# include <mln/debug/println.hh>
 
 // FIXME:
 
@@ -142,23 +144,12 @@
     /// 3).
     image2d_b(const box2d& b, unsigned bdr = border::thickness);
 
-    /// Copy constructor.
-    image2d_b(const image2d_b<T>& rhs);
 
-    /// Assignment operator.
-    image2d_b& operator=(const image2d_b<T>& rhs);
-
-    /// Destructor.
-    ~image2d_b();
-
-    /// detach data from an image (free it if nobody else hold it)
+    /// Detach data from an image (free it if nobody else hold it).
     void destroy();
 
 
     /// Initialize an empty image.
-    void init_with(int nrows, int ncols, unsigned bdr = border::thickness);
-
-    /// Initialize an empty image.
     void init_with(const box2d& b, unsigned bdr = border::thickness);
 
 
@@ -220,12 +211,21 @@
 
     /// Give a hook to the value buffer.
     T* buffer();
+  };
 
 
-  private:
+  namespace impl
+  {
 
-    typedef internal::image_base_< box2d, image2d_b<T> > super;
-  };
+    template <typename T, typename I>
+    void init_with_(image2d_b<T>& target, const I& model)
+    {
+      box2d b = model.domain();
+      unsigned bdr = border::get(model);
+      target = image2d_b<T>(b, bdr);
+    }
+    
+  } // end of namespace mln::impl
 
 
 
@@ -312,15 +312,7 @@
   template <typename T>
   image2d_b<T>::image2d_b(int nrows, int ncols, unsigned bdr)
   {
-    init_with(nrows, ncols, bdr);
-  }
-
-  template <typename T>
-  void
-  image2d_b<T>::init_with(int nrows, int ncols, unsigned bdr)
-  {
-    mln_precondition(! this->has_data());
-    this->data_ = new internal::data_< image2d_b<T> >(make::box2d(nrows, ncols), bdr);
+    init_with(make::box2d(nrows, ncols), bdr);
   }
 
   template <typename T>
@@ -338,27 +330,6 @@
   }
 
   template <typename T>
-  image2d_b<T>::image2d_b(const image2d_b<T>& rhs)
-  {
-  }
-
-  // assignment
-
-  template <typename T>
-  image2d_b<T>&
-  image2d_b<T>::operator=(const image2d_b<T>& rhs)
-  {
-    mln_precondition(rhs.has_data());
-    if (& rhs = this)
-      return *this;
-
-    this->data_ = rhs.data_;
-    return *this;
-  }
-
-  // methods
-
-  template <typename T>
   const typename image2d_b<T>::vset&
   image2d_b<T>::values() const
   {
@@ -446,11 +417,6 @@
   }
 
   template <typename T>
-  image2d_b<T>::~image2d_b()
-  {
-  }
-
-  template <typename T>
   const T*
   image2d_b<T>::buffer() const
   {
Index: mln/core/sub_image.hh
--- mln/core/sub_image.hh	(revision 1152)
+++ mln/core/sub_image.hh	(working copy)
@@ -63,6 +63,9 @@
     /// Skeleton.
     typedef sub_image< tag::image<I>, tag::pset<S> > skeleton;
 
+    /// Constructor without argument.
+    sub_image();
+
     /// Constructor.
     sub_image(I& ima, const S& pset);
 
@@ -109,6 +112,11 @@
   }
 
   template <typename I, typename S>
+  sub_image<I,S>::sub_image()
+  {
+  }
+
+  template <typename I, typename S>
   const S&
   sub_image<I,S>::domain() const
   {
Index: mln/core/clone.hh
--- mln/core/clone.hh	(revision 1152)
+++ mln/core/clone.hh	(working copy)
@@ -34,6 +34,7 @@
  */
 
 # include <mln/core/concept/image.hh>
+# include <mln/level/fill.hh>
 
 
 namespace mln
@@ -41,40 +42,24 @@
 
   /*! Clone the image \p ima with the values of the image \p data.
    *
-   * \param[in,out] ima The image to be cloneed.
-   * \param[in] data The image.
+   * \param[in] ima The image to be cloneed.
+   * \result The clone.
    *
-   * \warning The definition domain of \p ima has to be included in
-   * the one of \p data.
-   *
-   * \pre \p ima.domain <= \p data.domain.
-   *
-   * \todo Use memcpy when possible.
+   * \pre ima.has_data
    */
   template <typename I>
-  mln_concrete(I) clone(const Image<I>& ima);
-
+  mln_concrete(I) clone(const Image<I>& model);
 
 
 # ifndef MLN_INCLUDE_ONLY
 
-  namespace impl
-  {
-
-    template <typename I>
-    void clone_(mln_concrete(I)& result, const Image<I>& ima)
-    {
-      std::cerr << "oops" << std::endl; // FIXME: Fake code.
-    }    
-
-  } // end of namespace mln::impl
-
-
   template <typename I>
-  mln_concrete(I) clone(const Image<I>& ima)
+  mln_concrete(I) clone(const Image<I>& model)
   {
+    // FIXME: Add a static check that mln_concrete(I) actually *is* concrete...
     mln_concrete(I) tmp;
-    impl::clone_(ima, tmp);
+    impl::init_with_(tmp, exact(model));
+    level::fill(tmp, model);
     return tmp;
   }
 
Index: mln/border/get.hh
--- mln/border/get.hh	(revision 0)
+++ mln/border/get.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_BORDER_GET_HH
+# define MLN_BORDER_GET_HH
+
+/*! \file mln/border/get.hh
+ *
+ * \brief FIXME.
+ */
+
+# include <mln/core/internal/image_morpher.hh>
+
+
+namespace mln
+{
+
+  namespace border
+  {
+
+    /*! Get the virtual (outer) border thickness of image \p ima.
+     *
+     * \param[in] ima The image.
+     * \result The border thickness (0 if there is no border).
+     */
+    template <typename I>
+    unsigned get(const Image<I>& ima);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    namespace impl
+    {
+
+      template <typename I, typename S, typename E>
+      unsigned get__(const mln::internal::image_morpher_<I,S,E>& ima)
+      {
+	return border::get(ima.delegatee_());
+      }
+
+      template <typename S, typename E>
+      unsigned get__(const mln::internal::image_base_<S,E>& ima)
+      {
+	return 0;
+      }
+
+      template <typename I>
+      unsigned get_(const Image<I>& ima)
+      {
+	return border::impl::get__(exact(ima));
+      }
+
+      template <typename I>
+      unsigned get_(const Fast_Image<I>& ima)
+      {
+	return exact(ima).border();
+      }
+
+    } // end of namespace mln::border::impl
+
+
+    // Facade.
+
+    template <typename I>
+    unsigned get(const Image<I>& ima)
+    {
+      mln_precondition(exact(ima).has_data());
+      return border::impl::get_(exact(ima));
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::border
+
+} // end of namespace mln
+
+
+#endif // ! MLN_BORDER_GET_HH
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                          URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2007-09-21  Simon Nivault  <simon.nivault(a)lrde.epita.fr>
	A point can be considered as a metal::vec
	* mln/core/point.hh: Update.
	* tests/point2d.cc: (operator vec()).
---
 mln/core/point.hh |   14 +++++++++++---
 tests/point2d.cc  |    3 +++
 2 files changed, 14 insertions(+), 3 deletions(-)
Index: trunk/milena/tests/point2d.cc
===================================================================
--- trunk/milena/tests/point2d.cc	(revision 1151)
+++ trunk/milena/tests/point2d.cc	(revision 1152)
@@ -30,6 +30,7 @@
  * \brief Tests on mln::point2d.
  */
 
+#include <iostream>
 #include <mln/core/point2d.hh>
 
 
@@ -56,4 +57,6 @@
   q.set_all(0);
   for (unsigned i = 0; i < p.dim; ++i)
     mln_assertion(q[i] == 0);
+
+  std::cout << 3.4 * metal::vec<2, int>(p) << std::endl;
 }
Index: trunk/milena/mln/core/point.hh
===================================================================
--- trunk/milena/mln/core/point.hh	(revision 1151)
+++ trunk/milena/mln/core/point.hh	(revision 1152)
@@ -36,6 +36,7 @@
 # include <mln/core/concept/point.hh>
 # include <mln/core/internal/coord_impl.hh>
 # include <mln/fun/i2v/all.hh>
+# include <mln/metal/vec.hh>
 
 
 namespace mln
@@ -98,13 +99,13 @@
     point_<M,C>& operator+=(const dpoint& dp);
 
     /// Type of the array of coordinates.
-    typedef const C (&vec_t)[dim];
+    typedef metal::vec<dim, C> vec_t;
 
     /// Hook to coordinates.
-    vec_t to_vec() const { return coord_; }
+    operator metal::vec<dim, C>() const;
 
   protected:
-    C coord_[dim];
+    metal::vec<dim, C> coord_;
   };
 
 
@@ -157,6 +158,13 @@
     return *this;
   }
 
+  template <typename M, typename C>
+  point_<M,C>::operator metal::vec<dim, C>() const
+  {
+    return coord_;
+  }
+
+
 # endif // ! MLN_INCLUDE_ONLY
   
 } // end of namespace mln
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                          URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2007-09-21  Simon Nivault  <simon.nivault(a)lrde.epita.fr>
	Add quaternion based on vector 4d
	* mln/metal/vec.hh: Add sprod, vprod and normalize.
	* mln/norm/l2.hh: New, Works on C-tabs and on metal::vec.
	* mln/value/quat.hh: New.
	* tests/norm_l2.cc: New.
	* tests/value_quat.cc: New.
---
 mln/metal/vec.hh    |  117 +++++++++++++++++
 mln/norm/l2.hh      |  111 ++++++++++++++++
 mln/value/quat.hh   |  343 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/norm_l2.cc    |   54 ++++++++
 tests/value_quat.cc |   72 ++++++++++
 5 files changed, 694 insertions(+), 3 deletions(-)
Index: trunk/milena/tests/value_quat.cc
===================================================================
--- trunk/milena/tests/value_quat.cc	(revision 0)
+++ trunk/milena/tests/value_quat.cc	(revision 1151)
@@ -0,0 +1,72 @@
+// 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/value_int_u8.cc
+ *
+ * \brief Tests on mln::value::int_u8.
+ */
+
+#include <iostream>
+
+#include <mln/value/quat.hh>
+
+
+int main()
+{
+  using namespace mln;
+
+  value::quat q1(3.f, 4.f, 1.6f, 0.5f);
+  value::quat q2(1.2, make::vec(3, 6, 4));
+  value::quat q3(make::vec(1.3, 3., -6., 4.));
+
+  std::cout << q1 << std::endl;
+  std::cout << q2 << std::endl;
+  std::cout << q3 << std::endl;
+
+  std::cout << q1.scal() << std::endl;
+
+  q1.set_scal(2.6);
+  std::cout << q1 << std::endl;
+
+  std::cout << q1.vect() << std::endl;
+
+  q2.set_vect(make::vec(1.4, 5.9, 3.1));
+  std::cout << q2 << std::endl;
+
+  std::cout << q2 * q3 << std::endl;
+
+  mln_assertion(!q3.is_unit());
+  q3.set_unit();
+  std::cout << q3 << std::endl;
+  mln_assertion(q3.is_unit());
+
+  std::cout << q2.conj() << std::endl;
+  std::cout << q2.inv() << std::endl;
+  std::cout << norm::l2(q2) << ' ' << norm::l2(q2.inv()) << std::endl;
+  std::cout << q2.inv().inv() << std::endl;
+
+}
Index: trunk/milena/tests/norm_l2.cc
===================================================================
--- trunk/milena/tests/norm_l2.cc	(revision 0)
+++ trunk/milena/tests/norm_l2.cc	(revision 1151)
@@ -0,0 +1,54 @@
+// 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/norm_l2.cc
+ *
+ * \brief Tests on mln::norm::l2.
+ */
+
+#include <iostream>
+
+#include <mln/norm/l2.hh>
+
+#include <mln/metal/vec.hh>
+
+int main()
+{
+  using namespace mln;
+  
+  int t1[] = {2, 6, -1, 2};
+
+  std::cout << norm::l2(t1) << std::endl;
+
+  int t2[] = {2, -6, -1, 2};
+
+  std::cout << norm::l2_distance(t1, t2) << std::endl;
+
+  metal::vec<4,float> v = make::vec(2, 6, -1, 2);
+
+  std::cout << norm::l2(v);
+}
Index: trunk/milena/mln/metal/vec.hh
===================================================================
--- trunk/milena/mln/metal/vec.hh	(revision 1150)
+++ trunk/milena/mln/metal/vec.hh	(revision 1151)
@@ -29,6 +29,7 @@
 # define MLN_METAL_VEC_HH
 
 # include <iostream>
+# include <cmath>
 
 # include <mln/core/contract.hh>
 # include <mln/metal/binary_arith_trait.hh>
@@ -140,10 +141,84 @@
 
       void set_all(const T& val);
 
+      T sprod(const vec<n, T>& rhs) const;
+
       unsigned size() const;
 
+      const vec<n, T>& normalize();
   };
 
+    // eq
+
+    template <unsigned n, typename T, typename U>
+    bool operator==(const vec<n,T>& lhs, const vec<n,U>& rhs);
+
+    template <unsigned n, typename T, typename U>
+    bool operator!=(const vec<n,T>& lhs, const vec<n,U>& rhs);
+
+    // +
+
+    template <unsigned n, typename T, typename U>
+    vec<n,T>&
+    operator+=(vec<n,T>& lhs, const vec<n,U>& rhs);
+    
+    template <unsigned n, typename T, typename U>
+    vec<n, typename binary_arith_trait<T,U>::ret >
+    operator+(const vec<n,T>& lhs, const vec<n,U>& rhs);
+    
+    // -
+    
+    template <unsigned n, typename T, typename U>
+    vec<n,T>&
+    operator-=(vec<n,T>& lhs, const vec<n,U>& rhs);
+    
+    template <unsigned n, typename T, typename U>
+    vec<n, typename binary_arith_trait<T,U>::ret>
+    operator-(const vec<n,T>& lhs, const vec<n,U>& rhs);
+    
+    template <unsigned n, typename T>
+    vec<n, T>
+    operator-(const vec<n,T>& lhs);
+    
+    // *
+    
+    template <unsigned n, typename T, typename S>
+    vec<n,T>&
+    operator*=(vec<n,T>& lhs, const S& scalar);
+    
+    template <unsigned n, typename T, typename S>
+    vec<n, typename binary_arith_trait<T,S>::ret>
+    operator*(const S& scalar, const vec<n,T>& lhs);
+    
+    // /
+    
+    template <unsigned n, typename T, typename S>
+    vec<n,T>&
+    operator/=(vec<n,T>& lhs, const S& scalar);
+    
+    template <unsigned n, typename T, typename S>
+    vec<n, typename binary_arith_trait<T,S>::ret>
+    operator/(const vec<n,T>& lhs, const S& scalar);
+    
+    // <<
+    
+    template <unsigned n, typename T>
+    std::ostream&
+    operator<<(std::ostream& ostr, const vec<n,T>& v);
+
+    template <unsigned n>
+    std::ostream&
+    operator<<(std::ostream& ostr, const vec<n,unsigned char>& v);
+    
+    template <unsigned n>
+    std::ostream&
+    operator<<(std::ostream& ostr, const vec<n,signed char>& v);
+
+    // vprod
+
+    template <typename T, typename U>
+    vec<3, typename binary_arith_trait<T, U>::ret>
+    vprod(const vec<3, T>& lhs, const vec<3, U>& rhs);
 
 # ifndef MLN_INCLUDE_ONLY
 
@@ -193,11 +268,33 @@
     }
 
     template <unsigned n, typename T>
+    T vec<n,T>::sprod(const vec<n, T>& rhs) const
+    {
+      T tmp = 0;
+
+      for (unsigned i = 0; i < n; ++i)
+	tmp += data_[i] * rhs.data_[i];
+      return tmp;
+    }
+
+    template <unsigned n, typename T>
     unsigned vec<n,T>::size() const
     {
       return n;
     }
 
+    template <unsigned n, typename T>
+    const vec<n, T>& vec<n, T>::normalize()
+    {
+      float n_l2 = 0;
+      for (unsigned i = 0; i < n; ++i)
+	n_l2 += data_[i] * data_[i];
+      n_l2 = sqrt(n_l2);
+      for (unsigned i = 0; i < n; ++i)
+	data_[i] = T(data_[i] / n_l2);
+      return *this;
+    }
+
 
     // eq
 
@@ -284,7 +381,7 @@
     
     template <unsigned n, typename T, typename S>
     vec<n, typename binary_arith_trait<T,S>::ret>
-    operator*(const vec<n,T>& lhs, const S& scalar)
+    operator*(const S& scalar, const vec<n,T>& lhs)
     {
       vec<n, typename binary_arith_trait<T,S>::ret> tmp;
       for (unsigned i = 0; i < n; ++i)
@@ -299,7 +396,7 @@
     vec<n,T>&
     operator/=(vec<n,T>& lhs, const S& scalar)
     {
-      precondition(scalar != 0);
+      mln_precondition(scalar != 0);
       for (unsigned i = 0; i < n; ++i)
 	lhs[i] /= scalar;
       return lhs;
@@ -309,7 +406,7 @@
     vec<n, typename binary_arith_trait<T,S>::ret>
     operator/(const vec<n,T>& lhs, const S& scalar)
     {
-      precondition(scalar != 0);
+      mln_precondition(scalar != 0);
       vec<n, typename binary_arith_trait<T,S>::ret> tmp;
       for (unsigned i = 0; i < n; ++i)
 	tmp[i] = lhs[i] / scalar;
@@ -349,6 +446,20 @@
       return ostr;
     }
     
+    // vprod
+
+    template <typename T, typename U>
+    vec<3, typename binary_arith_trait<T, U>::ret>
+    vprod(const vec<3, T>& lhs, const vec<3, U>& rhs)
+    {
+      vec<3, typename binary_arith_trait<T, U>::ret> tmp;
+      tmp[0] = lhs[1] * rhs[2] - lhs[2] * rhs[1];
+      tmp[1] = lhs[2] * rhs[0] - lhs[0] * rhs[2];
+      tmp[2] = lhs[0] * rhs[1] - lhs[1] * rhs[0];
+      return tmp;
+    }
+
+    
     
 # endif // MLN_INCLUDE_ONLY
     
Index: trunk/milena/mln/norm/l2.hh
===================================================================
--- trunk/milena/mln/norm/l2.hh	(revision 0)
+++ trunk/milena/mln/norm/l2.hh	(revision 1151)
@@ -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_NORM_L2_HH
+# define MLN_NORM_L2_HH
+
+/*! \file mln/norm/l2.hh
+ *
+ * \brief Define some infinity-norm related routines.
+ */
+
+# include <cmath>
+
+# include <mln/metal/vec.hh>
+
+namespace mln
+{
+
+  namespace norm
+  {
+
+    /// Infinity-norm of a vector \p vec.
+    template <unsigned n, typename C>
+    float l2(const C (&vec)[n]);
+
+    /// Infinity-norm distance between vectors \p v1 and \p v2.
+    template <unsigned n, typename C>
+    float l2_distance(const C (&v1)[n], const C (&v2)[n]);
+
+    template <unsigned n, typename C>
+    float l2(const metal::vec<n,C>& vec);
+
+    template <unsigned n, typename C>
+    float l2_distance(const metal::vec<n,C>& vec1, const metal::vec<n,C>& vec2);
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <unsigned n, typename C>
+    float l2(const C (&vec)[n])
+    {
+      C c = 0;
+      for (unsigned i = 0; i < n; ++i)
+	c += vec[i] * vec[i];
+      return sqrt(c);
+    }
+
+    template <unsigned n, typename C>
+    float l2_distance(const C (&v1)[n], const C (&v2)[n])
+    {
+      C d = 0;
+      for (unsigned i = 0; i < n; ++i)
+      {
+	C dd = v1[i] - v2[i];
+	d += dd * dd;
+      }
+      return sqrt(d);
+    }
+
+    template <unsigned n, typename C>
+    float l2(const metal::vec<n,C>& vec)
+    {
+      C c = 0;
+      for (unsigned i = 0; i < n; ++i)
+	c += vec[i] * vec[i];
+      return sqrt(c);
+    }
+
+    template <unsigned n, typename C>
+    float l2(const metal::vec<n,C>& vec1, const metal::vec<n,C>& vec2)
+    {
+      C d = 0;
+      for (unsigned i = 0; i < n; ++i)
+      {
+	C dd = vec1[i] - vec2[i];
+	d += dd * dd;
+      }
+      return sqrt(d);
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::norm
+
+} // end of namespace mln
+
+
+#endif // ! MLN_NORM_L2_HH
Index: trunk/milena/mln/value/quat.hh
===================================================================
--- trunk/milena/mln/value/quat.hh	(revision 0)
+++ trunk/milena/mln/value/quat.hh	(revision 1151)
@@ -0,0 +1,343 @@
+// 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_QUAT_HH
+# define MLN_VALUE_QUAT_HH
+
+# include <cmath>
+
+# include <mln/metal/vec.hh>
+# include <mln/norm/l2.hh>
+# include <mln/value/props.hh>
+
+namespace mln
+{
+
+  namespace value
+  {
+
+    class quat : public metal::vec<4, float>
+    {
+      public:
+
+	// ctors
+
+	quat();
+	quat(float s, float x, float y, float z);
+
+	template <typename T>
+	quat(float s, const metal::vec<3,T>& v);
+
+	template <typename T>
+	quat(const metal::vec<4,T>& v);
+
+	// accessors/modifiers as a 'scalar+metal::vec<3>'
+
+	float scal() const;
+	void set_scal(float s);
+
+	metal::vec<3,float> vect() const;
+	void set_vect(float x, float y, float z);
+	template <typename T>
+	void set_vect(const metal::vec<3,T>& v);
+
+	// multiplication
+
+	quat operator*(const quat& rhs) const;
+
+	// tests
+
+	bool is_unit() const;
+	bool is_null() const;
+
+	// conjugate and invert
+
+	quat conj() const;
+	quat inv() const;
+
+	// transform into unit quaternion
+
+	quat& set_unit();
+	template <typename T>
+	void set_unit(float theta, const metal::vec<3,T>& uv);
+
+	// only for unit quaternions described by theta and uv such as:
+	// q = ( cos(theta), sin(theta) * uv )
+
+	template <typename T>
+	quat(unsigned one, float theta, const metal::vec<3, T>& uv);
+
+	float theta() const;
+	void set_theta(float theta);
+
+	metal::vec<3, float> uvect() const;
+	template <typename T>
+	void set_uvect(const metal::vec<3,T>& uv);
+
+    };
+
+    // overloaded math procs
+
+    quat log(const quat& q);
+    quat exp(const quat& q);
+    quat pow(const quat& q, double t);
+    template <typename T>
+    bool about_equal(const T& f, const T& q);
+    bool about_equal(const quat& p, const quat& q);
+
+
+    // meths and procs bodies...
+
+# ifndef MLN_INCLUDE_ONLY
+
+    //ctors
+
+
+    quat::quat()
+    {
+    }
+
+    quat::quat(float s, float x, float y, float z)
+    {
+      set_scal(s);
+      set_vect(x, y, z);
+    }
+
+    template <typename T>
+    quat::quat(float s, const metal::vec<3,T>& v)
+    {
+      set_scal(s);
+      set_vect(v);
+    }
+
+    template <typename T>
+    quat::quat(const metal::vec<4,T>& v)
+      : metal::vec<4,float>(v)
+    {
+    }
+
+
+    // accessors/modifiers as a 'scalar+vec<3>'
+
+
+    float quat::scal() const
+    {
+      return data_[0];
+    }
+
+
+    void quat::set_scal(float s)
+    {
+      data_[0] = s;
+    }
+
+
+    metal::vec<3, float> quat::vect() const
+    {
+      return make::vec(data_[1], data_[2], data_[3]);
+    }
+
+
+    void quat::set_vect(float x, float y, float z)
+    {
+      data_[1] = x;
+      data_[2] = y;
+      data_[3] = z;
+    }
+
+    template <typename T>
+    void quat::set_vect(const metal::vec<3,T>& v)
+    {
+      set_vect(v[0], v[1], v[2]);
+    }
+
+
+    // multiplication
+
+
+    quat quat::operator*(const quat& rhs) const
+    {
+      float
+	s1 = scal(),
+	s2 = rhs.scal();
+
+      metal::vec<3,float>
+	v1 = vect(),
+	v2 = rhs.vect();
+
+      return quat(s1 * s2 - v1.sprod(v2),
+		  metal::vprod(v1, v2)
+		  + s1 * v2 + s2 * v1);
+    }
+
+
+    // tests
+
+
+    bool quat::is_unit() const
+    {
+      return about_equal(norm::l2(*this), 1.f);
+    }
+
+
+    bool quat::is_null() const
+    {
+      return about_equal(norm::l2(*this), 0.f);
+    }
+
+
+    // conjugate and invert
+
+
+    quat quat::conj() const
+    {
+      return quat(scal(), - vect());
+    }
+
+
+    quat quat::inv() const
+    {
+      assert(! is_null());
+      float f = norm::l2(*this);
+
+      return conj() / (f * f);
+    }
+
+
+    // transform into unit quaternion
+
+
+    quat& quat::set_unit()
+    {
+      normalize();
+      return *this;
+    }
+
+
+    template <typename T>
+    void quat::set_unit(float theta, const metal::vec<3,T>& uv)
+    {
+      static const float pi = 3.14159265358979323846;
+
+      mln_precondition(theta > - pi - props<float>::epsilon()
+		       && theta < pi + props<float>::epsilon());
+      mln_precondition(about_equal(norm::l2(uv), 1.f));
+
+      data_[0] = cos(theta);
+      float sint = sin(theta);
+      data_[1] = uv[0] * sint;
+      data_[2] = uv[1] * sint;
+      data_[3] = uv[2] * sint;
+    }
+
+    // only for unit quaternions described by theta and uv such as:
+    // q = ( cos(theta), sin(theta) * uv )
+
+
+    template <typename T>
+    quat::quat(unsigned one, float theta, const metal::vec<3,T>& uv)
+    {
+      mln_precondition(one == 1);
+      set_unit(theta, uv);
+    }
+
+
+    float quat::theta() const
+    {
+      mln_precondition(is_unit());
+      return acos(scal());
+    }
+
+
+    void quat::set_theta(float theta)
+    {
+      mln_precondition(is_unit());
+      set_unit(theta, uvect());
+    }
+
+    metal::vec<3, float> quat::uvect() const
+    {
+      mln_precondition(is_unit());
+      metal::vec<3, float> v = vect();
+      return v.normalize();
+    }
+
+    template <typename T>
+    void quat::set_uvect(const metal::vec<3,T>& uv)
+    {
+      mln_precondition(is_unit());
+      set_unit(theta(), uv);
+    }
+
+
+    // overloaded math procs
+
+
+    quat log(const quat& q)
+    {
+      mln_precondition(q.is_unit());
+      return quat(0.f, q.theta() * q.uvect());
+    }
+
+
+    quat exp(const quat& q)
+    {
+      mln_precondition(about_equal(q.scal(), 0.f));
+      metal::vec<3, float> v = q.vect();
+      float theta = norm::l2(v);
+      mln_precondition(!about_equal(theta, 0.f));
+      metal::vec<3, float> uv = v / theta;
+      return quat(cos(theta), sin(theta) * uv);
+    }
+
+
+    quat pow(const quat& q, double t)
+    {
+      mln_precondition(q.is_unit());
+      return exp(t * log(q));
+    }
+
+    template <typename T>
+    bool about_equal(const T& f, const T& q)
+    {
+      if (f > q)
+	return (f - q ) < props<T>::epsilon();
+      return (q - f) < props<T>::epsilon();
+    }
+
+    bool about_equal(const quat& p, const quat& q)
+    {
+      return about_equal<float>(norm::l2(p - q), 0);
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::value
+
+} // end of namespace mln
+
+#endif // ! MLN_VALUE_QUAT_HH
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from  Thierry Geraud  <thierry.geraud(a)lrde.epita.fr>
	Make some image types share data.
	New stuff.
	* mln/core/internal/image_base.hh (data_): New.
	* mln/core/internal/image_morpher.hh (has_data): New.
	* mln/core/internal/image_primary.hh: New.
	* mln/core/clone.hh: New.
	* mln/core/window.hh: Add check.
	Split client image structure and image data.
	* mln/pw/image.hh,
	* mln/core/cast_image.hh,
	* mln/core/sub_image.hh,
	* mln/core/image1d_b.hh,
	* mln/core/image2d_b.hh,
	* mln/core/image3d_b.hh (data_): New.
	Update.
	Clean-up.
	* mln/core/internal/tracked_ptr.hh: Rename as...
	* mln/util/tracked_ptr.hh: ...this.
	(util): Add.
	* mln/core/internal/image_adaptor.hh,
	* mln/core/internal/image_value_morpher.hh (has_data),
	* mln/core/image1d_b_data.hh,
	* mln/core/image2d_b_data.hh,
	* mln/core/image3d_b_data.hh: Remove; obsolete.
 core/cast_image.hh                   |   62 ++++++++----
 core/clone.hh                        |   86 ++++++++++++++++
 core/image1d_b.hh                    |  180 ++++++++++++++++++-----------------
 core/image2d_b.hh                    |  164 +++++++++++++++++++++++--------
 core/image3d_b.hh                    |  175 ++++++++++++++++++++--------------
 core/internal/image_base.hh          |   30 +++++
 core/internal/image_morpher.hh       |   27 +++--
 core/internal/image_primary.hh       |   72 ++++++++++++++
 core/internal/image_value_morpher.hh |    9 -
 core/sub_image.hh                    |   72 ++++++++------
 core/window.hh                       |    2 
 pw/image.hh                          |   89 ++++++++---------
 util/tracked_ptr.hh                  |   21 +++-
 13 files changed, 671 insertions(+), 318 deletions(-)
Index: mln/pw/image.hh
--- mln/pw/image.hh	(revision 1149)
+++ mln/pw/image.hh	(working copy)
@@ -33,9 +33,8 @@
  * \brief Definition of an image class FIXME
  */
 
-# include <mln/core/internal/image_base.hh>
+# include <mln/core/internal/image_primary.hh>
 # include <mln/core/concept/function.hh>
-# include <mln/core/internal/tracked_ptr.hh>
 # include <mln/value/set.hh>
 
 
@@ -52,51 +51,39 @@
    */
   template <typename F, typename S>
   pw::image<F,S>
-
   operator | (const Function_p2v<F>& f, const Point_Set<S>& ps);
 
 
 
-  namespace pw
+  namespace internal
   {
 
-    /*! \brief data structure for pw::image
-     *
-     */
+    /// Data structure for mln::pw::image
     template <typename F, typename S>
-    struct image_data
+    struct data_< mln::pw::image<F,S> >
     {
-    public:
-      image_data(const Function_p2v<F>& f, const Point_Set<S>& ps);
+      data_(const F& f, const S& ps);
       F f_;
       S pset_;
     };
 
-    template <typename F, typename S>
-    image_data<F, S>::image_data(const Function_p2v<F>& f, const Point_Set<S>& ps)
-      : f_(exact(f)),
-	pset_(exact(ps))
+  } // end of namespace mln::internal
+
+
+
+  namespace pw
     {
-    }
 
     /*! \brief FIXME
      *
      */
     template <typename F, typename S>
-    class image : public internal::image_base_< S, image<F,S> >
+    struct image : public internal::image_primary_< S, image<F,S> >
     {
-      typedef internal::image_base_< S, image<F,S> > super_;
-    public:
-
-
       /// Skeleton.
       typedef image< tag::function<F>, tag::pset<S> > skeleton;
 
 
-      // From super class.
-      typedef mln_psite(super_) psite;
-
-
       /// Value associated type.
       typedef mln_result(F) value;
 
@@ -110,31 +97,27 @@
       typedef mln::value::set<mln_result(F)> vset;
 
 
-      /// Constructor.
-      image(const Function_p2v<F>& f, const Point_Set<S>& ps);
+      /// Constructor without argument.
       image();
 
+      /// Constructor.
+      image(const Function_p2v<F>& f, const Point_Set<S>& ps);
 
-      /// Test if this image has been initialized.
-      bool has_data() const;
 
       /// Test if a pixel value is accessible at \p p.
-      bool owns_(const psite& p) const;
+      bool owns_(const mln_psite(S)& p) const;
 
       /// Give the definition domain.
       const S& domain() const;
 
       /// Read-only access of pixel value at point site \p p.
-      mln_result(F) operator()(const psite& p) const;
+      mln_result(F) operator()(const mln_psite(S)& p) const;
 
       /// Read-write access is present but disabled.
-      void operator()(const psite&);
+      void operator()(const mln_psite(S)&);
 
       /// Give the set of values of the image.
       const vset& values() const;
-
-    protected:
-      tracked_ptr< image_data<F, S> > data_;
     };
 
   } // end of namespace mln::pw
@@ -143,6 +126,8 @@
 
 # ifndef MLN_INCLUDE_ONLY
 
+  // Operator.
+
   template <typename F, typename S>
   pw::image<F,S>
   operator | (const Function_p2v<F>& f, const Point_Set<S>& ps)
@@ -151,50 +136,60 @@
     return tmp;
   }
 
-  namespace pw
+  // internal::data_< pw::image<F,S> >
+
+  namespace internal
   {
 
     template <typename F, typename S>
-    image<F,S>::image()
+    data_< pw::image<F,S> >::data_(const F& f, const S& ps)
+      : f_(f),
+	pset_(ps)
     {
     }
 
+  }
+
+  // pw::image<F,S>
+
+  namespace pw
+  {
+
     template <typename F, typename S>
-    image<F,S>::image(const Function_p2v<F>& f, const Point_Set<S>& ps)
+    image<F,S>::image()
     {
-      data_ = new image_data<F, S>(f, ps);
     }
 
     template <typename F, typename S>
-    bool image<F,S>::has_data() const
+    image<F,S>::image(const Function_p2v<F>& f, const Point_Set<S>& ps)
     {
-      return true;
+      this->data_ = new internal::data_< pw::image<F,S> >(exact(f), exact(ps));
     }
 
     template <typename F, typename S>
-    bool image<F,S>::owns_(const psite& p) const
+    bool image<F,S>::owns_(const mln_psite(S)& p) const
     {
-      return data_->pset_.has(p);
+      return this->data_->pset_.has(p);
     }
 
     template <typename F, typename S>
     const S&
     image<F,S>::domain() const
     {
-      return data_->pset_;
+      return this->data_->pset_;
     }
 
     template <typename F, typename S>
     mln_result(F)
-      image<F,S>::operator()(const psite& p) const
+      image<F,S>::operator()(const mln_psite(S)& p) const
     {
-      mln_precondition(data_->pset_.has(p));
-      return data_->f_(p);
+      mln_precondition(this->data_->pset_.has(p));
+      return this->data_->f_(p);
     }
 
     template <typename F, typename S>
     void
-    image<F,S>::operator()(const psite&)
+    image<F,S>::operator()(const mln_psite(S)&)
     {
       mln_invariant(0); // FIXME: Turn into a compile-time error...
     }
Index: mln/core/window.hh
--- mln/core/window.hh	(revision 1149)
+++ mln/core/window.hh	(working copy)
@@ -41,6 +41,7 @@
 
 # include <mln/convert/to_dpoint.hh>
 # include <mln/geom/sym.hh>
+# include <mln/metal/is_a.hh>
 
 
 namespace mln
@@ -116,6 +117,7 @@
   template <typename D>
   window<D>::window()
   {
+    mln::metal::is_a<D, Dpoint>::check();
   }
 
   template <typename D>
Index: mln/core/internal/image_primary.hh
--- mln/core/internal/image_primary.hh	(revision 0)
+++ mln/core/internal/image_primary.hh	(revision 0)
@@ -0,0 +1,72 @@
+// 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_CORE_INTERNAL_IMAGE_PRIMARY_HH
+# define MLN_CORE_INTERNAL_IMAGE_PRIMARY_HH
+
+/*! \file mln/core/internal/image_primary.hh
+ *
+ * \brief Definition of a base class for primary images.
+ */
+
+# include <mln/core/internal/image_base.hh>
+
+
+namespace mln
+{
+
+  namespace internal
+  {
+
+
+    /*! \brief A base class for primary images.
+     *
+     * \internal
+     */
+    template <typename S, typename E>
+    struct image_primary_ : public image_base_<S, E>
+    {
+    protected:
+      image_primary_();
+    };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+    template <typename S, typename E>
+    image_primary_<S,E>::image_primary_()
+    {
+    }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::internal
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_INTERNAL_IMAGE_PRIMARY_HH
Index: mln/core/internal/image_value_morpher.hh
--- mln/core/internal/image_value_morpher.hh	(revision 1149)
+++ mln/core/internal/image_value_morpher.hh	(working copy)
@@ -57,8 +57,6 @@
       const mln_pset(I)& domain() const;
       bool owns_(const mln_psite(I)& p) const;
 
-      bool has_data() const; // Default impl.
-
     protected:
       image_value_morpher_();
     };
@@ -87,13 +85,6 @@
       return this->delegatee_()->owns_(p);
     }
 
-    template <typename I, typename E>
-    bool
-    image_value_morpher_<I,E>::has_data() const
-    {
-      return this->delegatee_() != 0 && this->delegatee_()->has_data();
-    }
-
 # endif // ! MLN_INCLUDE_ONLY
 
   } // end of namespace mln::internal
Index: mln/core/internal/image_base.hh
--- mln/core/internal/image_base.hh	(revision 1149)
+++ mln/core/internal/image_base.hh	(working copy)
@@ -35,11 +35,27 @@
 
 # include <mln/core/concept/image.hh>
 # include <mln/core/grids.hh>
+# include <mln/util/tracked_ptr.hh>
 
 
 namespace mln
 {
 
+
+
+  namespace internal
+  {
+
+    /// Class of image internal data.
+    template <typename I>
+    struct data_;
+
+    // FIXME: Say more about it!
+
+  } // end of namespace mln::internal
+
+
+
   namespace internal
   {
 
@@ -132,8 +148,15 @@
       /// Give the number of points of the image domain.
       std::size_t npoints() const;
 
+      /// Test if this image has been initialized; default impl.
+      bool has_data() const;
+
+      // FIXME: Add void init_data(..);
+
     protected:
       image_base_();
+
+      util::tracked_ptr< internal::data_<E> > data_;
     };
 
 
@@ -146,6 +169,13 @@
 
     template <typename S, typename E>
     bool
+    image_base_<S,E>::has_data() const
+    {
+      return data_ != 0;
+    }
+
+    template <typename S, typename E>
+    bool
     image_base_<S,E>::has(const psite& p) const
     {
       mln_precondition(exact(this)->has_data());
Index: mln/core/internal/image_morpher.hh
--- mln/core/internal/image_morpher.hh	(revision 1149)
+++ mln/core/internal/image_morpher.hh	(working copy)
@@ -56,18 +56,22 @@
 
       typedef I delegatee;
 
-      /// Return the delegatee_ pointer.
+      /// Return the delegatee_ pointer; default code.
       mlc_const(I)* delegatee_() const;
 
-      /// Return the delegatee_ pointer (non-const version).
+      /// Return the delegatee_ pointer (non-const version); default code.
       I* delegatee_();
 
-      /// Convertion to the underlying (morphed) image.
-      operator I() const; // FIXME: Dangerous?
-
-      /// Default for has_data is "delegatee has data".
+      /* \brief Test if this image has been initialized; default impl.
+       *
+       * This default impl is stronger than the one inherited from
+       * image_base_.
+       */
       bool has_data() const;
 
+      /// Convertion to the underlying (morphed) image.
+      operator I() const; // FIXME: Very dangerous? Remove?
+
     protected:
       image_morpher_();
     };
@@ -84,21 +88,20 @@
     mlc_const(I)*
     image_morpher_<I,S,E>::delegatee_() const
     {
-      return exact(this)->impl_delegatee_();
+      return this->data_ = 0 ? 0 : & this->data_->ima_;
     }
 
     template <typename I, typename S, typename E>
     I*
     image_morpher_<I,S,E>::delegatee_()
     {
-      return exact(this)->impl_delegatee_();
+      return this->data_ = 0 ? 0 : & this->data_->ima_;
     }
 
     template <typename I, typename S, typename E>
     image_morpher_<I,S,E>::operator I() const
     {
       mln_precondition(exact(this)->has_data());
-      mln_precondition(this->delegatee_() != 0); // FIXME: Redundant?
       return * this->delegatee_();
     }
 
@@ -106,8 +109,10 @@
     bool
     image_morpher_<I,S,E>::has_data() const
     {
-      mln_precondition(this->delegatee_() != 0); // FIXME: Redundant?
-      return this->delegatee_()->has_data();
+      return
+	this->data != 0 &&
+	this->delegatee_() != 0 &&
+	this->delegatee_()->has_data();
     }
 
 # endif // ! MLN_INCLUDE_ONLY
Index: mln/core/image2d_b.hh
--- mln/core/image2d_b.hh	(revision 1149)
+++ mln/core/image2d_b.hh	(working copy)
@@ -33,18 +33,14 @@
  * \brief Definition of the basic mln::image2d_b class.
  */
 
-# include <mln/core/internal/image_base.hh>
+# include <mln/core/internal/image_primary.hh>
 # include <mln/core/box2d.hh>
 
 # include <mln/border/thickness.hh>
 # include <mln/value/set.hh>
 # include <mln/fun/i2v/all.hh>
-
 # include <mln/core/line_piter.hh>
 
-# include <mln/core/internal/tracked_ptr.hh>
-# include <mln/core/image2d_b_data.hh>
-
 // FIXME:
 
 // # include <mln/core/pixter2d_b.hh>
@@ -58,6 +54,32 @@
   template <typename T> struct image2d_b;
 
 
+
+  namespace internal
+  {
+
+    template <typename T>
+    struct data_< image2d_b<T> >
+    {
+      data_(const box2d& b, unsigned bdr);
+      ~data_();
+      
+      T*  buffer_;
+      T** array_;
+      
+      box2d b_;  // theoretical box
+      unsigned bdr_;
+      box2d vb_; // virtual box, i.e., box including the virtual border
+
+      void update_vb_();
+      void allocate_();
+      void deallocate_();
+    };
+
+  } // end of namespace mln::internal
+
+
+
   namespace trait
   {
 
@@ -78,7 +100,7 @@
    * thickness around data.
    */
   template <typename T>
-  struct image2d_b : public internal::image_base_< box2d, image2d_b<T> >
+  struct image2d_b : public internal::image_primary_< box2d, image2d_b<T> >
   {
     // Warning: just to make effective types appear in Doxygen:
     typedef box2d   pset;
@@ -142,20 +164,18 @@
 
     /// Initialize an empty image.
     template <typename I>
-    void init_with(const Image<I>& other)
+    void init_with(const Image<I>& other) // FIXME: Remove this soon obsolete code!
     {
-      mln_precondition(data_ = 0);
+      mln_precondition(this->data_ = 0);
       mln_precondition(exact(other).has_data());
-      data_ = new image2d_b_data<T>(exact(other).bbox()); // FIXME: border?
+      this->data_ = new internal::data_< image2d_b<T> >(exact(other).bbox(),
+							exact(other).border());
     }
 
 
     /// Test if \p p is valid.
     bool owns_(const point2d& p) const;
 
-    /// Test if this image has been initialized.
-    bool has_data() const;
-
     /// Give the set of values of the image.
     const vset& values() const;
 
@@ -204,8 +224,6 @@
 
   private:
 
-    tracked_ptr< image2d_b_data<T> > data_;
-
     typedef internal::image_base_< box2d, image2d_b<T> > super;
   };
 
@@ -213,17 +231,86 @@
 
 # ifndef MLN_INCLUDE_ONLY
 
-  // ctors
+
+  // internal::data_< image2d_b<T> >
+
+  namespace internal
+  {
+
+    template <typename T>
+    data_< image2d_b<T> >::data_(const box2d& b, unsigned bdr)
+      : buffer_(0),
+	array_ (0),
+	b_     (b),
+	bdr_   (bdr)
+    {
+      allocate_();
+    }
+
+    template <typename T>
+    data_< image2d_b<T> >::~data_()
+    {
+      deallocate_();
+    }
+
+    template <typename T>
+    void
+    data_< image2d_b<T> >::update_vb_()
+    {
+      vb_.pmin() = b_.pmin() - dpoint2d(all(bdr_));
+      vb_.pmax() = b_.pmax() + dpoint2d(all(bdr_));
+    }
+
+    template <typename T>
+    void
+    data_< image2d_b<T> >::allocate_()
+    {
+      update_vb_();
+      unsigned
+	nr = vb_.len(0),
+	nc = vb_.len(1);
+      buffer_ = new T[nr * nc];
+      array_ = new T*[nr];
+      T* buf = buffer_ - vb_.pmin().col();
+      for (unsigned i = 0; i < nr; ++i)
+	{
+	  array_[i] = buf;
+	  buf += nc;
+	}
+      array_ -= vb_.pmin().row();
+      mln_postcondition(vb_.len(0) = b_.len(0) + 2 * bdr_);
+      mln_postcondition(vb_.len(1) = b_.len(1) + 2 * bdr_);
+    }
+
+    template <typename T>
+    void
+    data_< image2d_b<T> >::deallocate_()
+    {
+      if (buffer_)
+	{
+	  delete[] buffer_;
+	  buffer_ = 0;
+	}
+      if (array_)
+	{
+	  array_ += vb_.pmin().row();
+	  delete[] array_;
+	  array_ = 0;
+	}
+    }
+
+  } // end of namespace mln::internal
+
+
+  // image2d_b<T>
 
   template <typename T>
   image2d_b<T>::image2d_b()
-    : data_(0)
   {
   }
 
   template <typename T>
   image2d_b<T>::image2d_b(int nrows, int ncols, unsigned bdr)
-    : data_(0)
   {
     init_with(nrows, ncols, bdr);
   }
@@ -233,7 +320,7 @@
   image2d_b<T>::init_with(int nrows, int ncols, unsigned bdr)
   {
     mln_precondition(! this->has_data());
-    data_ = new image2d_b_data<T>(make::box2d(nrows, ncols), bdr);
+    this->data_ = new internal::data_< image2d_b<T> >(make::box2d(nrows, ncols), bdr);
   }
 
   template <typename T>
@@ -247,13 +334,11 @@
   image2d_b<T>::init_with(const box2d& b, unsigned bdr)
   {
     mln_precondition(! this->has_data());
-    data_ = new image2d_b_data<T>(b, bdr);
+    this->data_ = new internal::data_< image2d_b<T> >(b, bdr);
   }
 
   template <typename T>
   image2d_b<T>::image2d_b(const image2d_b<T>& rhs)
-    : super(rhs),
-      data_(rhs.data_)
   {
   }
 
@@ -274,13 +359,6 @@
   // methods
 
   template <typename T>
-  bool
-  image2d_b<T>::has_data() const
-  {
-    return data_ != 0;
-  }
-
-  template <typename T>
   const typename image2d_b<T>::vset&
   image2d_b<T>::values() const
   {
@@ -292,7 +370,7 @@
   image2d_b<T>::domain() const
   {
     mln_precondition(this->has_data());
-    return data_->b_;
+    return this->data_->b_;
   }
 
   template <typename T>
@@ -300,7 +378,7 @@
   image2d_b<T>::border() const
   {
     mln_precondition(this->has_data());
-    return data_->bdr_;
+    return this->data_->bdr_;
   }
 
   template <typename T>
@@ -308,7 +386,7 @@
   image2d_b<T>::ncells() const
   {
     mln_precondition(this->has_data());
-    return data_->vb_.npoints();
+    return this->data_->vb_.npoints();
   }
 
   template <typename T>
@@ -316,7 +394,7 @@
   image2d_b<T>::owns_(const point2d& p) const
   {
     mln_precondition(this->has_data());
-    return data_->vb_.has(p);
+    return this->data_->vb_.has(p);
   }
 
   template <typename T>
@@ -324,7 +402,7 @@
   image2d_b<T>::operator()(const point2d& p) const
   {
     mln_precondition(this->owns_(p));
-    return data_->array_[p.row()][p.col()];
+    return this->data_->array_[p.row()][p.col()];
   }
 
   template <typename T>
@@ -332,7 +410,7 @@
   image2d_b<T>::operator()(const point2d& p)
   {
     mln_precondition(this->owns_(p));
-    return data_->array_[p.row()][p.col()];
+    return this->data_->array_[p.row()][p.col()];
   }
 
   template <typename T>
@@ -340,7 +418,7 @@
   image2d_b<T>::operator[](unsigned o) const
   {
     mln_precondition(o < ncells());
-    return *(data_->buffer_ + o);
+    return *(this->data_->buffer_ + o);
   }
 
   template <typename T>
@@ -348,7 +426,7 @@
   image2d_b<T>::operator[](unsigned o)
   {
     mln_precondition(o < ncells());
-    return *(data_->buffer_ + o);
+    return *(this->data_->buffer_ + o);
   }
 
   template <typename T>
@@ -356,7 +434,7 @@
   image2d_b<T>::at(int row, int col) const
   {
     mln_precondition(this->owns_(make::point2d(row, col)));
-    return data_->array_[row][col];
+    return this->data_->array_[row][col];
   }
 
   template <typename T>
@@ -364,7 +442,7 @@
   image2d_b<T>::at(int row, int col)
   {
     mln_precondition(this->owns_(make::point2d(row, col)));
-    return data_->array_[row][col];
+    return this->data_->array_[row][col];
   }
 
   template <typename T>
@@ -377,7 +455,7 @@
   image2d_b<T>::buffer() const
   {
     mln_precondition(this->has_data());
-    return data_->buffer_;
+    return this->data_->buffer_;
   }
 
   template <typename T>
@@ -385,7 +463,7 @@
   image2d_b<T>::buffer()
   {
     mln_precondition(this->has_data());
-    return data_->buffer_;
+    return this->data_->buffer_;
   }
 
   template <typename T>
@@ -393,7 +471,7 @@
   image2d_b<T>::offset(const dpoint2d& dp) const
   {
     mln_precondition(this->has_data());
-    int o = dp[0] * data_->vb_.len(1) + dp[1];
+    int o = dp[0] * this->data_->vb_.len(1) + dp[1];
     return o;
   }
 
@@ -402,8 +480,8 @@
   image2d_b<T>::point_at_offset(unsigned o) const
   {
     mln_precondition(o < ncells());
-    point2d p = make::point2d(o / data_->vb_.len(1) + data_->vb_.min_row(),
-			      o % data_->vb_.len(1) + data_->vb_.min_col());
+    point2d p = make::point2d(o / this->data_->vb_.len(1) + this->data_->vb_.min_row(),
+			      o % this->data_->vb_.len(1) + this->data_->vb_.min_col());
     mln_postcondition(& this->operator()(p) = this->data_->buffer_ + o);
     return p;
   }
Index: mln/core/cast_image.hh
--- mln/core/cast_image.hh	(revision 1149)
+++ mln/core/cast_image.hh	(working copy)
@@ -31,6 +31,8 @@
 /*! \file mln/core/cast_image.hh
  *
  * \brief Definition of an image class FIXME
+ *
+ * \todo Rename as cast_image (without '_')!
  */
 
 # include <mln/core/internal/image_value_morpher.hh>
@@ -41,14 +43,30 @@
 namespace mln
 {
 
+  // Fwd decl.
+  template <typename T, typename I> class cast_image_;
+
+
+  namespace internal
+  {
+
+    template <typename T, typename I>
+    struct data_< cast_image_<T,I> >
+    {
+      data_(const I& ima);
+      const I& ima_;
+    };
+
+  } // end of namespace mln::internal
+
+
+
   /*! \brief FIXME
    *
    */
   template <typename T, typename I>
-  class cast_image_ : public internal::image_value_morpher_< I, cast_image_<T,I> >
+  struct cast_image_ : public internal::image_value_morpher_< I, cast_image_<T,I> >
   {
-  public:
-
     /// Value associated type.
     typedef T value;
 
@@ -78,12 +96,6 @@
 
     /// Give the set of values of the image.
     const vset& values() const;
-
-    /// Access to delegatee pointer.
-    const I* impl_delegatee_() const;
-
-  protected:
-    const I& ima_;
   };
 
 
@@ -101,26 +113,43 @@
 
 # ifndef MLN_INCLUDE_ONLY
 
+
+  // internal::data_< cast_image_<T,I> >
+
+  namespace internal
+  {
+
+    template <typename T, typename I>
+    data_< cast_image_<T,I> >::data_(const I& ima)
+      : ima_(ima)
+    {
+    }
+
+  } // end of namespace mln::internal
+
+
+  // cast_image_<T,I>
+
   template <typename T, typename I>
   cast_image_<T,I>::cast_image_(const Image<I>& ima)
-    : ima_(exact(ima))
   {
     mln_precondition(exact(ima).has_data());
+    this->data_ = new internal::data_< cast_image_<T,I> >(exact(ima));
   }
 
   template <typename T, typename I>
   T
   cast_image_<T,I>::operator()(const mln_psite(I)& p) const
   {
-    mln_precondition(ima_.owns_(p));
-    return mln::value::cast<T>( ima_(p) );
+    mln_precondition(this->data_->ima_.owns_(p));
+    return mln::value::cast<T>( this->data_->ima_(p) );
   }
 
   template <typename T, typename I>
   T
   cast_image_<T,I>::operator()(const mln_psite(I)& p)
   {
-    return mln::value::cast<T>( ima_(p) );
+    return mln::value::cast<T>( this->data_->ima_(p) );
   }
 
   template <typename T, typename I>
@@ -130,13 +159,6 @@
     return vset::the();
   }
 
-  template <typename T, typename I>
-  const I*
-  cast_image_<T,I>::impl_delegatee_() const
-  {
-    return & ima_;
-  }
-  
 # endif // ! MLN_INCLUDE_ONLY
 
 } // end of namespace mln
Index: mln/core/sub_image.hh
--- mln/core/sub_image.hh	(revision 1149)
+++ mln/core/sub_image.hh	(working copy)
@@ -34,29 +34,43 @@
 namespace mln
 {
 
-  // FIXME: Doc!
+
+  // Fwd decl.
+  template <typename I, typename S> class sub_image;
+
+
+  namespace internal
+  {
 
   template <typename I, typename S>
-  class sub_image : public internal::image_domain_morpher_< I, S, sub_image<I,S> >
+    struct data_< sub_image<I,S> >
   {
-  public:
+      data_(I& ima, const S& pset);
+
+      I& ima_;
+      const S& pset_;
+    };
+
+  } // end of namespace mln::internal
 
+
+
+  // FIXME: Doc!
+
+  template <typename I, typename S>
+  struct sub_image : public internal::image_domain_morpher_< I, S, sub_image<I,S> >
+  {
     /// Skeleton.
     typedef sub_image< tag::image<I>, tag::pset<S> > skeleton;
 
+    /// Constructor.
     sub_image(I& ima, const S& pset);
 
+    /// Give the definition domain.
     const S& domain() const;
 
     /// Const promotion via convertion.
     operator sub_image<const I, S>() const;
-
-    mlc_const(I)* impl_delegatee_() const;
-    I* impl_delegatee_();
-
-  protected:
-    I& ima_;
-    const S& pset_;
   };
 
 
@@ -71,42 +85,46 @@
 
 # ifndef MLN_INCLUDE_ONLY
 
+  // internal::data_< sub_image<I,S> >
+
+  namespace internal
+  {
+
   template <typename I, typename S>
-  sub_image<I,S>::sub_image(I& ima, const S& pset)
+    data_< sub_image<I,S> >::data_(I& ima, const S& pset)
     : ima_(ima),
       pset_(pset)
   {
   }
 
-  template <typename I, typename S>
-  const S&
-  sub_image<I,S>::domain() const
-  {
-    return pset_;
-  }
+  } // end of namespace mln::internal
+
+
+  // sub_image<I,S>
 
   template <typename I, typename S>
-  sub_image<I,S>::operator sub_image<const I, S>() const
+  sub_image<I,S>::sub_image(I& ima, const S& pset)
   {
-    sub_image<const I, S> tmp(this->adaptee_, this->pset_);
-    return tmp;
+    this->data_ = new internal::data_< sub_image<I,S> >(ima, pset);
   }
 
   template <typename I, typename S>
-  mlc_const(I)*
-  sub_image<I,S>::impl_delegatee_() const
+  const S&
+  sub_image<I,S>::domain() const
   {
-    return & ima_;
+    return this->data_->pset_;
   }
 
   template <typename I, typename S>
-  I*
-  sub_image<I,S>::impl_delegatee_()
+  sub_image<I,S>::operator sub_image<const I, S>() const
   {
-    return & ima_;
+    sub_image<const I, S> tmp(this->data_->ima_,
+			      this->data_->pset_);
+    return tmp;
   }
 
-  // operator
+
+  // Operators.
 
   template <typename I, typename S>
   sub_image<const I, S>
Index: mln/core/clone.hh
--- mln/core/clone.hh	(revision 0)
+++ mln/core/clone.hh	(revision 0)
@@ -0,0 +1,86 @@
+// 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_CORE_CLONE_HH
+# define MLN_CORE_CLONE_HH
+
+/*! \file mln/core/clone.hh
+ *
+ * \brief Clone an image, that is, get an effective copy.
+ */
+
+# include <mln/core/concept/image.hh>
+
+
+namespace mln
+{
+
+  /*! Clone the image \p ima with the values of the image \p data.
+   *
+   * \param[in,out] ima The image to be cloneed.
+   * \param[in] data The image.
+   *
+   * \warning The definition domain of \p ima has to be included in
+   * the one of \p data.
+   *
+   * \pre \p ima.domain <= \p data.domain.
+   *
+   * \todo Use memcpy when possible.
+   */
+  template <typename I>
+  mln_concrete(I) clone(const Image<I>& ima);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+  namespace impl
+  {
+
+    template <typename I>
+    void clone_(mln_concrete(I)& result, const Image<I>& ima)
+    {
+      std::cerr << "oops" << std::endl; // FIXME: Fake code.
+    }    
+
+  } // end of namespace mln::impl
+
+
+  template <typename I>
+  mln_concrete(I) clone(const Image<I>& ima)
+  {
+    mln_concrete(I) tmp;
+    impl::clone_(ima, tmp);
+    return tmp;
+  }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_CLONE_HH
Index: mln/core/image1d_b.hh
--- mln/core/image1d_b.hh	(revision 1149)
+++ mln/core/image1d_b.hh	(working copy)
@@ -33,7 +33,7 @@
  * \brief Definition of the basic mln::image1d_b class.
  */
 
-# include <mln/core/internal/image_base.hh>
+# include <mln/core/internal/image_primary.hh>
 # include <mln/core/box1d.hh>
 
 # include <mln/border/thickness.hh>
@@ -42,9 +42,6 @@
 
 # include <mln/core/line_piter.hh>
 
-# include <mln/core/internal/tracked_ptr.hh>
-# include <mln/core/image1d_b_data.hh>
-
 // FIXME:
 
 // # include <mln/core/pixter1d_b.hh>
@@ -71,14 +68,40 @@
 
 
 
+  namespace internal
+  {
+
+    /// Data structure for mln::image1d_b<T>.
+    template <typename T>
+    struct data_< image1d_b<T> >
+    {
+      data_(const box1d& b, unsigned bdr);
+      ~data_();
+
+      T*  buffer_;
+      T* array_;
+
+      box1d b_;  // theoretical box
+      unsigned bdr_;
+      box1d vb_; // virtual box, i.e., box including the virtual border
+
+      void update_vb_();
+      void allocate_();
+      void deallocate_();
+    };
+
+  } // end of namespace mln::internal
+
+
+
   /*! \brief Basic 1D image class.
    *
    * The parameter \c T is the type of pixel values.  This image class
    * stores data in memory and has a virtual border with constant
-   * thickness around data.
+   * thickness before and after data.
    */
   template <typename T>
-  struct image1d_b : public internal::image_base_< box1d, image1d_b<T> >
+  struct image1d_b : public internal::image_primary_< box1d, image1d_b<T> >
   {
     // Warning: just to make effective types appear in Doxygen:
     typedef box1d   pset;
@@ -112,26 +135,13 @@
     /// Constructor without argument.
     image1d_b();
 
-    /// Constructor with the numbers of indexes and the
-    /// border thickness.
-    image1d_b(int ninds, unsigned bdr = border::thickness);
+    /// Constructor with the number of indices and the border
+    /// thickness.
+    image1d_b(unsigned ninds, unsigned bdr = border::thickness);
 
-    /// Constructor with a box and the border thickness (default is
-    /// 3).
+    /// Constructor with a box and the border thickness.
     image1d_b(const box1d& b, unsigned bdr = border::thickness);
 
-    /// Copy constructor.
-    image1d_b(const image1d_b<T>& rhs);
-
-    /// Assignment operator.
-    image1d_b& operator=(const image1d_b<T>& rhs);
-
-    /// Destructor.
-    ~image1d_b();
-
-
-    /// Initialize an empty image.
-    void init_with(int ninds, unsigned bdr = border::thickness);
 
     /// Initialize an empty image.
     void init_with(const box1d& b, unsigned bdr = border::thickness);
@@ -140,9 +150,6 @@
     /// Test if \p p is valid.
     bool owns_(const point1d& p) const;
 
-    /// Test if this image has been initialized.
-    bool has_data() const;
-
     /// Give the set of values of the image.
     const vset& values() const;
 
@@ -187,85 +194,93 @@
 
     /// Give a hook to the value buffer.
     T* buffer();
-
-
-  private:
-
-    tracked_ptr< image1d_b_data<T> > data_;
-
-    typedef internal::image_base_< box1d, image1d_b<T> > super;
   };
 
 
 
 # ifndef MLN_INCLUDE_ONLY
 
-  // ctors
+  // internal::data_< image1d_b<T> >
+
+  namespace internal
+  {
 
   template <typename T>
-  image1d_b<T>::image1d_b()
-    : data_(0)
+    data_< image1d_b<T> >::data_(const box1d& b, unsigned bdr)
+      : buffer_(0),
+	array_ (0),
+	b_     (b),
+	bdr_   (bdr)
   {
+      allocate_();
   }
 
   template <typename T>
-  image1d_b<T>::image1d_b(int ninds, unsigned bdr)
-    : data_(0)
+    data_< image1d_b<T> >::~data_()
   {
-    init_with(ninds, bdr);
+      deallocate_();
   }
 
   template <typename T>
   void
-  image1d_b<T>::init_with(int ninds, unsigned bdr)
+    data_< image1d_b<T> >::update_vb_()
   {
-    mln_precondition(! this->has_data());
-    data_ = new image1d_b_data<T>(make::box1d(ninds), bdr);
+      vb_.pmin() = b_.pmin() - dpoint1d(all(bdr_));
+      vb_.pmax() = b_.pmax() + dpoint1d(all(bdr_));
   }
 
   template <typename T>
-  image1d_b<T>::image1d_b(const box1d& b, unsigned bdr)
-    : data_(0)
+    void
+    data_< image1d_b<T> >::allocate_()
   {
-    init_with(b, bdr);
+      update_vb_();
+      unsigned
+	ni = vb_.len(0);
+      buffer_ = new T[ni];
+      array_ = buffer_ - vb_.pmin().ind();
+      mln_postcondition(vb_.len(0) = b_.len(0) + 2 * bdr_);
   }
 
   template <typename T>
   void
-  image1d_b<T>::init_with(const box1d& b, unsigned bdr)
+    data_< image1d_b<T> >::deallocate_()
   {
-    mln_precondition(! this->has_data());
-    data_ = new image1d_b_data<T>(b, bdr);
+      if (buffer_)
+	{
+	  delete[] buffer_;
+	  buffer_ = 0;
+	}
   }
 
+  } // end of namespace mln::internal
+
+
+  // image1d_b<T>
+
   template <typename T>
-  image1d_b<T>::image1d_b(const image1d_b<T>& rhs)
-    : super(rhs),
-      data_(rhs.data_)
+  image1d_b<T>::image1d_b()
   {
   }
 
-  // assignment
-
   template <typename T>
-  image1d_b<T>&
-  image1d_b<T>::operator=(const image1d_b<T>& rhs)
+  image1d_b<T>::image1d_b(const box1d& b, unsigned bdr)
   {
-    mln_precondition(rhs.has_data());
-    if (& rhs = this)
-      return *this;
-
-    this->data_ = rhs.data_;
-    return *this;
+    init_with(b, bdr);
   }
 
-  // methods
+  template <typename T>
+  image1d_b<T>::image1d_b(unsigned ninds, unsigned bdr)
+  {
+    mln_precondition(ninds != 0);
+    init_with(make::box1d(ninds), bdr);
+  }
 
   template <typename T>
-  bool
-  image1d_b<T>::has_data() const
+  void
+  image1d_b<T>::init_with(const box1d& b, unsigned bdr)
   {
-    return data_ != 0;
+    mln_precondition(! this->has_data());
+    this->data_ = new internal::data_< image1d_b<T> >(b, bdr);
   }
 
   template <typename T>
@@ -280,7 +295,7 @@
   image1d_b<T>::domain() const
   {
     mln_precondition(this->has_data());
-    return data_->b_;
+    return this->data_->b_;
   }
 
   template <typename T>
@@ -288,7 +303,7 @@
   image1d_b<T>::border() const
   {
     mln_precondition(this->has_data());
-    return data_->bdr_;
+    return this->data_->bdr_;
   }
 
   template <typename T>
@@ -296,19 +311,15 @@
   image1d_b<T>::ncells() const
   {
     mln_precondition(this->has_data());
-    return data_->vb_.npoints();
+    return this->data_->vb_.npoints();
   }
 
   template <typename T>
   bool
   image1d_b<T>::owns_(const point1d& p) const
   {
-    if (! data_->vb_.has(p))
-      {
-	std::cout << " p = " <<  p << std::endl;
-      }
     mln_precondition(this->has_data());
-    return data_->vb_.has(p);
+    return this->data_->vb_.has(p);
   }
 
   template <typename T>
@@ -316,7 +327,7 @@
   image1d_b<T>::operator()(const point1d& p) const
   {
     mln_precondition(this->owns_(p));
-    return data_->array_[p.ind()];
+    return this->data_->array_[p.ind()];
   }
 
   template <typename T>
@@ -324,7 +335,7 @@
   image1d_b<T>::operator()(const point1d& p)
   {
     mln_precondition(this->owns_(p));
-    return data_->array_[p.ind()];
+    return this->data_->array_[p.ind()];
   }
 
   template <typename T>
@@ -332,7 +343,7 @@
   image1d_b<T>::operator[](unsigned o) const
   {
     mln_precondition(o < ncells());
-    return *(data_->buffer_ + o);
+    return *(this->data_->buffer_ + o);
   }
 
   template <typename T>
@@ -340,7 +351,7 @@
   image1d_b<T>::operator[](unsigned o)
   {
     mln_precondition(o < ncells());
-    return *(data_->buffer_ + o);
+    return *(this->data_->buffer_ + o);
   }
 
   template <typename T>
@@ -348,7 +359,7 @@
   image1d_b<T>::at(int ind) const
   {
     mln_precondition(this->owns_(make::point1d(ind)));
-    return data_->array_[ind];
+    return this->data_->array_[ind];
   }
 
   template <typename T>
@@ -356,12 +367,7 @@
   image1d_b<T>::at(int ind)
   {
     mln_precondition(this->owns_(make::point1d(ind)));
-    return data_->array_[ind];
-  }
-
-  template <typename T>
-  image1d_b<T>::~image1d_b()
-  {
+    return this->data_->array_[ind];
   }
 
   template <typename T>
@@ -369,7 +375,7 @@
   image1d_b<T>::buffer() const
   {
     mln_precondition(this->has_data());
-    return data_->buffer_;
+    return this->data_->buffer_;
   }
 
   template <typename T>
@@ -377,7 +383,7 @@
   image1d_b<T>::buffer()
   {
     mln_precondition(this->has_data());
-    return data_->buffer_;
+    return this->data_->buffer_;
   }
 
   template <typename T>
@@ -394,7 +400,7 @@
   image1d_b<T>::point_at_offset(unsigned o) const
   {
     mln_precondition(o < ncells());
-    point1d p = make::point1d(o + data_->vb_.min_ind());
+    point1d p = make::point1d(o + this->data_->vb_.min_ind());
     mln_postcondition(& this->operator()(p) = this->data_->buffer_ + o);
     return p;
   }
Index: mln/core/image3d_b.hh
--- mln/core/image3d_b.hh	(revision 1149)
+++ mln/core/image3d_b.hh	(working copy)
@@ -33,7 +33,7 @@
  * \brief Definition of the basic mln::image3d_b class.
  */
 
-# include <mln/core/internal/image_base.hh>
+# include <mln/core/internal/image_primary.hh>
 # include <mln/core/box3d.hh>
 
 # include <mln/border/thickness.hh>
@@ -42,9 +42,6 @@
 
 # include <mln/core/line_piter.hh>
 
-# include <mln/core/internal/tracked_ptr.hh>
-# include <mln/core/image3d_b_data.hh>
-
 // FIXME:
 
 // # include <mln/core/pixter3d_b.hh>
@@ -70,6 +67,31 @@
   } // end of mln::trait
 
 
+  namespace internal
+  {
+
+    template <typename T>
+    struct data_< image3d_b<T> >
+    {
+      data_(const box3d& b, unsigned bdr);
+      ~data_();
+
+      T*  buffer_;
+      T*** array_;
+
+      box3d b_;  // theoretical box
+      unsigned bdr_;
+      box3d vb_; // virtual box, i.e., box including the virtual border
+
+      void update_vb_();
+      void allocate_();
+      void deallocate_();
+
+    };
+
+  } // end of namespace mln::internal
+
+
 
   /*! \brief Basic 3D image class.
    *
@@ -78,7 +100,7 @@
    * thickness around data.
    */
   template <typename T>
-  struct image3d_b : public internal::image_base_< box3d, image3d_b<T> >
+  struct image3d_b : public internal::image_primary_< box3d, image3d_b<T> >
   {
     // Warning: just to make effective types appear in Doxygen:
     typedef box3d   pset;
@@ -112,37 +134,22 @@
     /// Constructor without argument.
     image3d_b();
 
-    /// Constructor with the numbers of indexes and the
-    /// border thickness.
-    image3d_b(int nslis, int nrows, int ncols, unsigned bdr = border::thickness);
-
     /// Constructor with a box and the border thickness (default is
     /// 3).
     image3d_b(const box3d& b, unsigned bdr = border::thickness);
 
-    /// Copy constructor.
-    image3d_b(const image3d_b<T>& rhs);
-
-    /// Assignment operator.
-    image3d_b& operator=(const image3d_b<T>& rhs);
-
-    /// Destructor.
-    ~image3d_b();
+    /// Constructor with the numbers of indexes and the
+    /// border thickness.
+    image3d_b(int nslis, int nrows, int ncols, unsigned bdr = border::thickness);
 
 
     /// Initialize an empty image.
-    void init_with(int nslis, int nrows, int ncols, unsigned bdr = border::thickness);
-
-    /// Initialize an empty image.
     void init_with(const box3d& b, unsigned bdr = border::thickness);
 
 
     /// Test if \p p is valid.
     bool owns_(const point3d& p) const;
 
-    /// Test if this image has been initialized.
-    bool has_data() const;
-
     /// Give the set of values of the image.
     const vset& values() const;
 
@@ -187,86 +194,121 @@
 
     /// Give a hook to the value buffer.
     T* buffer();
-
-
-  private:
-
-    tracked_ptr< image3d_b_data<T> > data_;
-
-    typedef internal::image_base_< box3d, image3d_b<T> > super;
   };
 
 
 
 # ifndef MLN_INCLUDE_ONLY
 
-  // ctors
+  // internal::data_< image3d_b<T> >
+
+  namespace internal
+  {
 
   template <typename T>
-  image3d_b<T>::image3d_b()
-    : data_(0)
+    data_< image3d_b<T> >::data_(const box3d& b, unsigned bdr)
+      : buffer_(0),
+	array_ (0),
+	b_     (b),
+	bdr_   (bdr)
   {
-    data_->bdr_ = border::thickness; // default value in ctors.
+      allocate_();
   }
 
   template <typename T>
-  image3d_b<T>::image3d_b(int nslis, int nrows, int ncols, unsigned bdr)
-    : data_(0)
+    data_< image3d_b<T> >::~data_()
   {
-    init_with(nslis, nrows, ncols, bdr);
+      deallocate_();
   }
 
   template <typename T>
   void
-  image3d_b<T>::init_with(int nslis, int nrows, int ncols, unsigned bdr)
+    data_< image3d_b<T> >::update_vb_()
   {
-    mln_precondition(! this->has_data());
-    data_ = new image3d_b_data<T>(make::box3d(nslis, nrows, ncols), bdr);
+      vb_.pmin() = b_.pmin() - dpoint3d(all(bdr_));
+      vb_.pmax() = b_.pmax() + dpoint3d(all(bdr_));
   }
 
   template <typename T>
-  image3d_b<T>::image3d_b(const box3d& b, unsigned bdr)
-    : data_(0)
+    void
+    data_< image3d_b<T> >::allocate_()
   {
-    init_with(b, bdr);
+      update_vb_();
+      unsigned
+	ns = vb_.len(0),
+	nr = vb_.len(1),
+	nc = vb_.len(2);
+      buffer_ = new T[nr * nc * ns];
+      array_ = new T**[ns];
+      T* buf = buffer_ - vb_.pmin().col();
+      for (unsigned i = 0; i < ns; ++i)
+	{
+	  T** tmp = new T*[nr];
+	  array_[i] = tmp;
+	  for (unsigned j = 0; j < nr; ++j)
+	    {
+	      array_[i][j] = buf;
+	      buf += nc;
+	    }
+	  array_[i] -= vb_.pmin().row();
+	}
+      array_ -= vb_.pmin().sli();
+      mln_postcondition(vb_.len(0) = b_.len(0) + 2 * bdr_);
   }
 
   template <typename T>
   void
-  image3d_b<T>::init_with(const box3d& b, unsigned bdr)
+    data_< image3d_b<T> >::deallocate_()
   {
-    mln_precondition(! this->has_data());
-    data_ = new image3d_b_data<T>(b, bdr);
+      if (buffer_)
+	{
+	  delete[] buffer_;
+	  buffer_ = 0;
   }
-
-  template <typename T>
-  image3d_b<T>::image3d_b(const image3d_b<T>& rhs)
-    : super(rhs),
-      data_(rhs.data_)
+      for (typename point3d::coord i = vb_.pmin().sli(); i <= vb_.pmax().sli(); ++i)
+	{
+	  if (array_[i])
+	    {
+	      array_[i] += vb_.pmin().row();
+	      delete[] array_[i];
+	      array_[i] = 0;
+	    }
+	}
+      if (array_)
   {
+	  array_ += vb_.pmin().sli();
+	  delete[] array_;
+	  array_ = 0;
   }
+    }
+
+  } // end of namespace mln::internal
 
-  // assignment
+  // image3d_b<T>
 
   template <typename T>
-  image3d_b<T>&
-  image3d_b<T>::operator=(const image3d_b<T>& rhs)
+  image3d_b<T>::image3d_b()
   {
-    mln_precondition(rhs.has_data());
-    if (& rhs = this)
-      return *this;
+  }
 
-    this->data_ = rhs.data_;
-    return *this;
+  template <typename T>
+  image3d_b<T>::image3d_b(const box3d& b, unsigned bdr)
+  {
+    init_with(b, bdr);
   }
 
-  // methods
+  template <typename T>
+  image3d_b<T>::image3d_b(int nslis, int nrows, int ncols, unsigned bdr)
+  {
+    init_with(make::box3d(nslis, nrows, ncols), bdr);
+  }
 
   template <typename T>
-  bool
-  image3d_b<T>::has_data() const
+  void
+  image3d_b<T>::init_with(const box3d& b, unsigned bdr)
   {
-    return data_ != 0;
+    mln_precondition(! this->has_data());
+    this->data_ = new internal::data_< image3d_b<T> >(b, bdr);
   }
 
   template <typename T>
@@ -357,11 +399,6 @@
   }
 
   template <typename T>
-  image3d_b<T>::~image3d_b()
-  {
-  }
-
-  template <typename T>
   const T*
   image3d_b<T>::buffer() const
   {
@@ -398,8 +435,6 @@
     return p;
   }
 
-
-
 # endif // ! MLN_INCLUDE_ONLY
 
 } // end of namespace mln
Index: mln/util/tracked_ptr.hh
--- mln/util/tracked_ptr.hh	(revision 1147)
+++ mln/util/tracked_ptr.hh	(working copy)
@@ -25,8 +25,15 @@
 // reasons why the executable file might be covered by the GNU General
 // Public License.
 
-#ifndef MLN_CORE_INTERNAL_TRACKED_PTR_HH
-# define MLN_CORE_INTERNAL_TRACKED_PTR_HH
+#ifndef MLN_UTIL_TRACKED_PTR_HH
+# define MLN_UTIL_TRACKED_PTR_HH
+
+/*! \file mln/util/tracked_ptr.hh
+ *
+ * \brief Definition of a smart pointer for shared data with tracking.
+ *
+ * \todo Split defs from decls.
+ */
 
 # include <set>
 # include <iostream>
@@ -34,9 +41,13 @@
 # include <mln/core/contract.hh>
 
 
+
 namespace mln
 {
 
+  namespace util
+  {
+
     template <typename T>
     struct tracked_ptr
     {
@@ -273,9 +284,11 @@
     }
 
 
-# endif
+# endif // ! MLN_INCLUDE_ONLY
+
+  } // end of namespace mln::util
 
 } // end of namespace mln
 
 
-#endif // ! MLN_CORE_INTERNAL_TRACKED_PTR_HH
+#endif // ! MLN_UTIL_TRACKED_PTR_HH
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0