* mln/world/binary_2d/enlarge.hh: new routine.
* tests/world/Makefile.am,
* tests/world/binary_2d/Makefile.am: new makefiles.
* tests/world/binary_2d/enlarge.cc: new associated test.
---
milena/ChangeLog | 11 +
milena/mln/world/binary_2d/enlarge.hh | 380 ++++++++++++++++++++++++++++++
milena/tests/world/Makefile.am | 1 +
milena/tests/world/binary_2d/Makefile.am | 12 +
milena/tests/world/binary_2d/enlarge.cc | 47 ++++
5 files changed, 451 insertions(+), 0 deletions(-)
create mode 100644 milena/mln/world/binary_2d/enlarge.hh
create mode 100644 milena/tests/world/binary_2d/Makefile.am
create mode 100644 milena/tests/world/binary_2d/enlarge.cc
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 87735dc..c68baff 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,16 @@
2009-05-28 Guillaume Lazzara <lazzara(a)lrde.epita.fr>
+ Add world::binary_2d::enlarge.
+
+ * mln/world/binary_2d/enlarge.hh: new routine.
+
+ * tests/world/Makefile.am,
+ * tests/world/binary_2d/Makefile.am: new makefiles.
+
+ * tests/world/binary_2d/enlarge.cc: new associated test.
+
+2009-05-28 Guillaume Lazzara <lazzara(a)lrde.epita.fr>
+
Add debug::superpose.
* mln/debug/all.hh: update includes.
diff --git a/milena/mln/world/binary_2d/enlarge.hh
b/milena/mln/world/binary_2d/enlarge.hh
new file mode 100644
index 0000000..6094a51
--- /dev/null
+++ b/milena/mln/world/binary_2d/enlarge.hh
@@ -0,0 +1,380 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// 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.
+
+#ifndef MLN_WORLD_BINARY_2D_ENLARGE_HH
+# define MLN_WORLD_BINARY_2D_ENLARGE_HH
+
+/// \file mln/world/binary_2d/enlarge.hh
+///
+/// Enlarge 2^n times a binary image.
+///
+/// \todo Make it much more generic.
+
+
+# include <iostream>
+
+# include <mln/core/image/image2d.hh>
+# include <mln/core/routine/initialize.hh>
+
+# include <mln/value/int_u8.hh>
+# include <mln/fun/p2v/ternary.hh>
+# include <mln/fun/v2b/threshold.hh>
+
+# include <mln/level/transform.hh>
+
+# include <mln/pw/image.hh>
+# include <mln/pw/cst.hh>
+# include <mln/pw/value.hh>
+# include <mln/opt/at.hh>
+
+# include <mln/geom/min_row.hh>
+# include <mln/geom/min_col.hh>
+
+# include <mln/core/routine/duplicate.hh>
+
+
+namespace mln
+{
+
+ namespace world
+ {
+
+ namespace binary_2d
+ {
+
+ /// Enlarge a binary image 2^n times
+ ///
+ /// \param[in] input A binary image.
+ /// \param[in] n The power of 2 setting up the enlargement.
+ ///
+ /// \return A binary image with a domain 2^\p n times larger.
+ //
+ template <typename I>
+ mln_concrete(I)
+ enlarge(const Image<I>& input, unsigned n);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ // Internal routines.
+
+ namespace internal
+ {
+
+ inline
+ float
+ val(bool b)
+ {
+ return b ? 1 : 0;
+ }
+
+ inline
+ int
+ do_threshold(float value)
+ {
+ return 255.f * value;
+ }
+
+ } // end of namespace mln::world::binary_2d
+
+
+
+
+ // Implementation.
+
+ namespace impl
+ {
+
+ ///FIXME: works only on 2d images.
+ inline
+ image2d<value::int_u8>
+ enlargex2(const image2d<bool>& input)
+ {
+ using value::int_u8;
+
+ mln_precondition(input.is_valid());
+
+ unsigned
+ mrow = geom::min_row(input),
+ mcol = geom::min_col(input);
+
+ image2d<int_u8> output(make::box2d(mrow, mcol,
+ mrow + 2 * input.nrows() - 1,
+ mcol + 2 * input.ncols() - 1));
+ float value;
+
+ // row 0
+ opt::at(output, mrow, mcol) = internal::do_threshold(opt::at(input, mrow, mcol));
+
+ for (unsigned col = 2; col < output.ncols(); col += 2)
+ {
+ value = internal::val(opt::at(input, mrow, mcol + col / 2));
+ value += internal::val(opt::at(input, mrow, mcol + col / 2 - 1));
+ opt::at(output, mrow, mcol + col) = internal::do_threshold(value / 2);
+ }
+
+ for (unsigned col = 1; col < output.ncols(); col += 2)
+ opt::at(output, mrow, mcol + col)
+ = internal::do_threshold(opt::at(input, mrow, mcol + col / 2));
+
+ // col 0
+
+ for (unsigned row = 2; row < output.nrows(); row += 2)
+ {
+ value = internal::val(opt::at(input, mrow + row / 2, mcol));
+ value += internal::val(opt::at(input, mrow + row / 2 - 1, mcol));
+ opt::at(output, mrow + row, mcol) = internal::do_threshold(value / 2);
+ }
+
+ for (unsigned row = 1; row < output.nrows(); row += 2)
+ opt::at(output, mrow + row, mcol)
+ = internal::do_threshold(opt::at(input, mrow + row / 2, mcol));
+
+ // others
+
+ for (unsigned row = 2; row < output.nrows(); row += 2)
+ {
+ for (unsigned col = 2; col < output.ncols(); col += 2)
+ {
+ value = internal::val(opt::at(input, mrow + row / 2, mcol + col / 2));
+ value += internal::val(opt::at(input, mrow + row / 2 - 1, mcol + col / 2));
+ value += internal::val(opt::at(input, mrow + row / 2, mcol + col / 2 - 1));
+ value += internal::val(opt::at(input, mrow + row / 2 - 1, mcol + col / 2 - 1));
+ opt::at(output, mrow + row, mcol + col)
+ = internal::do_threshold(value / 4);
+ }
+ for (unsigned col = 1; col < output.ncols(); col += 2)
+ {
+ value = internal::val(opt::at(input, mrow + row / 2, mcol + col / 2));
+ value += internal::val(opt::at(input, mrow + row / 2 - 1, mcol + col / 2));
+ opt::at(output, mrow + row, mcol + col) = internal::do_threshold(value / 2);
+ }
+ }
+
+ for (unsigned row = 1; row < output.nrows(); row += 2)
+ {
+ for (unsigned col = 2; col < output.ncols(); col += 2)
+ {
+ value = internal::val(opt::at(input, mrow + row / 2, mcol + col / 2));
+ value += internal::val(opt::at(input, mrow + row / 2, mcol + col / 2 - 1));
+ opt::at(output, mrow + row, mcol + col) = internal::do_threshold(value / 2);
+ }
+ for (unsigned col = 1; col < output.ncols(); col += 2)
+ opt::at(output, mrow + row, mcol + col)
+ = internal::do_threshold(opt::at(input, mrow + row / 2, mcol + col / 2));
+ }
+
+ return output;
+ }
+
+
+
+ inline
+ image2d<value::int_u8>
+ enlargex2(const image2d<value::int_u8>& input)
+ {
+ using value::int_u8;
+
+ unsigned
+ mrow = geom::min_row(input),
+ mcol = geom::min_col(input);
+
+ image2d<int_u8> output(make::box2d(mrow, mcol,
+ mrow + 2 * input.nrows() - 1,
+ mcol + 2 * input.ncols() - 1));
+ unsigned value;
+
+ // row 0
+ opt::at(output, mrow, mcol) = (opt::at(input, mrow, mcol));
+
+ for (unsigned col = 2; col < output.ncols(); col += 2)
+ {
+ value = (opt::at(input, mrow, mcol + col / 2));
+ value += (opt::at(input, mrow, mcol + col / 2 - 1));
+ opt::at(output, mrow, mcol + col) = (value / 2);
+ }
+
+ for (unsigned col = 1; col < output.ncols(); col += 2)
+ opt::at(output, mrow, mcol + col) = (opt::at(input, mrow, mcol + col / 2));
+
+ // col 0
+
+ for (unsigned row = 2; row < output.nrows(); row += 2)
+ {
+ value = (opt::at(input, mrow + row / 2, mcol));
+ value += (opt::at(input, mrow + row / 2 - 1, mcol));
+ opt::at(output, mrow + row, mcol) = (value / 2);
+ }
+
+ for (unsigned row = 1; row < output.nrows(); row += 2)
+ opt::at(output, mrow + row, mcol) = (opt::at(input, mrow + row / 2, mcol));
+
+ // others
+
+ for (unsigned row = 2; row < output.nrows(); row += 2)
+ {
+ for (unsigned col = 2; col < output.ncols(); col += 2)
+ {
+ value = (opt::at(input, mrow + row / 2, mcol + col / 2));
+ value += (opt::at(input, mrow + row / 2 - 1, mcol + col / 2));
+ value += (opt::at(input, mrow + row / 2, mcol + col / 2 - 1));
+ value += (opt::at(input, mrow + row / 2 - 1, mcol + col / 2 - 1));
+ opt::at(output, mrow + row, mcol + col) = ((unsigned(value)+2) / 4);
+ }
+ for (unsigned col = 1; col < output.ncols(); col += 2)
+ {
+ value = (opt::at(input, mrow + row / 2, mcol + col / 2));
+ value += (opt::at(input, mrow + row / 2 - 1, mcol + col / 2));
+ opt::at(output, mrow + row, mcol + col) = (value / 2);
+ }
+ }
+
+ for (unsigned row = 1; row < output.nrows(); row += 2)
+ {
+ for (unsigned col = 2; col < output.ncols(); col += 2)
+ {
+ value = (opt::at(input, mrow + row / 2, mcol + col / 2));
+ value += (opt::at(input, mrow + row / 2, mcol + col / 2 - 1));
+ opt::at(output, mrow + row, mcol + col) = (value / 2);
+ }
+ for (unsigned col = 1; col < output.ncols(); col += 2)
+ opt::at(output, mrow + row, mcol + col)
+ = (opt::at(input, mrow + row / 2, mcol + col / 2));
+ }
+
+ return output;
+ }
+
+
+ template <typename I>
+ inline
+ mln_ch_value(I,value::int_u8)
+ do_enlarge_gl(const I& input, unsigned n)
+ {
+ using value::int_u8;
+
+ mln_ch_value(I,int_u8) output = enlargex2(input);
+
+ while (--n)
+ output = enlargex2(output);
+
+ return output;
+ }
+
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ do_enlarge_bool(const I& input, unsigned n)
+ {
+ mln_ch_value(I,value::int_u8) tmp = do_enlarge_gl(input, n);
+ I output
+ = level::transform(tmp, fun::v2b::threshold<value::int_u8>(150));
+ return output;
+ }
+
+
+ } // end of namespace mln::world::binary_2d::impl
+
+
+
+
+ // Dispatch
+
+ namespace internal
+ {
+
+ template<typename I>
+ inline
+ mln_concrete(I)
+ enlarge_dispatch(const I& input, const bool&, unsigned n)
+ {
+ return impl::do_enlarge_bool(input, n);
+ }
+
+ template<typename I>
+ inline
+ mln_concrete(I)
+ enlarge_dispatch(const I& input, const value::int_u8&, unsigned n)
+ {
+ return impl::do_enlarge_gl(input, n);
+ }
+
+ template<typename I>
+ inline
+ mln_concrete(I)
+ enlarge_dispatch(const I& input, const mln_value(I)&, unsigned n)
+ {
+ mlc_abort(I)::check();
+ return mln_concrete(I)();
+ }
+
+ template<typename I>
+ inline
+ mln_concrete(I)
+ enlarge_dispatch(const Image<I>& input, unsigned n)
+ {
+ return enlarge_dispatch(exact(input), mln_value(I)(), n);
+ }
+
+ } // end of namespace mln::world::binary_2d::internal
+
+
+
+ // Facade
+
+ template <typename I>
+ inline
+ mln_concrete(I)
+ enlarge(const Image<I>& input, unsigned n)
+ {
+ trace::entering("mln::world::binary_2d::enlarge");
+
+ mln_precondition(exact(input).is_valid());
+ mlc_bool(mln_site_(I)::dim == 2)::check();
+
+ mln_concrete(I) output;
+ if (n == 0)
+ output = duplicate(input);
+ else
+ output = internal::enlarge_dispatch(input, n);
+
+ trace::exiting("mln::world::binary_2d::enlarge");
+ return output;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::world::binary_2d
+
+ } // end of namespace mln::world
+
+} // mln
+
+#endif // ! MLN_WORLD_BINARY_2D_ENLARGE_HH
diff --git a/milena/tests/world/Makefile.am b/milena/tests/world/Makefile.am
index 7a41ecd..75f3a7a 100644
--- a/milena/tests/world/Makefile.am
+++ b/milena/tests/world/Makefile.am
@@ -1,2 +1,3 @@
SUBDIRS = \
+ binary_2d \
inter_pixel
diff --git a/milena/tests/world/binary_2d/Makefile.am
b/milena/tests/world/binary_2d/Makefile.am
new file mode 100644
index 0000000..e04c66a
--- /dev/null
+++ b/milena/tests/world/binary_2d/Makefile.am
@@ -0,0 +1,12 @@
+## Process this file through Automake to create Makefile.in -*- Makefile -*-
+
+include $(top_srcdir)/milena/tests/tests.mk
+
+check_PROGRAMS = \
+ enlarge \
+ enlarge_hq2x
+
+enlarge_SOURCES = enlarge.cc
+enlarge_hq2x_SOURCES = enlarge_hq2x.cc
+
+TESTS = $(check_PROGRAMS)
diff --git a/milena/tests/world/binary_2d/enlarge.cc
b/milena/tests/world/binary_2d/enlarge.cc
new file mode 100644
index 0000000..0ef1981
--- /dev/null
+++ b/milena/tests/world/binary_2d/enlarge.cc
@@ -0,0 +1,47 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/level/compare.hh>
+#include <mln/world/binary_2d/enlarge.hh>
+#include <mln/make/image.hh>
+#include <mln/value/int_u8.hh>
+
+#include "tests/data.hh"
+
+mln::value::int_u8 vals_i[][4] = { { 4, 4, 4, 5 },
+ { 4, 4, 4, 5 },
+ { 3, 3, 4, 3 },
+ { 3, 3, 2, 2 } };
+
+bool vals_b[][4] = { { 0, 0, 0, 1 },
+ { 0, 0, 0, 1 },
+ { 0, 0, 0, 0 },
+ { 1, 1, 0, 0 } };
+
+int main()
+{
+ using namespace mln;
+
+ {
+ value::int_u8 vals[][2] = { { 4, 5 },
+ { 3, 2 } } ;
+
+ image2d<value::int_u8> input = make::image(vals);
+ image2d<value::int_u8> input_2x = world::binary_2d::enlarge(input,1);
+
+ image2d<value::int_u8> ref = make::image(vals_i);
+
+ mln_assertion(ref == input_2x);
+ }
+
+ {
+ bool vals[][2] = { { 0, 1 },
+ { 1, 0 } } ;
+
+ image2d<bool> input = make::image(vals);
+ image2d<bool> input_2x = world::binary_2d::enlarge(input,1);
+
+ image2d<bool> ref = make::image(vals_b);
+
+ mln_assertion(ref == input_2x);
+ }
+
+}
--
1.5.6.5