
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Revamp extension fill and fix dependant morpho operators. * tests/core/routine/extend.cc: New. * tests/core/routine/Makefile.am: Update. * sandbox/geraud/cs2d/dbl_neighb.cc: Rename as... * doc/examples/tuto_one.cc: ...this. Update. * mln/core/image/extension_ima.hh (change_extension): New. * mln/core/routine/extend.hh (todo): New. * mln/core/internal/image_morpher.hh (unmorph_): New. * mln/border/fill.hh: Revamp. * mln/morpho/closing_area.hh (closing_area): New up-to-date sig. * mln/morpho/erosion.spe.hh: Update. De-activate some parts because of multiple windows. (FIXME): New couple. * mln/morpho/erosion.hh (has): Replace by... (domain.has): ...this. * mln/morpho/dilation.hh: Likewise. * mln/morpho/meyer_wst.hh: Likewise. * mln/canvas/morpho/algebraic_union_find.hh: Likewise. * mln/canvas/labeling.hh: Likewise. * mln/morpho/includes.hh: New include. * mln/extension/fill.hh: Revamp. doc/examples/tuto_one.cc | 33 +++---- mln/border/fill.hh | 105 ++++++++++++++++++---- mln/canvas/labeling.hh | 4 mln/canvas/morpho/algebraic_union_find.hh | 2 mln/core/image/extension_ima.hh | 13 ++ mln/core/internal/image_morpher.hh | 15 +++ mln/core/routine/extend.hh | 1 mln/extension/fill.hh | 140 +++++++++++++++++++++++------- mln/morpho/closing_area.hh | 14 +++ mln/morpho/dilation.hh | 4 mln/morpho/erosion.hh | 4 mln/morpho/erosion.spe.hh | 59 +++++++----- mln/morpho/includes.hh | 2 mln/morpho/meyer_wst.hh | 6 - tests/core/routine/Makefile.am | 2 tests/core/routine/extend.cc | 72 +++++++++++++++ 16 files changed, 374 insertions(+), 102 deletions(-) Index: tests/core/routine/Makefile.am --- tests/core/routine/Makefile.am (revision 2408) +++ tests/core/routine/Makefile.am (working copy) @@ -5,10 +5,12 @@ check_PROGRAMS = \ clone \ exact \ + extend \ initialize clone_SOURCES = clone.cc exact_SOURCES = exact.cc +extend_SOURCES = extend.cc initialize_SOURCES = initialize.cc TESTS = $(check_PROGRAMS) Index: tests/core/routine/extend.cc --- tests/core/routine/extend.cc (revision 0) +++ tests/core/routine/extend.cc (revision 0) @@ -0,0 +1,72 @@ +// Copyright (C) 2008 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/core/routine/extend.cc + * + * \brief Tests on mln::extend. + */ + +#include <mln/core/var.hh> + +#include <mln/core/image/image2d.hh> +#include <mln/core/image/sub_image.hh> + +#include <mln/core/image/extended.hh> +#include <mln/core/routine/extend.hh> + +#include <mln/debug/iota.hh> +#include <mln/debug/println.hh> + +#include <mln/extension/fill.hh> + + + +int main() +{ + using namespace mln; + + image2d<int> ima(3, 3, 1); + debug::iota(ima); + + box2d bb = ima.domain().to_larger(1); + box2d BB = ima.domain().to_larger(2); + + debug::println(ima); + debug::println(extended_to(ima, bb)); + + mln_VAR(ima_, extend(ima | make::box2d(2,2), 7)); + debug::println(ima_); + + debug::println(extended_to(ima_, BB)); + + extension::fill(ima_, 8); + + debug::println(ima_); + debug::println(extended_to(ima_, BB)); + + debug::println(ima_); +} Index: doc/examples/tuto_one.cc --- doc/examples/tuto_one.cc (revision 2406) +++ doc/examples/tuto_one.cc (working copy) @@ -3,6 +3,7 @@ # include <mln/value/int_u8.hh> # include <mln/value/rgb8.hh> +# include <mln/core/var.hh> # include <mln/core/image/image2d.hh> # include <mln/core/alias/neighb2d.hh> # include <mln/core/alias/window2d.hh> @@ -11,7 +12,7 @@ # include <mln/convert/to_image.hh> # include <mln/debug/println.hh> -# include "dbl_neighb.hh" +# include <mln/make/double_neighb2d.hh> # include <mln/io/pgm/load.hh> # include <mln/io/pgm/save.hh> @@ -29,14 +30,6 @@ -struct is_chess_t -{ - bool operator()(const mln::point2d& p) const - { - return p.col() % 2 == p.row() % 2; - } -}; - struct colorize : mln::Function_v2v< colorize > { @@ -58,6 +51,12 @@ }; + bool is_chess(const mln::point2d& p) + { + return p.col() % 2 == p.row() % 2; + } + + void usage(char* argv[]) { std::cerr << "usage: " << argv[0] << " input.pgm lambda output.ppm" << std::endl; @@ -70,6 +69,7 @@ using namespace mln; using value::int_u8; + if (argc != 4) usage(argv); @@ -84,26 +84,27 @@ 1, 0, 1, 1, 1, 0 }; - dbl_neighb_<dpoint2d, is_chess_t> nbh; - nbh - .when_true (make::neighb2d(vert)) - .when_false(make::neighb2d(hori)); + mln_VAR( nbh, make::double_neighb2d(is_chess, vert, hori) ); +// mln_VAR(nbh, c4()); +// mln_VAR(nbh, c8()); - image2d<int_u8> clo, grad = morpho::gradient(lena, nbh); - // io::pgm::save(grad, "grad.pgm"); + image2d<int_u8> clo, grad = morpho::gradient(lena, nbh.win()); + // io::pgm::save(grad, "tmp_grad.pgm"); int lambda = atoi(argv[2]); if (lambda > 1) { clo = morpho::closing_area(grad, nbh, lambda); - // io::pgm::save(clo, "clo.pgm"); + io::pgm::save(clo, "tmp_clo.pgm"); } else clo = grad; unsigned l; image2d<unsigned> wst = morpho::meyer_wst(clo, nbh, l); + std::cout << "l = " << l << std::endl; + debug::println(wst); io::ppm::save(level::transform(wst, colorize(l)), argv[3]); Index: mln/core/image/extension_ima.hh --- mln/core/image/extension_ima.hh (revision 2408) +++ mln/core/image/extension_ima.hh (working copy) @@ -39,6 +39,7 @@ */ # include <mln/core/internal/image_identity.hh> +# include <mln/level/fill_with_value.hh> @@ -142,6 +143,9 @@ /// Mutable access to the extension domain (image). This domain /// can be modified if J a read-write image type. J& extension(); + + /// Change the value in the extension domain (image). + void change_extension(const mln_value(I)& v); }; @@ -266,6 +270,15 @@ return this->data_->ext_; } + template <typename I, typename J> + inline + void + extension_ima<I, J>::change_extension(const mln_value(I)& v) + { + mlc_equal(mln_trait_image_value_io(J), + trait::image::value_io::read_write)::check(); + level::fill_with_value(v); + } // init_ Index: mln/core/routine/extend.hh --- mln/core/routine/extend.hh (revision 2408) +++ mln/core/routine/extend.hh (working copy) @@ -35,6 +35,7 @@ * * \todo Use the 'instant' mechanism. * \todo Deal with ambiguities. + * \todo Check that there is no extension yet (except "extendable"). */ # include <mln/core/image/extension_ima.hh> Index: mln/core/internal/image_morpher.hh --- mln/core/internal/image_morpher.hh (revision 2408) +++ mln/core/internal/image_morpher.hh (working copy) @@ -61,6 +61,11 @@ /// Return the delegatee_ pointer (non-const version); default code. I* delegatee_(); + + /// Give the morphed image. + I& unmorph_(); + + /* \brief Test if this image has been initialized; default impl. * * This default impl is stronger than the one inherited from @@ -130,6 +135,16 @@ template <typename I, typename T, typename S, typename E> inline + I& + image_morpher<I, T, S, E>::unmorph_() + { + I* ptr = delegatee_(); + mln_assertion(ptr != 0); + return *ptr; + } + + template <typename I, typename T, typename S, typename E> + inline image_morpher<I, T, S, E>::operator I() const { mln_precondition(exact(this)->has_data()); Index: mln/border/fill.hh --- mln/border/fill.hh (revision 2408) +++ mln/border/fill.hh (working copy) @@ -58,16 +58,34 @@ template <typename I> void fill(const Image<I>& ima, const mln_value(I)& v); + # ifndef MLN_INCLUDE_ONLY + + namespace internal + { + + template <typename I> + inline + void fill_tests(const Image<I>& ima, const mln_value(I)& v) + { + mln_precondition(exact(ima).has_data()); + } + + } // end of namespace mln::border::internal + + namespace impl { template <typename I> inline - void fill_size_1_(const I& ima, const mln_value(I)& v) + void fill_size_1(const Image<I>& ima_, const mln_value(I)& v) { - trace::entering("border::impl::fill_size_1_"); + trace::entering("border::impl::fill_size_1"); + + const I& ima = exact(ima_); + internal::fill_tests(ima, v); typedef mln_psite(I) P; typedef mln_psite(I) P; @@ -88,14 +106,18 @@ *(const int*)(&v), ima.nelements () - st); - trace::exiting("border::impl::fill_size_1_"); + trace::exiting("border::impl::fill_size_1"); } + template <typename I> inline - void fill_size_n_(const I& ima, const mln_value(I)& v) + void fill_size_n(const I& ima_, const mln_value(I)& v) { - trace::entering("border::impl::fill_size_n_"); + trace::entering("border::impl::fill_size_n"); + + const I& ima = exact(ima_); + internal::fill_tests(ima, v); typedef mln_psite(I) P; mln_box_runstart_piter(I) pl(ima.domain()); @@ -112,34 +134,81 @@ for (std::size_t i = st; i < ima.nelements (); ++i) const_cast<I&>(ima).element(i) = v; - trace::exiting("border::impl::fill_size_n_"); + trace::exiting("border::impl::fill_size_n"); + } + + + } // end of namespace mln::border::impl + + + namespace internal + { + + // Dispatch. + + template <typename I> + inline + void fill_dispatch(const Image<I>& ima, const mln_value(I)& v); + + template <typename I> + inline + void fill_dispatch(mln::trait::image::category::primary, + mln::trait::image::speed::fastest, + I& ima, const mln_value(I)& v) + { + if (sizeof(mln_value(I)) == 1) + impl::fill_size_1(ima, v); + else + impl::fill_size_n(ima, v); + } + + template <typename I> + inline + void fill_dispatch(mln::trait::image::category::primary, + mln::trait::image::speed::any, + I& ima, const mln_value(I)& v) + { + // No border so no-op. } + template <typename I> + inline + void fill_dispatch(mln::trait::image::category::morpher, + mln::trait::image::speed::any, + I& ima, const mln_value(I)& v) + { + fill_dispatch(ima.unmorph_(), v); } + template <typename I> + inline + void fill_dispatch(const Image<I>& ima_, const mln_value(I)& v) + { + I& ima = const_cast<I&>(exact(ima_)); + fill_dispatch(mln_trait_image_category(I)(), + mln_trait_image_speed(I)(), + ima, v); + } + + } // end of namespace mln::border::internal + + + // Facade. template <typename I> inline - void fill(const Image<I>& ima_, const mln_value(I)& v) + void fill(const Image<I>& ima, const mln_value(I)& v) { trace::entering("border::fill"); - typedef mln_psite(I) P; - const I& ima = exact(ima_); - - mlc_is(mln_trait_image_speed(I), trait::image::speed::fastest)::check(); - mln_precondition(ima.has_data()); - if (!ima.border ()) - return; - if (sizeof(mln_value(I)) == 1) - impl::fill_size_1_(ima, v); - else - impl::fill_size_n_(ima, v); + internal::fill_tests(ima, v); + internal::fill_dispatch(ima, v); trace::exiting("border::fill"); } + # endif // ! MLN_INCLUDE_ONLY } // end of namespace mln::border Index: mln/morpho/closing_area.hh --- mln/morpho/closing_area.hh (revision 2408) +++ mln/morpho/closing_area.hh (working copy) @@ -48,6 +48,10 @@ void closing_area(const Image<I>& input, const Neighborhood<N>& nbh, std::size_t lambda, Image<O>& output); + template <typename I, typename N> + mln_concrete(I) closing_area(const Image<I>& input, const Neighborhood<N>& nbh, + std::size_t lambda); + # ifndef MLN_INCLUDE_ONLY @@ -62,6 +66,16 @@ closing_attribute< accu::count_<pix_t> >(input, nbh, lambda, output); } + template <typename I, typename N> + mln_concrete(I) closing_area(const Image<I>& input, const Neighborhood<N>& nbh, + std::size_t lambda) + { + mln_concrete(I) output; + initialize(output, input); + closing_area(input, nbh, lambda, output); + return output; + } + # endif // ! MLN_INCLUDE_ONLY } // end of namespace mln::morpho Index: mln/morpho/erosion.spe.hh --- mln/morpho/erosion.spe.hh (revision 2408) +++ mln/morpho/erosion.spe.hh (working copy) @@ -93,7 +93,7 @@ O output; initialize(output, input); -// border::fill(input, mln_max(mln_value(I))); + extension::fill(input, mln_max(mln_value(I))); mln_pixter(const I) p(input); mln_pixter(O) o(output); @@ -124,7 +124,7 @@ O output; initialize(output, input); -// border::fill(input, true); + extension::fill(input, true); mln_pixter(const I) p(input); mln_pixter(O) p_out(output); @@ -154,7 +154,7 @@ const W& win = exact(win_); O output; -// border::fill(input, true); + extension::fill(input, true); output = clone(input); mln_piter(I) p(input.domain()); @@ -183,7 +183,7 @@ const W& win = exact(win_); O output; -// border::fill(input, true); + extension::fill(input, true); output = clone(input); mln_pixter(const I) p(input); @@ -439,26 +439,29 @@ // dispatch for the generic version - template <typename I, typename W> - mln_concrete(I) - erosion_dispatch_for_generic(trait::image::kind::logic, // On sets. - trait::image::speed::fastest, - const I& input, const W& win) - { - if (win.is_centered()) - return impl::erosion_on_set_centered_fastest(input, win); - else - return impl::erosion_on_set_fastest(input, win); - } + // FIXME: De-activate because when the window is multiple, the access + // win.dp(i), used in dpoints_pixter, is impossible. - template <typename I, typename W> - mln_concrete(I) - erosion_dispatch_for_generic(trait::image::kind::any, // On functions. - trait::image::speed::fastest, - const I& input, const W& win) - { - return impl::erosion_on_function_fastest(input, win); - } +// template <typename I, typename W> +// mln_concrete(I) +// erosion_dispatch_for_generic(trait::image::kind::logic, // On sets. +// trait::image::speed::fastest, +// const I& input, const W& win) +// { +// if (win.is_centered()) +// return impl::erosion_on_set_centered_fastest(input, win); +// else +// return impl::erosion_on_set_fastest(input, win); +// } + +// template <typename I, typename W> +// mln_concrete(I) +// erosion_dispatch_for_generic(trait::image::kind::any, // On functions. +// trait::image::speed::fastest, +// const I& input, const W& win) +// { +// return impl::erosion_on_function_fastest(input, win); +// } template <typename I, typename W> mln_concrete(I) @@ -543,9 +546,13 @@ mln_concrete(I) erosion_dispatch_wrt_win(const I& input, const W& win) { - if (erosion_chooses_arbitrary(input, win)) - return erosion_dispatch_for_arbitrary(input, win); - else + // FIXME: De-activate because, when win is multiple, + // geom::shift does not work. We have to introduce + // props from windows, then re-write geom::shift. + +// if (erosion_chooses_arbitrary(input, win)) +// return erosion_dispatch_for_arbitrary(input, win); +// else return erosion_dispatch_for_generic(input, win); } Index: mln/morpho/erosion.hh --- mln/morpho/erosion.hh (revision 2408) +++ mln/morpho/erosion.hh (working copy) @@ -79,7 +79,7 @@ for_all(p) { min.init(); - for_all(q) if (input.has(q)) + for_all(q) if (input.domain().has(q)) min.take(input(q)); output(p) = min; } @@ -107,7 +107,7 @@ mln_qiter(W) q(win, p); for_all(p) { - for_all(q) if (input.has(q)) + for_all(q) if (input.domain().has(q)) if (input(q) == false) break; output(p) = ! q.is_valid(); Index: mln/morpho/dilation.hh --- mln/morpho/dilation.hh (revision 2408) +++ mln/morpho/dilation.hh (working copy) @@ -99,7 +99,7 @@ for_all(p) { max.init(); - for_all(q) if (input.has(q)) + for_all(q) if (input.domain().has(q)) max.take(input(q)); output(p) = max.to_result(); } @@ -122,7 +122,7 @@ mln_qiter(W) q(win, p); for_all(p) if (!input(p)) - for_all(q) if (input.has(q)) + for_all(q) if (input.domain().has(q)) if (input(q)) { output(p) = true; Index: mln/morpho/includes.hh --- mln/morpho/includes.hh (revision 2408) +++ mln/morpho/includes.hh (working copy) @@ -54,7 +54,9 @@ # include <mln/level/fill.hh> # include <mln/test/positive.hh> + // # include <mln/border/all.hh> +# include <mln/extension/fill.hh> # include <mln/geom/sym.hh> # include <mln/set/inter.hh> Index: mln/morpho/meyer_wst.hh --- mln/morpho/meyer_wst.hh (revision 2408) +++ mln/morpho/meyer_wst.hh (working copy) @@ -138,7 +138,7 @@ for_all (p) if (output(p) == unmarked) for_all(n) - if (output.has(n) && output(n) != unmarked) + if (output.domain().has(n) && output(n) != unmarked) { queue.push(p); break; @@ -157,7 +157,7 @@ bool single_adjacent_marker_p = true; mln_niter(N) n(nbh, p); for_all(n) - if (output.has(n) && output(n) != unmarked) + if (output.domain().has(n) && output(n) != unmarked) { if (adjacent_marker == unmarked) { @@ -179,7 +179,7 @@ { output(p) = adjacent_marker; for_all(n) - if (output.has(n) && output(n) == unmarked) + if (output.domain().has(n) && output(n) == unmarked) queue.push(n); } } Index: mln/canvas/morpho/algebraic_union_find.hh --- mln/canvas/morpho/algebraic_union_find.hh (revision 2408) +++ mln/canvas/morpho/algebraic_union_find.hh (working copy) @@ -92,7 +92,7 @@ { make_set(p); for_all(n) - if (f.input.has(n) && deja_vu(n)) + if (f.input.domain().has(n) && deja_vu(n)) do_union(n, p); deja_vu(p) = true; } Index: mln/canvas/labeling.hh --- mln/canvas/labeling.hh (revision 2408) +++ mln/canvas/labeling.hh (working copy) @@ -1,4 +1,4 @@ -// Copyright (C) 2007 EPITA Research and Development Laboratory +// Copyright (C) 2007, 2008 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 @@ -173,7 +173,7 @@ { make_set(p); for_all(n) - if (f.input.has(n) && deja_vu(n)) + if (f.input.domain().has(n) && deja_vu(n)) { if (f.equiv(n, p)) do_union(n, p); Index: mln/extension/fill.hh --- mln/extension/fill.hh (revision 2408) +++ mln/extension/fill.hh (working copy) @@ -25,7 +25,6 @@ // reasons why the executable file might be covered by the GNU General // Public License. - #ifndef MLN_CORE_EXTENSION_FILL_HH # define MLN_CORE_EXTENSION_FILL_HH @@ -33,6 +32,9 @@ * * \brief Define function that fills domain extension. * + * + * \todo Test the compatibility between val and mln_value(I) because, + * while unmorphing, this type can change... */ # include <mln/core/concept/image.hh> @@ -40,6 +42,7 @@ # include <mln/border/fill.hh> # include <mln/level/fill_with_value.hh> + namespace mln { @@ -50,63 +53,136 @@ * single value \p v. * * \param[in,out] ima The image whose domain extension is to be filled. - * \param[in] v The value to assign. + * \param[in] val The value to assign. * * \pre \p ima has to be initialized. * * \todo Optimize with memset if possible. */ template <typename I> - void fill(const Image<I>& ima, const mln_value(I)& v); + void fill(const Image<I>& ima, const mln_value(I)& val); + + + +# ifndef MLN_INCLUDE_ONLY + - namespace impl + namespace internal { + + // Do it. + + template <typename I> + void do_fill(I& ima, const mln_value(I)& val); // Entry point. + template <typename I> - void fill_fixed_extension(const Image<I>& ima, const mln_value(I)& v); + void do_fill(mln::trait::image::ext_domain::some, + mln::trait::image::ext_value::single, + mln::trait::image::ext_domain::none, + I& ima, const mln_value(I)& val) + { + ima.change_extension(val); } -# ifndef MLN_INCLUDE_ONLY + template <typename I> + void do_fill(mln::trait::image::ext_domain::some, + mln::trait::image::ext_value::multiple, + mln::trait::image::ext_domain::none, + I& ima, const mln_value(I)& val) + { + border::fill(ima, val); + ima.change_extension(val); + } template <typename I> - void fill(const Image<I>& ima, const mln_value(I)& v) + void do_fill(mln::trait::image::ext_domain::some, + mln::trait::image::ext_value::any, + mln::trait::image::ext_domain::some, + I& ima, const mln_value(I)& val) { - // Case of ext_io::read_only. - if (mlc_equal(mln_trait_image_ext_io(I), - mln::trait::image::ext_io::read_only)::value == true) - return; // No-op. + mln::extension::fill(ima.unmorph_(), val); + } - // Case of ext_domain::none. - if (mlc_equal(mln_trait_image_ext_domain(I), - mln::trait::image::ext_domain::none)::value == true) - return; // No-op. + template <typename I> + void do_fill(mln::trait::image::ext_domain::none, + mln::trait::image::ext_value::any, + mln::trait::image::ext_domain::any, + I& ima, const mln_value(I)& val) + { + // Oops... + } + + template <typename I> + void do_fill(I& ima, const mln_value(I)& val) + { + typedef typename I::delegatee D; + do_fill(mln_trait_image_ext_domain(I)(), + mln_trait_image_ext_value(I)(), + mln_trait_image_ext_domain(D)(), + ima, val); + } - // Case of ext_domain::extendable. - if (mlc_equal(mln_trait_image_ext_domain(I), - mln::trait::image::ext_domain::extendable)::value == true) - return mln::border::fill(ima, v); - // Case of ext_domain::fixed. - if (mlc_equal(mln_trait_image_ext_domain(I), - mln::trait::image::ext_domain::fixed)::value == true) + // Dispatch. - // Case of ext_value::single. - if (mlc_equal(mln_trait_image_ext_value(I), - mln::trait::image::ext_value::single)::value == true) - return impl::fill_fixed_extension(const_cast<I&>(exact(ima)), v); - else - return mln::level::fill_with_value(const_cast<I&>(exact(ima)), v); + template <typename I> + void fill_dispatch(mln::trait::image::ext_domain::none, + mln::trait::image::ext_io::any, + I& ima, const mln_value(I)& val) + { + // No-op cause no extension domain, no border. + } + template <typename I> + void fill_dispatch(mln::trait::image::ext_domain::some, + mln::trait::image::ext_io::read_only, + I& ima, const mln_value(I)& val) + { + // No-op for the extension domain, yet: + border::fill(ima, val); + } + + template <typename I> + void fill_dispatch(mln::trait::image::ext_domain::extendable, + mln::trait::image::ext_io::read_write, + I& ima, const mln_value(I)& val) + { + // Just fill the border. + border::fill(ima, val); } - namespace impl + template <typename I> + void fill_dispatch(mln::trait::image::ext_domain::some, + mln::trait::image::ext_io::read_write, + I& ima, const mln_value(I)& val) { + do_fill(ima, val); + } + template <typename I> - void fill_fixed_extension(Image<I>& ima_, const mln_value(I)& v) + void fill_dispatch(const Image<I>& ima_, const mln_value(I)& val) { - I& ima = exact(ima_); - ima.extension() = v; + I& ima = const_cast<I&>(exact(ima_)); + fill_dispatch(mln_trait_image_ext_domain(I)(), + mln_trait_image_ext_io(I)(), + ima, val); } + + } // end of namespace mln::extension::internal + + + // Facade. + + template <typename I> + void fill(const Image<I>& ima, const mln_value(I)& val) + { + trace::entering("extension::fill"); + + mln_precondition(exact(ima).has_data()); + internal::fill_dispatch(ima, val); + + trace::exiting("extension::fill"); } # endif // ! MLN_INCLUDE_ONLY