Commit cd1dff58 authored by Guillaume Duhamel's avatar Guillaume Duhamel
Browse files

Subdirectory border ready for rereading.


	* mln/border/all.hh: Update with all headers.

	* mln/border/mirror.hh: Add 2d version.

	* mln/border/adjust.hh,
	* mln/border/duplicate.hh,
	* mln/border/equalize.hh,
	* mln/border/fill.hh,
	* mln/border/find.hh,
	* mln/border/resize.hh,
	* mln/border/get.hh: Check typo and tracing.

	Tests

	* tests/border/equalize.cc,
	* tests/border/mirror.cc: New test for these algorithms.

	* tests/border/Makefile.am: Add previous tests.

git-svn-id: https://svn.lrde.epita.fr/svn/oln/trunk@1518 4aad255d-cdde-0310-9447-f3009e2ae8c0
parent af2ef844
2007-11-22 Guillaume Duhamel <guillaume.duhamel@lrde.epita.fr>
Subdirectory border ready for rereading.
* mln/border/all.hh: Update with all headers.
* mln/border/mirror.hh: Add 2d version.
* mln/border/adjust.hh,
* mln/border/duplicate.hh,
* mln/border/equalize.hh,
* mln/border/fill.hh,
* mln/border/find.hh,
* mln/border/resize.hh,
* mln/border/get.hh: Check typo and tracing.
Tests
* tests/border/equalize.cc,
* tests/border/mirror.cc: New test for these algorithms.
* tests/border/Makefile.am: Add previous tests.
2007-11-22 Thierry Geraud <thierry.geraud@lrde.epita.fr>
Fix modulus definition involving builtin.
......
......@@ -58,13 +58,13 @@ namespace mln
void adjust(const Image<I>& ima, unsigned min_thickness);
# ifndef MLN_INCLUDE_ONLY
template <typename I>
void adjust(const Image<I>& ima_, unsigned min_thickness)
{
trace::entering("border::adjust");
mlc_is(mln_trait_image_border(I), trait::image::border::some)::check();
const I& ima = exact(ima_);
mln_precondition(ima.has_data());
......@@ -73,6 +73,7 @@ namespace mln
border::resize(ima, min_thickness);
mln_postcondition(border::get(ima) >= min_thickness);
trace::exiting("border::adjust");
}
......
......@@ -41,18 +41,25 @@ namespace mln
namespace border
{
/// Implementation namespace of border namespace.
namespace impl {}
namespace impl {
/// Generic implementation namespace of border namespace.
namespace generic {}
}
}
}
# include <mln/border/adjust.hh>
# include <mln/border/duplicate.hh>
# include <mln/border/equalize.hh>
# include <mln/border/fill.hh>
# include <mln/border/find.hh>
# include <mln/border/get.hh>
# include <mln/border/mirror.hh>
# include <mln/border/resize.hh>
# include <mln/border/adjust.hh>
# include <mln/border/equalize.hh>
# include <mln/border/thickness.hh>
......
......@@ -52,7 +52,7 @@ namespace mln
*
* \pre \p ima has to be initialized.
*
* \todo Implement it + optimize with memcpy if possible.
* \todo Optimize with memcpy if possible.
*/
template <typename I>
void duplicate(const Image<I>& ima);
......@@ -66,7 +66,7 @@ namespace mln
template <typename I>
void duplicate_1d_(const I& ima)
{
mln_precondition(ima.has_data());
trace::entering("border::impl::duplicate_1d_");
typedef mln_point(I) P;
typename I::line_piter pl(ima.domain());
......@@ -79,12 +79,14 @@ namespace mln
std::size_t st = border + len_c - 1;
for (std::size_t i = st + 1; i < ima.ncells (); ++i)
const_cast<I&>(ima)[i] = ima[st];
trace::exiting("border::impl::duplicate_1d_");
}
template <typename I>
void duplicate_2d_(const I& ima)
{
mln_precondition(ima.has_data());
trace::entering("border::impl::duplicate_2d_");
typedef mln_point(I) P;
typename I::line_piter pl(ima.domain());
......@@ -117,11 +119,15 @@ namespace mln
for (std::size_t k = 1; k <= border; ++k)
for (std::size_t i = st; i < st + real_len_c; ++i)
const_cast<I&>(ima)[k * real_len_c + i] = ima[i];
trace::exiting("border::impl::duplicate_2d_");
}
template <typename I>
void duplicate_3d_(const Image<I>& ima_)
{
trace::entering("border::impl::duplicate_3d_");
const I& ima = exact(ima_);
mln_precondition(ima.has_data());
......@@ -178,25 +184,26 @@ namespace mln
for (std::size_t k = 1; k <= border; ++k)
for (std::size_t i = 0; i < face; ++i)
const_cast<I&>(ima)[st + k * face + i] = ima[st + i];
}
trace::exiting("border::impl::duplicate_3d_");
}
} // end of namespace mln::border::impl
// Facade.
template <typename I>
void duplicate(const Image<I>& ima_)
{
mlc_is(mln_trait_image_speed(I), trait::image::speed::fastest)::check();
const I& ima = exact(ima_);
typedef mln_point(I) P;
trace::entering("border::duplicate");
mln_precondition(ima.has_data());
mlc_is(mln_trait_image_speed(I), trait::image::speed::fastest)::check();
const I& ima = exact(ima_);
typedef mln_point(I) P;
if (!ima.border ())
return;
......
......@@ -50,7 +50,8 @@ namespace mln
* \param[in,out] ima2 The second image whose border is to be equalizeed.
* \param[in] min_thickness The expected border minimum thickness of both images.
*
* \pre \p ima has to be initialized.
* \pre \p ima1 has to be initialized.
* \pre \p ima2 has to be initialized.
*
* \warning If both image borders already have the same thickness
* and if this thickness is larger than \p min_thickness, this
......@@ -64,46 +65,67 @@ namespace mln
# ifndef MLN_INCLUDE_ONLY
namespace impl
{
template <typename I, typename J>
void equalize_(const I& ima1, const J& ima2, unsigned min_thickness)
{
trace::entering("border::impl::equalize_");
unsigned b1 = border::get(ima1), b2 = border::get(ima2);
if (! (b1 == b2 && b2 >= min_thickness))
// Something has to be done.
{
if (b1 < min_thickness && b2 < min_thickness)
// Both images have to be border-resized.
{
border::resize(ima1, min_thickness);
border::resize(ima2, min_thickness);
}
else
// A single image has to be border-resized with
// the other image thickness.
if (b1 < min_thickness)
{
mln_assertion(b2 >= min_thickness);
border::resize(ima1, b2);
}
else
{
mln_assertion(b2 < min_thickness);
mln_assertion(b1 >= min_thickness);
border::resize(ima2, b1);
}
}
trace::exiting("border::impl::equalize_");
}
} // end of namespace mln::border::impl
// Facade
template <typename I, typename J>
void equalize(const Image<I>& ima1_, const Image<J>& ima2_,
unsigned min_thickness)
{
trace::entering("border::equalize");
mlc_is(mln_trait_image_border(I), trait::image::border::some)::check();
mlc_is(mln_trait_image_border(J), trait::image::border::some)::check();
const I& ima1 = exact(ima1_);
const J& ima2 = exact(ima2_);
mln_precondition(ima1.has_data() && ima2.has_data());
unsigned b1 = border::get(ima1), b2 = border::get(ima2);
if (! (b1 == b2 && b2 >= min_thickness))
// Something has to be done.
{
if (b1 < min_thickness && b2 < min_thickness)
// Both images have to be border-resized.
{
border::resize(ima1, min_thickness);
border::resize(ima2, min_thickness);
}
else
// A single image has to be border-resized with
// the other image thickness.
if (b1 < min_thickness)
{
mln_assertion(b2 >= min_thickness);
border::resize(ima1, b2);
}
else
{
mln_assertion(b2 < min_thickness);
mln_assertion(b1 >= min_thickness);
border::resize(ima2, b1);
}
}
impl::equalize_(ima1, ima2, min_thickness);
mln_postcondition(border::get(ima1) == border::get(ima2) &&
border::get(ima1) >= min_thickness &&
border::get(ima2) >= min_thickness);
trace::exiting("border::equalize");
}
......
......@@ -50,7 +50,7 @@ namespace mln
*
* \pre \p ima has to be initialized.
*
* \todo Implement it + optimize with memset if possible.
* \todo Optimize with memset if possible.
*/
template <typename I>
void fill(const Image<I>& ima, const mln_value(I)& v);
......@@ -63,6 +63,8 @@ namespace mln
template <typename I>
void fill_size_1_(const I& ima, const mln_value(I)& v)
{
trace::entering("border::impl::fill_size_1_");
typedef mln_point(I) P;
typedef mln_point(I) P;
typename I::line_piter pl(ima.domain());
......@@ -80,11 +82,15 @@ namespace mln
std::memset((void*)&ima[st],
*(const int*)(&v),
ima.ncells () - st);
trace::exiting("border::impl::fill_size_1_");
}
template <typename I>
void fill_size_n_(const I& ima, const mln_value(I)& v)
{
trace::entering("border::impl::fill_size_n_");
typedef mln_point(I) P;
typename I::line_piter pl(ima.domain());
std::size_t len_r = ima.bbox().len(P::dim - 1);
......@@ -99,15 +105,19 @@ namespace mln
}
for (std::size_t i = st; i < ima.ncells (); ++i)
const_cast<I&>(ima)[i] = v;
trace::exiting("border::impl::fill_size_n_");
}
}
// Facade.
template <typename I>
void fill(const Image<I>& ima_, const mln_value(I)& v)
{
trace::entering("border::fill");
typedef mln_point(I) P;
const I& ima = exact(ima_);
......@@ -119,6 +129,7 @@ namespace mln
impl::fill_size_1_(ima, v);
else
impl::fill_size_n_(ima, v);
trace::exiting("border::fill");
}
......
......@@ -46,6 +46,9 @@ namespace mln
*
* \param[in] ima The image.
* \result The border thickness (0 if there is no border).
*
* \pre \p ima has to be initialized.
*
*/
template <typename I>
unsigned find(const Image<I>& ima);
......@@ -88,8 +91,13 @@ namespace mln
template <typename I>
unsigned find(const Image<I>& ima)
{
trace::entering("border::find");
mln_precondition(exact(ima).has_data());
return border::impl::find_(mln_trait_image_speed(I)(), exact(ima));
unsigned res = border::impl::find_(mln_trait_image_speed(I)(), exact(ima));
trace::exiting("border::find");
return res;
}
# endif // ! MLN_INCLUDE_ONLY
......
......@@ -46,6 +46,9 @@ namespace mln
*
* \param[in] ima The image.
* \result The border thickness (0 if there is no border).
*
* \pre \p ima has to be initialized.
*
*/
template <typename I>
unsigned get(const Image<I>& ima);
......@@ -86,9 +89,14 @@ namespace mln
template <typename I>
unsigned get(const Image<I>& ima)
{
trace::entering("border::get");
mln_precondition(exact(ima).has_data());
return border::impl::get_(mln_trait_image_border(I)(), mln_trait_image_category(I)(),
exact(ima));
unsigned res = border::impl::get_(mln_trait_image_border(I)(), mln_trait_image_category(I)(),
exact(ima));
trace::exiting("border::get");
return res;
}
# endif // ! MLN_INCLUDE_ONLY
......
......@@ -51,7 +51,7 @@ namespace mln
*
* \pre \p ima has to be initialized.
*
* \todo Implement it + optimize with memset if possible.
* \todo Implement 1d and 3d version + optimize with memset if possible.
*/
template <typename I>
void mirror(const Image<I>& ima);
......@@ -59,15 +59,110 @@ namespace mln
# ifndef MLN_INCLUDE_ONLY
namespace impl
{
template <typename I>
void mirror_1d_(const I& ima)
{
mln::internal::fixme();
}
template <typename I>
void mirror_2d_(const I& ima)
{
trace::entering("border::impl::mirror_2d_");
std::size_t border = ima.border ();
std::size_t nbrows = geom::max_row(ima) - geom::min_row(ima);
std::size_t nbcols = geom::max_col(ima) - geom::min_col(ima);
std::size_t real_nbcols = (nbcols + 1) + 2 * border;
std::size_t start = real_nbcols * border + border;
std::size_t s = start;
// duplicate top left corner
for (std::size_t i = 0; i < border; ++i)
for (std::size_t j = 0; j < border; ++j)
const_cast<I&>(ima)[i * ((nbcols + 1) + 2 * border) + j] = ima[s];
// duplicate top left corner
s = start + nbcols;
for (std::size_t i = 0; i < border; ++i)
for (std::size_t j = 1; j <= border; ++j)
const_cast<I&>(ima)[i * ((nbcols + 1) + 2 * border) + (nbcols + border + j)] = ima[s];
// duplicate bottom left corner
s = start + (nbrows * real_nbcols);
for (std::size_t i = 1; i <= border; ++i)
for (std::size_t j = 1; j <= border; ++j)
const_cast<I&>(ima)[s - i + (j * (real_nbcols))] = ima[s];
// duplicate bottom right corner
s = start + (nbrows * real_nbcols) + nbcols;
for (std::size_t i = 1; i <= border; ++i)
for (std::size_t j = 1; j <= border; ++j)
const_cast<I&>(ima)[s + i + (j * real_nbcols)] = ima[s];
// mirror top border
s = start;
for (std::size_t i = 0; i <= nbcols; ++i)
for (std::size_t j = 1; j <= border; ++j)
const_cast<I&>(ima)[s + i - (j * real_nbcols)] = ima[s + i + ((j - 1)* real_nbcols)];
// mirror left border
s = start;
for (std::size_t i = 0; i <= nbrows; ++i)
for (std::size_t j = 1; j <= border; ++j)
const_cast<I&>(ima)[s + (i * real_nbcols) - j] = ima[s + (i * real_nbcols) + (j - 1)];
// mirror right border
s = start;
for (std::size_t i = 0; i <= nbrows; ++i)
for (std::size_t j = 1; j <= border; ++j)
const_cast<I&>(ima)[s + (i * real_nbcols + nbcols) + j] = ima[s + (i * real_nbcols + nbcols) - (j - 1)];
// mirror bottom border
s = start + (nbrows * real_nbcols);
for (std::size_t i = 0; i <= nbcols; ++i)
for (std::size_t j = 1; j <= border; ++j)
const_cast<I&>(ima)[s + i + (j * real_nbcols)] = ima[s + i - ((j - 1)* real_nbcols)];
trace::exiting("border::impl::mirror_2d_");
}
template <typename I>
void mirror_3d_(const I& ima)
{
mln::internal::fixme();
}
} // end of namespace mln::border::mirror
template <typename I>
void mirror(const Image<I>& ima_)
{
trace::entering("border::mirror");
const I& ima = exact(ima_);
mlc_is(mln_trait_image_speed(I), trait::image::speed::fastest)::check();
mln_precondition(ima.has_data());
mln::internal::fixme();
mlc_is(mln_trait_image_speed(I), trait::image::speed::fastest)::check();
typedef mln_point(I) P;
if (!ima.border ())
return;
if (P::dim == 1)
impl::mirror_1d_(ima);
if (P::dim == 2)
impl::mirror_2d_(ima);
if (P::dim == 3)
impl::mirror_3d_(ima);
trace::exiting("border::mirror");
}
# endif // ! MLN_INCLUDE_ONLY
......
......@@ -95,6 +95,7 @@ namespace mln
void resize(const Image<I>& ima_, unsigned thickness)
{
trace::entering("border::resize");
mlc_is(mln_trait_image_border(I), trait::image::border::some)::check();
const I& ima = exact(ima_);
mln_precondition(ima.has_data());
......@@ -103,9 +104,10 @@ namespace mln
return; // No-op.
// Otherwise: do-it.
impl::resize_(mln_trait_image_category(I)(),
ima, thickness);
ima, thickness);
mln_postcondition(border::get(ima) == thickness);
trace::exiting("border::resize");
}
......
......@@ -5,16 +5,20 @@ include $(top_srcdir)/milena/tests/tests.mk
check_PROGRAMS = \
adjust \
duplicate \
equalize \
fill \
find \
get \
mirror \
resize
adjust_SOURCES = adjust.cc
duplicate_SOURCES = duplicate.cc
equalize_SOURCES = equalize.cc
fill_SOURCES = fill.cc
find_SOURCES = find.cc
get_SOURCES = get.cc
mirror_SOURCES = mirror.cc
resize_SOURCES = resize.cc
TESTS = $(check_PROGRAMS)
// Copyright (C) 2007 EPITA Research and Development Laboratory
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
// of the GNU General Public License version 2 as published by the
// Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this library; see the file COPYING. If not, write to
// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
// Boston, MA 02111-1307, USA.
//
// As a special exception, you may use this file as part of a free
// software library without restriction. Specifically, if other files
// instantiate templates or use macros or inline functions from this
// file, or you compile this file and link it with other files to
// produce an executable, this file does not by itself cause the
// resulting executable to be covered by the GNU General Public
// License. This exception does not however invalidate any other
// reasons why the executable file might be covered by the GNU General
// Public License.
/*! \file tests/border/equalize.cc
*
* \brief Tests on mln::border::equalize.
*/
#include <mln/core/image2d.hh>
#include <mln/border/get.hh>
#include <mln/border/equalize.hh>
int main()
{
using namespace mln;
image2d<int> ima1(3,3, 36);
image2d<int> ima2(3,3, 42);
border::equalize(ima1, ima2, 51);
mln_assertion(border::get(ima1) == 51);
mln_assertion(border::get(ima2) == 51);
}
// Copyright (C) 2007 EPITA Research and Development Laboratory
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
// of the GNU General Public License version 2 as published by the
// Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this library; see the file COPYING. If not, write to
// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
// Boston, MA 02111-1307, USA.
//
// As a special exception, you may use this file as part of a free
// software library without restriction. Specifically, if other files
// instantiate templates or use macros or inline functions from this
// file, or you compile this file and link it with other files to
// produce an executable, this file does not by itself cause the
// resulting executable to be covered by the GNU General Public
// License. This exception does not however invalidate any other
// reasons why the executable file might be covered by the GNU General
// Public License.