Commit 6d760b1c authored by Edwin Carlinet's avatar Edwin Carlinet
Browse files

Improve documentation.

parent d75e6fa4
......@@ -4,9 +4,20 @@
# include <mln/core/image/image.hpp>
# include <mln/core/algorithm/copy.hpp>
/// \file
/// \brief Header file for clone algorithm.
namespace mln
{
/// \ingroup Algorithms
/// \brief Make and return a deep copy of an image.
///
/// If the image is not already concrete (e.g. a morpher with no
/// proper memory), the image is concretized.
///
/// \tparam I The input image type
/// \param ima The image to clone.
template <typename I>
mln_concrete(I)
clone(const Image<I>& ima);
......
......@@ -28,11 +28,10 @@ namespace mln {
/// This is equivalent to the following code.
///
/// \code
/// vin = std::begin(input.values())
/// vend = std::end(input.values())
/// vout = std::begin(output.values())
/// while (vin != vend)
/// vout++ = vin++;
/// mln_iter(vin, input.values())
/// mln_iter(vout, output.values())
/// mln_forall(vin, vout)
/// *vout = *vin;
/// \endcode
///
/// \param[in] input Input Image
......
......@@ -15,7 +15,7 @@ namespace mln {
/// This is equivalent to the following code:
///
/// \code
/// for (auto px: input.pixels())
/// mln_foreach (auto px, input.pixels())
/// output(px.point()) = px.val()
/// \endcode
///
......@@ -49,10 +49,9 @@ namespace mln {
{
mln_pixter(px, ima);
mln_forall(px)
out(px->point()) = px->val();
out(px->point()) = px->val();
}
}
template <typename InputImage, typename OutputImage>
......
......@@ -3,13 +3,34 @@
# include <mln/core/image/image.hpp>
namespace mln {
/// \file
namespace mln {
/// \ingroup Algorithms
/// \brief Transform the value of an image through a function.
///
/// This is equivalent to the following code.
/// \code
/// mln_iter(vout, out.values())
/// mln_iter(vin, in.values())
/// mln_forall(vin, vout)
/// *vout = f(*vin)
///
/// \endcode
///
/// \tparam InputImage A model of :concept:ref:`forward_image`
/// \tparam OutputImage A model of Writable :concept:ref:`forward_image`
/// \tparam UnaryFunction A mondel of unary function.
/// \param input The input image.
/// \param f The unary function.
/// \param output The output image.
/// \see mln::imtransform
template <typename InputImage, typename OutputImage, class UnaryFunction>
OutputImage&
transform(const Image<InputImage>& input, UnaryFunction f, Image<OutputImage>& output);
/// \overload
template <typename InputImage, typename OutputImage, class UnaryFunction>
OutputImage&&
transform(const Image<InputImage>& input, UnaryFunction f, Image<OutputImage>&& output);
......@@ -18,6 +39,7 @@ namespace mln {
unary_image_expr<UnaryFunction, InputImage>
lazy_transform(InputImage&& input, UnaryFunction f);
/// \overload
template <typename InputImage, class UnaryFunction>
mln_ch_value(InputImage,
typename std::decay<
......@@ -38,7 +60,7 @@ namespace mln {
{
mln_viter(vin, vout, input, output);
mln_forall(vin, vout)
*vout = f(*vin);
*vout = f(*vin);
}
}
......
......@@ -2,12 +2,14 @@
# define MLN_CORE_ALGORITHMS_HPP
/// \file
/// \defgroup Algorithms
/// \defgroup Algorithms General Image Algorithms.
/// \{
# include <mln/core/algorithm/accumulate.hpp>
# include <mln/core/algorithm/copy.hpp>
# include <mln/core/algorithm/iota.hpp>
# include <mln/core/algorithm/fill.hpp>
# include <mln/core/algorithm/paste.hpp>
# include <mln/core/algorithm/transform.hpp>
/// \}
#endif //!MLN_CORE_ALGORITHMS_HPP
#ifndef MLN_CORE_CH_VALUE_HPP
# define MLN_CORE_CH_VALUE_HPP
/// \file
/// \brief Meta-Function to transform images.
# define mln_ch_value(I, V) typename image_ch_value<I, V>::type
# define mln_concrete(I) typename image_concrete<I>::type
......
......@@ -29,9 +29,9 @@ namespace mln
template <typename T, unsigned dim, typename E> struct ndimage_base;
/******************************************/
/**** Traits ****/
/******************************************/
/******************************************/
/**** Traits ****/
/******************************************/
template <typename T, unsigned dim, typename E>
......@@ -46,9 +46,9 @@ namespace mln
typedef mln::extension::border_extension_tag extension;
};
/******************************************/
/**** Definition ****/
/******************************************/
/******************************************/
/**** Definition ****/
/******************************************/
namespace internal
{
......@@ -114,8 +114,12 @@ 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> >
struct ndimage_base
#ifndef MLN_DOXYGEN
: image_base<E, point<short, dim>, T,
ndimage_pixel<T, dim, E>,
ndimage_pixel<const T, dim, const E> >
#endif
{
private:
typedef ndimage_base<T, dim, E> this_type;
......@@ -126,29 +130,65 @@ namespace mln
template <unsigned d, typename T1, typename E1, typename T2, typename E2>
friend
bool are_indexes_compatible(const ndimage_base<T1, d, E1>& self,
const ndimage_base<T2, d, E2>& other);
const ndimage_base<T2, d, E2>& other);
public:
// As an Image
/// \name Image point/value/pixel types
/// \{
typedef box<short, dim> domain_type;
/// \copydoc image::site_type
typedef point<short,dim> site_type;
/// \copydoc image::point_type
typedef point<short,dim> point_type;
typedef ndimage_pixel<const T, dim, const E> const_pixel_type;
/// \copydoc image::pixel_type
typedef ndimage_pixel<T, dim, E> pixel_type;
typedef T value_type;
enum { ndim = dim};
// As a ContainerImage
typedef T& reference;
typedef const T& const_reference;
typedef T* pointer;
typedef const T* const_pointer;
typedef int difference_type;
typedef unsigned index_type;
typedef unsigned size_type;
/// \copydoc image::const_pixel_type
typedef ndimage_pixel<const T, dim, const E> const_pixel_type;
/// \copydoc image::value_type
typedef T value_type;
/// \copydoc image::reference
typedef T& reference;
/// \copydoc image::const_reference
typedef const T& const_reference;
/// \copydoc image::difference_type
typedef int difference_type;
/// \copydoc image::size_type
typedef unsigned size_type;
typedef unsigned index_type;
typedef T* pointer;
typedef const T* const_pointer;
/// \}
/// \name Image Ranges Types
/// \{
/// \copydoc image::domain_type
typedef box<short, dim> domain_type;
/// \copydoc image::value_range
typedef ndimage_value_range<this_type, T> value_range;
/// \copydoc image::const_value_range
typedef ndimage_value_range<const this_type, const T> const_value_range;
/// \copydoc image::pixel_range
typedef ndimage_pixel_range<this_type, T> pixel_range;
/// \copydoc image::const_pixel_range
typedef ndimage_pixel_range<const this_type, const T> const_pixel_range;
/// \}
enum { ndim = dim};
// As an Image
// Constructors
......@@ -157,84 +197,133 @@ namespace mln
explicit ndimage_base(const domain_type& domain, unsigned border = 3, T v = T());
// \}
const domain_type& domain() const;
/// \name Accession Operators
/// \{
/// \copydoc image::operator()(const site_type& p) const
reference operator() (const site_type& p);
/// \copydoc image::operator()(const site_type& p) const
const_reference operator() (const site_type& p) const;
/// \copydoc image::operator[](size_type i) const
reference operator[] (size_type i);
/// \copydoc image::operator[](size_type i) const
const_reference operator[] (size_type i) const;
/// \copydoc image::at(const site_type& p) const
reference at (const site_type& p);
/// \copydoc image::at(const site_type& p) const
const_reference at (const site_type& p) const;
/// \}
// FIXME move to base
pixel_type pixel_at(const site_type& p)
{
pixel_type pix;
pix.point_ = p;
pix.ima_ = (E*)this;
pix.ptr_ = (char*) & (operator () (p));
return pix;
}
/// \name Pixel utilities
/// \{
const_pixel_type pixel_at(const site_type& p) const
{
const_pixel_type pix((const E*) this);
pix.point_ = p;
pix.ptr_ = (char*) & (operator () (p));
return pix;
}
/// \copydoc image::pixel_at(const point_type&) const
pixel_type pixel_at(const point_type& p);
/// \copydoc image::pixel_at(const point_type&) const
const_pixel_type pixel_at(const point_type& p) const;
pixel_type pixel(const site_type& p)
{
mln_precondition(domain_.has(p));
return pixel_at(p);
}
/// \copydoc image::pixel(const point_type&) const
pixel_type pixel(const point_type& p);
const_pixel_type pixel(const site_type& p) const
{
mln_precondition(domain_.has(p));
return pixel_at(p);
}
/// \copydoc image::pixel(const point_type&) const
const_pixel_type pixel(const point_type& p) const;
/// \}
// As a Resizable Image
void resize(const domain_type& domain, unsigned border = 3, T v = T());
// As an IterableImage
typedef ndimage_value_range<this_type, T> value_range;
typedef ndimage_value_range<const this_type, const T> const_value_range;
typedef typename value_range::iterator value_iterator;
typedef typename value_range::reverse_iterator reverse_value_iterator;
typedef typename const_value_range::iterator const_value_iterator;
typedef typename value_range::iterator value_iterator;
typedef typename value_range::reverse_iterator reverse_value_iterator;
typedef typename const_value_range::iterator const_value_iterator;
typedef typename const_value_range::reverse_iterator const_reverse_value_iterator;
typedef ndimage_pixel_range<this_type, T> pixel_range;
typedef ndimage_pixel_range<const this_type, const T> const_pixel_range;
typedef typename pixel_range::iterator pixel_iterator;
typedef typename pixel_range::reverse_iterator reverse_pixel_iterator;
typedef typename const_pixel_range::iterator const_pixel_iterator;
typedef typename pixel_range::iterator pixel_iterator;
typedef typename pixel_range::reverse_iterator reverse_pixel_iterator;
typedef typename const_pixel_range::iterator const_pixel_iterator;
typedef typename const_pixel_range::reverse_iterator const_reverse_pixel_iterator;
/// \name Image Ranges
/// \{
/// \copydoc image::domain()
const domain_type& domain() const;
/// \copydoc image::values()
value_range values();
value_range values();
const_value_range values() const;
/// \copydoc image::values() const
const_value_range values() const;
/// \copydoc image::pixels()
pixel_range pixels();
/// \copydoc image::pixels() const
const_pixel_range pixels() const;
/// \}
/// \name Concrete-related Image Methods
/// \{
/// \brief Resize the image to fit \p domain.
///
/// Resize the image w.r.t to \p domain and \p border. The image is
/// initialized with value \p v.
/// \warning The old values are not kept.
/// \param domain The new domain of the image.
/// \param border The new border of the image.
/// \param v The initialization value of the image. If \p is given, values
/// are copy constructed from \p v, otherwise, they are default-initialized.
void resize(const domain_type& domain, unsigned border = 3, T v = T());
/// \brief Re-indexation of the image.
///
/// Reindex the image so that the index of the first point is \p
/// index_first.
/// \param index_first
/// \postcondition `this->index_of_point(domain().pmin) == index_first`
void reindex(size_type index_first)
{
std::ptrdiff_t diff = index_first - m_index_first;
m_ptr_origin -= diff;
m_index_first += diff;
m_index_last += diff;
}
/// \}
/// \name Index-related methods
/// \{
/// \copydoc image::index_of_point(const point_type&) const
size_type index_of_point(const point_type& p) const;
/// \copydoc image::point_at_index(size_type i) const
point_type point_at_index(size_type i) const;
/// \copydoc image::delta_index(const point_type&) const
difference_type delta_index(const point_type& p) const;
/// \}
// As a Raw Image
const size_t* strides() const;
const std::size_t* strides() const;
int border() const { return border_; }
// 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);
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_>
......@@ -248,55 +337,15 @@ namespace mln
// bool friend_index_compatible(ndimage_base self, const Image<O>& other) const;
void reindex(std::size_t index_first)
{
std::ptrdiff_t diff = index_first - m_index_first;
m_ptr_origin -= diff;
m_index_first += diff;
m_index_last += diff;
}
size_type index_of_point(const point_type& p) const
{
std::size_t idx = m_index_first;
point_type q = p - domain_.pmin;
for (unsigned i = 0; i < dim; ++i)
idx += q[i] * m_index_strides[i];
return idx;
}
point_type point_at_index(size_type idx) const
{
int k = idx;
int kpmin = m_index_first;
point_type p = point_type ();
for (unsigned i = 0; i < dim; ++i) {
std::div_t off = std::div((int)kpmin, (int)m_index_strides[i]);
std::div_t res = std::div((int)k, (int)m_index_strides[i]);
p[i] = res.quot - off.quot + domain_.pmin[i];
k = res.rem;
kpmin = off.rem;
}
//p -= (domain_.pmin + border_);
mln_postcondition(vbox_.has(p));
return p;
}
difference_type delta_index(const point_type& p) const
{
difference_type idx = 0;
for (unsigned i = 0; i < dim; ++i)
idx += p[i] * m_index_strides[i];
return idx;
}
difference_type delta_offset(const point_type& p) const
{
difference_type idx = 0;
for (unsigned i = 0; i < dim; ++i)
idx += p[i] * strides_[i];
idx += p[i] * strides_[i];
return idx;
}
......@@ -365,7 +414,7 @@ namespace mln
ndimage_data<T, dim>::ndimage_data(size_t* shape_, unsigned border, T v)
{
for (unsigned i = 0; i < dim; ++i)
shape[i] = shape_[i] + 2 * border;
shape[i] = shape_[i] + 2 * border;
strides[dim-1] = sizeof(T);
......@@ -374,18 +423,18 @@ namespace mln
#ifdef MLN_128B_ALIGNMENT
if (ndim >= 2)
{
strides[dim-2] = ((shape[dim-1] * sizeof(T)) & ~(size_t)15) + (size_t) 16;
for (int i = dim-3; i >= 0; --i)
strides[i] = shape[i+1] * strides[i+1];
}
{
strides[dim-2] = ((shape[dim-1] * sizeof(T)) & ~(size_t)15) + (size_t) 16;
for (int i = dim-3; i >= 0; --i)
strides[i] = shape[i+1] * strides[i+1];
}
#else
if (ndim >= 2)
{
strides[dim-2] = shape[dim-1] * sizeof(T);
for (int i = dim-3; i >= 0; --i)
strides[i] = shape[i+1] * strides[i+1];
}
{
strides[dim-2] = shape[dim-1] * sizeof(T);
for (int i = dim-3; i >= 0; --i)
strides[i] = shape[i+1] * strides[i+1];
}
#endif
// Allocate data
......@@ -394,11 +443,11 @@ namespace mln
// Construct
{
char* ptr = buffer;
unsigned nlines = 1;
for (unsigned i = 0; i < dim-1; ++i)
nlines *= shape[i];
unsigned nelements = shape[dim-1];
char* ptr = buffer;
unsigned nlines = 1;
for (unsigned i = 0; i < dim-1; ++i)
nlines *= shape[i];
unsigned nelements = shape[dim-1];
if (dim > 1) {
for (unsigned i = 0; i < nlines; ++i, ptr += strides[dim-2]) {
......@@ -421,7 +470,7 @@ namespace mln
char* ptr = buffer;
unsigned nlines = 1;
for (unsigned i = 0; i < dim-1; ++i)
nlines *= shape[i];
nlines *= shape[i];
unsigned nelements = shape[dim-1];
if (dim == 1) {
for (unsigned k = 0; k < nelements; ++k)
......@@ -440,7 +489,7 @@ namespace mln
template <typename T, unsigned dim, typename E>
ndimage_base<T,dim,E>::ndimage_base(unsigned border)
: domain_ (), border_ (border), ptr_ (NULL)
: domain_ (), border_ (border), ptr_ (NULL)
{
for (unsigned i = 0; i < dim; ++i){
mln_postcondition(domain_.pmin[i] == 0);
......@@ -481,11 +530,11 @@ namespace mln
last_ = data_->buffer + (border + sz[dim-1] - 1) * strides_[dim-1];
for (int i = dim-2; i >= 0; --i)
{
m_index_strides[i] = strides_[i] / sizeof(T);
m_index_first += border_ * m_index_strides[i];
m_index_last += (border_ + sz[i] - 1) * m_index_strides[i];
ptr_ += border * strides_[i];
last_ += (border + sz[i] - 1) * strides_[i];
m_index_strides[i] = strides_[i] / sizeof(T);
m_index_first += border_ * m_index_strides[i];
m_index_last += (border_ + sz[i] - 1) * m_index_strides[i];
ptr_ += border * strides_[i];
last_ += (border + sz[i] - 1) * strides_[i];
}
}
......@@ -570,6 +619,90 @@ namespace mln
return *(m_ptr_origin + i);
}
template <typename T, unsigned dim, typename E>
inline
typename ndimage_base<T,dim,E>::pixel_type
ndimage_base<T,dim,E>::pixel_at(const point_type& p)
{
pixel_type pix;
pix.point_ = p;
pix.ima_ = (E*)this;
pix.ptr_ = (char*) & (operator () (p));
return pix;
}
template <typename T, unsigned dim, typename E>
inline
typename ndimage_base<T,dim,E>::const_pixel_type
ndimage_base<T,dim,E>::pixel_at(const point_type& p) const
{
const_pixel_type pix((const E*) this);
pix.point_ = p;
pix.ptr_ = (char*) & (operator () (p));
return pix;
}
template <typename T, unsigned dim, typename E>
inline
typename ndimage_base<T,dim,E>::pixel_type
ndimage_base<T,dim,E>::pixel(const point_type& p)
{
mln_precondition(domain_.has(p));
return pixel_at(p);