
https://svn.lrde.epita.fr/svn/oln/trunk/milena Index: ChangeLog from Roland Levillain <roland@lrde.epita.fr> Overhaul mln::t_image<I>. * mln/core/t_image.hh (mln::internal::data_t< t_image<I> >): New. (mln::t_image): Revamp. Inherit from internal::image_morpher_< I, mln_pset(I), t_image<I> >. (t_image<I>::super_): Adjust typedef. (t_image<I>::psite, t_image<I>::value) (t_image<I>::rvalue, t_image<I>::vset): New properties. (t_image<I>::lvalue): Fix properties. (t_image<I>::t_image): Adjust for mln::internal::data_t< t_image<I> >. Document ctor. (t_image<I>::has_data, t_image<I>::values): New methods. (t_image<I>::c1_, t_image<I>::c2_, t_image<I>::b_): Remove. Superseded by data_::dim1_, data_::dim2_ and data_::box_. (t_image<I>::exchange_coords_): New method. Use it to redefine... (t_image<I>::transpose_): ...this method. Document. (t_image<I>::owns_, t_image<I>::operator()): Adjust. * tests/t_image.cxx: Rename as... * tests/t_image.cc: ...this. s/image2d_b/image2d/. mln/core/t_image.hh | 215 ++++++++++++++++++++++++++++++++++++++++------------ tests/t_image.cc | 8 - 2 files changed, 173 insertions(+), 50 deletions(-) Index: mln/core/t_image.hh --- mln/core/t_image.hh (revision 1555) +++ mln/core/t_image.hh (working copy) @@ -33,12 +33,45 @@ * \brief Definition of the "transposed" image class mln::t_image. */ -# include <mln/core/internal/image_adaptor.hh> +# include <mln/core/internal/image_morpher.hh> +# include <mln/core/box.hh> namespace mln { + // Fwd decl. + template <typename I> struct t_image; + + namespace internal + { + + /// Data held by a mln::t_image. + template <typename I> + struct data_< t_image<I> > + { + /// \brief Build the data object held by a t_image. + /// + /// \param ima The underlying image. + /// \param dim1 The first dimension to be swapped. + /// \param dim2 The second dimension to be swapped. + /// \param box The bounding box (domain) of the morphed image. + data_(I& ima, unsigned dim1, unsigned dim2, + mln::box_<mln_point(I)>& box); + + /// Underlying image. + I ima_; + /// The swapped dimensions. + /// \{ + unsigned dim1_; + unsigned dim2_; + /// \} + /// The bounding box of the morphed image. + mln::box_<mln_point(I)> box_; + }; + + } // end of namespace mln::internal + /*! \brief Transposed image class. * @@ -47,11 +80,52 @@ * \warning This class only works on images whose domain is a box. */ template <typename I> - struct t_image : public internal::image_adaptor_< I, t_image<I> > + class t_image + : public internal::image_morpher_< I, mln_pset(I), t_image<I> > { + public: + /// Super type. + typedef + internal::image_morpher_< I, mln_pset(I), t_image<I> > super_; + + /// Point_Site associated type. + typedef mln_psite(I) psite; + + /// Value associated type. + typedef mln_value(I) value; + + /// Type returned by the read-write pixel value operator. + typedef typename internal::morpher_lvalue_<I>::ret lvalue; + + /// Return type of read-only access. + typedef mln_rvalue(I) rvalue; + + /// Value set associated type. + typedef mln::value::set<value> vset; + + /// Skeleton. typedef t_image< tag::image_<I> > skeleton; + public: + /// \brief Build the generalized transpose of an image. + /// + /// In the 2-dimension case, \a dim1 and \a dim2 must be resp. 1 and 2 + /// (or 2 and 1), and t_image is a transpose of a matrix with the + /// usual meaning. + /// + /// In dimensions greater than 2, mln::t_image represents a view + /// of the underlying image where two dimensions (i.e., two + /// components of each point) have been exchanged. + /// + /// \param ima The underlying image. + /// \param dim1 The first dimension to be swapped. + /// \param dim2 The second dimension to be swapped. + t_image(I& ima, unsigned dim1, unsigned dim2); + + /// Test if this image has been initialized. + bool has_data() const; + /// Test if a pixel value is accessible at \p p. bool owns_(const mln_point(I)& p) const; @@ -61,90 +135,108 @@ /// Read-only access of pixel value at point site \p p. mln_rvalue(I) operator()(const mln_point(I)& p) const; - /// Type returned by the read-write pixel value operator. - typedef typename internal::morpher_lvalue_<I>::ret lvalue; - /// Read-write access of pixel value at point site \p p. lvalue operator()(const mln_point(I)& p); - /// Constructor. - t_image(I& ima, unsigned c1, unsigned c2); + /// Give the set of values of the image. + const vset& values() const; protected: - - typedef internal::image_adaptor_< I, t_image<I> > super_; - const unsigned c1_, c2_; // coords to swap - box_<mln_point(I)> b_; - + /// Exchange components \a dim1_ and \a dim2_ of point \a p. mln_point(I) transpose_(const mln_point(I)& p) const; + /// Exchange components \a dim1 and \a dim2 of point \a p. + mln_point(I) exchange_coords_(const mln_point(I)& p, + unsigned dim1, unsigned dim2) const; }; + /* FIXME: Shouldn't we move these elsewhere? I (Roland) think mixing + data structure and routines is confusing, even if they are + closely related. What about mln/geom/swap_coords.hh? */ template <typename I> - t_image<I> swap_coords(Image<I>& ima, unsigned c1, unsigned c2); + t_image<I> + swap_coords(Image<I>& ima, unsigned dim1, unsigned dim2); template <typename I> - t_image<const I> swap_coords(const Image<I>& ima, unsigned c1, unsigned c2); + t_image<const I> + swap_coords(const Image<I>& ima, unsigned dim1, unsigned dim2); # ifndef MLN_INCLUDE_ONLY + namespace internal + { + + // internal::data_< t_image<I,S> > + template <typename I> - t_image<I> swap_coords(Image<I>& ima, unsigned c1, unsigned c2) + data_< t_image<I> >::data_(I& ima, + unsigned dim1, unsigned dim2, + mln::box_<mln_point(I)>& box) + : ima_(ima), + dim1_(dim1), dim2_(dim2), + box_(box) { - typedef mln_point(I) P; - mln_precondition(c1 != c2); - mln_precondition(c1 <= P::dim && c2 <= P::dim); - t_image<I> tmp(exact(ima), c1, c2); - return tmp; } + } // end of namespace mln::internal + + template <typename I> - t_image<const I> swap_coords(const Image<I>& ima, unsigned c1, unsigned c2) + t_image<I>::t_image(I& ima, unsigned dim1, unsigned dim2) { - typedef mln_point(I) P; - mln_precondition(c1 != c2); - mln_precondition(c1 <= P::dim && c2 <= P::dim); - t_image<const I> tmp(exact(ima), c1, c2); - return tmp; + mln_precondition(ima.has_data()); + /* FIXME: Add a precondition on the fact that the domain of ima is + a box. */ + // We don't use mln::t_image::transpose here, since one its + // prerequisite is that data_ is initialized, which is not done + // yet at this point. + box_<mln_point(I)> box(exchange_coords_(ima.bbox().pmin(), dim1, dim2), + exchange_coords_(ima.bbox().pmax(), dim1, dim2)); + this->data_ = new internal::data_< t_image<I> >(ima, dim1, dim2, box); } template <typename I> - t_image<I>::t_image(I& ima, unsigned c1, unsigned c2) - : super_(ima), - c1_(c1), - c2_(c2) + bool t_image<I>::has_data() const { - mln_precondition(ima.has_data()); - b_.pmin() = transpose_(this->adaptee_.bbox().pmin()); - b_.pmax() = transpose_(this->adaptee_.bbox().pmax()); + mln_invariant(this->delegatee_()->has_data()); + return true; + } + + template <typename I> + bool + t_image<I>::owns_(const mln_point(I)& p) const + { + mln_precondition(this->has_data()); + return this->delegatee_()->owns_(transpose_(p)); } template <typename I> mln_point(I) t_image<I>::transpose_(const mln_point(I)& p) const { - mln_point(I) tmp(p); - tmp[c1_] = p[c2_]; - tmp[c2_] = p[c1_]; - return tmp; + mln_precondition(this->has_data()); + return exchange_coords_(p, this->data_->dim1_, this->data_->dim2_); } template <typename I> - const box_<mln_point(I)>& - t_image<I>::domain() const + mln_point(I) + t_image<I>::exchange_coords_(const mln_point(I)& p, + unsigned dim1, unsigned dim2) const { - mln_precondition(this->has_data()); - return b_; + mln_point(I) tmp(p); + tmp[dim1] = p[dim2]; + tmp[dim2] = p[dim1]; + return tmp; } template <typename I> - bool - t_image<I>::owns_(const mln_point(I)& p) const + const box_<mln_point(I)>& + t_image<I>::domain() const { mln_precondition(this->has_data()); - return this->adaptee_.owns_(transpose_(p)); + return this->data_->box_; } template <typename I> @@ -152,7 +244,7 @@ t_image<I>::operator()(const mln_point(I)& p) const { mln_precondition(this->owns_(p)); - return this->adaptee_(transpose_(p)); + return this->data_->ima_(transpose_(p)); } template <typename I> @@ -160,7 +252,38 @@ t_image<I>::operator()(const mln_point(I)& p) { mln_precondition(this->owns_(p)); - return this->adaptee_(transpose_(p)); + return this->data_->ima_(transpose_(p)); + } + + template <typename I> + const typename t_image<I>::vset& + t_image<I>::values() const + { + mln_precondition(this->delegatee_() != 0); + return this->delegatee_()->values(); + } + + + template <typename I> + t_image<I> + swap_coords(Image<I>& ima, unsigned dim1, unsigned dim2) + { + typedef mln_point(I) P; + mln_precondition(dim1 != dim2); + mln_precondition(dim1 <= P::dim && dim2 <= P::dim); + t_image<I> tmp(exact(ima), dim1, dim2); + return tmp; + } + + template <typename I> + t_image<const I> + swap_coords(const Image<I>& ima, unsigned dim1, unsigned dim2) + { + typedef mln_point(I) P; + mln_precondition(dim1 != dim2); + mln_precondition(dim1 <= P::dim && dim2 <= P::dim); + t_image<const I> tmp(exact(ima), dim1, dim2); + return tmp; } # endif // ! MLN_INCLUDE_ONLY Index: tests/t_image.cc --- tests/t_image.cc (revision 1423) +++ tests/t_image.cc (working copy) @@ -30,7 +30,7 @@ * \brief Tests on mln::t_image. */ -#include <mln/core/image2d_b.hh> +#include <mln/core/image2d.hh> #include <mln/core/t_image.hh> #include <mln/debug/iota.hh> @@ -41,12 +41,12 @@ { using namespace mln; - typedef image2d_b<int> I; + typedef image2d<int> I; I ima(2, 3); debug::iota(ima); debug::println(ima); - t_image<I> tima(ima, 0, 1); - debug::println(tima); + t_image<I> t_ima(ima, 0, 1); + debug::println(t_ima); }