URL:
https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2007-11-22 Guillaume Duhamel <guillaume.duhamel(a)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.
---
mln/border/adjust.hh | 3 -
mln/border/all.hh | 13 ++++--
mln/border/duplicate.hh | 23 ++++++----
mln/border/equalize.hh | 40 ++++++++++++++----
mln/border/fill.hh | 13 +++++-
mln/border/find.hh | 10 ++++
mln/border/get.hh | 10 ++++
mln/border/mirror.hh | 101 +++++++++++++++++++++++++++++++++++++++++++++--
mln/border/resize.hh | 2
tests/border/Makefile.am | 4 +
tests/border/equalize.cc | 46 +++++++++++++++++++++
tests/border/mirror.cc | 90 +++++++++++++++++++++++++++++++++++++++++
12 files changed, 328 insertions(+), 27 deletions(-)
Index: trunk/milena/tests/border/equalize.cc
===================================================================
--- trunk/milena/tests/border/equalize.cc (revision 0)
+++ trunk/milena/tests/border/equalize.cc (revision 1518)
@@ -0,0 +1,46 @@
+// 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);
+}
Index: trunk/milena/tests/border/Makefile.am
===================================================================
--- trunk/milena/tests/border/Makefile.am (revision 1517)
+++ trunk/milena/tests/border/Makefile.am (revision 1518)
@@ -5,16 +5,20 @@
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)
Index: trunk/milena/tests/border/mirror.cc
===================================================================
--- trunk/milena/tests/border/mirror.cc (revision 0)
+++ trunk/milena/tests/border/mirror.cc (revision 1518)
@@ -0,0 +1,90 @@
+// 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_duplicate/test_border_duplicate_image2d_1.cc
+ *
+ * \brief Tests on mln::border::duplicate.
+ */
+
+#include <mln/core/image2d.hh>
+#include <mln/debug/iota.hh>
+#include <mln/border/mirror.hh>
+
+using namespace mln;
+
+int
+main (void)
+{
+ image2d<int> ima(2, 3, 2);
+
+ debug::iota(ima);
+ border::mirror(ima);
+
+ mln_assertion(ima[ 0] == 1);
+ mln_assertion(ima[ 1] == 1);
+ mln_assertion(ima[ 2] == 4);
+ mln_assertion(ima[ 3] == 5);
+ mln_assertion(ima[ 4] == 6);
+ mln_assertion(ima[ 5] == 3);
+ mln_assertion(ima[ 6] == 3);
+ mln_assertion(ima[ 7] == 1);
+ mln_assertion(ima[ 8] == 1);
+ mln_assertion(ima[ 9] == 1);
+ mln_assertion(ima[10] == 2);
+ mln_assertion(ima[11] == 3);
+ mln_assertion(ima[12] == 3);
+ mln_assertion(ima[13] == 3);
+ mln_assertion(ima[14] == 2);
+ mln_assertion(ima[15] == 1);
+ mln_assertion(ima[16] == 1);
+ mln_assertion(ima[17] == 2);
+ mln_assertion(ima[18] == 3);
+ mln_assertion(ima[19] == 3);
+ mln_assertion(ima[20] == 2);
+ mln_assertion(ima[21] == 5);
+ mln_assertion(ima[22] == 4);
+ mln_assertion(ima[23] == 4);
+ mln_assertion(ima[24] == 5);
+ mln_assertion(ima[25] == 6);
+ mln_assertion(ima[26] == 6);
+ mln_assertion(ima[27] == 5);
+ mln_assertion(ima[28] == 4);
+ mln_assertion(ima[29] == 4);
+ mln_assertion(ima[30] == 4);
+ mln_assertion(ima[31] == 5);
+ mln_assertion(ima[32] == 6);
+ mln_assertion(ima[33] == 6);
+ mln_assertion(ima[34] == 6);
+ mln_assertion(ima[35] == 4);
+ mln_assertion(ima[36] == 4);
+ mln_assertion(ima[37] == 1);
+ mln_assertion(ima[38] == 2);
+ mln_assertion(ima[39] == 3);
+ mln_assertion(ima[40] == 6);
+ mln_assertion(ima[41] == 6);
+}
+
Index: trunk/milena/mln/border/resize.hh
===================================================================
--- trunk/milena/mln/border/resize.hh (revision 1517)
+++ trunk/milena/mln/border/resize.hh (revision 1518)
@@ -95,6 +95,7 @@
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());
@@ -106,6 +107,7 @@
ima, thickness);
mln_postcondition(border::get(ima) == thickness);
+
trace::exiting("border::resize");
}
Index: trunk/milena/mln/border/fill.hh
===================================================================
--- trunk/milena/mln/border/fill.hh (revision 1517)
+++ trunk/milena/mln/border/fill.hh (revision 1518)
@@ -50,7 +50,7 @@
*
* \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 @@
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 @@
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 @@
}
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 @@
impl::fill_size_1_(ima, v);
else
impl::fill_size_n_(ima, v);
+
trace::exiting("border::fill");
}
Index: trunk/milena/mln/border/all.hh
===================================================================
--- trunk/milena/mln/border/all.hh (revision 1517)
+++ trunk/milena/mln/border/all.hh (revision 1518)
@@ -41,18 +41,25 @@
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>
Index: trunk/milena/mln/border/duplicate.hh
===================================================================
--- trunk/milena/mln/border/duplicate.hh (revision 1517)
+++ trunk/milena/mln/border/duplicate.hh (revision 1518)
@@ -52,7 +52,7 @@
*
* \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 @@
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 @@
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 @@
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,9 +184,9 @@
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
@@ -190,13 +196,14 @@
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;
Index: trunk/milena/mln/border/mirror.hh
===================================================================
--- trunk/milena/mln/border/mirror.hh (revision 1517)
+++ trunk/milena/mln/border/mirror.hh (revision 1518)
@@ -51,7 +51,7 @@
*
* \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 @@
# 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_);
+ mln_precondition(ima.has_data());
mlc_is(mln_trait_image_speed(I), trait::image::speed::fastest)::check();
- mln_precondition(ima.has_data());
- mln::internal::fixme();
+ 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
Index: trunk/milena/mln/border/adjust.hh
===================================================================
--- trunk/milena/mln/border/adjust.hh (revision 1517)
+++ trunk/milena/mln/border/adjust.hh (revision 1518)
@@ -58,13 +58,13 @@
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 @@
border::resize(ima, min_thickness);
mln_postcondition(border::get(ima) >= min_thickness);
+
trace::exiting("border::adjust");
}
Index: trunk/milena/mln/border/equalize.hh
===================================================================
--- trunk/milena/mln/border/equalize.hh (revision 1517)
+++ trunk/milena/mln/border/equalize.hh (revision 1518)
@@ -50,7 +50,8 @@
* \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,18 +65,16 @@
# ifndef MLN_INCLUDE_ONLY
+ namespace impl
+ {
+
template <typename I, typename J>
- void equalize(const Image<I>& ima1_, const Image<J>& ima2_,
- unsigned min_thickness)
+ void equalize_(const I& ima1, const 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());
+ 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.
{
@@ -101,9 +100,32 @@
}
}
+ 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());
+
+ 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");
}
Index: trunk/milena/mln/border/get.hh
===================================================================
--- trunk/milena/mln/border/get.hh (revision 1517)
+++ trunk/milena/mln/border/get.hh (revision 1518)
@@ -46,6 +46,9 @@
*
* \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 @@
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)(),
+ 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
Index: trunk/milena/mln/border/find.hh
===================================================================
--- trunk/milena/mln/border/find.hh (revision 1517)
+++ trunk/milena/mln/border/find.hh (revision 1518)
@@ -46,6 +46,9 @@
*
* \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 @@
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