
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena Index: ChangeLog from Nicolas Ballas <ballas@lrde.epita.fr> Update dispatch of the fill_with image and paste routines. * tests/level/fill_with_image.cc: New test. * tests/level/paste.cc: Update. * tests/level/Makefile.am: Add the new test. * mln/trait/image/props.hh: Fix documentation. * mln/trait/images.hh: Fix properties delegation. * mln/core/image/image_if.hh, * mln/core/image/flat_image.hh, * mln/core/image/sub_image.hh, * mln/pw/image.hh, * mln/core/image/complex_image.hh: Update image properties. * mln/core/image/status.txt: Update. * mln/level/fill_with_image.hh, * mln/level/fill_with_image.spe.hh: Specialize fill_with_value routine. * mln/level/fill_with_value.hh: Update documentation. * mln/level/fill_with_value.spe.hh: Fix a bug in the dispatch. * mln/level/transform.hh: Update. * mln/level/paste.hh, * mln/level/paste.spe.hh: Specialize paste routine. * mln/morpho/gradient.hh: Delete trailing whitespaces. mln/core/image/complex_image.hh | 6 +- mln/core/image/image_if.hh | 3 + mln/core/image/status.txt | 4 - mln/core/image/sub_image.hh | 3 + mln/level/fill_with_image.hh | 7 +- mln/level/fill_with_image.spe.hh | 94 ++++++++++++++++++++++++++++++- mln/level/fill_with_value.hh | 3 - mln/level/fill_with_value.spe.hh | 7 +- mln/level/paste.hh | 56 ++++++++++-------- mln/level/paste.spe.hh | 116 ++++++++++++++++++++++++++++++--------- mln/level/transform.hh | 1 mln/pw/image.hh | 4 + mln/trait/image/props.hh | 4 - mln/trait/images.hh | 4 + tests/level/Makefile.am | 2 tests/level/fill_with_image.cc | 91 ++++++++++++++++++++++++++++++ tests/level/paste.cc | 16 +++-- 17 files changed, 349 insertions(+), 72 deletions(-) Index: tests/level/fill_with_image.cc --- tests/level/fill_with_image.cc (revision 0) +++ tests/level/fill_with_image.cc (revision 0) @@ -0,0 +1,91 @@ +// 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 +// 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/level/fill_with_value.cc + * + * \brief Tests on mln::level::fill_with_value + */ + +#include <mln/level/fill_with_value.hh> +#include <mln/level/fill_with_image.hh> + +#include <mln/core/image/image2d.hh> +#include <mln/core/image/flat_image.hh> +#include <mln/core/image/sub_image.hh> + +#include <mln/core/image/image_if.hh> +#include <mln/level/compare.hh> + +#include <mln/debug/iota.hh> +#include <mln/debug/println.hh> +#include <mln/fun/p2b/chess.hh> + + +int main() +{ + using namespace mln; + const unsigned size = 100; + + { + image2d<unsigned int> ima(size, size); + image2d<unsigned int> ima2(size, size); + debug::iota(ima2); + + level::fill_with_image(ima, ima2); + mln_assertion(ima == ima2); + } + + { + box2d b(point2d(1,2), point2d(2,4)); + image2d<int> ima(b, 2); + + box2d b2(point2d(-1,-2), point2d(3,6)); + image2d<int> ima2(b2, 0); + debug::iota(ima2); + + level::fill_with_image(ima, ima2); + assert(ima == (ima2 | b)); + } + + { + typedef image2d<unsigned char> I; + typedef image_if<I, fun::p2b::chess_t> II; + + I ima(size, size); + I ima2(size, size); + level::fill_with_value(ima, 51); + level::fill_with_value(ima2, 42); + + II ima_if = ima | fun::p2b::chess; + level::fill_with_image(ima_if, ima2); + + II::piter p(ima_if.domain()); + for_all(p) + mln_assertion(ima_if(p) == 42); + + } +} Index: tests/level/paste.cc --- tests/level/paste.cc (revision 2612) +++ tests/level/paste.cc (working copy) @@ -56,11 +56,13 @@ image2d<int> ima2(b2, 0); debug::iota(ima2); - level::paste(ima, ima2); // Fast version. - assert(ima == (ima2 | b)); + image2d<int> ima3(b, 2); - level::impl::generic::paste(ima, ima2); // Not so fast version... + level::paste(ima, ima2); // Not so fast version... assert(ima == (ima2 | b)); + + level::paste(ima, ima3); // Fast version... + assert(ima == ima3); } // tests in three dimension @@ -73,10 +75,12 @@ image3d<int> ima2(b2, 2); debug::iota(ima2); - level::paste(ima, ima2); // Fast version. - assert(ima == (ima2 | b)); + image3d<int> ima3(b, 2); - level::impl::generic::paste(ima, ima2); // Not so fast version... + level::paste(ima, ima2); // Not so fast version... assert(ima == (ima2 | b)); + + level::paste(ima, ima3); // Fast version... + assert(ima == ima3); } } Index: tests/level/Makefile.am --- tests/level/Makefile.am (revision 2612) +++ tests/level/Makefile.am (working copy) @@ -13,6 +13,7 @@ compute \ fill \ fill_with_value \ + fill_with_image \ median \ median_ \ median_dir \ @@ -36,6 +37,7 @@ compute_SOURCES = compute.cc fill_SOURCES = fill.cc fill_with_value_SOURCES = fill_with_value.cc +fill_with_image_SOURCES = fill_with_image.cc median_SOURCES = median.cc median__SOURCES = median_.cc median_dir_SOURCES = median_dir.cc Index: mln/trait/image/props.hh --- mln/trait/image/props.hh (revision 2612) +++ mln/trait/image/props.hh (working copy) @@ -122,7 +122,7 @@ // | // +-- with_grid // | -// +-- no_aligned +// +-- not_aligned // | // +-- irrelevant @@ -363,7 +363,7 @@ // | // +-- with_grid // | -// +-- no_aligned +// +-- not_aligned // | // +-- irrelevant struct value_alignement Index: mln/trait/images.hh --- mln/trait/images.hh (revision 2612) +++ mln/trait/images.hh (working copy) @@ -190,12 +190,16 @@ typedef mln_internal_trait_image_speed_from(D) speed; // un-fastest // value => delegation + typedef typename image_<D>::vw_io vw_io; + typedef typename image_<D>::vw_set vw_set; + typedef typename image_<D>::value_alignement value_alignement; typedef typename image_<D>::value_access value_access; typedef typename image_<D>::value_storage value_storage; typedef typename image_<D>::value_browsing value_browsing; typedef mln_internal_trait_image_value_io_from(D) value_io; // un-write when D is const // site => delegation + typedef typename image_<D>::pw_io pw_io; typedef typename image_<D>::localization localization; typedef typename image_<D>::dimension dimension; Index: mln/core/image/image_if.hh --- mln/core/image/image_if.hh (revision 2612) +++ mln/core/image/image_if.hh (working copy) @@ -79,6 +79,9 @@ typedef trait::image::ext_value::irrelevant ext_value; typedef trait::image::ext_io::irrelevant ext_io; + typedef trait::image::vw_io::none vw_io; + typedef trait::image::vw_set::none vw_set; + typedef trait::image::value_alignement::not_aligned value_alignement; typedef trait::image::value_storage::disrupted value_storage; }; Index: mln/core/image/status.txt --- mln/core/image/status.txt (revision 2612) +++ mln/core/image/status.txt (working copy) @@ -17,8 +17,8 @@ ok image2d ok pw::image -KO image1d -KO image3d +ok image1d +ok image3d ** run-based Index: mln/core/image/flat_image.hh Index: mln/core/image/sub_image.hh --- mln/core/image/sub_image.hh (revision 2612) +++ mln/core/image/sub_image.hh (working copy) @@ -86,6 +86,9 @@ typedef trait::image::ext_value::irrelevant ext_value; typedef trait::image::ext_io::irrelevant ext_io; + typedef trait::image::vw_io::none vw_io; + typedef trait::image::vw_set::none vw_set; + typedef trait::image::value_alignement::not_aligned value_alignement; typedef trait::image::value_storage::disrupted value_storage; // HOT FIXME: except if S is a Box }; Index: mln/core/image/complex_image.hh --- mln/core/image/complex_image.hh (revision 2612) +++ mln/core/image/complex_image.hh (working copy) @@ -86,11 +86,15 @@ // Value. typedef trait::image::value_access::direct value_access; // FIXME: Is that right? - typedef trait::image::value_storage::one_block value_storage; + typedef trait::image::vw_io::read_write vw_io; + typedef trait::image::vw_set::multi vw_set; + typedef trait::image::value_storage::disrupted value_storage; typedef trait::image::value_browsing::site_wise_only value_browsing; + typedef trait::image::value_alignement::irrelevant value_alignement; typedef trait::image::value_io::read_write value_io; // Site / domain. + typedef trait::image::pw_io::read_write pw_io; typedef trait::image::localization::space localization; /* FIXME: Depends on G. We could use `trait::image::space_from_point<mln_site(G)>::ret' in most Index: mln/level/fill_with_image.hh --- mln/level/fill_with_image.hh (revision 2612) +++ mln/level/fill_with_image.hh (working copy) @@ -79,8 +79,8 @@ (void)ima; (void)data; - mlc_is(mln_trait_image_value_io(I), - mln::trait::image::value_io::read_write)::check(); + mlc_is(mln_trait_image_pw_io(I), + mln::trait::image::pw_io::read_write)::check(); mlc_converts_to(mln_value(J), mln_value(I))::check(); mln_precondition(exact(ima).has_data()); mln_precondition(exact(data).has_data()); @@ -125,8 +125,7 @@ { trace::entering("level::fill_with_image"); - internal::fill_with_image_tests(ima, data); - internal::fill_with_image_dispatch(ima, data); + internal::fill_with_image_(ima, data); trace::exiting("level::fill_with_image"); } Index: mln/level/paste.spe.hh --- mln/level/paste.spe.hh (revision 2612) +++ mln/level/paste.spe.hh (working copy) @@ -51,15 +51,26 @@ namespace level { + namespace internal + { + + + template <typename I, typename J> + inline + void paste_tests(const Image<I>& input, Image<J>& output); + } + namespace impl { namespace generic { template <typename I, typename J> - void paste(const Image<I>& data, Image<J>& destination); + void paste_(const Image<I>& input, Image<J>& output); } + + // template <typename I, typename J> // inline // void paste_lines_(const I& data, J& destination) @@ -83,42 +94,97 @@ // } -// // Disjunction. + template <typename I, typename J> + void paste_fast(const Image<I>& input_, Image<J>& output_) + { + trace::entering("level::impl::paste_fast"); -// // Remember: raw < linear < stored, computed. + const I& input = exact(input_); + J& output = exact(output_); -// template <typename I, typename J> -// inline -// void paste_(trait::image::value_storage::any, const I& data, -// trait::image::value_storage::any, J& destination) -// { -// generic::paste_(data, destination); -// } + level::internal::paste_tests(input, output); -// template <typename I, typename J> -// inline -// void paste_(trait::image::value_storage::one_block, const I& data, -// trait::image::value_storage::one_block, J& destination) -// { -// if (sizeof(mln_value(I)) == sizeof(mln_value(J))) -// paste_lines_(data, destination); -// else -// generic::paste_(data, destination); -// } + mln_pixter(const I) pi(input); + mln_pixter(J) po(output); + po.start(); + for_all(pi) + { + po.val() = pi.val(); + } + trace::entering("level::impl::paste_fast"); + } + + } // end of namespace impl. - } // end of namespace mln::level::impl + // Dispatch. namespace internal { + + template <typename I, typename J> + inline + void paste_(trait::image::value_storage::any, + trait::image::value_storage::any, + const Image<I>& input, + Image<J>& output) + { + impl::generic::paste_(input, output); + } + + template <typename I, typename J> + inline + void paste_(trait::image::value_storage::one_block, + trait::image::value_storage::one_block, + const Image<I>& input_, + Image<J>& output_) + { + const I& input = exact(input_); + J& output = exact(output_); + + /// Check basic properties + if (mlc_is(mln_trait_image_value_access(J), + trait::image::value_access::direct)::value && + mlc_is(mln_trait_image_value_access(I), + trait::image::value_access::direct)::value && + mlc_is(mln_trait_image_value_alignement(I), + trait::image::value_alignement::with_grid)::value && + mlc_is(mln_trait_image_value_alignement(J), + trait::image::value_alignement::with_grid)::value) + { + /// Check ext_domain + if ( + ((mlc_is(mln_trait_image_ext_domain(I), + trait::image::ext_domain::fixed)::value || + mlc_is(mln_trait_image_ext_domain(I), + trait::image::ext_domain::extendable)::value) && + (mlc_is(mln_trait_image_ext_domain(J), + trait::image::ext_domain::fixed)::value || + mlc_is(mln_trait_image_ext_domain(J), + trait::image::ext_domain::extendable)::value) && + input.border() == output.border()) || + (mlc_is(mln_trait_image_ext_domain(I), + trait::image::ext_domain::none)::value && + mlc_is(mln_trait_image_ext_domain(J), + trait::image::ext_domain::none)::value)) + { + /// Check domain + if (input.domain() == output.domain()) + impl::paste_fast(input, output); + } + } + impl::generic::paste_(input, output); + } + + template <typename I, typename J> inline - void paste_dispatch(const Image<I>& data, Image<J>& destination) + void paste_(const Image<I>& input, Image<J>& output) { - impl::generic::paste(data, destination); -// impl::paste_(mln_trait_image_value_storage(I)(), data, -// mln_trait_image_value_storage(J)(), destination); + paste_(mln_trait_image_value_storage(I)(), + mln_trait_image_value_storage(J)(), + input, output); } } // end of namespace mln::level::internal Index: mln/level/fill_with_value.spe.hh --- mln/level/fill_with_value.spe.hh (revision 2612) +++ mln/level/fill_with_value.spe.hh (working copy) @@ -78,6 +78,7 @@ { trace::entering("level::impl::fill_with_value_one_block"); + I& ima = exact(ima_); internal::fill_with_value_tests(ima, val); mln_precondition(((mlc_is(mln_trait_image_pw_io(I), @@ -178,14 +179,16 @@ trait::image::vw_io::read_write, Image<I>& ima, const V& val) { - impl::fill_with_value_cell_wise(ima, val); + // FIXME + //impl::fill_with_value_cell_wise(ima, val); + impl::generic::fill_with_value(ima, val); } template <typename I, typename V> void fill_with_value_dispatch(trait::image::value_storage::disrupted, - trait::image::vw_io::read, + trait::image::vw_io::any, Image<I>& ima, const V& val) { impl::generic::fill_with_value(ima, val); Index: mln/level/fill_with_image.spe.hh --- mln/level/fill_with_image.spe.hh (revision 2612) +++ mln/level/fill_with_image.spe.hh (working copy) @@ -49,6 +49,17 @@ namespace level { + namespace internal + { + + template <typename I, typename J> + inline + void fill_with_image_tests(Image<I>& ima, const Image<J>& data); + + } // end of namespace mln::level::internal + + + namespace impl { @@ -58,20 +69,99 @@ void fill_with_image(Image<I>& ima, const Image<J>& data); } - // FIXME: Add specializations here... + template <typename I, typename J> + void fill_with_image_fast(Image<I>& ima_, const Image<J>& data_) + { + trace::entering("level::impl::fill_with_image_fast"); + + I& ima = exact(ima_); + const J& data = exact(data_); + + level::internal::fill_with_image_tests(ima, data); + + mln_pixter(I) pi(ima); + mln_pixter(const J) d(data); + d.start(); + for_all(pi) + { + pi.val() = d.val(); + } + trace::entering("level::impl::fill_with_image_fast"); + } } // end of namespace mln::level::impl + + + // Namespace dispatch namespace internal { template <typename I, typename J> inline - void fill_with_image_dispatch(Image<I>& ima, const Image<J>& data) + void fill_with_image_(trait::image::value_storage::any, + trait::image::value_storage::any, + Image<I>& ima, + const Image<J>& data) { impl::generic::fill_with_image(ima, data); } + template <typename I, typename J> + inline + void fill_with_image_(trait::image::value_storage::one_block, + trait::image::value_storage::one_block, + Image<I>& ima_, + const Image<J>& data_) + { + I& ima = exact(ima_); + const J& data = exact(data_); + + /// Check basic properties + if (mlc_is(mln_trait_image_value_access(J), + trait::image::value_access::direct)::value && + mlc_is(mln_trait_image_value_access(I), + trait::image::value_access::direct)::value && + mlc_is(mln_trait_image_value_alignement(I), + trait::image::value_alignement::with_grid)::value && + mlc_is(mln_trait_image_value_alignement(J), + trait::image::value_alignement::with_grid)::value) + { + /// Check ext_domain + if ( + ((mlc_is(mln_trait_image_ext_domain(I), + trait::image::ext_domain::fixed)::value || + mlc_is(mln_trait_image_ext_domain(I), + trait::image::ext_domain::extendable)::value) && + (mlc_is(mln_trait_image_ext_domain(J), + trait::image::ext_domain::fixed)::value || + mlc_is(mln_trait_image_ext_domain(J), + trait::image::ext_domain::extendable)::value) && + data.border() == data.border()) || + (mlc_is(mln_trait_image_ext_domain(I), + trait::image::ext_domain::none)::value && + mlc_is(mln_trait_image_ext_domain(J), + trait::image::ext_domain::none)::value)) + { + /// Check domain + if (data.domain() == data.domain()) + impl::fill_with_image_fast(ima, data); + } + } + impl::generic::fill_with_image(ima, data); + } + + + + template <typename I, typename J> + inline + void fill_with_image_(Image<I>& ima, const Image<J>& data) + { + fill_with_image_(mln_trait_image_value_storage(I)(), + mln_trait_image_value_storage(J)(), + ima, data); + } + } // end of namespace mln::level::internal } // end of namespace mln::level Index: mln/level/transform.hh --- mln/level/transform.hh (revision 2612) +++ mln/level/transform.hh (working copy) @@ -128,6 +128,7 @@ O& output = exact(output_); level::internal::transform_tests(input, f, output); + mlc_is(mln_trait_image_pw_io(O), trait::image::pw_io::read_write)::check(); Index: mln/level/paste.hh --- mln/level/paste.hh (revision 2612) +++ mln/level/paste.hh (working copy) @@ -49,25 +49,25 @@ namespace level { - /// \brief Paste the contents of image \p data into the image \p - /// destination. + /// \brief Paste the contents of image \p input into the image \p + /// output. /// - /// \param[in] data The input image providing pixels values. - /// \param[in,out] destination The image in which values are + /// \param[in] input The input image providing pixels values. + /// \param[in,out] output The image in which values are /// assigned. /// /// This routine runs: \n - /// for all p of \p data, \p destination(p) = \p data(p). + /// for all p of \p input, \p output(p) = \p input(p). /// - /// \warning The definition domain of \p data has to be included in - /// the one of \p destination; so using mln::safe_image does not - /// make pasting outside the destination domain work. + /// \warning The definition domain of \p input has to be included in + /// the one of \p output; so using mln::safe_image does not + /// make pasting outside the output domain work. /// - /// \pre \p data.domain <= \p destination.domain + /// \pre \p input.domain <= \p output.domain /// /// \{ template <typename I, typename J> - void paste(const Image<I>& data, Image<J>& destination); + void paste(const Image<I>& input, Image<J>& output); /// \} @@ -79,14 +79,17 @@ template <typename I, typename J> inline - void paste_tests(const Image<I>& data, Image<J>& destination) + void paste_tests(const Image<I>& input, Image<J>& output) { - mlc_is(mln_trait_image_value_io(J), trait::image::value_io::read_write)::check(); + mlc_is(mln_trait_image_pw_io(J), trait::image::pw_io::read_write):: + check(); mlc_converts_to(mln_value(I), mln_value(J))::check(); - mln_precondition(exact(data).has_data()); - mln_precondition(exact(data).domain() <= exact(destination).domain()); - (void)data; - (void)destination; + + mln_precondition(exact(input).has_data()); + mln_precondition(exact(input).domain() <= exact(output).domain()); + + (void)input; + (void)output; } } // end of namespace mln::level::internal @@ -99,17 +102,19 @@ template <typename I, typename J> inline - void paste(const Image<I>& data_, Image<J>& destination_) + void paste_(const Image<I>& input_, Image<J>& output_) { trace::entering("level::impl::generic::paste"); - level::internal::paste_tests(data_, destination_); - const I& data = exact(data_); - J& destination = exact(destination_); + level::internal::paste_tests(input_, output_); + + const I& input = exact(input_); + J& output = exact(output_); - mln_piter(I) p(data.domain()); + + mln_piter(I) p(input.domain()); for_all(p) - destination(p) = data(p); + output(p) = input(p); trace::exiting("level::impl::generic::paste"); } @@ -123,12 +128,13 @@ template <typename I, typename J> inline - void paste(const Image<I>& data, Image<J>& destination) + void paste(const Image<I>& input, Image<J>& output) { trace::entering("level::paste"); - internal::paste_tests(data, destination); - internal::paste_dispatch(data, destination); + + internal::paste_tests(input, output); + internal::paste_(input, output); trace::exiting("level::paste"); } Index: mln/level/fill_with_value.hh --- mln/level/fill_with_value.hh (revision 2612) +++ mln/level/fill_with_value.hh (working copy) @@ -33,9 +33,6 @@ * \brief Fill an image with a value, that is, set all pixel values to * the given value. * - * \todo Overload for fastest images. - * \todo Handle all value_storage properties (piecewise, etc.) - * \todo Make memset_ work and use it when appropriate. * \todo Move specializations in a extra file. * \toto Activate fill_with_value_cell_wise. * \todo Optimize when \p ima is large and sizeof(mln_value(I)) > 1. Index: mln/pw/image.hh --- mln/pw/image.hh (revision 2612) +++ mln/pw/image.hh (working copy) @@ -89,12 +89,16 @@ typedef trait::image::size::regular size; // value + typedef trait::image::vw_io::none vw_io; + typedef trait::image::vw_set::none vw_set; typedef trait::image::value_access::computed value_access; typedef trait::image::value_storage::disrupted value_storage; typedef trait::image::value_browsing::site_wise_only value_browsing; + typedef trait::image::value_alignement::irrelevant value_alignement; typedef trait::image::value_io::read_only value_io; // site / domain + typedef trait::image::pw_io::read pw_io; typedef /* FIXME: depends on S */ undef localization; typedef /* FIXME: depends on S */ undef dimension; Index: mln/morpho/gradient.hh