Commit e50eb476 authored by Edwin Carlinet's avatar Edwin Carlinet
Browse files

Fix image2d to alias ndimage<T, 2> without inheritance and move

2D features to a mixin class. This enables to provides basic N-d
features (e.g. indexing with a pair x, y) to any image inheriting from
image_base (i.e almost all images incl. morphers)


	* mln/core/domain/box.hpp,
	* mln/core/image/image2d.hpp,
	* mln/core/image/internal/nested_loop_iterator.hpp,
	* mln/core/image/ndimage.hpp,
	* mln/core/image/sub_image.spe.hpp,
	* mln/core/image_base.hpp: Fix
	* mln/core/image/internal/image_base_at_mixin.hpp: New
parent 036b4cfa
......@@ -219,7 +219,7 @@ namespace mln
/// Traits
/// Forward
template <typename> struct image2d;
template <typename T, unsigned dim> struct ndimage;
template <>
struct image_from_domain<box2d>
......@@ -227,7 +227,7 @@ namespace mln
template <typename T>
struct apply
{
typedef image2d<T> type;
typedef ndimage<T, 2> type;
};
};
......@@ -237,7 +237,7 @@ namespace mln
template <typename T>
struct apply
{
typedef image2d<T> type;
typedef ndimage<T, 2> type;
};
};
......
......@@ -6,22 +6,6 @@
namespace mln {
// FWD declaration
template <typename T> struct image2d;
// Specialization of traits
template <typename T>
struct image_traits< image2d<T> > : image_traits< ndimage_base<T, 2, image2d<T> > >
{
};
template <typename T, typename V>
struct image_ch_value< image2d<T>, V >
{
typedef image2d<V> type;
};
///
/// \brief The standard 2D image type.
///
......@@ -33,48 +17,7 @@ namespace mln {
/// \p image2d models a Writable Point-Accessible Image concept.
/// See \see image2d \see image3d
template <typename T>
struct image2d : ndimage_base<T, 2, image2d<T> >
{
private:
typedef ndimage_base<T, 2, image2d<T> > base_type;
typedef ndimage_base<T, 2, image2d<T> > base;
public:
typedef typename base_type::domain_type domain_type;
explicit image2d (unsigned border = 3) : ndimage_base<T,2,image2d<T> > (border)
{
}
explicit image2d(const domain_type& domain, unsigned border = 3)
: ndimage_base<T,2, image2d<T> >(domain, border)
{
}
image2d(short nrows, short ncols, unsigned border = 3)
: ndimage_base<T,2, image2d<T> >( (box<short,2>) {{0,0},{nrows, ncols}}, border)
{
}
using base::at;
T& at(short nrows, short ncols)
{
return base::at(typename base::point_type(nrows, ncols));
}
const T& at(short nrows, short ncols) const
{
return base::at(typename base::point_type(nrows, ncols));
}
unsigned nrows() const { return this->domain_.pmax[0] - this->domain_.pmin[0]; }
unsigned ncols() const { return this->domain_.pmax[1] - this->domain_.pmin[1]; }
};
using image2d = ndimage<T, 2>;
} // end of namespace mln
......
#ifndef MLN_CORE_IMAGE_INTERNAL_IMAGE_BASE_AT_MIXIN_HPP
# define MLN_CORE_IMAGE_INTERNAL_IMAGE_BASE_AT_MIXIN_HPP
# include <mln/core/point.hpp>
namespace mln
{
namespace internal
{
template <typename Derived, typename Point, typename Reference, typename ConstReference, typename Enable = void>
struct image_base_at_mixin
{
};
template <typename Derived, typename T, typename Reference, typename ConstReference>
struct image_base_at_mixin<Derived, point<T, 2>, Reference, ConstReference, typename std::enable_if< image_traits<Derived>::accessible::value >::type>
{
Reference at(T coord0, T coord1) { return this->derived()->at(point<T,2>{coord0, coord1}); }
ConstReference at(T coord0, T coord1) const { return this->derived()->at(point<T,2>{coord0, coord1}); }
Reference operator() (T coord0, T coord1) { return (*this->derived())(point<T,2>{coord0, coord1}); }
ConstReference operator()(T coord0, T coord1) const { return (*this->derived())(point<T,2>{coord0, coord1}); }
private:
Derived* derived() { return reinterpret_cast<Derived*>(this); }
const Derived* derived() const { return reinterpret_cast<const Derived*>(this); }
};
template <typename Derived, typename T, typename Reference, typename ConstReference>
struct image_base_at_mixin<Derived, point<T, 3>, Reference, ConstReference, typename std::enable_if< image_traits<Derived>::accessible::value >::type>
{
Reference at(T coord0, T coord1, T coord2) { return derived()->at(point<T,3>{coord0, coord1, coord2}); }
ConstReference at(T coord0, T coord1, T coord2) const { return derived()->at(point<T,3>{coord0, coord1, coord2}); }
Reference operator() (T coord0, T coord1, T coord2) { return (*this->derived())(point<T,3>{coord0, coord1, coord2}); }
ConstReference operator()(T coord0, T coord1, T coord2) const { return (*this->derived())(point<T,3>{coord0, coord1, coord2}); }
private:
Derived* derived() { return reinterpret_cast<Derived*>(this); }
const Derived* derived() const { return reinterpret_cast<const Derived*>(this); }
};
}
}
#endif // ! MLN_CORE_IMAGE_INTERNAL_IMAGE_BASE_AT_MIXIN_HPP
......@@ -246,7 +246,7 @@ namespace mln
strided_domain_point_visitor_backward(const P& pmin, const P& pmax, const P& strides) :
pmin_ (pmin), pmax_(pmax), strides_ (strides)
{
mln_precondition( (pmax - pmin) % strides == P (literal::zero) );
mln_precondition( (pmax - pmin).as_vec() % strides.as_vec() == literal::zero );
}
void initialize(P& point) const { point = pmax_; point -= strides_; }
......
......@@ -16,23 +16,21 @@
namespace mln
{
template <typename T, unsigned dim, typename E> struct ndimage_base;
// FWD
//template <typename I, typename T> struct ndimage_iter;
//template <typename I, typename T> struct ndimage_rev_iter;
//template <typename T, unsigned dim, typename I> struct ndimage_pixel_iterator;
//template <typename T, unsigned dim, typename I> struct ndimage_rev_pixel_iterator;
template <typename T, unsigned dim, typename I> struct ndimage_pixel;
template <typename T, unsigned dim, typename E> struct ndimage_base;
template <typename T, unsigned dim> struct ndimage;
/******************************************/
/**** Traits ****/
/******************************************/
template <typename T, unsigned dim, typename E>
struct image_traits< ndimage_base<T, dim, E> >
template <typename T, unsigned dim>
struct image_traits< ndimage<T, dim> >
{
typedef raw_image_tag category;
typedef std::true_type accessible;
......@@ -41,6 +39,14 @@ namespace mln
typedef std::true_type shallow_copy;
};
template <typename T, unsigned dim, typename V>
struct image_ch_value< ndimage<T, dim>, V >
{
typedef ndimage<V, dim> type;
};
/******************************************/
/**** Definition ****/
/******************************************/
......@@ -64,12 +70,17 @@ namespace mln
}
template <typename T, unsigned dim, typename E>
struct ndimage_base :
image_base<E, point<short, dim>, T, ndimage_pixel<T, dim, E>, ndimage_pixel<const T, dim, const E> >
template <typename T, unsigned dim>
struct ndimage :
image_base< ndimage<T, dim>, point<short, dim>, T, ndimage_pixel<T, dim, ndimage<T, dim> >, ndimage_pixel<const T, dim, const ndimage<T, dim> > >
{
private:
typedef ndimage_base<T, dim, E> this_type;
typedef image_base< ndimage<T, dim>,
point<short, dim>, T,
ndimage_pixel<T, dim, ndimage<T, dim> >,
ndimage_pixel<const T, dim, const ndimage<T, dim> > > base;
typedef ndimage<T, dim> this_type;
typedef ndimage<T, dim> E;
public:
// As an Image
......@@ -95,8 +106,16 @@ namespace mln
// As an Image
// \group Constructors
// \{
explicit ndimage_base(unsigned border = 3);
explicit ndimage_base(const domain_type& domain, unsigned border = 3, T v = T());
explicit ndimage(unsigned border = 3);
explicit ndimage(const domain_type& domain, unsigned border = 3, T v = T());
template <typename = typename std::enable_if<dim == 2>::type>
ndimage(short nrows, short ncols, unsigned border = 3, T v = T()) :
domain_ {{0,0},{nrows, ncols}},
border_ (border)
{
resize_(domain_, border, v);
}
// \}
const domain_type& domain() const;
......@@ -104,6 +123,10 @@ namespace mln
// As an ContainerImage
// \group Point-wise access
// \{
using base::operator ();
using base::at;
reference operator() (const site_type& p);
const_reference operator() (const site_type& p) const;
......@@ -165,13 +188,9 @@ namespace mln
// Specialized algorithm
template <typename T_, unsigned dim_, typename E_, typename Domain_>
friend typename std::enable_if<std::is_convertible<Domain_, typename ndimage_base<T_, dim_, E_>::domain_type>::value, E_>::type
make_subimage(ndimage_base<T_, dim_, E_>&, const Domain_& domain);
// template <typename T_, unsigned dim_, typename E_, typename Domain_>
// friend E_ make_subimage(ndimage_base<T_, dim_, E_>&, const Domain_& domain);
// template <typename T_, unsigned dim_, typename E_, typename Domain_>
// friend typename E_ make_subimage(ndimage_base<T_, dim_, E_>&&, const Domain_& domain);
template <typename T_, unsigned dim_, typename Domain_>
friend typename std::enable_if<std::is_convertible<Domain_, typename ndimage<T_, dim_>::domain_type>::value, ndimage<T_, dim_> >::type
make_subimage(const ndimage<T_, dim_>&, const Domain_& domain);
// As an Indexable Image
......@@ -212,10 +231,17 @@ namespace mln
}
template <typename = typename std::enable_if<dim == 2>::type >
unsigned nrows() const { return this->domain_.pmax[0] - this->domain_.pmin[0]; }
template <typename = typename std::enable_if<dim == 2>::type >
unsigned ncols() const { return this->domain_.pmax[1] - this->domain_.pmin[1]; }
protected:
friend struct ndimage_pixel<T, dim, E>;
friend struct ndimage_pixel<const T, dim, const E>;
template <typename, typename, unsigned, typename> friend struct indexible_ndimage_base;
template <typename, typename, unsigned, typename> friend struct indexible_ndimage;
template <typename, typename> friend struct ndimage_value_range;
template <typename, typename> friend struct ndimage_pixel_range;
......@@ -238,33 +264,11 @@ namespace mln
size_t m_index_last; ///< index of pmax
};
/******************************/
/** Free function Impl */
/******************************/
template <typename T>
struct image3d : ndimage_base<T, 3, image3d<T> >
{
protected:
typedef ndimage_base<T, 3, image3d<T> > base;
typedef typename base::domain_type domain_type;
public:
explicit image3d (unsigned border = 3) : base (border) {}
explicit image3d(const domain_type& domain, unsigned border = 3)
: base(domain, border)
{
}
image3d(short nslices, short nrows, short ncols, unsigned border = 3)
: base( (box<short,3>) {{{0,0,0}},{{nslices, nrows, ncols}}}, border)
{
}
};
namespace internal
{
template <typename T, unsigned dim>
......@@ -344,8 +348,8 @@ namespace mln
}
template <typename T, unsigned dim, typename E>
ndimage_base<T,dim,E>::ndimage_base(unsigned border)
template <typename T, unsigned dim>
ndimage<T,dim>::ndimage(unsigned border)
: domain_ (), border_ (border), ptr_ (NULL)
{
for (unsigned i = 0; i < dim; ++i){
......@@ -354,17 +358,17 @@ namespace mln
}
}
template <typename T, unsigned dim, typename E>
ndimage_base<T,dim,E>::ndimage_base(const domain_type& domain, unsigned border, T v)
template <typename T, unsigned dim>
ndimage<T,dim>::ndimage(const domain_type& domain, unsigned border, T v)
: domain_ (domain),
border_ (border)
{
resize_(domain_, border, v);
}
template <typename T, unsigned dim, typename E>
template <typename T, unsigned dim>
void
ndimage_base<T,dim,E>::resize_(const domain_type& domain, unsigned border, T v)
ndimage<T,dim>::resize_(const domain_type& domain, unsigned border, T v)
{
site_type shp = domain.shape();
point<size_t, dim> sz;
......@@ -396,19 +400,19 @@ namespace mln
}
template <typename T, unsigned dim, typename E>
template <typename T, unsigned dim>
void
ndimage_base<T,dim,E>::resize(const domain_type& domain, unsigned border, T v)
ndimage<T,dim>::resize(const domain_type& domain, unsigned border, T v)
{
domain_ = domain;
border_ = border;
resize_(domain_, border, v);
}
template <typename T, unsigned dim, typename E>
template <typename T, unsigned dim>
inline
T&
ndimage_base<T,dim,E>::at (const site_type& p)
ndimage<T,dim>::at (const site_type& p)
{
mln_precondition(vbox_.has(p));
......@@ -419,10 +423,10 @@ namespace mln
}
template <typename T, unsigned dim, typename E>
template <typename T, unsigned dim>
inline
const T&
ndimage_base<T,dim,E>::at (const site_type& p) const
ndimage<T,dim>::at (const site_type& p) const
{
mln_precondition(vbox_.has(p));
......@@ -433,71 +437,71 @@ namespace mln
}
template <typename T, unsigned dim, typename E>
template <typename T, unsigned dim>
inline
T&
ndimage_base<T,dim,E>::operator() (const site_type& p)
ndimage<T,dim>::operator() (const site_type& p)
{
mln_precondition(domain_.has(p));
return at(p);
}
template <typename T, unsigned dim, typename E>
template <typename T, unsigned dim>
inline
const T&
ndimage_base<T,dim,E>::operator() (const site_type& p) const
ndimage<T,dim>::operator() (const site_type& p) const
{
mln_precondition(domain_.has(p));
return at(p);
}
template <typename T, unsigned dim, typename E>
template <typename T, unsigned dim>
inline
T&
ndimage_base<T,dim,E>::operator[] (std::size_t i)
ndimage<T,dim>::operator[] (std::size_t i)
{
mln_precondition(vbox_.has(point_at_index(i)));
return *(m_ptr_origin + i);
}
template <typename T, unsigned dim, typename E>
template <typename T, unsigned dim>
inline
const T&
ndimage_base<T,dim,E>::operator[] (std::size_t i) const
ndimage<T,dim>::operator[] (std::size_t i) const
{
mln_precondition(vbox_.has(point_at_index(i)));
return *(m_ptr_origin + i);
}
// template <typename T, unsigned dim, typename E>
// template <typename T, unsigned dim>
// inline
// T&
// ndimage_base<T,dim,E>::element (difference_type n)
// ndimage<T,dim>::element (difference_type n)
// {
// return *reinterpret_cast<T*>(ptr_+n);
// }
// template <typename T, unsigned dim, typename E>
// template <typename T, unsigned dim>
// inline
// const T&
// ndimage_base<T,dim,E>::element (difference_type n) const
// ndimage<T,dim>::element (difference_type n) const
// {
// return *reinterpret_cast<const T*>(ptr_+n);
// }
template <typename T, unsigned dim, typename E>
template <typename T, unsigned dim>
const size_t*
ndimage_base<T,dim,E>::strides () const
ndimage<T,dim>::strides () const
{
return &strides_[0];
}
// template <typename T, unsigned dim, typename E>
// template <typename T, unsigned dim>
// ptrdiff_t
// ndimage_base<T,dim,E>::offset (point_type dp) const
// ndimage<T,dim>::offset (point_type dp) const
// {
// ptrdiff_t x = 0;
// for (unsigned i = 0; i < dim; ++i)
......@@ -505,44 +509,44 @@ namespace mln
// return x;
// }
template <typename T, unsigned dim, typename E>
template <typename T, unsigned dim>
inline
const typename ndimage_base<T,dim,E>::domain_type&
ndimage_base<T,dim,E>::domain () const
const typename ndimage<T,dim>::domain_type&
ndimage<T,dim>::domain () const
{
return domain_;
}
/* -- Value range -- */
template <typename T, unsigned dim, typename E>
template <typename T, unsigned dim>
inline
typename ndimage_base<T,dim,E>::const_value_range
ndimage_base<T,dim,E>::values () const
typename ndimage<T,dim>::const_value_range
ndimage<T,dim>::values () const
{
return const_value_range(exact(*this));
}
template <typename T, unsigned dim, typename E>
template <typename T, unsigned dim>
inline
typename ndimage_base<T,dim,E>::value_range
ndimage_base<T,dim,E>::values ()
typename ndimage<T,dim>::value_range
ndimage<T,dim>::values ()
{
return value_range(*this);
}
template <typename T, unsigned dim, typename E>
template <typename T, unsigned dim>
inline
typename ndimage_base<T,dim,E>::const_pixel_range
ndimage_base<T,dim,E>::pixels () const
typename ndimage<T,dim>::const_pixel_range
ndimage<T,dim>::pixels () const
{
return const_pixel_range(*this);
}
template <typename T, unsigned dim, typename E>
template <typename T, unsigned dim>
inline
typename ndimage_base<T,dim,E>::pixel_range
ndimage_base<T,dim,E>::pixels ()
typename ndimage<T,dim>::pixel_range
ndimage<T,dim>::pixels ()
{
return pixel_range(*this);
}
......
......@@ -10,19 +10,19 @@ namespace mln
// fwd decl
template <typename, unsigned, typename> struct ndimage_base;
template <typename T, unsigned dim, typename E, typename Domain>
typename std::enable_if< std::is_convertible<Domain, typename ndimage_base<T, dim, E>::domain_type>::value, const E>::type
make_subimage(const ndimage_base<T, dim, E>&,
template <typename T, unsigned dim, typename Domain>
typename std::enable_if< std::is_convertible<Domain, typename ndimage<T, dim>::domain_type>::value, ndimage<T, dim> >::type
make_subimage(const ndimage<T, dim>&,
const Domain& domain);
template <typename T, unsigned dim, typename E, typename Domain>
typename std::enable_if< std::is_convertible<Domain, typename ndimage_base<T, dim, E>::domain_type>::value, E>::type
make_subimage(ndimage_base<T, dim, E>&,
template <typename T, unsigned dim, typename Domain>
typename std::enable_if< std::is_convertible<Domain, typename ndimage<T, dim>::domain_type>::value, ndimage<T, dim> >::type
make_subimage(ndimage<T, dim>&,
const Domain& domain);
template <typename T, unsigned dim, typename E, typename Domain>
typename std::enable_if< std::is_convertible<Domain, typename ndimage_base<T, dim, E>::domain_type>::value, E>::type
make_subimage(ndimage_base<T, dim, E>&&,
template <typename T, unsigned dim, typename Domain>
typename std::enable_if< std::is_convertible<Domain, typename ndimage<T, dim>::domain_type>::value, ndimage<T, dim> >::type
make_subimage(ndimage<T, dim>&&,
const Domain& domain);
......@@ -30,13 +30,22 @@ namespace mln
/**** Implementation ****/
/******************************************/
template <typename T, unsigned dim, typename E, typename Domain>
template <typename T, unsigned dim, typename Domain>
inline
typename std::enable_if< std::is_convertible<Domain, typename ndimage_base<T, dim, E>::domain_type>::value, E>::type
make_subimage(ndimage_base<T, dim, E>& image,
typename std::enable_if< std::is_convertible<Domain, typename ndimage<T, dim>::domain_type>::value, ndimage<T, dim> >::type
make_subimage(ndimage<T, dim>& image,
const Domain& domain)
{
E other(exact(image));
return make_subimage((const ndimage<T, dim>&) image, domain);
}
template <typename T, unsigned dim, typename Domain>
inline
typename std::enable_if< std::is_convertible<Domain, typename ndimage<T, dim>::domain_type>::value, ndimage<T, dim> >::type
make_subimage(const ndimage<T, dim>& image,
const Domain& domain)
{
ndimage<T, dim> other(image);
other.domain_ = domain;