
https://svn.lrde.epita.fr/svn/oln/trunk/milena Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Add local convolution. * mln/core/concept/doc/generalized_pixel.hh, * mln/core/concept/generalized_pixel.hh, * mln/core/internal/pixel_impl.hh (ima): New. * mln/core/concept/doc/generalized_pixel.hh, * mln/core/concept/doc/pixel_iterator.hh * mln/core/concept/generalized_pixel.hh, * mln/core/concept/pixel_iterator.hh, * mln/core/dpoints_pixter.hh (ctor): Better sig. (center_value): Rename as... (center_val): ...this. * mln/core/internal/pixel_impl.hh (operator*): Rename as... (val): ...this. * mln/debug/iota.hh, * mln/histo/compute.hh, * mln/level/apply.hh, * mln/level/assign.hh, * mln/level/fast_median.hh, * mln/level/take.hh, * mln/level/transform.hh, * mln/linear/convolve.hh, : Update. * mln/core/pixel.hh (is_valid): Disambiguate. (include): Fix. * mln/linear/local: New directory. * mln/linear/local/convolve.hh: New. * mln/make/pixel.hh: New. * mln/metal/const.hh: New. * tests/decorated_image.cc: Fix warning. * tests/local_convolve.cc: New. * tests/pixel.cc: Update and augment. * tests/pixter_point2d.cc: Rename as... * tests/pixter2d_b.cc: ...this. Clean, update, and augment. * tests/pixter_dpoint2d.cc: Rename as... * tests/dpoints_pixter.cc: ...this. Clean, update, and augment. mln/core/concept/doc/generalized_pixel.hh | 9 + mln/core/concept/doc/pixel_iterator.hh | 4 mln/core/concept/generalized_pixel.hh | 14 +- mln/core/concept/pixel_iterator.hh | 4 mln/core/dpoints_pixter.hh | 26 ++-- mln/core/internal/pixel_impl.hh | 35 +++++- mln/core/macros.hh | 1 mln/core/pixel.hh | 12 +- mln/debug/iota.hh | 2 mln/histo/compute.hh | 2 mln/level/apply.hh | 2 mln/level/assign.hh | 2 mln/level/fast_median.hh | 14 +- mln/level/take.hh | 2 mln/level/transform.hh | 4 mln/linear/convolve.hh | 16 +- mln/linear/local/convolve.hh | 174 ++++++++++++++++++++++++++++++ mln/make/pixel.hh | 78 +++++++++++++ mln/metal/const.hh | 58 ++++++++++ tests/decorated_image.cc | 2 tests/dpoints_pixter.cc | 67 ++++++----- tests/fast_median.cc | 8 - tests/local_convolve.cc | 78 +++++++++++++ tests/pixel.cc | 13 +- tests/pixter2d_b.cc | 76 +++++++++---- 25 files changed, 589 insertions(+), 114 deletions(-) Index: tests/local_convolve.cc --- tests/local_convolve.cc (revision 0) +++ tests/local_convolve.cc (revision 0) @@ -0,0 +1,78 @@ +// 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/convolve.cc + * + * \brief Tests on mln::linear::convolve. + */ + +#include <mln/core/image2d_b.hh> +#include <mln/value/int_u8.hh> + +#include <mln/core/w_window2d_int.hh> +#include <mln/core/win/rectangle2d.hh> +#include <mln/core/pixel.hh> + +#include <mln/debug/iota.hh> +#include <mln/pw/cst.hh> +#include <mln/border/thickness.hh> +#include <mln/linear/local/convolve.hh> + + +int main() +{ + using namespace mln; + using value::int_u8; + + const unsigned size = 3; + border::thickness = size - 1; + + image2d_b<int_u8> ima(size, size); + debug::iota(ima); + + point2d p = make::point2d(1,1); + w_window2d_int w_win = make::w_window(win::rectangle2d(size, size), + pw::cst(1)); + + int res; + { + linear::local::convolve(ima, p, w_win, res); + mln_assertion(res = size*size * (size*size + 1) / 2); + } + + { + typedef image2d_b<int_u8> I; + linear::local::convolve(pixel<const I>(ima, p), w_win, res); + linear::local::convolve(pixel<I>(ima, p), w_win, res); + } + { + linear::local::convolve(make::pixel(ima, p), w_win, res); + mln_assertion(res = size*size * (size*size + 1) / 2); + } + + res = 0; +} Index: tests/fast_median.cc --- tests/fast_median.cc (revision 1053) +++ tests/fast_median.cc (working copy) @@ -57,16 +57,16 @@ { mln_qixter(I, W) qix(input, win, p); for_all(qix) - std::cout << *qix << ' '; - std::cout << " : " << qix.center_value() << std::endl; + std::cout << qix.val() << ' '; + std::cout << " : " << qix.center_val() << std::endl; } { pixel<I> pix(input, p); mln_qixter(I, W) qix(input, win, pix); for_all(qix) - std::cout << *qix << ' '; - std::cout << " : " << qix.center_value() << std::endl; + std::cout << qix.val() << ' '; + std::cout << " : " << qix.center_val() << std::endl; } } Index: tests/decorated_image.cc --- tests/decorated_image.cc (revision 1053) +++ tests/decorated_image.cc (working copy) @@ -39,7 +39,7 @@ template <typename I> struct counter { - void reading(const I& ima, const mln_psite(I)& p) const + void reading(const I&, const mln_psite(I)&) const { ++count_read; } Index: tests/pixter2d_b.cc --- tests/pixter2d_b.cc (revision 1053) +++ tests/pixter2d_b.cc (working copy) @@ -25,38 +25,70 @@ // reasons why the executable file might be covered by the GNU General // Public License. -#include <cassert> -#include <mln/core/image2d_b.hh> +/*! \file tests/pixter2d_b.cc + * + * \brief Tests on mln::fwd_pixter2d_b. + */ +#include <mln/core/image2d_b.hh> -int -main() -{ - using namespace mln; - typedef image2d_b<int> I; - I ima(20, 20); +const unsigned size = 20; +const int v = 51; - mln_piter_(I) p(ima.domain()); - mln_pixter_(I) pix(ima); - int i = 0; +template <typename I> +void test_fill(I& ima) +{ + mln_pixter(I) pxl(ima); + unsigned i = 0; + for_all(pxl) + { + ++i; + pxl.val() = v; + } + mln_assertion(i = size * size); + mln_assertion(! pxl.is_valid()); + mln_piter(I) p(ima.domain()); for_all(p) - ima(p) = i++; - i = 0; + mln_assertion(ima(p) = v); +} - for_all(pix) + +template <typename I> +void test_const(const I& imac, I& ima) +{ { - mln_assertion(*pix = i ++); - *pix = 5; + mln_pixter(const I) pxl(imac); // const is mandatory + pxl.start(); + mln_assertion(pxl.val() = v); + // pxl.val() = v; // error is OK since pixter on 'const I' + } + { + // mln_pixter(I) pxl_(imac); // error is OK since mutable I but const imac + mln_pixter(I) pxl(ima); + pxl.start(); + pxl.val() = 2 * pxl.val(); + mln_assertion(pxl.val() = 2 * v); + } + { + mln_pixter(const I) pxl(ima); // const promotion is OK + pxl.start(); + mln_assertion(pxl.val() = 2 * v); + // pxl.val() = v; // error is OK since pixter on 'const I' + } } - for_all(p) - mln_assertion(ima(p) = 5); - pix.start(); - mln_assertion(pix.is_valid()); - pix.invalidate(); - mln_assertion(! pix.is_valid()); + +int main() +{ + using namespace mln; + + typedef image2d_b<int> I; + I ima(size, size); + + test_fill(ima); + test_const(ima, ima); } Index: tests/dpoints_pixter.cc --- tests/dpoints_pixter.cc (revision 1053) +++ tests/dpoints_pixter.cc (working copy) @@ -25,49 +25,56 @@ // reasons why the executable file might be covered by the GNU General // Public License. -/*! \file tests/pixter_dpoint2d.cc +/*! \file tests/dpoints_pixter.cc * * \brief Test on mln::dpoints_fwd_pixter. */ -#include <cassert> -#include <iostream> - #include <mln/core/image2d_b.hh> -#include <mln/core/window.hh> -#include <mln/core/dpoints_pixter.hh> +#include <mln/core/win/rectangle2d.hh> +#include <mln/make/pixel.hh> -#include <mln/level/fill.hh> -int main() +template <typename I, typename W> +void test_fill(I& ima, const W& win) { - using namespace mln; + mln_piter(I) p(ima.domain()); + mln_qixter(I, W) q(ima, win, p); + for_all(p) + { + unsigned i = 0; + for_all(q) + ++i, q.val() = 51; + mln_assertion(i = 9); + } +} - typedef image2d_b<int> I; - typedef I::dpoint D; - typedef window<D> W; - typedef dpoints_fwd_pixter<I> qixter; +// FIXME: test promotion and other constructions - const unsigned size = 20; - I ima(size, size); - const int value = 51; - level::fill(ima, value); - - W win; - win - .insert(make::dpoint2d(0, -1)) - .insert(make::dpoint2d(0, -1)) - .insert(make::dpoint2d(1, 0)) - .insert(make::dpoint2d(1, 0)); +template <typename P, typename W> +void test_pixel(const P& pxl, const W& win) +{ + mln_qixter(mln_image(P), W) q(pxl, win); + for_all(q) + q.val() = 2 * q.val(); +} - mln_piter_(I) p(ima.domain()); - qixter qix(ima, win, p); - for_all(p) - if (p[0] > 0 && p[1] > 0 && p[0] < int(size - 1) && p[1] < int(size - 1)) - for_all(qix) - mln_assertion(*qix = value); + +int main() +{ + using namespace mln; + + border::thickness = 1; + typedef image2d_b<int> I; + I ima(5, 5); + + win::rectangle2d rect(3, 3); + point2d p = make::point2d(1, 1); + + test_fill(ima, rect); + test_pixel(make::pixel(ima, p), rect); } Index: tests/pixel.cc --- tests/pixel.cc (revision 1053) +++ tests/pixel.cc (working copy) @@ -30,8 +30,9 @@ * \brief Tests on mln::pixel. */ -#include <mln/core/pixel.hh> #include <mln/core/image2d_b.hh> +#include <mln/core/pixel.hh> +#include <mln/metal/equal.hh> int main() @@ -43,18 +44,22 @@ { pixel<I> pxl(ima, make::point2d(1, 1)); - *pxl = 51; + pxl.val() = 51; mln_assertion(ima.at(1, 1) = 51); } { pixel<const I> pxl(ima, make::point2d(1, 1)); ima.at(1, 1) = 51; - mln_assertion(*pxl = 51); + mln_assertion(pxl.val() = 51); // hopefully the code below does not compile: - // *pxl = 0; + // pxl.val() = 0; // assignment of read-only location } + { + mln::metal::equal< mln_image_(pixel<I>), I >::check(); + mln::metal::equal< mln_image_(pixel<const I>), const I >::check(); + } } Index: mln/histo/compute.hh --- mln/histo/compute.hh (revision 1053) +++ mln/histo/compute.hh (working copy) @@ -71,7 +71,7 @@ data<mln_vset(I)> h(input.values()); mln_pixter(const I) p(input); for_all(p) - ++h(*p); + ++h(p.val()); return h; } Index: mln/debug/iota.hh --- mln/debug/iota.hh (revision 1053) +++ mln/debug/iota.hh (working copy) @@ -69,7 +69,7 @@ I& input = exact(input_); mln_pixter(I) p(input); for_all(p) - *p = ++i; + p.val() = ++i; } } // end of namespace mln::debug::impl Index: mln/core/macros.hh --- mln/core/macros.hh (revision 1053) +++ mln/core/macros.hh (working copy) @@ -94,6 +94,7 @@ /// Shortcut to access the image type associated to T. # define mln_image(T) typename T::image +# define mln_image_(T) T::image // l Index: mln/core/dpoints_pixter.hh --- mln/core/dpoints_pixter.hh (revision 1053) +++ mln/core/dpoints_pixter.hh (working copy) @@ -71,14 +71,12 @@ /*! \brief Constructor. * - * \param[in] image Image subject to iteration. + * \param[in] pxl_ref Center (generalized) pixel to iterate around. * \param[in] dps Object that can provide a set of delta-points. - * \param[in] p_ref Center (generalized) pixel to iterate around. */ template <typename Dps, typename Pref> - dpoints_fwd_pixter(I& image, - const Dps& dps, - const Generalized_Pixel<Pref>& p_ref); + dpoints_fwd_pixter(const Generalized_Pixel<Pref>& pxl_ref, + const Dps& dps); /// Start an iteration. void start(); @@ -97,7 +95,7 @@ void update(); /// The value around which this iterator moves. - const mln_value(I)& center_value() const; + const mln_value(I)& center_val() const; private: @@ -140,23 +138,23 @@ init_(dps); } - template <typename I> template <typename Dps, typename Pref> - dpoints_fwd_pixter<I>::dpoints_fwd_pixter(I& image, - const Dps& dps, - const Generalized_Pixel<Pref>& p_ref) - : super_(image) + dpoints_fwd_pixter<I>::dpoints_fwd_pixter(const Generalized_Pixel<Pref>& pxl_ref_, + const Dps& dps) + : super_(internal::force_exact<Pref>(pxl_ref_).ima()) { - mln_precondition(image.has_data()); + const Pref& pxl_ref = internal::force_exact<Pref>(pxl_ref_); + mln_precondition(pxl_ref.ima().has_data()); p_ref_ = 0; - value_ref_ = internal::force_exact<Pref>(p_ref).address_(); + // potential promotion from (T**) to (const T**) shall be forced: + value_ref_ = (mln_qlf_value(I)**)(void*)(pxl_ref.address_()); init_(dps); } template <typename I> const mln_value(I)& - dpoints_fwd_pixter<I>::center_value() const + dpoints_fwd_pixter<I>::center_val() const { mln_invariant(value_ref_ != 0 || p_ref_ != 0); if (p_ref_) Index: mln/core/internal/pixel_impl.hh --- mln/core/internal/pixel_impl.hh (revision 1053) +++ mln/core/internal/pixel_impl.hh (working copy) @@ -67,10 +67,14 @@ /// pixel iterator value. - lvalue operator*(); + lvalue val(); /// Get the pixel iterator value. - rvalue operator*() const; + rvalue val() const; + + + /// Give the pixel image. + I& ima() const; /// Address of the current iterator value/pixel. @@ -113,7 +117,11 @@ /// Get the pixel iterator value. - rvalue operator*() const; + rvalue val() const; + + + /// Give the pixel image. + const I& ima() const; /// Address of the current iterator value/pixel. @@ -155,7 +163,7 @@ template <typename I, typename E> mln_lvalue(I) - pixel_impl_<I, E>::operator*() + pixel_impl_<I, E>::val() { mln_precondition(is_valid_()); return *value_ptr_; @@ -163,13 +171,21 @@ template <typename I, typename E> mln_rvalue(I) - pixel_impl_<I, E>::operator*() const + pixel_impl_<I, E>::val() const { mln_precondition(is_valid_()); return *value_ptr_; } template <typename I, typename E> + I& + pixel_impl_<I, E>::ima() const + { + // a const pixel, yet a mutable image + return const_cast<I&>(image_); + } + + template <typename I, typename E> mln_value(I) ** pixel_impl_<I, E>::address_() const { @@ -195,13 +211,20 @@ template <typename I, typename E> mln_rvalue(I) - pixel_impl_<const I, E>::operator*() const + pixel_impl_<const I, E>::val() const { mln_precondition(is_valid_()); return *value_ptr_; } template <typename I, typename E> + const I& + pixel_impl_<const I, E>::ima() const + { + return image_; + } + + template <typename I, typename E> const mln_value(I) ** pixel_impl_<const I, E>::address_() const { Index: mln/core/pixel.hh --- mln/core/pixel.hh (revision 1053) +++ mln/core/pixel.hh (working copy) @@ -96,12 +96,11 @@ bool pixel<I>::is_valid() const { - I& ima = this->image_; - if (this->value_ptr_ = 0 || ! ima.has_data()) + if (this->value_ptr_ = 0 || ! this->image_.has_data()) return false; - int o = this->value_ptr_ - ima.buffer(); - mln_point(I) p = ima.point_at_offset(o); - return ima.owns_(p); + int o = this->value_ptr_ - this->image_.buffer(); + mln_point(I) p = this->image_.point_at_offset(o); + return this->image_.owns_(p); } # endif // ! MLN_INCLUDE_ONLY @@ -109,4 +108,7 @@ } // end of namespace mln +# include <mln/make/pixel.hh> + + #endif // ! MLN_CORE_PIXEL_HH Index: mln/core/concept/pixel_iterator.hh --- mln/core/concept/pixel_iterator.hh (revision 1053) +++ mln/core/concept/pixel_iterator.hh (working copy) @@ -57,7 +57,7 @@ only if the iterator is constructed on a mutable image: typedef lvalue; - lvalue operator*(); + lvalue val(); */ protected: Pixel_Iterator(); @@ -70,7 +70,7 @@ Pixel_Iterator<E>::Pixel_Iterator() { // typedef mln_lvalue(E) lvalue; -// lvalue (E::*m)() = & E::operator*; +// lvalue (E::*m)() = & E::val; // m = 0; } Index: mln/core/concept/generalized_pixel.hh --- mln/core/concept/generalized_pixel.hh (revision 1053) +++ mln/core/concept/generalized_pixel.hh (working copy) @@ -62,9 +62,10 @@ /* typedef value; typedef rvalue; - typedef image; + typedef image; // is const or not - rvalue operator*() const; + rvalue val() const; + image& ima() const; mln_qlf_value(image)** address_() const; */ protected: @@ -80,13 +81,16 @@ typedef mln_value(E) value; typedef mln_rvalue(E) rvalue; - rvalue (E::*m1)() const = & E::operator*; + rvalue (E::*m1)() const = & E::val; m1 = 0; typedef mln_image(E) image; - - mln_qlf_value(image)** (E::*m2)() const = & E::address_; + // FIXME: check "without &" + image& (E::*m2)() const = & E::ima; m2 = 0; + + mln_qlf_value(image)** (E::*m3)() const = & E::address_; + m3 = 0; } # endif // ! MLN_INCLUDE_ONLY Index: mln/core/concept/doc/pixel_iterator.hh --- mln/core/concept/doc/pixel_iterator.hh (revision 1053) +++ mln/core/concept/doc/pixel_iterator.hh (working copy) @@ -47,12 +47,12 @@ */ typedef void lvalue; - /*! \brief Dereference operator. + /*! \brief Give the pixel value. * * \return The current pixel value; this value cannot be * modified. */ - lvalue operator*() const; + lvalue val() const; protected: Pixel_Iterator(); Index: mln/core/concept/doc/generalized_pixel.hh --- mln/core/concept/doc/generalized_pixel.hh (revision 1053) +++ mln/core/concept/doc/generalized_pixel.hh (working copy) @@ -61,7 +61,14 @@ * * \return A read-only value. */ - rvalue operator*() const; + rvalue val() const; + + /*! \brief Give the image of this generalized pixel. + * + * The constness of a pixel object is not transmitted to the + * underlying image. + */ + image& ima() const; /*! \brief Give a hook to the value address. * Index: mln/metal/const.hh --- mln/metal/const.hh (revision 0) +++ mln/metal/const.hh (revision 0) @@ -0,0 +1,58 @@ +// 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. + +#ifndef MLN_METAL_CONST_HH +# define MLN_METAL_CONST_HH + + +# define mlc_const(T) typename mln::metal::const_< T >::ret + + +namespace mln +{ + + namespace metal + { + + template <typename T> + struct const_ + { + typedef const T ret; + }; + + template <typename T> + struct const_< const T > + { + typedef const T ret; + }; + + } // end of namespace mln::metal + +} // end of namespace mln + + +#endif // ! MLN_METAL_CONST_HH Index: mln/level/take.hh --- mln/level/take.hh (revision 1053) +++ mln/level/take.hh (working copy) @@ -77,7 +77,7 @@ const I& input = exact(input_); mln_pixter(const I) pxl(input); for_all(pxl) - a.take(*pxl); + a.take(pxl.val()); } } // end of namespace mln::level::impl Index: mln/level/assign.hh --- mln/level/assign.hh (revision 1053) +++ mln/level/assign.hh (working copy) @@ -80,7 +80,7 @@ mln_pixter(L) lhs(target); mln_pixter(const R) rhs(data); for_all_2(lhs, rhs) - *lhs = *rhs; + lhs.val() = rhs.val(); } } // end of namespace mln::level::impl Index: mln/level/apply.hh --- mln/level/apply.hh (revision 1053) +++ mln/level/apply.hh (working copy) @@ -86,7 +86,7 @@ mln_pixter(const I) pxl(input); for_all(pxl) - f(input(*pxl)); + f(pxl.val()); return f; } Index: mln/level/fast_median.hh --- mln/level/fast_median.hh (revision 1053) +++ mln/level/fast_median.hh (working copy) @@ -99,7 +99,7 @@ { mln_qixter(const I, W) q(input, win, p); for_all(q) - med.take(*q); + med.take(q.val()); } int& row = p.row(); @@ -114,10 +114,10 @@ // "go down" for_all(q_top) - med.untake(*q_top); + med.untake(q_top.val()); for_all(q_bot) - med.take(*q_bot); + med.take(q_bot.val()); output(p) = med.to_value(); @@ -127,9 +127,9 @@ { ++col; for_all(q_fm) - med.untake(*q_fm); + med.untake(q_fm.val()); for_all(q_fp) - med.take(*q_fp); + med.take(q_fp.val()); output(p) = med.to_value(); } else @@ -138,9 +138,9 @@ { --col; for_all(q_bm) - med.untake(*q_bm); + med.untake(q_bm.val()); for_all(q_bp) - med.take(*q_bp); + med.take(q_bp.val()); output(p) = med.to_value(); } // change browsing Index: mln/level/transform.hh --- mln/level/transform.hh (revision 1053) +++ mln/level/transform.hh (working copy) @@ -31,6 +31,8 @@ /*! \file mln/level/transform.hh * * \brief Transform the contents of an image into another one. + * + * \todo Clean this file + overload with pixel iterators. */ # include <mln/core/concept/image.hh> @@ -110,7 +112,7 @@ // po.start(); // for_all(pi) // { -// *po = lut(*pi); +// po.val() = lut(pi.val()); // po.next(); // } // } Index: mln/linear/convolve.hh --- mln/linear/convolve.hh (revision 1053) +++ mln/linear/convolve.hh (working copy) @@ -46,11 +46,14 @@ namespace linear { - /*! Convolution of image \p input by the weighted window \p win. + /*! Convolution of image \p input by the weighted window \p w_win. * * \warning Computation of \p output(p) is performed with the * value type of \p output. * + * \warning The weighted window is used as-is, considering that + * its symmetrization is handled by the client. + * * \pre output.domain = input.domain */ template <typename I, typename W, typename O> @@ -97,26 +100,29 @@ mln_pixter(O) p_out(output); mln_pixter(const I) p(input); - mln_qixter(const I, W) q(input, w_win, p); + mln_qixter(const I, W) q(p, w_win); for_all_2(p, p_out) { mln_value(O) v = 0; unsigned i = 0; for_all(q) - v += w_win.w(i++) * *q; - *p_out = v; + v += w_win.w(i++) * q.val(); + p_out.val() = v; } } } // end of namespace mln::linear::impl + + // Facade. + template <typename I, typename W, typename O> void convolve(const Image<I>& input, const Weighted_Window<W>& w_win, Image<O>& output) { mln_precondition(exact(output).domain() = exact(input).domain()); - impl::convolve(exact(input), - exact(w_win), exact(output)); + impl::convolve(exact(input), exact(w_win), exact(output)); } # endif // ! MLN_INCLUDE_ONLY Index: mln/linear/local/convolve.hh --- mln/linear/local/convolve.hh (revision 0) +++ mln/linear/local/convolve.hh (revision 0) @@ -0,0 +1,174 @@ +// 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. + +#ifndef MLN_LINEAR_LOCAL_CONVOLVE_HH +# define MLN_LINEAR_LOCAL_CONVOLVE_HH + +/*! \file mln/linear/local/convolve.hh + * + * \brief Local convolution at a point. + */ + +# include <mln/core/concept/image.hh> +# include <mln/core/concept/generalized_point.hh> +# include <mln/core/concept/generalized_pixel.hh> +# include <mln/core/concept/weighted_window.hh> +# include <mln/metal/const.hh> + + + +namespace mln +{ + + namespace linear + { + + namespace local + { + + /*! Local convolution of image \p input at point \p p by the + * weighted window \p w_win. + * + * \warning Computation of the \p result is performed with the + * type \c R. + * + * \warning The weighted window is used as-is, considering that + * its symmetrization is handled by the client. + */ + template <typename I, typename P, typename W, typename R> + void convolve(const Image<I>& input, + const Generalized_Point<P>& p, + const Weighted_Window<W>& w_win, + R& result); + + + /*! Local convolution around (generalized) pixel \p by the + * weighted window \p w_win. + * + * \warning Computation of the \p result is performed with the + * type \c R. + * + * \warning The weighted window is used as-is, considering that + * its symmetrization is handled by the client. + */ + template <typename P, typename W, typename R> + void convolve(const Generalized_Pixel<P>& p, + const Weighted_Window<W>& w_win, + R& result); + + +# ifndef MLN_INCLUDE_ONLY + + namespace impl + { + + template <typename I, typename P, typename W, typename R> + void convolve(const Image<I>& input_, + const Generalized_Point<P>& p_, + const W& w_win, + R& result) + { + const I& input = exact(input_); + const P& p = internal::force_exact<P>(p_); + + R tmp = 0; // FIXME: zero? + mln_qiter(W) q(w_win, p); + for_all(q) if (input.has(q)) + tmp += input(q) * q.w(); + result = tmp; + } + + template <typename I, typename P, typename W, typename R> + void convolve(const Fast_Image<I>& input_, + const Generalized_Point<P>& p_, + const W& w_win, + R& result) + { + const I& input = exact(input_); + const P& p = internal::force_exact<P>(p_); + + mln_precondition(input.border() >= w_win.delta()); + + R tmp = 0; + unsigned i = 0; + mln_qixter(const I, W) q(input, w_win, p); + for_all(q) + tmp += w_win.w(i++) * q.val(); + result = tmp; + } + + template <typename P, typename W, typename R> + void convolve(const Generalized_Pixel<P>& p_, + const W& w_win, + R& result) + { + const P& p = internal::force_exact<P>(p_); + mln_precondition(p.ima().border() >= w_win.delta()); + + R tmp = 0; + unsigned i = 0; + // FIXME: mln_qixter(const P, W) should work + // FIXME: so make the trait make this job... + mln_qixter(mlc_const(mln_image(P)), W) q(p, w_win); + for_all(q) + tmp += w_win.w(i++) * q.val(); + result = tmp; + } + + } // end of namespace mln::linear::impl + + + // Facades. + + template <typename I, typename P, typename W, typename R> + void convolve(const Image<I>& input, + const Generalized_Point<P>& p, + const Weighted_Window<W>& w_win, + R& result) + { + mln_precondition(exact(input).has_data()); + impl::convolve(exact(input), p, exact(w_win), result); + } + + template <typename P, typename W, typename R> + void convolve(const Generalized_Pixel<P>& p, + const Weighted_Window<W>& w_win, + R& result) + { + impl::convolve(p, exact(w_win), result); + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::linear::local + + } // end of namespace mln::linear + +} // end of namespace mln + + +#endif // ! MLN_LINEAR_LOCAL_CONVOLVE_HH Index: mln/make/pixel.hh --- mln/make/pixel.hh (revision 0) +++ mln/make/pixel.hh (revision 0) @@ -0,0 +1,78 @@ +// 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. + +#ifndef MLN_MAKE_PIXEL_HH +# define MLN_MAKE_PIXEL_HH + +/*! \file mln/make/pixel.hh + * + * \brief Routine to construct an mln::pixel. + */ + +# include <mln/core/concept/image.hh> +# include <mln/core/pixel.hh> + + +namespace mln +{ + + namespace make + { + + /// Create an mln::pixel from a constant image \p ima and a point \p p. + template <typename I> + mln::pixel<const I> pixel(const Image<I>& ima, const mln_point(I)& p); + + /// Create an mln::pixel from a mutable image \p ima and a point \p p. + template <typename I> + mln::pixel<I> pixel(Image<I>& ima, const mln_point(I)& p); + + +# ifndef MLN_INCLUDE_ONLY + + template <typename I> + mln::pixel<const I> pixel(const Image<I>& ima, const mln_point(I)& p) + { + mln::pixel<const I> tmp(exact(ima), p); + return tmp; + } + + template <typename I> + mln::pixel<I> pixel(Image<I>& ima, const mln_point(I)& p) + { + mln::pixel<I> tmp(exact(ima), p); + return tmp; + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::make + +} // end of namespace mln + + +#endif // ! MLN_MAKE_PIXEL_HH