Commit 4876b965 authored by edwin.carlinet's avatar edwin.carlinet
Browse files

Add base algorithms.


  * mln/core/algorithm/copy.hpp,
  * mln/core/algorithm/equal.hpp,
  * mln/core/algorithm/fill.hpp,
  * mln/core/algorithm/iota.hpp,
  * mln/core/algorithm/paste.hpp,
  * mln/core/algorithms.hpp,
  * tests/core/algorithm/copy.cpp,
  * tests/core/algorithm/equal.cpp,
  * tests/core/algorithm/fill.cpp,
  * tests/core/algorithm/paste.cpp: Algorithms + test
parent 59148208
#ifndef MLN_CORE_ALGORITHM_COPY_HPP
# define MLN_CORE_ALGORITHM_COPY_HPP
# include <mln/core/assert.hpp>
# include <mln/core/concept/image.hpp>
# include <boost/range/algorithm/copy.hpp>
/// \file
namespace mln {
/*
// \brief Copy an image to memory pointed by the iterator \p it.
//
// \param[in] input Input image
// \param it Output iterator
//
// \return it + number of elements in the image.
//
template <typename I, typename OutputIterator>
OutputIterator
copy(const Image<I>& input, OutputIterator it);
*/
/// \brief Copy a source image to an output image regardless domain.
///
/// \ingroup Algorithms
///
/// The output image must have a domain larger than the input image.
/// 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++;
/// \endcode
///
/// \param[in] input Input Image
/// \param[out] output Output Image
/// \return The image where values have been copied in.
///
/// \todo add specialization for raw images
///
template <typename InputImage, typename OutputImage>
OutputImage&
copy(const Image<InputImage>& input, Image<OutputImage>& output);
/// \overload
/// \ingroup Algorithms
template <typename InputImage, typename OutputImage>
OutputImage&&
copy(const Image<InputImage>& input, Image<OutputImage>&& output);
/******************************************/
/**** Implementation ****/
/******************************************/
namespace impl
{
template <typename I, typename OutputIterator>
inline
OutputIterator
copy(const I& input, OutputIterator it)
{
return boost::copy(input.values(), it);
}
}
template <typename InputImage, typename OutputImage>
OutputImage&
copy(const Image<InputImage>& input, Image<OutputImage>& output)
{
impl::copy(exact(input), std::begin(exact(output).values()));
return exact(output);
}
template <typename InputImage, typename OutputImage>
OutputImage&&
copy(const Image<InputImage>& input, Image<OutputImage>&& output)
{
impl::copy(exact(input), std::begin(fwd_exact(output).values()));
return fwd_exact(output);
}
} // end of namespace mln
#endif //!MLN_CORE_ALGORITHM_COPY_HPP
#ifndef MLN_CORE_ALGORITHM_EQUAL_HPP
# define MLN_CORE_ALGORITHM_EQUAL_HPP
# include <mln/core/concept/image.hpp>
# include <mln/core/image/zip_image.hpp>
namespace mln
{
/// \brief Compare if two image are equals.
///
/// Two image are said equal if their domains
/// are equals and have the same values.
///
/// \param ima1 First image
/// \param ima2 Second image
///
/// \tparam I must model a Readable Forward Image
/// \tparam J must model a Readable Forward Image
///
/// \return True if image are equals.
///
template <typename I, typename J>
bool
equal(const Image<I>& ima1, const Image<J>& ima2);
/******************************************/
/**** Implementation ****/
/******************************************/
template <typename I, typename J>
inline
bool
equal(const Image<I>& ima1, const Image<J>& ima2)
{
// FIXME: add test for domain comparison
for (auto x: imzip(exact(ima1), exact(ima2)).values())
if (boost::get<0>(x) != boost::get<1>(x))
return false;
return true;
};
} // end of namespace mln
#endif //!MLN_CORE_ALGORITHM_EQUAL_HPP
#ifndef MLN_CORE_ALGORITHM_IMFILL_HPP
# define MLN_CORE_ALGORITHM_IMFILL_HPP
# include <mln/core/concept/image.hpp>
# include <boost/range/algorithm/fill.hpp>
namespace mln {
/// \brief \p fill assigns the value \p val to every element of the image \p
/// ima.
/// \ingroup Algorithms
///
/// \param[out] output The output image.
/// \param val The value to assign.
///
/// \return The image.
///
/// \tparam OutputImage is a model of the Writable Forward Image.
/// \tparam Value must be convertible to Image's value type.
/// \ingroup algorithms
template <typename OutputImage, typename Value>
OutputImage&
fill(Image<OutputImage>& output, const Value& val);
/// \overload
/// \ingroup Algorithms
template <typename OutputImage, typename Value>
OutputImage&&
fill(Image<OutputImage>&& output, const Value& val);
/******************************************/
/**** Implementation ****/
/******************************************/
template <typename OutputImage, typename Value>
OutputImage&&
fill(Image<OutputImage>&& output_, const Value& val)
{
OutputImage&& output = fwd_exact(output_);
boost::fill(output.values(), val);
return fwd_exact(output);
}
template <typename OutputImage, typename Value>
OutputImage&
fill(Image<OutputImage>& output_, const Value& val)
{
OutputImage& output = exact(output_);
boost::fill(output.values(), val);
return output;
}
} // end of namespace mln
#endif //!MLN_CORE_ALGORITHM_IMFILL_HPP
#ifndef MLN_CORE_ALGORITHM_IOTA_HPP
# define MLN_CORE_ALGORITHM_IOTA_HPP
# include <mln/core/concept/image.hpp>
# include <boost/range/algorithm_ext/iota.hpp>
namespace mln {
/// \brief \p iota traverses the image, the `i`th pixel is assigned
/// with `val + i`
///
/// \ingroup Algorithms
///
/// \param[out] ima The output image.
/// \param val The value to assign.
///
/// \return The image.
///
/// \tparam I is a model of the Writable Forward Image.
/// \tparam Value must be convertible to Image's value type.
template <typename I, typename Value>
I&
iota(Image<I>& output, Value val);
/// \overload
/// \ingroup Algorithms
template <typename I, typename Value>
I&&
iota(Image<I>&& output, Value val);
/******************************************/
/**** Implementation ****/
/******************************************/
template <typename I, typename Value>
inline
I&&
iota(Image<I>&& output_, Value val)
{
I&& output = fwd_exact(output_);
boost::iota(output.values(), val);
return std::forward<I>(output);
}
template <typename I, typename Value>
inline
I&
iota(Image<I>& output_, Value val)
{
I& output = exact(output_);
boost::iota(output.values(), val);
return output;
}
} // end of namespace mln
#endif //!MLN_CORE_ALGORITHM_IMFILL_HPP
#ifndef MLN_CORE_ALGORITHM_PASTE_HPP
# define MLN_CORE_ALGORITHM_PASTE_HPP
# include <mln/core/concept/image.hpp>
namespace mln {
/// \brief \p paste copy each pixel from the input image to the output image.
///
/// \ingroup Algorithms
///
/// Each pixel of the input image is paste to the output image. It implies
/// that \p input's domain must be included in \p output's domain.
/// This is equivalent to the following code:
///
/// \code
/// for (auto px: input.pixels())
/// output(px.point()) = px.val()
/// \endcode
///
/// \param[in] input The input image.
/// \param[out] output The output image
///
/// \return The output image.
///
/// \pre `output.domain()` includes `input.domain()`
/// \tparam InputImage is a model of the Forward Image.
/// \tparam OutputImage is a model of the Writable Point-Accessible Image
template <typename InputImage, typename OutputImage>
OutputImage&
paste(const Image<InputImage>& input, Image<OutputImage>& output);
/// \ingroup Algorithms
/// \overload
template <typename InputImage, typename OutputImage>
OutputImage&&
paste(const Image<InputImage>& input, Image<OutputImage>&& output);
/******************************************/
/**** Implementation ****/
/******************************************/
template <typename InputImage, typename OutputImage>
OutputImage&
paste(const Image<InputImage>& input, Image<OutputImage>& output_)
{
paste(input, fwd_exact(output_));
return exact(output_);
}
template <typename InputImage, typename OutputImage>
OutputImage&&
paste(const Image<InputImage>& input_, Image<OutputImage>&& output_)
{
OutputImage&& output = fwd_exact(output_);
for (auto px: exact(input_).pixels())
output(px.point()) = px.val();
return std::forward<OutputImage>(output);
}
} // end of namespace mln
#endif //!MLN_CORE_ALGORITHM_IMFILL_HPP
#ifndef MLN_CORE_ALGORITHMS_HPP
# define MLN_CORE_ALGORITHMS_HPP
/// \file
/// \defgroup Algorithms
/// \{
# include <mln/core/algorithm/copy.hpp>
# include <mln/core/algorithm/iota.hpp>
# include <mln/core/algorithm/fill.hpp>
# include <mln/core/algorithm/paste.hpp>
/// \}
#endif //!MLN_CORE_ALGORITHMS_HPP
#include <mln/core/image/image2d.hpp>
#include <mln/core/grays.hpp>
#include <mln/core/algorithm/copy.hpp>
#define BOOST_TEST_MODULE Algorithm
#include <boost/test/unit_test.hpp>
#include <boost/range/algorithm/equal.hpp>
#include <boost/range/algorithm_ext/iota.hpp>
BOOST_AUTO_TEST_CASE(Copy)
{
using namespace mln;
image2d<uint8> ima(10, 10);
image2d<uint8> out(10, 10);
boost::iota(ima.values(), 0);
copy(ima, out);
BOOST_CHECK( boost::equal(ima.values(), out.values()) );
}
#include <mln/core/image/image2d.hpp>
#include <mln/core/grays.hpp>
#include <mln/core/algorithm/equal.hpp>
#include <mln/core/algorithm/iota.hpp>
#define BOOST_TEST_MODULE Algorithm
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_CASE(Equal)
{
using namespace mln;
image2d<uint8> ima(10, 10);
image2d<uint8> out(10, 10);
iota(ima, 0);
iota(out, 0);
BOOST_CHECK(equal(ima, out));
point2d p = {{2,3}};
out(p) = 12;
BOOST_CHECK(not equal(ima, out));
}
#include <mln/core/image/image2d.hpp>
#include <mln/core/grays.hpp>
#include <mln/core/algorithm/fill.hpp>
#define BOOST_TEST_MODULE Algorithm
#include <boost/test/unit_test.hpp>
#include <boost/range/algorithm/count.hpp>
BOOST_AUTO_TEST_CASE(Fill)
{
using namespace mln;
image2d<uint8> ima(10, 10);
fill(ima, 69);
BOOST_CHECK( boost::count(ima.values(), 69) == 100 );
}
#include <mln/core/image/image2d.hpp>
#include <mln/core/grays.hpp>
#include <mln/core/algorithm/paste.hpp>
#include <mln/core/algorithm/fill.hpp>
#include <mln/core/algorithm/iota.hpp>
#define BOOST_TEST_MODULE Algorithm
#include <boost/test/unit_test.hpp>
#include <boost/range/numeric.hpp>
BOOST_AUTO_TEST_CASE(Paste)
{
using namespace mln;
box2d b = {{1,1}, {3,3}};
image2d<uint8> ima(b);
image2d<uint8> out(15, 15);
fill(ima, 69);
iota(out, 1);
paste(ima, out);
// 1 2 3 4..
// 16 x x 19
// 31 x x 34
// 46 47 48 49
int r = boost::accumulate(out.values(), 0);
BOOST_CHECK_EQUAL( r, 225*226/2 - (17+18+32+33) + 69*4 );
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment