https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Roland Levillain <roland(a)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);
}