
https://svn.lrde.epita.fr/svn/oln/trunk/milena Index: ChangeLog from Thierry Geraud <thierry.geraud@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