1406: Update the form of routines so that images are returned.

https://svn.lrde.epita.fr/svn/oln/trunk/milena Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Update the form of routines so that images are returned. * mln/fun/ops.hh: Add traits. (mln_decl_binary_expr_): Replace <opname> by <opname>_ when it is a language keyword. (mln_decl_unary_expr_): Likewise. * mln/core/image_if_interval.hh: Update. Use the "image foo(..)" form instead of "foo(.., output)"; Insert tracing calls to routines. * tests/morpho_hit_or_miss.cc: . * tests/labeling_level_fast.cc: . * tests/arith_plus.cc: . * tests/morpho_gradient.cc: . * tests/window2d.cc: . * tests/value_int_s.cc: . * tests/morpho_thinning.cc: . * tests/morpho_laplacian.cc: . * tests/value_int_u8.cc: . * tests/morpho_contrast.cc: . * tests/pw_value.cc: . * mln/core/concept/image.hh: . * mln/core/clone.hh: . * mln/arith/plus.hh: . * mln/arith/min.hh: . * mln/arith/revert.hh: . * mln/arith/minus.hh: . * mln/convert/to_image.hh: . * mln/morpho/thickening.hh: . * mln/morpho/plus.hh: . * mln/morpho/min.hh: . * mln/morpho/laplacian.hh: . * mln/morpho/minus.hh: . * mln/morpho/gradient.hh: . * mln/morpho/contrast.hh: . * mln/morpho/thick_miss.hh: . * mln/morpho/closing.hh: . * mln/morpho/top_hat.hh: . * mln/morpho/complementation.hh: . * mln/morpho/opening.hh: . * mln/morpho/dilation.hh: . * mln/morpho/thin_fit.hh: . * mln/morpho/includes.hh: . * mln/morpho/thinning.hh: . * mln/morpho/hit_or_miss.hh: . * mln/logical/and.hh: . * mln/logical/and_not.hh: . * mln/logical/or.hh: . * mln/logical/not.hh: . Misc. * mln/value/builtin/ops.hh: Add versions for builtin OP= object. * mln/value/cast.hh (cast_): Update using value::equiv. * mln/trait/op/minus.hh (mln_trait_op_minus_twice): New. * mln/fun/cast.hh: New. * mln/fun/v2v/cast.hh: New. * mln/fun/v2v/all.hh: Update. * mln/arith/includes.hh: Update. * img/picasso.pbm: New. img/picasso.pbm | 0 mln/arith/includes.hh | 1 mln/arith/min.hh | 47 +++-- mln/arith/minus.hh | 344 ++++++++++++++++++++++++++++++++++++++---- mln/arith/plus.hh | 285 +++++++++++++++++++++++++++++----- mln/arith/revert.hh | 43 +++-- mln/convert/to_image.hh | 2 mln/core/clone.hh | 4 mln/core/concept/image.hh | 2 mln/core/image_if_interval.hh | 2 mln/fun/cast.hh | 84 ++++++++++ mln/fun/ops.hh | 48 ++++- mln/fun/v2v/all.hh | 1 mln/fun/v2v/cast.hh | 80 +++++++++ mln/fun/v2v/saturate.hh | 17 +- mln/logical/and.hh | 44 +++-- mln/logical/and_not.hh | 44 +++-- mln/logical/not.hh | 35 ++-- mln/logical/or.hh | 46 +++-- mln/morpho/closing.hh | 25 +-- mln/morpho/complementation.hh | 66 +++++--- mln/morpho/contrast.hh | 31 +-- mln/morpho/dilation.hh | 18 ++ mln/morpho/gradient.hh | 83 ++++------ mln/morpho/hit_or_miss.hh | 270 +++++++++++++++++--------------- mln/morpho/includes.hh | 3 mln/morpho/laplacian.hh | 34 +++- mln/morpho/min.hh | 58 ++++--- mln/morpho/minus.hh | 66 ++++---- mln/morpho/opening.hh | 25 +-- mln/morpho/plus.hh | 65 ++++--- mln/morpho/thick_miss.hh | 27 +-- mln/morpho/thickening.hh | 28 +-- mln/morpho/thin_fit.hh | 29 ++- mln/morpho/thinning.hh | 43 ++--- mln/morpho/top_hat.hh | 82 ++++------ mln/trait/op/minus.hh | 1 mln/value/builtin/ops.hh | 84 ++++++++-- mln/value/cast.hh | 23 ++ tests/arith_plus.cc | 17 +- tests/labeling_level_fast.cc | 10 - tests/morpho_contrast.cc | 26 --- tests/morpho_gradient.cc | 8 tests/morpho_hit_or_miss.cc | 16 + tests/morpho_laplacian.cc | 5 tests/morpho_thinning.cc | 19 +- tests/pw_value.cc | 6 tests/value_int_s.cc | 2 tests/value_int_u8.cc | 5 tests/window2d.cc | 2 50 files changed, 1609 insertions(+), 697 deletions(-) Index: tests/morpho_hit_or_miss.cc --- tests/morpho_hit_or_miss.cc (revision 1405) +++ tests/morpho_hit_or_miss.cc (working copy) @@ -38,8 +38,8 @@ #include <mln/geom/shift.hh> #include <mln/set/diff.hh> -#include <mln/io/pgm/load.hh> -#include <mln/io/pgm/save.hh> +#include <mln/io/pbm/load.hh> +#include <mln/io/pbm/save.hh> #include <mln/level/fill.hh> #include <mln/level/stretch.hh> @@ -75,11 +75,13 @@ border::thickness = 2; - image2d<int_u8> - pic = io::pgm::load("../img/picasso.pgm"), - out(pic.domain()); + image2d<bool> + pic = io::pbm::load("../img/picasso.pbm"), + out = morpho::hit_or_miss(pic, win_hit, win_miss); + io::pbm::save(out, "out.pbm"); - morpho::hit_or_miss(pic, win_hit, win_miss, out); + mln_postcondition(morpho::hit_or_miss(morpho::complementation(pic), + win_miss, win_hit) = out); - io::pgm::save(out, "out.pgm"); + // FIXME: Do not work if the input image is pgm! } Index: tests/labeling_level_fast.cc --- tests/labeling_level_fast.cc (revision 1405) +++ tests/labeling_level_fast.cc (working copy) @@ -42,20 +42,20 @@ #include <mln/debug/iota.hh> #include <mln/debug/println.hh> + int main() { using namespace mln; using value::int_u8; - unsigned border = 1; - - image2d<value::int_u8> i1(5, 5, border); + image2d<value::int_u8> i1(5, 5); debug::iota(i1); - i1[10] = i1[17] = i1[18] = i1[25] = i1[26] = i1[22] = i1[29] = 2; + i1(point2d(0, 2)) = i1(point2d(1, 2)) = i1(point2d(1, 3)) = i1(point2d(2, 3)) = i1(point2d(2, 4)) = 2; + i1(point2d(2, 0)) = i1(point2d(3, 0)) = 2; debug::println(i1); unsigned n; - image2d<value::int_u8> out(i1.domain(), border); + image2d<value::int_u8> out(i1.domain()); labeling::level(i1, 2, c4(), out, n); std::cout << "n = " << n << std::endl; Index: tests/arith_plus.cc --- tests/arith_plus.cc (revision 1405) +++ tests/arith_plus.cc (working copy) @@ -37,6 +37,7 @@ #include <mln/arith/plus.hh> #include <mln/arith/times.hh> #include <mln/level/compare.hh> +#include <mln/fun/v2v/cast.hh> #include <mln/debug/iota.hh> #include <mln/debug/println.hh> @@ -47,6 +48,8 @@ { using namespace mln; + // trace::quiet = false; + { image2d<int> ref(3,3); debug::iota(ref); @@ -55,12 +58,16 @@ ima_i += ima_i; mln_assertion(ima_i = 2 * ref); -// debug::println(ima_i); -// ima_i += 1; -// debug::println(ima_i); + debug::println(ima_i); + ima_i += 1; + debug::println(ima_i); + + image2d<float> ima_f(3,3); + debug::iota(ima_f); + debug::println(ima_i + ima_f); -// debug::iota(ima_f); -// debug::println(ima_i + ima_f); + point2d p(0, 0); + std::cout << arith::plus<float>(ima_i, ima_i)(p) / 5 << std::endl; } } Index: tests/morpho_gradient.cc --- tests/morpho_gradient.cc (revision 1405) +++ tests/morpho_gradient.cc (working copy) @@ -49,10 +49,8 @@ win::rectangle2d rect(5, 5); border::thickness = 2; - image2d<int_u8> - lena = io::pgm::load("../img/tiny.pgm"), - out(lena.domain()); + image2d<int_u8> lena = io::pgm::load("../img/tiny.pgm"); - morpho::gradient(lena, rect, out); - io::pgm::save(out, "out.pgm"); + io::pgm::save( morpho::gradient(lena, rect), + "out.pgm" ); } Index: tests/window2d.cc --- tests/window2d.cc (revision 1405) +++ tests/window2d.cc (working copy) @@ -34,6 +34,7 @@ #include <mln/core/image2d.hh> #include <mln/convert/to_image.hh> #include <mln/debug/println.hh> +#include <mln/logical/not.hh> @@ -51,6 +52,7 @@ image2d<bool> ima = convert::to_image(w); debug::println(ima); + debug::println(logical::not_(ima)); mln_assertion(w.delta() = 1); } Index: tests/value_int_s.cc --- tests/value_int_s.cc (revision 1405) +++ tests/value_int_s.cc (working copy) @@ -31,6 +31,7 @@ */ #include <mln/value/int_s.hh> +#include <mln/value/int_u.hh> int main() @@ -47,5 +48,4 @@ mln_assertion(-i = -2); mln_assertion(-3 * i = -6); } - } Index: tests/morpho_thinning.cc --- tests/morpho_thinning.cc (revision 1405) +++ tests/morpho_thinning.cc (working copy) @@ -36,7 +36,9 @@ #include <mln/win/rectangle2d.hh> #include <mln/core/window2d.hh> +#include <mln/io/pbm/load.hh> #include <mln/io/pgm/load.hh> +#include <mln/io/pbm/save.hh> #include <mln/io/pgm/save.hh> #include <mln/morpho/thinning.hh> @@ -59,11 +61,14 @@ border::thickness = 2; - image2d<int_u8> - pic = io::pgm::load("../img/picasso.pgm"), - out(pic.domain()); - - morpho::thinning(pic, win_fg, win_bg, out); - - io::pgm::save(out, "out.pgm"); + { + image2d<bool> pic = io::pbm::load("../img/picasso.pbm"); + io::pbm::save( morpho::thinning(pic, win_fg, win_bg), + "out.pbm" ); + } +// { +// image2d<int_u8> pic = io::pgm::load("../img/picasso.pgm"); +// io::pgm::save( morpho::thinning(pic, win_fg, win_bg), +// "out.pgm" ); +// } } Index: tests/morpho_laplacian.cc --- tests/morpho_laplacian.cc (revision 1405) +++ tests/morpho_laplacian.cc (working copy) @@ -57,7 +57,6 @@ image2d<int> lap(lena.domain()); morpho::laplacian(lena, rect, lap); - image2d< value::int_u_sat<8> > out(lena.domain()); - arith::plus_cst(lap, 128, out); - io::pgm::save(out, "out.pgm"); + io::pgm::save( arith::plus_cst< value::int_u_sat<8> >(lap, 128), + "out.pgm" ); } Index: tests/value_int_u8.cc --- tests/value_int_u8.cc (revision 1405) +++ tests/value_int_u8.cc (working copy) @@ -41,6 +41,11 @@ int_u8 i = 3, j; + { + int k = 0; + k += value::scalar(k); + } + // Assignment. { i = 51; Index: tests/morpho_contrast.cc --- tests/morpho_contrast.cc (revision 1405) +++ tests/morpho_contrast.cc (working copy) @@ -41,9 +41,6 @@ #include <mln/morpho/contrast.hh> -#include <mln/level/fill.hh> -#include <mln/level/saturate.hh> - int main() { @@ -53,27 +50,16 @@ win::rectangle2d rect(5, 5); border::thickness = 2; - image2d<int_u8> - lena = io::pgm::load("../img/tiny.pgm"), - out(lena.domain()); - - image2d< value::int_s<10> > - in(lena.domain()), - tmp(lena.domain()); - - level::fill(in, lena); - morpho::contrast(in, rect, tmp); - - level::saturate(tmp, out); + image2d<int_u8> lena = io::pgm::load("../img/tiny.pgm"); + image2d<int_u8> out = morpho::contrast(lena, rect); io::pgm::save(out, "out.pgm"); { // self-duality test: - morpho::complementation_inplace(in); - image2d< value::int_s<10> > tmp_(lena.domain()); - morpho::contrast(in, rect, tmp_); - morpho::complementation_inplace(tmp_); - mln_assertion(tmp_ = tmp); + image2d<int_u8> out_ = morpho::complementation( morpho::contrast( morpho::complementation(lena), + rect ) + ); + mln_assertion(out_ = out); } } Index: tests/pw_value.cc --- tests/pw_value.cc (revision 1405) +++ tests/pw_value.cc (working copy) @@ -44,4 +44,10 @@ point2d p = make::point2d(1, 1); ima(p) = 51; mln_assertion( (pw::value(ima) = pw::cst(51))(p) = true ); + + { + image2d<float> imaf(3,3); + imaf(p) = 51; + mln_assertion(((pw::value(ima) + pw::value(imaf))(p) / 20) - 5.1 < 0.00001); + } } Index: mln/trait/op/minus.hh --- mln/trait/op/minus.hh (revision 1405) +++ mln/trait/op/minus.hh (working copy) @@ -39,6 +39,7 @@ # define mln_trait_op_minus(L, R) typename mln::trait::op::minus< L , R >::ret # define mln_trait_op_minus_(L, R) mln::trait::op::minus< L , R >::ret +# define mln_trait_op_minus_twice(T) mln_trait_op_minus(T, T) namespace mln Index: mln/core/image_if_interval.hh --- mln/core/image_if_interval.hh (revision 1405) +++ mln/core/image_if_interval.hh (working copy) @@ -39,7 +39,7 @@ # include <mln/value/interval.hh> -# define F fun::and_p2b_expr_< \ +# define F fun::and__p2b_expr_< \ fun::geq_p2b_expr_< \ pw::value_<I>, \ pw::cst_<mln_value(I)> >, \ Index: mln/core/concept/image.hh --- mln/core/concept/image.hh (revision 1405) +++ mln/core/concept/image.hh (working copy) @@ -183,12 +183,14 @@ template <typename I, typename J> void initialize(Image<I>& target, const Image<J>& model) { + trace::entering("core::initialize"); mln_precondition(! exact(target).has_data()); mln_precondition(exact(model).has_data()); init_(tag::image, exact(target), exact(model)); mln_postcondition(exact(target).has_data()); + trace::exiting("core::initialize"); } Index: mln/core/clone.hh --- mln/core/clone.hh (revision 1405) +++ mln/core/clone.hh (working copy) @@ -58,9 +58,13 @@ mln_concrete(I) clone(const Image<I>& model) { // FIXME: Add a static check that mln_concrete(I) actually *is* concrete... + trace::entering("core::clone"); + mln_concrete(I) tmp; initialize(tmp, model); level::fill(tmp, model); + + trace::exiting("core::clone"); return tmp; } Index: mln/arith/plus.hh --- mln/arith/plus.hh (revision 1405) +++ mln/arith/plus.hh (working copy) @@ -67,6 +67,7 @@ mln_trait_op_plus(L,R) operator+(const Image<L>& lhs, const Image<R>& rhs); + template <typename L, typename R> L& operator+=(Image<L>& lhs, const Image<R>& rhs); @@ -76,6 +77,7 @@ mln_trait_op_plus(I,S) operator+(const Image<I>& ima, const value::Scalar<S>& s); + template <typename I, typename S> I& operator+=(Image<I>& ima, const value::Scalar<S>& s); @@ -89,39 +91,111 @@ * * \param[in] lhs First operand image. * \param[in] rhs Second operand image. - * \param[out] output The result image. + * \result The result image. * - * \pre \p output.domain = \p lhs.domain = \p rhs.domain + * \pre \p lhs.domain = \p rhs.domain */ - template <typename L, typename R, typename O> - void plus(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output); + template <typename L, typename R> + mln_trait_op_plus(L, R) + plus(const Image<L>& lhs, const Image<R>& rhs); - /*! Point-wise addition of the value \p val to image \p input. + /*! Point-wise addition of images \p lhs and \p rhs. * - * \param[in] input The image. - * \param[in] val The value. - * \param[out] output The result image. + * \param[in] lhs First operand image. + * \param[in] rhs Second operand image. + * \param[in] f Function. + * \result The result image. + * + * \pre \p lhs.domain = \p rhs.domain + */ + template <typename L, typename R, typename F> + mln_ch_value(L, mln_result(F)) + plus(const Image<L>& lhs, const Image<R>& rhs, const Function_v2v<F>& f); + + + /*! Point-wise addition of images \p lhs and \p rhs. * - * \pre \p output.domain = \p input.domain + * \param[in] lhs First operand image. + * \param[in] rhs Second operand image. + * \result The result image. + * + * The free parameter \c V sets the destination value type. + * + * \pre \p lhs.domain = \p rhs.domain */ - template <typename I, typename V, typename O> - void plus_cst(const Image<I>& input, const V& val, Image<O>& output); + template <typename V, typename L, typename R> + mln_ch_value(L, V) + plus(const Image<L>& lhs, const Image<R>& rhs); /*! Point-wise addition of image \p rhs in image \p lhs. * - * \param[in] lhs First operand image (subject to addition). - * \param[in,out] rhs Second operand image (to be added to \p lhs). + * \param[in,out] lhs First operand image (subject to addition). + * \param[in] rhs Second operand image (to be added to \p lhs). * * This addition performs: \n * for all p of rhs.domain \n * lhs(p) += rhs(p) * - * \pre \p rhs.domain <= \p lhs.domain + * \pre \p rhs.domain = \p lhs.domain */ template <typename L, typename R> - void plus_inplace(Image<L>& lhs, const Image<R>& rhs); + void + plus_inplace(Image<L>& lhs, const Image<R>& rhs); + + + /*! Point-wise addition of the value \p val to image \p input. + * + * \param[in] input The image. + * \param[in] val The value. + * \result The result image. + * + * \pre \p input.has_data + */ + template <typename I, typename V> + mln_trait_op_plus(I, V) + plus_cst(const Image<I>& input, const V& val); + + + /*! Point-wise addition of the value \p val to image \p input. + * + * \param[in] input The image. + * \param[in] val The value. + * \param[in] f Function. + * \result The result image. + * + * \pre \p input.has_data + */ + template <typename I, typename V, typename F> + mln_ch_value(I, mln_result(F)) + plus_cst(const Image<I>& input, const V& val, const Function_v2v<F>& f); + + + /*! Point-wise addition of the value \p val to image \p input. + * + * \param[in] input The image. + * \param[in] val The value. + * \param[in] f Function. + * \result The result image. + * + * \pre \p input.has_data + */ + template <typename W, typename I, typename V> + mln_ch_value(I, W) + plus_cst(const Image<I>& input, const V& val); + + + /*! Point-wise addition of the value \p val to image \p input. + * + * \param[in,out] input The image. + * \param[in] val The value. + * + * \pre \p input.has_data + */ + template <typename I, typename V> + I& + plus_cst_inplace(Image<I>& input, const V& val); } // end of namespace mln::arith @@ -136,19 +210,25 @@ mln_trait_op_plus(L,R) operator+(const Image<L>& lhs, const Image<R>& rhs) { + trace::entering("operator::plus"); mln_precondition(exact(rhs).domain() = exact(lhs).domain()); - mln_trait_op_plus(L,R) tmp; - initialize(tmp, lhs); - arith::plus(lhs, rhs, tmp); - return tmp; + + mln_trait_op_plus(L,R) output = arith::plus(lhs, rhs); + + trace::exiting("operator::plus"); + return output; } template <typename L, typename R> L& operator+=(Image<L>& lhs, const Image<R>& rhs) { + trace::entering("operator::plus_eq"); mln_precondition(exact(rhs).domain() = exact(lhs).domain()); + arith::plus_inplace(lhs, rhs); + + trace::exiting("operator::plus_eq"); return exact(lhs); } @@ -157,19 +237,25 @@ mln_trait_op_plus(I,S) operator+(const Image<I>& ima, const value::Scalar<S>& s) { + trace::entering("operator::plus"); mln_precondition(exact(ima).has_data()); - mln_trait_op_plus(I,S) tmp; - initialize(tmp, ima); - arith::plus_cst(ima, exact(s), tmp); - return tmp; + + mln_trait_op_plus(I,S) output = arith::plus_cst(ima, exact(s)); + + trace::exiting("operator::plus"); + return output; } template <typename I, typename S> I& operator+=(Image<I>& ima, const value::Scalar<S>& s) { + trace::entering("operator::plus_eq"); mln_precondition(exact(ima).has_data()); - arith::plus_cst(ima, exact(s), ima); + + arith::plus_cst_inplace(ima, exact(s)); + + trace::exiting("operator::plus_eq"); return exact(ima); } @@ -183,18 +269,25 @@ template <typename L, typename R, typename O> void plus_(trait::image::speed::any, const L& lhs, - trait::image::speed::any, const R& rhs, - trait::image::speed::any, O& output) + trait::image::speed::any, const R& rhs, O& output) { mln_piter(L) p(lhs.domain()); for_all(p) output(p) = lhs(p) + rhs(p); } + template <typename L, typename R, typename F, typename O> + void plus_(trait::image::speed::any, const L& lhs, + trait::image::speed::any, const R& rhs, const F& f, O& output) + { + mln_piter(L) p(lhs.domain()); + for_all(p) + output(p) = f(lhs(p) + rhs(p)); + } + template <typename L, typename R, typename O> void plus_(trait::image::speed::fastest, const L& lhs, - trait::image::speed::fastest, const R& rhs, - trait::image::speed::fastest, O& output) + trait::image::speed::fastest, const R& rhs, O& output) { mln_pixter(const L) lp(lhs); mln_pixter(const R) rp(rhs); @@ -203,11 +296,22 @@ op.val() = lp.val() + rp.val(); } + template <typename L, typename R, typename F, typename O> + void plus_(trait::image::speed::fastest, const L& lhs, + trait::image::speed::fastest, const R& rhs, const F& f, O& output) + { + mln_pixter(const L) lp(lhs); + mln_pixter(const R) rp(rhs); + mln_pixter(O) op(output); + for_all_3(lp, rp, op) + op.val() = f(lp.val() + rp.val()); + } + template <typename L, typename R> void plus_inplace_(trait::image::speed::any, L& lhs, trait::image::speed::any, const R& rhs) { - mln_piter(R) p(rhs.domain()); + mln_piter(L) p(lhs.domain()); for_all(p) lhs(p) += rhs(p); } @@ -218,7 +322,7 @@ { mln_pixter(L) lp(lhs); mln_pixter(const R) rp(rhs); - for_all_2(rp, lp) + for_all_2(lp, rp) lp.val() += rp.val(); } @@ -227,38 +331,133 @@ // Facades. - template <typename L, typename R, typename O> - void plus(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output) + + template <typename L, typename R> + mln_trait_op_plus(L, R) + plus(const Image<L>& lhs, const Image<R>& rhs) + { + trace::entering("arith::plus"); + mln_precondition(exact(rhs).domain() = exact(lhs).domain()); + + mln_trait_op_plus(L, R) output; + initialize(output, lhs); + impl::plus_(mln_trait_image_speed(L)(), exact(lhs), + mln_trait_image_speed(R)(), exact(rhs), output); + + trace::exiting("arith::plus"); + return output; + } + + + template <typename L, typename R, typename F> + mln_ch_value(L, mln_result(F)) + plus(const Image<L>& lhs, const Image<R>& rhs, const Function_v2v<F>& f) { + trace::entering("arith::plus"); mln_precondition(exact(rhs).domain() = exact(lhs).domain()); - mln_precondition(exact(output).domain() = exact(lhs).domain()); + + mln_ch_value(L, mln_result(F)) output; + initialize(output, lhs); impl::plus_(mln_trait_image_speed(L)(), exact(lhs), - mln_trait_image_speed(R)(), exact(rhs), - mln_trait_image_speed(O)(), exact(output)); + mln_trait_image_speed(R)(), exact(rhs), exact(f), output); + + trace::exiting("arith::plus"); + return output; + } + + + template <typename V, typename L, typename R> + mln_ch_value(L, V) + plus(const Image<L>& lhs, const Image<R>& rhs) + { + trace::entering("arith::plus"); + mln_precondition(exact(rhs).domain() = exact(lhs).domain()); + + // Calls the previous version. + mln_ch_value(L, V) output = plus(lhs, rhs, + mln::fun::v2v::cast<V>()); + + trace::exiting("arith::plus"); + return output; + } + + + template <typename I, typename V> + mln_trait_op_plus(I, V) + plus_cst(const Image<I>& input, const V& val) + { + trace::entering("arith::plus_cst"); + mln_precondition(exact(input).has_data()); + + // Calls the previous version. + mln_trait_op_plus(I, V) output = plus(input, + pw::cst(val) | exact(input).domain()); + + trace::exiting("arith::plus_cst"); + return output; + } + + + template <typename I, typename V, typename F> + mln_ch_value(I, mln_result(F)) + plus_cst(const Image<I>& input, const V& val, const Function_v2v<F>& f) + { + trace::entering("arith::plus_cst"); + mln_precondition(exact(input).has_data()); + + // Calls the previous version. + mln_ch_value(I, mln_result(F)) output = plus(input, + pw::cst(val) | exact(input).domain(), + f); + + trace::exiting("arith::plus_cst"); + return output; } - template <typename I, typename V, typename O> - void plus_cst(const Image<I>& input, const V& val, Image<O>& output) + + template <typename W, typename I, typename V> + mln_ch_value(I, W) + plus_cst(const Image<I>& input, const V& val) { - mln_precondition(exact(output).domain() = exact(input).domain()); - plus(input, pw::cst(val) | exact(input).domain(), output); + trace::entering("arith::plus_cst"); + mln_precondition(exact(input).has_data()); + // Calls the previous version. + mln_ch_value(I, W) output = plus_cst(input, val, + mln::fun::v2v::cast<W>()); + + trace::exiting("arith::plus_cst"); + return output; } + template <typename L, typename R> - void plus_inplace(Image<L>& lhs, const Image<R>& rhs) + void + plus_inplace(Image<L>& lhs, const Image<R>& rhs) { - mln_precondition(exact(rhs).domain() <= exact(lhs).domain()); + trace::entering("arith::plus_inplace"); + mln_precondition(exact(rhs).domain() = exact(lhs).domain()); + impl::plus_inplace_(mln_trait_image_speed(L)(), exact(lhs), mln_trait_image_speed(R)(), exact(rhs)); + + trace::exiting("arith::plus_inplace"); } + template <typename I, typename V> - void plus_cst_inplace(Image<I>& input, const V& val) + I& + plus_cst_inplace(Image<I>& input, const V& val) { + trace::entering("arith::plus_cst_inplace"); mln_precondition(exact(input).has_data()); - plus_inplace(input, pw::cst(val) | exact(input).domain()); + // Calls the previous version. + plus_inplace(input, + pw::cst(val) | exact(input).domain()); + + trace::exiting("arith::plus_cst_inplace"); + return exact(input); } } // end of namespace mln::arith Index: mln/arith/min.hh --- mln/arith/min.hh (revision 1405) +++ mln/arith/min.hh (working copy) @@ -46,12 +46,13 @@ * * \param[in] lhs First operand image. * \param[in] rhs Second operand image. - * \param[out] output The result image. + * \result The result image. * - * \pre \p output.domain = \p lhs.domain = \p rhs.domain + * \pre \p lhs.domain = \p rhs.domain */ - template <typename L, typename R, typename O> - void min(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output); + template <typename L, typename R> + mln_concrete(L) + min(const Image<L>& lhs, const Image<R>& rhs); /*! Point-wise min of image \p lhs in image \p rhs. @@ -59,12 +60,7 @@ * \param[in,out] lhs First operand image. * \param[in] rhs Second operand image. * - * This substraction performs: \n - * for all p of rhs.domain \n - * if rhs(p) < lhs(p) \n - * lhs(p) = rhs(p) - * - * \pre \p rhs.domain <= \p lhs.domain + * \pre \p rhs.domain = \p lhs.domain */ template <typename L, typename R> void min_inplace(Image<L>& lhs, const Image<R>& rhs); @@ -77,8 +73,7 @@ template <typename L, typename R, typename O> void min_(trait::image::speed::any, const L& lhs, - trait::image::speed::any, const R& rhs, - trait::image::speed::any, O& output) + trait::image::speed::any, const R& rhs, O& output) { mln_piter(L) p(lhs.domain()); for_all(p) @@ -87,8 +82,7 @@ template <typename L, typename R, typename O> void min_(trait::image::speed::fastest, const L& lhs, - trait::image::speed::fastest, const R& rhs, - trait::image::speed::fastest, O& output) + trait::image::speed::fastest, const R& rhs, O& output) { mln_pixter(const L) lp(lhs); mln_pixter(const R) rp(rhs); @@ -101,7 +95,7 @@ void min_inplace_(trait::image::speed::any, L& lhs, trait::image::speed::any, const R& rhs) { - mln_piter(R) p(rhs.domain()); + mln_piter(L) p(lhs.domain()); for_all(p) if (rhs(p) < lhs(p)) lhs(p) = rhs(p); @@ -113,7 +107,7 @@ { mln_pixter(L) lp(lhs); mln_pixter(const R) rp(rhs); - for_all_2(rp, lp) + for_all_2(lp, rp) if (rp.val() < lp.val()) lp.val() = rp.val(); } @@ -123,22 +117,31 @@ // Facades. - template <typename L, typename R, typename O> - void min(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output) + template <typename L, typename R> + mln_concrete(L) min(const Image<L>& lhs, const Image<R>& rhs) { + trace::entering("arith::min"); mln_precondition(exact(rhs).domain() = exact(lhs).domain()); - mln_precondition(exact(output).domain() = exact(lhs).domain()); + + mln_concrete(L) output; + initialize(output, lhs); impl::min_(mln_trait_image_speed(L)(), exact(lhs), - mln_trait_image_speed(R)(), exact(rhs), - mln_trait_image_speed(O)(), exact(output)); + mln_trait_image_speed(R)(), exact(rhs), output); + + trace::exiting("arith::min"); + return output; } template <typename L, typename R> void min_inplace(Image<L>& lhs, const Image<R>& rhs) { - mln_precondition(exact(rhs).domain() <= exact(lhs).domain()); + trace::entering("arith::min_inplace"); + mln_precondition(exact(rhs).domain() = exact(lhs).domain()); + impl::min_inplace_(mln_trait_image_speed(L)(), exact(lhs), mln_trait_image_speed(R)(), exact(rhs)); + + trace::exiting("arith::min_inplace"); } # endif // ! MLN_INCLUDE_ONLY Index: mln/arith/includes.hh --- mln/arith/includes.hh (revision 1405) +++ mln/arith/includes.hh (working copy) @@ -37,6 +37,7 @@ # include <mln/value/ops.hh> # include <mln/pw/cst.hh> # include <mln/pw/image.hh> +# include <mln/fun/v2v/cast.hh> #endif // ! MLN_ARITH_INCLUDES_HH Index: mln/arith/revert.hh --- mln/arith/revert.hh (revision 1405) +++ mln/arith/revert.hh (working copy) @@ -52,18 +52,24 @@ /*! Point-wise reversion of image \p input. * * \param[in] input the input image. - * \param[out] output The result image. + * \result The result image. * - * \pre \p output.domain = \p input.domain + * \pre \p input.has_data + * + * It performs: \n + * for all p of input.domain \n + * output(p) = min + (max - input(p)) */ - template <typename I, typename O> - void revert(const Image<I>& input, Image<O>& output); + template <typename I> + mln_concrete(I) revert(const Image<I>& input); /*! Point-wise in-place reversion of image \p input. * * \param[in,out] input The target image. * + * \pre \p input.has_data + * * It performs: \n * for all p of input.domain \n * input(p) = min + (max - input(p)) @@ -78,8 +84,7 @@ { template <typename I, typename O> - void revert_(trait::image::speed::any, const I& input, - trait::image::speed::any, O& output) + void revert_(trait::image::speed::any, const I& input, O& output) { typedef mln_value(I) V; mln_piter(I) p(input.domain()); @@ -88,8 +93,7 @@ } template <typename I, typename O> - void revert_(trait::image::speed::fastest, const I& input, - trait::image::speed::fastest, O& output) + void revert_(trait::image::speed::fastest, const I& input, O& output) { typedef mln_value(I) V; mln_pixter(const I) ip(input); @@ -103,20 +107,29 @@ // Facades. - template <typename I, typename O> - void revert(const Image<I>& input, Image<O>& output) + template <typename I> + mln_concrete(I) revert(const Image<I>& input) { - mln_precondition(exact(output).domain() = exact(input).domain()); - impl::revert_(mln_trait_image_speed(I)(), exact(input), - mln_trait_image_speed(O)(), exact(output)); + trace::entering("arith::revert"); + mln_precondition(exact(input).has_data()); + + mln_concrete(I) output; + initialize(output, input); + impl::revert_(mln_trait_image_speed(I)(), exact(input), output); + + trace::exiting("arith::revert"); + return output; } template <typename I> void revert_inplace(Image<I>& input) { + trace::entering("arith::revert_inplace"); mln_precondition(exact(input).has_data()); - impl::revert_(mln_trait_image_speed(I)(), exact(input), - mln_trait_image_speed(I)(), exact(input)); + + impl::revert_(mln_trait_image_speed(I)(), exact(input), exact(input)); + + trace::exiting("arith::revert_inplace"); } # endif // ! MLN_INCLUDE_ONLY Index: mln/arith/minus.hh --- mln/arith/minus.hh (revision 1405) +++ mln/arith/minus.hh (working copy) @@ -31,63 +31,249 @@ /*! \file mln/arith/minus.hh * * \brief Point-wise substraction between images. + * + * \todo Speedup; some versions are not optimal. */ -# include <mln/core/concept/image.hh> +# include <mln/arith/includes.hh> namespace mln { + + namespace trait + { + + template <typename L, typename R> + struct set_binary_< op::minus, Image, L, Image, R > + { + typedef mln_trait_op_minus(mln_value(L), mln_value(R)) value; + typedef mln_ch_value(L, value) ret; + }; + + template <typename I, typename S> + struct set_binary_< op::minus, Image, I, mln::value::Scalar, S > + { + typedef mln_trait_op_minus(mln_value(I), S) value; + typedef mln_ch_value(I, value) ret; + }; + + } // end of namespace mln::trait + + + + template <typename L, typename R> + mln_trait_op_minus(L,R) + operator-(const Image<L>& lhs, const Image<R>& rhs); + + + template <typename L, typename R> + L& + operator-=(Image<L>& lhs, const Image<R>& rhs); + + + template <typename I, typename S> + mln_trait_op_minus(I,S) + operator-(const Image<I>& ima, const value::Scalar<S>& s); + + + template <typename I, typename S> + I& + operator-=(Image<I>& ima, const value::Scalar<S>& s); + + + namespace arith { - /*! Point-wise substraction of images \p lhs and \p rhs. + /*! Point-wise addition of images \p lhs and \p rhs. * * \param[in] lhs First operand image. * \param[in] rhs Second operand image. - * \param[out] output The result image. + * \result The result image. * - * \pre \p output.domain = \p lhs.domain = \p rhs.domain + * \pre \p lhs.domain = \p rhs.domain */ - template <typename L, typename R, typename O> - void minus(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output); + template <typename L, typename R> + mln_trait_op_minus(L, R) + minus(const Image<L>& lhs, const Image<R>& rhs); - /*! Point-wise substraction of image \p lhs in image \p rhs. + /*! Point-wise addition of images \p lhs and \p rhs. * - * \param[in,out] lhs First operand image (subject to substraction). - * \param[in] rhs Second operand image (to be substracted to \p lhs). + * \param[in] lhs First operand image. + * \param[in] rhs Second operand image. + * \param[in] f Function. + * \result The result image. * - * This substraction performs: \n + * \pre \p lhs.domain = \p rhs.domain + */ + template <typename L, typename R, typename F> + mln_ch_value(L, mln_result(F)) + minus(const Image<L>& lhs, const Image<R>& rhs, const Function_v2v<F>& f); + + + /*! Point-wise addition of images \p lhs and \p rhs. + * + * \param[in] lhs First operand image. + * \param[in] rhs Second operand image. + * \result The result image. + * + * The free parameter \c V sets the destination value type. + * + * \pre \p lhs.domain = \p rhs.domain + */ + template <typename V, typename L, typename R> + mln_ch_value(L, V) + minus(const Image<L>& lhs, const Image<R>& rhs); + + + /*! Point-wise addition of image \p rhs in image \p lhs. + * + * \param[in,out] lhs First operand image (subject to addition). + * \param[in] rhs Second operand image (to be added to \p lhs). + * + * This addition performs: \n * for all p of rhs.domain \n * lhs(p) -= rhs(p) * - * \pre \p rhs.domain <= \p lhs.domain + * \pre \p rhs.domain = \p lhs.domain */ template <typename L, typename R> - void minus_inplace(Image<L>& lhs, const Image<R>& rhs); + void + minus_inplace(Image<L>& lhs, const Image<R>& rhs); + + + /*! Point-wise addition of the value \p val to image \p input. + * + * \param[in] input The image. + * \param[in] val The value. + * \result The result image. + * + * \pre \p input.has_data + */ + template <typename I, typename V> + mln_trait_op_minus(I, V) + minus_cst(const Image<I>& input, const V& val); + + + /*! Point-wise addition of the value \p val to image \p input. + * + * \param[in] input The image. + * \param[in] val The value. + * \param[in] f Function. + * \result The result image. + * + * \pre \p input.has_data + */ + template <typename I, typename V, typename F> + mln_ch_value(I, mln_result(F)) + minus_cst(const Image<I>& input, const V& val, const Function_v2v<F>& f); + + + /*! Point-wise addition of the value \p val to image \p input. + * + * \param[in,out] input The image. + * \param[in] val The value. + * + * \pre \p input.has_data + */ + template <typename I, typename V> + I& + minus_cst_inplace(Image<I>& input, const V& val); + + + } // end of namespace mln::arith + + # ifndef MLN_INCLUDE_ONLY + + template <typename L, typename R> + mln_trait_op_minus(L,R) + operator-(const Image<L>& lhs, const Image<R>& rhs) + { + trace::entering("operator::minus"); + mln_precondition(exact(rhs).domain() = exact(lhs).domain()); + + mln_trait_op_minus(L,R) output = arith::minus(lhs, rhs); + + trace::exiting("operator::minus"); + return output; + } + + template <typename L, typename R> + L& + operator-=(Image<L>& lhs, const Image<R>& rhs) + { + trace::entering("operator::minus_eq"); + mln_precondition(exact(rhs).domain() = exact(lhs).domain()); + + arith::minus_inplace(lhs, rhs); + + trace::exiting("operator::minus_eq"); + return exact(lhs); + } + + + template <typename I, typename S> + mln_trait_op_minus(I,S) + operator-(const Image<I>& ima, const value::Scalar<S>& s) + { + trace::entering("operator::minus"); + mln_precondition(exact(ima).has_data()); + + mln_trait_op_minus(I,S) output = arith::minus_cst(ima, exact(s)); + + trace::exiting("operator::minus"); + return output; + } + + template <typename I, typename S> + I& + operator-=(Image<I>& ima, const value::Scalar<S>& s) + { + trace::entering("operator::minus_eq"); + mln_precondition(exact(ima).has_data()); + + arith::minus_cst_inplace(ima, exact(s)); + + trace::exiting("operator::minus_eq"); + return exact(ima); + } + + + + namespace arith + { + namespace impl { template <typename L, typename R, typename O> void minus_(trait::image::speed::any, const L& lhs, - trait::image::speed::any, const R& rhs, - trait::image::speed::any, O& output) + trait::image::speed::any, const R& rhs, O& output) { mln_piter(L) p(lhs.domain()); for_all(p) output(p) = lhs(p) - rhs(p); } + template <typename L, typename R, typename F, typename O> + void minus_(trait::image::speed::any, const L& lhs, + trait::image::speed::any, const R& rhs, const F& f, O& output) + { + mln_piter(L) p(lhs.domain()); + for_all(p) + output(p) = f(lhs(p) - rhs(p)); + } + template <typename L, typename R, typename O> void minus_(trait::image::speed::fastest, const L& lhs, - trait::image::speed::fastest, const R& rhs, - trait::image::speed::fastest, O& output) + trait::image::speed::fastest, const R& rhs, O& output) { mln_pixter(const L) lp(lhs); mln_pixter(const R) rp(rhs); @@ -96,11 +282,22 @@ op.val() = lp.val() - rp.val(); } + template <typename L, typename R, typename F, typename O> + void minus_(trait::image::speed::fastest, const L& lhs, + trait::image::speed::fastest, const R& rhs, const F& f, O& output) + { + mln_pixter(const L) lp(lhs); + mln_pixter(const R) rp(rhs); + mln_pixter(O) op(output); + for_all_3(lp, rp, op) + op.val() = f(lp.val() - rp.val()); + } + template <typename L, typename R> void minus_inplace_(trait::image::speed::any, L& lhs, trait::image::speed::any, const R& rhs) { - mln_piter(R) p(rhs.domain()); + mln_piter(L) p(lhs.domain()); for_all(p) lhs(p) -= rhs(p); } @@ -111,7 +308,7 @@ { mln_pixter(L) lp(lhs); mln_pixter(const R) rp(rhs); - for_all_2(rp, lp) + for_all_2(lp, rp) lp.val() -= rp.val(); } @@ -120,28 +317,123 @@ // Facades. - template <typename L, typename R, typename O> - void minus(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output) + + template <typename L, typename R> + mln_trait_op_minus(L, R) + minus(const Image<L>& lhs, const Image<R>& rhs) { + trace::entering("arith::minus"); mln_precondition(exact(rhs).domain() = exact(lhs).domain()); - mln_precondition(exact(output).domain() = exact(lhs).domain()); + + mln_trait_op_minus(L, R) output; + initialize(output, lhs); impl::minus_(mln_trait_image_speed(L)(), exact(lhs), - mln_trait_image_speed(R)(), exact(rhs), - mln_trait_image_speed(O)(), exact(output)); + mln_trait_image_speed(R)(), exact(rhs), output); + + trace::exiting("arith::minus"); + return output; } + + template <typename L, typename R, typename F> + mln_ch_value(L, mln_result(F)) + minus(const Image<L>& lhs, const Image<R>& rhs, const Function_v2v<F>& f) + { + trace::entering("arith::minus"); + mln_precondition(exact(rhs).domain() = exact(lhs).domain()); + + mln_ch_value(L, mln_result(F)) output; + initialize(output, lhs); + impl::minus_(mln_trait_image_speed(L)(), exact(lhs), + mln_trait_image_speed(R)(), exact(rhs), exact(f), output); + + trace::exiting("arith::minus"); + return output; + } + + + template <typename V, typename L, typename R> + mln_ch_value(L, V) + minus(const Image<L>& lhs, const Image<R>& rhs) + { + trace::entering("arith::minus"); + mln_precondition(exact(rhs).domain() = exact(lhs).domain()); + + // Calls the previous version. + mln_ch_value(L, V) output = minus(lhs, rhs, + mln::fun::v2v::cast<V>()); + + trace::exiting("arith::minus"); + return output; + } + + + template <typename I, typename V> + mln_trait_op_minus(I, V) + minus_cst(const Image<I>& input, const V& val) + { + trace::entering("arith::minus_cst"); + mln_precondition(exact(input).has_data()); + + // Calls the previous version. + mln_trait_op_minus(I, V) output = minus(input, + pw::cst(val) | exact(input).domain()); + + trace::exiting("arith::minus_cst"); + return output; + } + + + template <typename I, typename V, typename F> + mln_ch_value(I, mln_result(F)) + minus_cst(const Image<I>& input, const V& val, const Function_v2v<F>& f) + { + trace::entering("arith::minus_cst"); + mln_precondition(exact(input).has_data()); + + // Calls the previous version. + mln_ch_value(I, mln_result(F)) output = minus(input, + pw::cst(val) | exact(input).domain(), + f); + + trace::exiting("arith::minus_cst"); + return output; + } + + template <typename L, typename R> - void minus_inplace(Image<L>& lhs, const Image<R>& rhs) + void + minus_inplace(Image<L>& lhs, const Image<R>& rhs) { - mln_precondition(exact(rhs).domain() <= exact(lhs).domain()); + trace::entering("arith::minus_inplace"); + mln_precondition(exact(rhs).domain() = exact(lhs).domain()); + impl::minus_inplace_(mln_trait_image_speed(L)(), exact(lhs), mln_trait_image_speed(R)(), exact(rhs)); + + trace::exiting("arith::minus_inplace"); } -# endif // ! MLN_INCLUDE_ONLY + + template <typename I, typename V> + I& + minus_cst_inplace(Image<I>& input, const V& val) + { + trace::entering("arith::minus_cst_inplace"); + mln_precondition(exact(input).has_data()); + + // Calls the previous version. + minus_inplace(input, + pw::cst(val) | exact(input).domain()); + + trace::exiting("arith::minus_cst_inplace"); + return exact(input); + } } // end of namespace mln::arith +# endif // ! MLN_INCLUDE_ONLY + } // end of namespace mln Index: mln/value/cast.hh --- mln/value/cast.hh (revision 1405) +++ mln/value/cast.hh (working copy) @@ -34,6 +34,7 @@ */ # include <mln/core/concept/value.hh> +# include <mln/value/equiv.hh> namespace mln @@ -56,24 +57,34 @@ template <typename S> const S& - cast_(const S& src, ...) + cast_(const void*, const S& src) { return src; } - template <typename T, typename S> - typename S::equiv // FIXME: Is-that equiv here? - cast_(const T&, const Value<S>& src) + template <typename O, typename S> + const S& + cast_(const Object<O>*, const S& src) + { + return src; + } + + template <typename V, typename S> + mln_value_equiv(S) + cast_(const Value<V>*, const S& src) { - return exact(src); + return mln::value::equiv(src); } } // end of namespace mln::value::internal + template <typename Dest, typename Src> Dest cast(const Src& src) { - return internal::cast_(src, src); + // FIXME: Add static_cast<Dest>? + // FIXME: Add exact()? + return internal::cast_(&src, src); } # endif // ! MLN_INCLUDE_ONLY Index: mln/value/builtin/ops.hh --- mln/value/builtin/ops.hh (revision 1405) +++ mln/value/builtin/ops.hh (working copy) @@ -185,7 +185,6 @@ // Operator "Builtin minus Object" is a special case. - # define mln_internal_decl_bi_minus_obj_(Builtin) \ \ template <typename O> \ @@ -194,7 +193,6 @@ \ struct m_a_c_r_o__e_n_d__w_i_t_h__s_e_m_i_c_o_l_u_m_n - # define mln_internal_def_bi_minus_obj_(Builtin) \ \ template <typename O> \ @@ -227,7 +225,6 @@ // Operator "Builtin 'div or mod' Object" is a special case. - # define mln_internal_decl_bi_dvmd_obj_(Symb, Name, Builtin) \ \ template <typename O> \ @@ -236,7 +233,6 @@ \ struct m_a_c_r_o__e_n_d__w_i_t_h__s_e_m_i_c_o_l_u_m_n - # define mln_internal_def_bi_dvmd_obj_(Symb, Name, Builtin) \ \ template <typename O> \ @@ -264,7 +260,6 @@ \ struct m_a_c_r_o__e_n_d__w_i_t_h__s_e_m_i_c_o_l_u_m_n - # define mln_internal_op_builtins_cmp_(De, Symb, Name) \ \ mln_internal_##De##_op_cmp_(Symb, Name, signed char); \ @@ -280,6 +275,48 @@ \ struct m_a_c_r_o__e_n_d__w_i_t_h__s_e_m_i_c_o_l_u_m_n + + +// Operator "Builtin Op= Object" is a special case. + + +# define mln_internal_decl_bi_opeq_obj_(Symb, Builtin) \ + \ + template <typename O> \ + Builtin & \ + operator Symb##= (Builtin & lhs, const Object<O>& rhs); \ + \ + struct m_a_c_r_o__e_n_d__w_i_t_h__s_e_m_i_c_o_l_u_m_n + +# define mln_internal_def_bi_opeq_obj_(Symb, Builtin) \ + \ + template <typename O> \ + Builtin & \ + operator Symb##= (Builtin & lhs, const Object<O>& rhs) \ + { \ + lhs Symb##= exact(rhs).to_equiv(); \ + return lhs; \ + } \ + \ + struct m_a_c_r_o__e_n_d__w_i_t_h__s_e_m_i_c_o_l_u_m_n + +# define mln_internal_builtins_opeq_obj_(De, Symb) \ + \ + mln_internal_##De##_bi_opeq_obj_(Symb, signed char); \ + mln_internal_##De##_bi_opeq_obj_(Symb, unsigned char); \ + mln_internal_##De##_bi_opeq_obj_(Symb, signed short); \ + mln_internal_##De##_bi_opeq_obj_(Symb, unsigned short); \ + mln_internal_##De##_bi_opeq_obj_(Symb, signed int); \ + mln_internal_##De##_bi_opeq_obj_(Symb, unsigned int); \ + mln_internal_##De##_bi_opeq_obj_(Symb, signed long); \ + mln_internal_##De##_bi_opeq_obj_(Symb, unsigned long); \ + mln_internal_##De##_bi_opeq_obj_(Symb, float); \ + mln_internal_##De##_bi_opeq_obj_(Symb, double); \ + \ + struct m_a_c_r_o__e_n_d__w_i_t_h__s_e_m_i_c_o_l_u_m_n + + + // FIXME: What about pointers, arrays, bool, etc. // FIXME: Mod is not defined for float and double... @@ -339,11 +376,10 @@ template<> struct set_precise_unary_< op::uminus, unsigned short > { typedef int ret; }; template<> struct set_precise_unary_< op::uminus, signed int > { typedef signed int ret; }; - // Disabled cause no correct result can be obtained - // e.g., (- unsigned int) is an (unsigned int)! - template<> struct set_precise_unary_< op::uminus, unsigned int > {}; - template<> struct set_precise_unary_< op::uminus, signed long > {}; - template<> struct set_precise_unary_< op::uminus, unsigned long > {}; + template<> struct set_precise_unary_< op::uminus, unsigned int > { typedef signed int ret; }; + template<> struct set_precise_unary_< op::uminus, signed long > { typedef signed long ret; }; + template<> struct set_precise_unary_< op::uminus, unsigned long > { typedef signed long ret; }; + template<> struct set_precise_unary_< op::uminus, bool > {}; template<> struct set_precise_unary_< op::uminus, float > { typedef float ret; }; @@ -356,11 +392,20 @@ // A couple of builtins => promotion... mln_internal_set_builtin_trait_is_promotion_(op::plus); - mln_internal_set_builtin_trait_is_promotion_(op::minus); mln_internal_set_builtin_trait_is_promotion_(op::times); mln_internal_set_builtin_trait_is_promotion_(op::div); mln_internal_set_builtin_trait_is_promotion_(op::mod); + // mln_internal_set_builtin_trait_is_promotion_(op::minus); + + template <typename Bl, typename Br> + struct set_binary_< op::minus, + mln::value::Built_In, Bl, mln::value::Built_In, Br > + { + typedef mln_trait_op_uminus(Br) minus_Br; + typedef mln_trait_promote(Bl, minus_Br) ret; + }; + // For comparisons (such as "less-than"), we get bool. mln_internal_set_builtin_trait_is_bool_(op::eq); @@ -495,6 +540,15 @@ // FIXME: ... + // Ops "bi Op= obj" + mln_internal_builtins_opeq_obj_(decl, +); + mln_internal_builtins_opeq_obj_(decl, -); + mln_internal_builtins_opeq_obj_(decl, *); + mln_internal_builtins_opeq_obj_(decl, /); + mln_internal_builtins_opeq_obj_(decl, %); + + + # ifndef MLN_INCLUDE_ONLY mln_internal_op_obj_builtins_(def, +, plus); @@ -521,6 +575,14 @@ // FIXME: Add less, etc. + // Ops "bi Op= obj" + mln_internal_builtins_opeq_obj_(def, +); + mln_internal_builtins_opeq_obj_(def, -); + mln_internal_builtins_opeq_obj_(def, *); + mln_internal_builtins_opeq_obj_(def, /); + mln_internal_builtins_opeq_obj_(def, %); + + # endif // ! MLN_INCLUDE_ONLY } // end of namespace mln Index: mln/convert/to_image.hh --- mln/convert/to_image.hh (revision 1405) +++ mln/convert/to_image.hh (working copy) @@ -124,6 +124,8 @@ template <typename S> image1d<std::size_t> to_image(const mln::histo::data<S>& h); + + # ifndef MLN_INCLUDE_ONLY template <typename S> Index: mln/fun/ops.hh --- mln/fun/ops.hh (revision 1405) +++ mln/fun/ops.hh (working copy) @@ -35,6 +35,7 @@ # include <mln/core/concept/function.hh> # include <mln/fun/internal/selector.hh> +# include <mln/trait/all.hh> @@ -47,7 +48,8 @@ struct Name##_##Out##_expr_ \ : public Function_##Out < Name##_##Out##_expr_<L,R> > \ { \ - typedef mln_result(L) result; \ + typedef typename mln::trait::op:: Name < mln_result(L), \ + mln_result(R) >::ret result; \ \ Name##_##Out##_expr_(const L& l, const R& r) \ : l_(l), r_(r) \ @@ -67,6 +69,18 @@ \ } \ \ + namespace trait \ + { \ + \ + template <typename L, typename R> \ + struct set_binary_< op::Name, \ + Function_##In, L, \ + Function_##In, R > \ + { \ + typedef fun::Name##_##Out##_expr_<L,R> ret; \ + }; \ + } \ + \ template <typename L, typename R> \ fun::Name##_##Out##_expr_<L,R> \ operator Symbol (const Function_##In<L>& lhs, const Function_##In<R>& rhs) \ @@ -75,7 +89,7 @@ return tmp; \ } \ \ - struct dummy + struct e_n_d__w_i_t_h__s_e_m_i_c_o_l_u_m_n # define mln_decl_unary_expr_(In, Out, Name, Symbol) \ @@ -87,7 +101,7 @@ struct Name##_##Out##_expr_ \ : public Function_##Out< Name##_##Out##_expr_<F> > \ { \ - typedef mln_result(F) result; \ + typedef typename mln::trait::op:: Name < mln_result(F) >::ret result; \ \ Name##_##Out##_expr_(const F& f) \ : f_(f) \ @@ -106,6 +120,16 @@ \ } \ \ + namespace trait \ + { \ + template <typename F> \ + struct set_unary_< op::Name, \ + Function_##In, F > \ + { \ + typedef fun::Name##_##Out##_expr_<F> ret; \ + }; \ + } \ + \ template <typename F> \ fun::Name##_##Out##_expr_<F> \ operator Symbol (const Function_##In<F>& f) \ @@ -114,7 +138,7 @@ return tmp; \ } \ \ - struct dummy + struct e_n_d__w_i_t_h__s_e_m_i_c_o_l_u_m_n @@ -130,11 +154,11 @@ mln_decl_binary_expr_(p2v, p2b, geq, >=); mln_decl_binary_expr_(p2v, p2b, greater, >); - mln_decl_binary_expr_(p2b, p2b, and, &&); - mln_decl_binary_expr_(p2b, p2b, or, ||); - mln_decl_binary_expr_(p2b, p2b, xor, ^); + mln_decl_binary_expr_(p2b, p2b, and_, &&); + mln_decl_binary_expr_(p2b, p2b, or_, ||); + mln_decl_binary_expr_(p2b, p2b, xor_, ^); - mln_decl_unary_expr_(p2b, p2b, not, !); + mln_decl_unary_expr_(p2b, p2b, not_, !); mln_decl_binary_expr_(p2v, p2v, plus, +); mln_decl_binary_expr_(p2v, p2v, minus, -); @@ -155,11 +179,11 @@ mln_decl_binary_expr_(v2v, v2b, geq, >=); mln_decl_binary_expr_(v2v, v2b, greater, >); - mln_decl_binary_expr_(v2b, v2b, and, &&); - mln_decl_binary_expr_(v2b, v2b, or, ||); - mln_decl_binary_expr_(v2b, v2b, xor, ^); + mln_decl_binary_expr_(v2b, v2b, and_, &&); + mln_decl_binary_expr_(v2b, v2b, or_, ||); + mln_decl_binary_expr_(v2b, v2b, xor_, ^); - mln_decl_unary_expr_(v2b, v2b, not, !); + mln_decl_unary_expr_(v2b, v2b, not_, !); } // end of namespace mln Index: mln/fun/cast.hh --- mln/fun/cast.hh (revision 0) +++ mln/fun/cast.hh (revision 0) @@ -0,0 +1,84 @@ +// 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_FUN_CAST_HH +# define MLN_FUN_CAST_HH + +/*! \file mln/fun/cast.hh + * + * \brief FIXME. + */ + +# include <mln/core/concept/function.hh> + + +namespace mln +{ + + namespace fun + { + + // FIXME: Doc! + template <typename V, typename F> + struct cast_p2v_expr_ : public Function_p2v< cast_p2v_expr_<V,F> > + { + typedef V result; + + cast_p2v_expr_(const F& f) + : f_(f) + {} + + template <typename P> + V operator()(const P& p) const + { + return static_cast<V>(f_(p)); // FIXME: value::cast? + } + + protected: + const F f_; + }; + + + +# ifndef MLN_INCLUDE_ONLY + + template <typename V, typename F> + cast_p2v_expr_<V, F> + cast(const Function_p2v<F>& f) + { + cast_p2v_expr_<V, F> tmp(exact(f)); + return tmp; + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::fun + +} // end of namespace mln + + +#endif // ! MLN_FUN_CAST_HH Index: mln/fun/v2v/saturate.hh --- mln/fun/v2v/saturate.hh (revision 1405) +++ mln/fun/v2v/saturate.hh (working copy) @@ -87,16 +87,21 @@ V saturate<V>::operator()(const W& w) const { + // FIXME: Check that W is a larger type than V; otherwise + // alt code. + static const W min_W = mln::value::cast<W>(min_); + static const W max_W = mln::value::cast<W>(max_); + // FIXME: Below we need something more powerful that mlc_converts_to - // FIXME: for instance, with W=int_s<10u> and V=int_u<8u>, it does not - // FIXME: works cause the cast is not obvious... + // for instance, with W=int_s<10u> and V=int_u<8u>, it does not + // works cause the cast is not obvious... // mlc_converts_to(W, V)::check(); - V w_ = mln::value::cast<V>(w); - if (w_ < min_) + + if (w < min_W) return min_; - if (w_ > max_) + if (w > max_W) return max_; - return w_; + return mln::value::cast<W>(w); } # endif // ! MLN_INCLUDE_ONLY Index: mln/fun/v2v/all.hh --- mln/fun/v2v/all.hh (revision 1405) +++ mln/fun/v2v/all.hh (working copy) @@ -50,6 +50,7 @@ # include <mln/fun/v2v/abs.hh> +# include <mln/fun/v2v/cast.hh> # include <mln/fun/v2v/enc.hh> # include <mln/fun/v2v/id.hh> # include <mln/fun/v2v/linear.hh> Index: mln/fun/v2v/cast.hh --- mln/fun/v2v/cast.hh (revision 0) +++ mln/fun/v2v/cast.hh (revision 0) @@ -0,0 +1,80 @@ +// 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_FUN_V2V_CAST_HH +# define MLN_FUN_V2V_CAST_HH + +/*! \file mln/fun/v2v/cast.hh + * + * \brief FIXME. + */ + +# include <mln/core/concept/function.hh> +# include <mln/value/cast.hh> + + +namespace mln +{ + + namespace fun + { + + namespace v2v + { + + // FIXME: Doc! + + template <typename V> + struct cast : public Function_v2v< cast<V> > + { + typedef V result; + + template <typename W> + V operator()(const W& w) const; + }; + + +# ifndef MLN_INCLUDE_ONLY + + template <typename V> + template <typename W> + V + cast<V>::operator()(const W& w) const + { + return mln::value::cast<V>(w); + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::fun::v2v + + } // end of namespace mln::fun + +} // end of namespace mln + + +#endif // ! MLN_FUN_V2V_CAST_HH Index: mln/morpho/thickening.hh --- mln/morpho/thickening.hh (revision 1405) +++ mln/morpho/thickening.hh (working copy) @@ -47,26 +47,30 @@ * * This operator is THICK_B = Id + HMT_B, where B = (Bfg, Bbg). */ - template <typename I, typename Wfg, typename Wbg, typename O> - void thickening(const Image<I>& input, - const Window<Wfg>& win_fg, const Window<Wbg>& win_bg, - Image<O>& output); + template <typename I, typename Wfg, typename Wbg> + mln_concrete(I) + thickening(const Image<I>& input, + const Window<Wfg>& win_fg, const Window<Wbg>& win_bg); # ifndef MLN_INCLUDE_ONLY - template <typename I, typename Wfg, typename Wbg, typename O> - void thickening(const Image<I>& input, - const Window<Wfg>& win_fg, const Window<Wbg>& win_bg, - Image<O>& output) + template <typename I, typename Wfg, typename Wbg> + mln_concrete(I) + thickening(const Image<I>& input, + const Window<Wfg>& win_fg, const Window<Wbg>& win_bg) { - mln_precondition(exact(output).domain() = exact(input).domain()); + trace::entering("morpho::thickening"); + mln_precondition(exact(input).has_data()); mln_precondition(exact(win_bg).is_centered()); + mln_precondition(! exact(win_fg).is_empty()); mln_precondition(set::inter(exact(win_fg), exact(win_bg)).is_empty()); - O temp(exact(input).domain()); - hit_or_miss(input, win_fg, win_bg, temp); - morpho::plus(input, temp, output); + mln_concrete(I) output = morpho::plus( input, + hit_or_miss(input, win_fg, win_bg) ); + + trace::exiting("morpho::thickening"); + return output; } # endif // ! MLN_INCLUDE_ONLY Index: mln/morpho/plus.hh --- mln/morpho/plus.hh (revision 1405) +++ mln/morpho/plus.hh (working copy) @@ -49,16 +49,16 @@ /*! Morphological plus: either a "logical or" (if morpho on sets) * or an "arithmetical plus" (if morpho on functions). */ - template <typename I, typename J, typename O> - void plus(const Image<I>& lhs, const Image<J>& rhs, - Image<O>& output); - - /*! Morphological plus, inplace version: either a "logical or" (if - * morpho on sets) or an "arithmetical plus" (if morpho on - * functions). - */ template <typename I, typename J> - void plus_inplace(Image<I>& lhs, const Image<J>& rhs); + mln_concrete(I) plus(const Image<I>& lhs, const Image<J>& rhs); + + +// /*! Morphological plus, inplace version: either a "logical or" (if +// * morpho on sets) or an "arithmetical plus" (if morpho on +// * functions). +// */ +// template <typename I, typename J> +// void plus_inplace(Image<I>& lhs, const Image<J>& rhs); # ifndef MLN_INCLUDE_ONLY @@ -66,20 +66,22 @@ namespace impl { - template <typename I, typename J, typename O> - void plus_(trait::image::kind::logic, // binary => morphology on sets - const Image<I>& lhs, const Image<J>& rhs, - Image<O>& output) + // Binary => morphology on sets. + + template <typename I, typename J> + mln_concrete(I) plus_(trait::image::kind::logic, + const I& lhs, const J& rhs) { - return logical::or_(lhs, rhs, output); + return logical::or_(lhs, rhs); } - template <typename K, typename I, typename J, typename O> - void plus_(K, // otherwise => morphology on functions - const Image<I>& lhs, const Image<J>& rhs, - Image<O>& output) + // Otherwise => morphology on functions. + + template <typename I, typename J> + mln_concrete(I) plus_(trait::image::kind::any, + const I& lhs, const J& rhs) { - return arith::plus(lhs, rhs, output); + return arith::plus<mln_value(I)>(lhs, rhs); } } // end of namespace mln::morpho::impl @@ -87,21 +89,26 @@ // Facades. - template <typename I, typename J, typename O> - void plus(const Image<I>& lhs, const Image<J>& rhs, Image<O>& output) - { - mln_precondition(exact(rhs).domain() = exact(lhs).domain()); - mln_precondition(exact(output).domain() = exact(lhs).domain()); - impl::plus_(mln_trait_image_kind(I)(), exact(lhs), exact(rhs), output); - } - template <typename I, typename J> - void plus_inplace(Image<I>& lhs, const Image<J>& rhs) + mln_concrete(I) plus(const Image<I>& lhs, const Image<J>& rhs) { + trace::entering("morpho::plus"); mln_precondition(exact(rhs).domain() = exact(lhs).domain()); - morpho::plus(lhs, rhs, lhs); // Calls the previous version. + + mln_concrete(I) output = impl::plus_(mln_trait_image_kind(I)(), + exact(lhs), exact(rhs)); + + trace::exiting("morpho::plus"); + return output; } +// template <typename I, typename J> +// void plus_inplace(Image<I>& lhs, const Image<J>& rhs) +// { +// mln_precondition(exact(rhs).domain() = exact(lhs).domain()); +// morpho::plus(lhs, rhs, lhs); // Calls the previous version. +// } + # endif // ! MLN_INCLUDE_ONLY } // end of namespace mln::morpho Index: mln/morpho/min.hh --- mln/morpho/min.hh (revision 1405) +++ mln/morpho/min.hh (working copy) @@ -49,9 +49,10 @@ /*! Morphological min: either a logical "and" (if morpho on sets) * or an arithmetical min (if morpho on functions). */ - template <typename I, typename J, typename O> - void min(const Image<I>& lhs, const Image<J>& rhs, - Image<O>& output); + template <typename I, typename J> + mln_concrete(I) + min(const Image<I>& lhs, const Image<J>& rhs); + /*! Morphological min, inplace version: either a logical "and" (if * morpho on sets) or an arithmetical min (if morpho on @@ -66,36 +67,36 @@ namespace impl { + // Binary => morphology on sets. + template <typename I, typename J, typename O> - void min_(trait::image::kind::logic, // binary => morphology on sets - const Image<I>& lhs, const Image<J>& rhs, - Image<O>& output) + mln_concrete(I) min_(trait::image::kind::logic, + const I& lhs, const J& rhs) { - return logical::and_(lhs, rhs, output); + return logical::and_(lhs, rhs); } - template <typename K, typename I, typename J, typename O> - void min_(K, // otherwise => morphology on functions - const Image<I>& lhs, const Image<J>& rhs, - Image<O>& output) + template <typename I, typename J> + void min_inplace_(trait::image::kind::logic, + I& lhs, const J& rhs) { - return arith::min(lhs, rhs, output); + logical::and_inplace(lhs, rhs); } - // in place + // Otherwise => morphology on functions. template <typename I, typename J> - void min_inplace_(trait::image::kind::logic, // binary => morphology on sets - Image<I>& lhs, const Image<J>& rhs) + mln_concrete(I) min_(trait::image::kind::any, + const I& lhs, const J& rhs) { - return logical::and_inplace(lhs, rhs); + return arith::min(lhs, rhs); } - template <typename K, typename I, typename J> - void min_inplace_(K, // otherwise => morphology on functions - Image<I>& lhs, const Image<J>& rhs) + template <typename I, typename J> + void min_inplace_(trait::image::kind::any, + I& lhs, const J& rhs) { - return arith::min_inplace(lhs, rhs); + arith::min_inplace(lhs, rhs); } } // end of namespace mln::morpho::impl @@ -103,19 +104,28 @@ // Facades. - template <typename I, typename J, typename O> - void min(const Image<I>& lhs, const Image<J>& rhs, Image<O>& output) + template <typename I, typename J> + mln_concrete(I) + min(const Image<I>& lhs, const Image<J>& rhs) { + trace::entering("morpho::min"); mln_precondition(exact(rhs).domain() = exact(lhs).domain()); - mln_precondition(exact(output).domain() = exact(lhs).domain()); - impl::min_(mln_trait_image_kind(I)(), exact(lhs), exact(rhs), output); + + mln_concrete(I) output = impl::min_(mln_trait_image_kind(I)(), exact(lhs), exact(rhs)); + + trace::exiting("morpho::min"); + return output; } template <typename I, typename J> void min_inplace(Image<I>& lhs, const Image<J>& rhs) { + trace::entering("morpho::min_inplace"); mln_precondition(exact(rhs).domain() = exact(lhs).domain()); + impl::min_inplace_(mln_trait_image_kind(I)(), exact(lhs), exact(rhs)); + + trace::exiting("morpho::min_inplace_"); } # endif // ! MLN_INCLUDE_ONLY Index: mln/morpho/laplacian.hh --- mln/morpho/laplacian.hh (revision 1405) +++ mln/morpho/laplacian.hh (working copy) @@ -53,24 +53,42 @@ Image<O>& output); + template <typename I, typename W> + mln_trait_op_minus_twice(mln_concrete(I)) + laplacian(const Image<I>& input, const Window<W>& win); + + # ifndef MLN_INCLUDE_ONLY template <typename I, typename W, typename O> void laplacian(const Image<I>& input, const Window<W>& win, Image<O>& output) { + trace::entering("morpho::laplacian"); mln_precondition(exact(output).domain() = exact(input).domain()); mln_precondition(! exact(win).is_empty()); - dilation(input, win, output); // output = dilation - morpho::minus_inplace(output, input); // now output = dilation - input + mln_concrete(I) + d_I = morpho::minus(dilation(input, win), input), + e_I = morpho::minus(input, erosion(input, win)); + level::fill(output, d_I - e_I); - O temp(exact(input).domain()); - { - O temp_(exact(input).domain()); - erosion(input, win, temp_); // temp_ = erosion - morpho::minus(input, temp_, temp); // temp = input - erosion + trace::exiting("morpho::laplacian"); } - morpho::minus_inplace(output, temp); // now output = (dilation - input) - (input - erosion) + + template <typename I, typename W> + mln_trait_op_minus_twice(mln_concrete(I)) + laplacian(const Image<I>& input, const Window<W>& win) + { + trace::entering("morpho::laplacian"); + mln_precondition(exact(input).has_data()); + mln_precondition(! exact(win).is_empty()); + + mln_trait_op_minus_twice(mln_concrete(I)) output; + initialize(output, input); + laplacian(input, win, output); // Calls previous version. + + trace::exiting("morpho::laplacian"); + return output; } # endif // ! MLN_INCLUDE_ONLY Index: mln/morpho/minus.hh --- mln/morpho/minus.hh (revision 1405) +++ mln/morpho/minus.hh (working copy) @@ -49,16 +49,16 @@ /*! Morphological minus: either a logical "and not" (if morpho on * sets) or an arithmetical minus (if morpho on functions). */ - template <typename I, typename J, typename O> - void minus(const Image<I>& lhs, const Image<J>& rhs, - Image<O>& output); - - /*! Morphological minus, inplace version: either a logical "and - * not" (if morpho on sets) or an arithmetical minus (if morpho - * on functions). - */ template <typename I, typename J> - void minus_inplace(Image<I>& lhs, const Image<J>& rhs); + mln_concrete(I) minus(const Image<I>& lhs, const Image<J>& rhs); + + +// /*! Morphological minus, inplace version: either a logical "and +// * not" (if morpho on sets) or an arithmetical minus (if morpho +// * on functions). +// */ +// template <typename I, typename J> +// void minus_inplace(Image<I>& lhs, const Image<J>& rhs); # ifndef MLN_INCLUDE_ONLY @@ -66,20 +66,22 @@ namespace impl { - template <typename I, typename J, typename O> - void minus_(trait::image::kind::logic, // binary => morphology on sets - const Image<I>& lhs, const Image<J>& rhs, - Image<O>& output) + // Binary => morphology on sets. + + template <typename I, typename J> + mln_concrete(I) minus_(trait::image::kind::logic, + const I& lhs, const J& rhs) { - return logical::and_not(lhs, rhs, output); + return logical::and_not(lhs, rhs); } - template <typename K, typename I, typename J, typename O> - void minus_(K, // otherwise => morphology on functions - const Image<I>& lhs, const Image<J>& rhs, - Image<O>& output) + // Otherwise => morphology on functions. + + template <typename I, typename J> + mln_concrete(I) minus_(trait::image::kind::any, + const I& lhs, const J& rhs) { - return arith::minus(lhs, rhs, output); + return arith::minus<mln_value(I)>(lhs, rhs); } } // end of namespace mln::morpho::impl @@ -87,21 +89,27 @@ // Facades. - template <typename I, typename J, typename O> - void minus(const Image<I>& lhs, const Image<J>& rhs, Image<O>& output) - { - mln_precondition(exact(rhs).domain() = exact(lhs).domain()); - mln_precondition(exact(output).domain() = exact(lhs).domain()); - impl::minus_(mln_trait_image_kind(I)(), exact(lhs), exact(rhs), output); - } - template <typename I, typename J> - void minus_inplace(Image<I>& lhs, const Image<J>& rhs) + mln_concrete(I) + minus(const Image<I>& lhs, const Image<J>& rhs) { + trace::entering("morpho::minus"); mln_precondition(exact(rhs).domain() = exact(lhs).domain()); - morpho::minus(lhs, rhs, lhs); // Calls the previous version. + + mln_concrete(I) output = impl::minus_(mln_trait_image_kind(I)(), + exact(lhs), exact(rhs)); + + trace::exiting("morpho::minus"); + return output; } +// template <typename I, typename J> +// void minus_inplace(Image<I>& lhs, const Image<J>& rhs) +// { +// mln_precondition(exact(rhs).domain() = exact(lhs).domain()); +// morpho::minus(lhs, rhs, lhs); // Calls the previous version. +// } + # endif // ! MLN_INCLUDE_ONLY } // end of namespace mln::morpho Index: mln/morpho/gradient.hh --- mln/morpho/gradient.hh (revision 1405) +++ mln/morpho/gradient.hh (working copy) @@ -48,82 +48,73 @@ * * This operator is d_B - e_B. */ - template <typename I, typename W, typename O> - void gradient(const Image<I>& input, const Window<W>& win, - Image<O>& output); + template <typename I, typename W> + mln_concrete(I) gradient(const Image<I>& input, const Window<W>& win); /*! Morphological internal gradient. * * This operator is Id - e_B. */ - template <typename I, typename W, typename O> - void gradient_internal(const Image<I>& input, const Window<W>& win, - Image<O>& output); + template <typename I, typename W> + mln_concrete(I) gradient_internal(const Image<I>& input, const Window<W>& win); /*! Morphological external gradient. * * This operator is d_B - Id. */ - template <typename I, typename W, typename O> - void gradient_external(const Image<I>& input, const Window<W>& win, - Image<O>& output); + template <typename I, typename W> + mln_concrete(I) gradient_external(const Image<I>& input, const Window<W>& win); # ifndef MLN_INCLUDE_ONLY - template <typename I, typename W, typename O> - void gradient(const Image<I>& input_, const Window<W>& win_, Image<O>& output_) + template <typename I, typename W> + mln_concrete(I) gradient(const Image<I>& input, const Window<W>& win) { - const I& input = exact(input_); - const W& win = exact(win_); - O& output = exact(output_); - - mln_precondition(output.domain() = input.domain()); - mln_precondition(! win.is_empty()); - - dilation(input, win, output); // output = dilation - O temp(input.domain()); - erosion(input, win, temp); // temp = erosion - morpho::minus_inplace(output, temp); // now output = dilation - erosion + trace::entering("morpho::gradient"); + mln_precondition(exact(input).has_data()); + mln_precondition(! exact(win).is_empty()); + + mln_concrete(I) output = morpho::minus(dilation(input, win), + erosion(input, win)); mln_postcondition(test::positive(output)); + trace::exiting("morpho::gradient"); + return output; } - template <typename I, typename W, typename O> - void gradient_internal(const Image<I>& input_, const Window<W>& win_, - Image<O>& output_) + + template <typename I, typename W> + mln_concrete(I) gradient_internal(const Image<I>& input, const Window<W>& win) { - const I& input = exact(input_); - const W& win = exact(win_); - O& output = exact(output_); - - mln_precondition(output.domain() = input.domain()); - mln_precondition(! win.is_empty()); - - O temp(input.domain()); - erosion(input, win, temp); // temp = erosion - morpho::minus(input, temp, output); // output = input - erosion + trace::entering("morpho::gradient_internal"); + mln_precondition(exact(input).has_data()); + mln_precondition(! exact(win).is_empty()); + + mln_concrete(I) output = morpho::minus(input, + erosion(input, win)); mln_postcondition(test::positive(output)); + trace::exiting("morpho::gradient_internal"); + return output; } - template <typename I, typename W, typename O> - void gradient_external(const Image<I>& input_, const Window<W>& win_, - Image<O>& output_) - { - const I& input = exact(input_); - const W& win = exact(win_); - O& output = exact(output_); - mln_precondition(output.domain() = input.domain()); - mln_precondition(! win.is_empty()); + template <typename I, typename W> + mln_concrete(I) gradient_external(const Image<I>& input, const Window<W>& win) + { + trace::entering("morpho::gradient_external"); + mln_precondition(exact(input).has_data()); + mln_precondition(! exact(win).is_empty()); - dilation(input, win, output); // output = dilation - morpho::minus_inplace(output, input); // now output = dilation - input + mln_concrete(I) output = morpho::minus(dilation(input, win), + input); mln_postcondition(test::positive(output)); + trace::exiting("morpho::gradient_external"); + return output; } # endif // ! MLN_INCLUDE_ONLY Index: mln/morpho/contrast.hh --- mln/morpho/contrast.hh (revision 1405) +++ mln/morpho/contrast.hh (working copy) @@ -48,28 +48,25 @@ * * This operator is Id + wth_B - bth_B. */ - template <typename I, typename W, typename O> - void contrast(const Image<I>& input, const Window<W>& win, - Image<O>& output); + template <typename I, typename W> + mln_concrete(I) contrast(const Image<I>& input, const Window<W>& win); # ifndef MLN_INCLUDE_ONLY - template <typename I, typename W, typename O> - void contrast(const Image<I>& input_, const Window<W>& win_, Image<O>& output_) + template <typename I, typename W> + mln_concrete(I) contrast(const Image<I>& input, const Window<W>& win) { - const I& input = exact(input_); - const W& win = exact(win_); - O& output = exact(output_); - - mln_precondition(output.domain() = input.domain()); - mln_precondition(! win.is_empty()); - - top_hat_white(input, win, output); // output = wth - morpho::plus_inplace(output, input); // now output = wth + input - O temp(input.domain()); - top_hat_black(input, win, temp); // temp = bth - morpho::minus_inplace(output, temp); // now output = wth + input - bth + trace::entering("morpho::contrast"); + mln_precondition(exact(input).has_data()); + mln_precondition(! exact(win).is_empty()); + + mln_concrete(I) output = arith::plus( input, + top_hat_white(input, win) - top_hat_black(input, win), + fun::v2v::saturate<mln_value(I)>() ); + + trace::exiting("morpho::contrast"); + return output; } # endif // ! MLN_INCLUDE_ONLY Index: mln/morpho/thick_miss.hh --- mln/morpho/thick_miss.hh (revision 1405) +++ mln/morpho/thick_miss.hh (working copy) @@ -47,26 +47,31 @@ * * This operator is THICK_B = Id + HMTopeBG_B, where B = (Bfg, Bbg). */ - template <typename I, typename Wfg, typename Wbg, typename O> - void thick_miss(const Image<I>& input, - const Window<Wfg>& win_fg, const Window<Wbg>& win_bg, - Image<O>& output); + template <typename I, typename Wfg, typename Wbg> + mln_concrete(I) + thick_miss(const Image<I>& input, + const Window<Wfg>& win_fg, const Window<Wbg>& win_bg); # ifndef MLN_INCLUDE_ONLY - template <typename I, typename Wfg, typename Wbg, typename O> - void thick_miss(const Image<I>& input, - const Window<Wfg>& win_fg, const Window<Wbg>& win_bg, - Image<O>& output) + template <typename I, typename Wfg, typename Wbg> + mln_concrete(I) + thick_miss(const Image<I>& input, + const Window<Wfg>& win_fg, const Window<Wbg>& win_bg) { + trace::entering("morpho::thick_miss"); mln_precondition(exact(output).domain() = exact(input).domain()); mln_precondition(exact(win_miss).is_centered()); mln_precondition(set::inter(exact(win_fg), exact(win_bg)).is_empty()); - O temp(exact(input).domain()); - hit_or_miss_background_opening(input, win_fg, win_bg, temp); - morpho::plus(input, temp, output); + mln_concrete(I) + output = morpho::plus( input, + hit_or_miss_background_opening(input, + win_fg, win_bg) ); + + trace::exiting("morpho::thick_miss"); + return output; } # endif // ! MLN_INCLUDE_ONLY Index: mln/morpho/closing.hh --- mln/morpho/closing.hh (revision 1405) +++ mln/morpho/closing.hh (working copy) @@ -46,27 +46,24 @@ * * This operator is e_{-B} o d_B. */ - template <typename I, typename W, typename O> - void closing(const Image<I>& input, const Window<W>& win, Image<O>& output); + template <typename I, typename W> + mln_concrete(I) closing(const Image<I>& input, const Window<W>& win); # ifndef MLN_INCLUDE_ONLY - template <typename I, typename W, typename O> - void closing(const Image<I>& input_, const Window<W>& win_, Image<O>& output_) + template <typename I, typename W> + mln_concrete(I) closing(const Image<I>& input, const Window<W>& win) { - const I& input = exact(input_); - const W& win = exact(win_); - O& output = exact(output_); - - mln_precondition(output.domain() = input.domain()); - mln_precondition(! win.is_empty()); - - O temp(input.domain()); - dilation(input, win, temp); - erosion(temp, geom::sym(win), output); + trace::entering("morpho::closing"); + mln_precondition(exact(input).has_data()); + mln_precondition(! exact(win).is_empty()); + + mln_concrete(I) output = erosion(dilation(input, win), geom::sym(win)); mln_postcondition(output >= input); + trace::exiting("morpho::closing"); + return output; } # endif // ! MLN_INCLUDE_ONLY Index: mln/morpho/top_hat.hh --- mln/morpho/top_hat.hh (revision 1405) +++ mln/morpho/top_hat.hh (working copy) @@ -49,18 +49,18 @@ * * This operator is Id - ope_B. */ - template <typename I, typename W, typename O> - void top_hat_white(const Image<I>& input, const Window<W>& win, - Image<O>& output); + template <typename I, typename W> + mln_concrete(I) + top_hat_white(const Image<I>& input, const Window<W>& win); /*! Morphological black top-hat (for background / dark objects). * * This operator is clo_B - Id. */ - template <typename I, typename W, typename O> - void top_hat_black(const Image<I>& input, const Window<W>& win, - Image<O>& output); + template <typename I, typename W> + mln_concrete(I) + top_hat_black(const Image<I>& input, const Window<W>& win); /*! Morphological self-complementary top-hat. @@ -70,62 +70,56 @@ * = (input - opening) + (closing - input) \n * = closing - opening. \n */ - template <typename I, typename W, typename O> - void top_hat_self_complementary(const Image<I>& input, const Window<W>& win, - Image<O>& output); + template <typename I, typename W> + mln_concrete(I) + top_hat_self_complementary(const Image<I>& input, const Window<W>& win); # ifndef MLN_INCLUDE_ONLY - template <typename I, typename W, typename O> - void top_hat_white(const Image<I>& input_, const Window<W>& win_, Image<O>& output_) + template <typename I, typename W> + mln_concrete(I) top_hat_white(const Image<I>& input, const Window<W>& win) { - const I& input = exact(input_); - const W& win = exact(win_); - O& output = exact(output_); - - mln_precondition(output.domain() = input.domain()); - mln_precondition(! win.is_empty()); - - O temp(input.domain()); - opening(input, win, temp); // temp = opening - morpho::minus(input, temp, output); // output = input - opening + trace::entering("morpho::top_hat_white"); + mln_precondition(exact(input).has_data()); + mln_precondition(! exact(win).is_empty()); + + mln_concrete(I) output = morpho::minus(input, + opening(input, win)); mln_postcondition(test::positive(output)); + trace::exiting("morpho::top_hat_white"); + return output; } - template <typename I, typename W, typename O> - void top_hat_black(const Image<I>& input_, const Window<W>& win_, Image<O>& output_) + template <typename I, typename W> + mln_concrete(I) top_hat_black(const Image<I>& input, const Window<W>& win) { - const I& input = exact(input_); - const W& win = exact(win_); - O& output = exact(output_); - - mln_precondition(output.domain() = input.domain()); - mln_precondition(! win.is_empty()); + trace::entering("morpho::top_hat_black"); + mln_precondition(exact(input).has_data()); + mln_precondition(! exact(win).is_empty()); - closing(input, win, output); // output = closing - morpho::minus_inplace(output, input); // now output = closing - input + mln_concrete(I) output = morpho::minus(closing(input, win), + input); mln_postcondition(test::positive(output)); + trace::exiting("morpho::top_hat_black"); + return output; } - template <typename I, typename W, typename O> - void top_hat_self_complementary(const Image<I>& input_, const Window<W>& win_, Image<O>& output_) + template <typename I, typename W> + mln_concrete(I) top_hat_self_complementary(const Image<I>& input, const Window<W>& win) { - const I& input = exact(input_); - const W& win = exact(win_); - O& output = exact(output_); - - mln_precondition(output.domain() = input.domain()); - mln_precondition(! win.is_empty()); - - closing(input, win, output); // output = closing - O temp(input.domain()); - opening(input, win, temp); // temp = opening - morpho::minus_inplace(output, temp); // now output = closing - opening + trace::entering("morpho::top_hat_self_complementary"); + mln_precondition(exact(input).has_data()); + mln_precondition(! exact(win).is_empty()); + + mln_concrete(I) output = morpho::minus(closing(input, win), + opening(input, win)); mln_postcondition(test::positive(output)); + trace::exiting("morpho::top_hat_self_complementary"); + return output; } # endif // ! MLN_INCLUDE_ONLY Index: mln/morpho/complementation.hh --- mln/morpho/complementation.hh (revision 1405) +++ mln/morpho/complementation.hh (working copy) @@ -50,8 +50,8 @@ * morpho on sets) or an arithmetical complementation (if morpho * on functions). */ - template <typename I, typename O> - void complementation(const Image<I>& input, Image<O>& output); + template <typename I> + mln_concrete(I) complementation(const Image<I>& input); /*! Morphological complementation, inplace version: either a @@ -67,20 +67,41 @@ namespace impl { - template <typename I, typename O> - void complementation_(trait::image::kind::logic, // binary => morphology on sets - const Image<I>& input, - Image<O>& output) + // Binary => morphology on sets. + + template <typename I> + mln_concrete(I) + complementation_(trait::image::kind::logic, + const Image<I>& input) + { + return logical::not_(input); + } + + template <typename I> + void + complementation_inplace_(trait::image::kind::logic, + Image<I>& input) + { + logical::not_inplace(input); + } + + + // Otherwise => morphology on functions. + + template <typename I> + mln_concrete(I) + complementation_(trait::image::kind::any, + const Image<I>& input) { - return logical::not_(input, output); + return arith::revert(input); } - template <typename K, typename I, typename O> - void complementation_(K, // otherwise => morphology on functions - const Image<I>& input, - Image<O>& output) + template <typename I> + void + complementation_inplace_(trait::image::kind::any, + Image<I>& input) { - return arith::revert(input, output); + arith::revert_inplace(input); } } // end of namespace mln::morpho::impl @@ -88,18 +109,29 @@ // Facades. - template <typename I, typename O> - void complementation(const Image<I>& input, Image<O>& output) + template <typename I> + mln_concrete(I) complementation(const Image<I>& input) { - mln_precondition(exact(output).domain() = exact(input).domain()); - impl::complementation_(mln_trait_image_kind(I)(), exact(input), output); + trace::entering("morpho::complementation"); + mln_precondition(exact(input).has_data()); + + mln_concrete(I) output = impl::complementation_(mln_trait_image_kind(I)(), + input); + + trace::exiting("morpho::complementation"); + return output; } template <typename I> void complementation_inplace(Image<I>& input) { + trace::entering("morpho::complementation_inplace"); mln_precondition(exact(input).has_data()); - morpho::complementation(input, input); // Calls the previous version. + + impl::complementation_inplace_(mln_trait_image_kind(I)(), + input); + + trace::exiting("morpho::complementation_inplace"); } # endif // ! MLN_INCLUDE_ONLY Index: mln/morpho/opening.hh --- mln/morpho/opening.hh (revision 1405) +++ mln/morpho/opening.hh (working copy) @@ -46,27 +46,24 @@ * * This operator is d_{-B} o e_B. */ - template <typename I, typename W, typename O> - void opening(const Image<I>& input, const Window<W>& win, Image<O>& output); + template <typename I, typename W> + mln_concrete(I) opening(const Image<I>& input, const Window<W>& win); # ifndef MLN_INCLUDE_ONLY - template <typename I, typename W, typename O> - void opening(const Image<I>& input_, const Window<W>& win_, Image<O>& output_) + template <typename I, typename W> + mln_concrete(I) opening(const Image<I>& input, const Window<W>& win) { - const I& input = exact(input_); - const W& win = exact(win_); - O& output = exact(output_); - - mln_precondition(output.domain() = input.domain()); - mln_precondition(! win.is_empty()); - - O temp(input.domain()); - erosion(input, win, temp); - dilation(temp, geom::sym(win), output); + trace::entering("morpho::opening"); + mln_precondition(exact(input).has_data()); + mln_precondition(! exact(win).is_empty()); + + mln_concrete(I) output = dilation(erosion(input, win), geom::sym(win)); mln_postcondition(output <= input); + trace::exiting("morpho::opening"); + return output; } # endif // ! MLN_INCLUDE_ONLY Index: mln/morpho/dilation.hh --- mln/morpho/dilation.hh (revision 1405) +++ mln/morpho/dilation.hh (working copy) @@ -51,6 +51,10 @@ template <typename I, typename W, typename O> void dilation(const Image<I>& input, const Window<W>& win, Image<O>& output); + template <typename I, typename W> + mln_concrete(I) dilation(const Image<I>& input, const Window<W>& win); + + # ifndef MLN_INCLUDE_ONLY @@ -194,6 +198,20 @@ mln_postcondition(output >= input); } + template <typename I, typename W> + mln_concrete(I) + dilation(const Image<I>& input, const Window<W>& win) + { + trace::entering("morpho::dilation"); + + mln_concrete(I) output; + initialize(output, input); + dilation(input, win, output); + + trace::exiting("morpho::dilation"); + return output; + } + # endif // ! MLN_INCLUDE_ONLY } // end of namespace mln::morpho Index: mln/morpho/thin_fit.hh --- mln/morpho/thin_fit.hh (revision 1405) +++ mln/morpho/thin_fit.hh (working copy) @@ -47,26 +47,31 @@ * * This operator is THIN_B = Id - HMTope_B where B = (Bfg, Bbg). */ - template <typename I, typename Wfg, typename Wbg, typename O> - void thin_fit(const Image<I>& input, - const Window<Wfg>& win_fg, const Window<Wbg>& win_bg, - Image<O>& output); + template <typename I, typename Wfg, typename Wbg> + mln_concrete(I) + thin_fit(const Image<I>& input, + const Window<Wfg>& win_fg, const Window<Wbg>& win_bg); # ifndef MLN_INCLUDE_ONLY - template <typename I, typename Wfg, typename Wbg, typename O> - void thin_fit(const Image<I>& input, - const Window<Wfg>& win_fg, const Window<Wbg>& win_bg, - Image<O>& output) + template <typename I, typename Wfg, typename Wbg> + mln_concrete(I) + thin_fit(const Image<I>& input, + const Window<Wfg>& win_fg, const Window<Wbg>& win_bg) { - mln_precondition(exact(output).domain() = exact(input).domain()); + trace::entering("morpho::thin_fit"); + mln_precondition(exact(input).has_data()); mln_precondition(exact(win_fg).is_centered()); mln_precondition(set::inter(exact(win_fg), exact(win_bg)).is_empty()); - O temp(exact(input).domain()); - hit_or_miss_opening(input, win_fg, win_bg, temp); - morpho::minus(input, temp, output); + mln_concrete(I) + output = morpho::minus( input, + hit_or_miss_opening(input, + win_fg, win_bg) ); + + trace::exiting("morpho::thin_fit"); + return output; } # endif // ! MLN_INCLUDE_ONLY Index: mln/morpho/includes.hh --- mln/morpho/includes.hh (revision 1405) +++ mln/morpho/includes.hh (working copy) @@ -45,11 +45,12 @@ # include <mln/accu/min_h.hh> # include <mln/accu/max_h.hh> +# include <mln/fun/v2v/saturate.hh> + # include <mln/level/compare.hh> # include <mln/level/fill.hh> # include <mln/test/positive.hh> - # include <mln/border/resize.hh> # include <mln/border/fill.hh> Index: mln/morpho/thinning.hh --- mln/morpho/thinning.hh (revision 1405) +++ mln/morpho/thinning.hh (working copy) @@ -36,6 +36,8 @@ # include <mln/morpho/hit_or_miss.hh> # include <mln/morpho/thickening.hh> +#include <mln/io/pgm/save.hh> + namespace mln { @@ -48,37 +50,32 @@ * * This operator is THIN_B = Id - HMT_B, where B = (Bfg, Bbg). */ - template <typename I, typename Wfg, typename Wbg, typename O> - void thinning(const Image<I>& input, - const Window<Wfg>& win_fg, const Window<Wbg>& win_bg, - Image<O>& output); + template <typename I, typename Wfg, typename Wbg> + mln_concrete(I) + thinning(const Image<I>& input, + const Window<Wfg>& win_fg, const Window<Wbg>& win_bg); # ifndef MLN_INCLUDE_ONLY - template <typename I, typename Wfg, typename Wbg, typename O> - void thinning(const Image<I>& input, - const Window<Wfg>& win_fg, const Window<Wbg>& win_bg, - Image<O>& output) + template <typename I, typename Wfg, typename Wbg> + mln_concrete(I) + thinning(const Image<I>& input, + const Window<Wfg>& win_fg, const Window<Wbg>& win_bg) { - mln_precondition(exact(output).domain() = exact(input).domain()); + trace::entering("morpho::thinning"); + mln_precondition(exact(input).has_data()); mln_precondition(exact(win_fg).is_centered()); + mln_precondition(! exact(win_bg).is_empty()); mln_precondition(set::inter(exact(win_fg), exact(win_bg)).is_empty()); - O temp(exact(input).domain()); - hit_or_miss(input, win_fg, win_bg, temp); - morpho::minus(input, temp, output); - // FIXME: Pass postcondition! -# ifndef NDEBUG - { - O temp(exact(input).domain()); - complementation(input, temp); - O output_(exact(input).domain()); - thickening(temp, win_bg, win_fg, output_); - complementation_inplace(output_); - mln_postcondition(output_ = output); - } -# endif // ! NDEBUG + mln_concrete(I) output = morpho::minus( input, + hit_or_miss(input, win_fg, win_bg) ); + + mln_postcondition( complementation( thickening( complementation(input), + win_bg, win_fg ) ) = output); + trace::exiting("morpho::thinning"); + return output; } # endif // ! MLN_INCLUDE_ONLY Index: mln/morpho/hit_or_miss.hh --- mln/morpho/hit_or_miss.hh (revision 1405) +++ mln/morpho/hit_or_miss.hh (working copy) @@ -38,6 +38,7 @@ # include <mln/morpho/includes.hh> # include <mln/pw/all.hh> # include <mln/fun/p2v/ternary.hh> +# include <mln/fun/cast.hh> # include <mln/literal/zero.hh> @@ -55,46 +56,51 @@ * * This operator is HMT_(Bh,Bm) = e_Bh /\ (e_Bm o C). */ - template <typename I, typename Wh, typename Wm, typename O> - void hit_or_miss(const Image<I>& input, - const Window<Wh>& win_hit, const Window<Wm>& win_miss, - Image<O>& output); + template <typename I, typename Wh, typename Wm> + mln_concrete(I) + hit_or_miss(const Image<I>& input, + const Window<Wh>& win_hit, const Window<Wm>& win_miss); + /*! Morphological hit-or-miss opening. * * This operator is HMTope_(Bh,Bm) = d_(-Bh) o HMT_(Bh,Bm). */ - template <typename I, typename Wh, typename Wm, typename O> - void hit_or_miss_opening(const Image<I>& input, - const Window<Wh>& win_hit, const Window<Wm>& win_miss, - Image<O>& output); + template <typename I, typename Wh, typename Wm> + mln_concrete(I) + hit_or_miss_opening(const Image<I>& input, + const Window<Wh>& win_hit, const Window<Wm>& win_miss); + /*! Morphological hit-or-miss opening of the background. * * This operator is HMTopeBG = HMTope_(Bm,Bh) o C = d_(-Bm) o HMT_(Bh,Bm). */ - template <typename I, typename Wh, typename Wm, typename O> - void hit_or_miss_background_opening(const Image<I>& input, - const Window<Wh>& win_hit, const Window<Wm>& win_miss, - Image<O>& output); + template <typename I, typename Wh, typename Wm> + mln_concrete(I) + hit_or_miss_background_opening(const Image<I>& input, + const Window<Wh>& win_hit, const Window<Wm>& win_miss); + /*! Morphological hit-or-miss closing. * * This operator is C o HMTope o C. */ - template <typename I, typename Wh, typename Wm, typename O> - void hit_or_miss_closing(const Image<I>& input, - const Window<Wh>& win_hit, const Window<Wm>& win_miss, - Image<O>& output); + template <typename I, typename Wh, typename Wm> + mln_concrete(I) + hit_or_miss_closing(const Image<I>& input, + const Window<Wh>& win_hit, const Window<Wm>& win_miss); + /*! Morphological hit-or-miss closing of the background. * * This operator is C o HMTopeBG o C. */ - template <typename I, typename Wh, typename Wm, typename O> - void hit_or_miss_background_closing(const Image<I>& input, - const Window<Wh>& win_hit, const Window<Wm>& win_miss, - Image<O>& output); + template <typename I, typename Wh, typename Wm> + mln_concrete(I) + hit_or_miss_background_closing(const Image<I>& input, + const Window<Wh>& win_hit, const Window<Wm>& win_miss); + # ifndef MLN_INCLUDE_ONLY @@ -102,164 +108,172 @@ namespace impl { + // Preconditions. - template <typename I, typename Wh, typename Wm, typename O> + template <typename I, typename Wh, typename Wm> void hit_or_miss_preconditions_(const Image<I>& input, - const Window<Wh>& win_hit, const Window<Wm>& win_miss, - Image<O>& output) + const Window<Wh>& win_hit, const Window<Wm>& win_miss) { - mln_precondition(exact(output).domain() = exact(input).domain()); + mln_precondition(exact(input).has_data()); mln_precondition(set::inter(exact(win_hit), exact(win_miss)).is_empty()); } + // On sets. - template <typename I, typename Wh, typename Wm, typename O> - void hit_or_miss_(trait::image::kind::logic, // binary => morphology on sets - const Image<I>& input, - const Window<Wh>& win_hit, const Window<Wm>& win_miss, - Image<O>& output) + template <typename I, typename Wh, typename Wm> + mln_concrete(I) + hit_or_miss_(trait::image::kind::logic, + const I& input, + const Wh& win_hit, const Wm& win_miss) { - erosion(input, win_hit, output); // output = ero(input)_hit - - O temp_1(exact(input).domain()); - complementation(input, temp_1); // temp1 = C(input) - - O temp_2(exact(input).domain()); - erosion(temp_1, win_miss, temp_2); // temp_2 = ero(C(input))_miss - - logical::and_inplace(output, temp_2); // output = ero(input)_hit /\ ero(C(input))_miss + return logical::and_(erosion(input, win_hit), + erosion(complementation(input), win_miss)); } + // On functions. - template <typename K, - typename I, typename Wh, typename Wm, typename O> - void hit_or_miss_(K, // otherwise => morphology on functions - const Image<I>& input, - const Window<Wh>& win_hit, const Window<Wm>& win_miss, - Image<O>& output) + template <typename I, typename Wh, typename Wm> + mln_concrete(I) + hit_or_miss_(trait::image::kind::any, + const I& input, + const Wh& win_hit, const Wm& win_miss) { - typedef mln_value(O) V; + typedef mln_value(I) V; + mln_value(I) zero_V = literal::zero; + + mln_concrete(I) output; + initialize(output, input); if (constrained_hit_or_miss) // CHMT. { - if (exact(win_hit).is_centered()) + if (win_hit.is_centered()) { - O ero_fg(exact(input).domain()), dil_bg(exact(input).domain()); - erosion(input, win_hit, ero_fg); - dilation(input, win_miss, dil_bg); + mln_concrete(I) + ero_fg = erosion(input, win_hit), + dil_bg = dilation(input, win_miss); level::fill(output, fun::p2v::ternary(pw::value(input) = pw::value(ero_fg) && pw::value(dil_bg) < pw::value(input), - pw::value(input) - pw::value(dil_bg), - pw::cst( V(literal::zero) ))); - - // FIXME: Replace 'pw::cst(V::zero)' by 'pw::cst(V(literal::zero))' - // FIXME: and then by 'literal::zero'! + fun::cast<V>(pw::value(input) - pw::value(dil_bg)), + pw::cst(zero_V))); } - else if (exact(win_miss).is_centered()) + else if (win_miss.is_centered()) { - O ero_bg(exact(input).domain()), dil_fg(exact(input).domain()); - erosion(input, win_miss, ero_bg); - dilation(input, win_hit, dil_fg); + mln_concrete(I) + ero_bg = erosion(input, win_miss), + dil_fg = dilation(input, win_hit); level::fill(output, fun::p2v::ternary(pw::value(input) = pw::value(dil_fg) && pw::value(ero_bg) > pw::value(input), - pw::value(ero_bg) - pw::value(input), - pw::cst( V(literal::zero) ))); + fun::cast<V>(pw::value(ero_bg) - pw::value(input)), + pw::cst(zero_V))); } else - level::fill(output, V(literal::zero)); + level::fill(output, zero_V); } else // Unconstrained: UHMT. { - O ero(exact(input).domain()), dil(exact(input).domain()); - erosion(input, win_hit, ero); - dilation(input, win_miss, dil); + mln_concrete(I) + ero = erosion(input, win_hit), + dil = dilation(input, win_miss); level::fill(output, fun::p2v::ternary(pw::value(dil) < pw::value(ero), - pw::value(ero) - pw::value(dil), - pw::cst( V(literal::zero) ))); + fun::cast<V>(pw::value(ero) - pw::value(dil)), + pw::cst(zero_V))); } + + return output; } + } // end of mln::morpho::impl - template <typename I, typename Wh, typename Wm, typename O> - void hit_or_miss(const Image<I>& input, - const Window<Wh>& win_hit, const Window<Wm>& win_miss, - Image<O>& output) + + template <typename I, typename Wh, typename Wm> + mln_concrete(I) + hit_or_miss(const Image<I>& input, + const Window<Wh>& win_hit, const Window<Wm>& win_miss) + { + trace::entering("morpho::hit_or_miss"); + impl::hit_or_miss_preconditions_(input, win_hit, win_miss); + + mln_concrete(I) output = impl::hit_or_miss_(mln_trait_image_kind(I)(), + exact(input), + exact(win_hit), exact(win_miss)); + + trace::exiting("morpho::hit_or_miss"); + return output; + } + + + template <typename I, typename Wh, typename Wm> + mln_concrete(I) + hit_or_miss_opening(const Image<I>& input, + const Window<Wh>& win_hit, const Window<Wm>& win_miss) { - impl::hit_or_miss_preconditions_(input, win_hit, win_miss, output); - impl::hit_or_miss_(mln_trait_image_kind(I)(), input, win_hit, win_miss, output); + trace::entering("morpho::hit_or_miss_opening"); + impl::hit_or_miss_preconditions_(input, win_hit, win_miss); + + mln_concrete(I) output = dilation( hit_or_miss(input, win_hit, win_miss), + geom::sym(win_hit) ); + + trace::exiting("morpho::hit_or_miss_opening"); + return output; } - template <typename I, typename Wh, typename Wm, typename O> - void hit_or_miss_opening(const Image<I>& input, - const Window<Wh>& win_hit, const Window<Wm>& win_miss, - Image<O>& output) + + template <typename I, typename Wh, typename Wm> + mln_concrete(I) + hit_or_miss_background_opening(const Image<I>& input, + const Window<Wh>& win_hit, const Window<Wm>& win_miss) { - impl::hit_or_miss_preconditions_(input, win_hit, win_miss, output); + trace::entering("morpho::hit_or_miss_background_opening"); + impl::hit_or_miss_preconditions_(input, win_hit, win_miss); - O temp(exact(input).domain()); - hit_or_miss(input, win_hit, win_miss, temp); - dilation(temp, geom::sym(win_hit), output); - // FIXME: Postcondition. + mln_concrete(I) output = hit_or_miss_opening(complementation(input), win_miss, win_hit); + + mln_postcondition( dilation( hit_or_miss(input, win_hit, win_miss), + geom::sym(win_miss) ) = output); + trace::exiting("morpho::hit_or_miss_background_opening"); + return output; } - template <typename I, typename Wh, typename Wm, typename O> - void hit_or_miss_background_opening(const Image<I>& input, - const Window<Wh>& win_hit, const Window<Wm>& win_miss, - Image<O>& output) - { - impl::hit_or_miss_preconditions_(input, win_hit, win_miss, output); - O temp(exact(input).domain()); - complementation(input, temp); - hit_or_miss_opening(temp, win_miss, win_hit, output); -# ifndef NDEBUG - { - O temp(exact(input).domain()); - hit_or_miss(input, win_hit, win_miss, temp); - O output_(exact(input).domain()); - dilation(temp, geom::sym(win_miss), output_); - mln_postcondition(output_ = output); - } -# endif // ! NDEBUG - } - - template <typename I, typename Wh, typename Wm, typename O> - void hit_or_miss_closing(const Image<I>& input, - const Window<Wh>& win_hit, const Window<Wm>& win_miss, - Image<O>& output) - { - impl::hit_or_miss_preconditions_(input, win_hit, win_miss, output); - I temp(input.domain()); - complementation(input, temp); - hit_or_miss_opening(temp, win_hit, win_miss, output); - complementation_inplace(output); + + template <typename I, typename Wh, typename Wm> + mln_concrete(I) + hit_or_miss_closing(const Image<I>& input, + const Window<Wh>& win_hit, const Window<Wm>& win_miss) + { + trace::entering("morpho::hit_or_miss_closing"); + impl::hit_or_miss_preconditions_(input, win_hit, win_miss); + + mln_concrete(I) output = complementation( hit_or_miss_opening( complementation(input), + win_hit, win_miss ) ); + // FIXME: Postcondition. + trace::exiting("morpho::hit_or_miss_closing"); + return output; } - template <typename I, typename Wh, typename Wm, typename O> - void hit_or_miss_background_closing(const Image<I>& input, - const Window<Wh>& win_hit, const Window<Wm>& win_miss, - Image<O>& output) - { - impl::hit_or_miss_preconditions_(input, win_hit, win_miss, output); - hit_or_miss_closing(input, win_miss, win_hit, output); -# ifndef NDEBUG - { - O temp(exact(input).domain()); - complementation(input, temp); - O output_(exact(input).domain()); - hit_or_miss_background_opening(temp, win_hit, win_miss, output_); - complementation_inplace(output_); - mln_postcondition(output_ = output); - } -# endif // ! NDEBUG + + template <typename I, typename Wh, typename Wm> + mln_concrete(I) + hit_or_miss_background_closing(const Image<I>& input, + const Window<Wh>& win_hit, const Window<Wm>& win_miss) + { + trace::entering("morpho::hit_or_miss_background_closing"); + impl::hit_or_miss_preconditions_(input, win_hit, win_miss); + + mln_concrete(I) output = hit_or_miss_closing(input, win_miss, win_hit); + + mln_postcondition( complementation( hit_or_miss_background_opening( complementation(input), + win_hit, win_miss ) ) = output ); + trace::exiting("morpho::hit_or_miss_background_closing"); + return output; } # endif // ! MLN_INCLUDE_ONLY Index: mln/logical/and.hh --- mln/logical/and.hh (revision 1405) +++ mln/logical/and.hh (working copy) @@ -48,24 +48,24 @@ * * \param[in] lhs First operand image. * \param[in] rhs Second operand image. - * \param[out] output The result image. + * \result The result image. * - * \pre \p output.domain = \p lhs.domain = \p rhs.domain + * \pre \p lhs.domain = \p rhs.domain */ - template <typename L, typename R, typename O> - void and_(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output); + template <typename L, typename R> + mln_concrete(L) and_(const Image<L>& lhs, const Image<R>& rhs); /*! Point-wise in-place "logical and" of image \p rhs in image \p lhs. * - * \param[in] lhs First operand image. - * \param[in,out] rhs Second operand image. + * \param[in,out] lhs First operand image. + * \param[in] rhs Second operand image. * * It performs: \n * for all p of rhs.domain \n * lhs(p) = lhs(p) and rhs(p) * - * \pre \p rhs.domain <= \p lhs.domain + * \pre \p rhs.domain >= \p lhs.domain */ template <typename L, typename R> void and_inplace(Image<L>& lhs, const Image<R>& rhs); @@ -78,8 +78,7 @@ template <typename L, typename R, typename O> void and__(trait::image::speed::any, const L& lhs, - trait::image::speed::any, const R& rhs, - trait::image::speed::any, O& output) + trait::image::speed::any, const R& rhs, O& output) { mln_piter(L) p(lhs.domain()); for_all(p) @@ -88,8 +87,7 @@ template <typename L, typename R, typename O> void and__(trait::image::speed::fastest, const L& lhs, - trait::image::speed::fastest, const R& rhs, - trait::image::speed::fastest, O& output) + trait::image::speed::fastest, const R& rhs, O& output) { mln_pixter(const L) lp(lhs); mln_pixter(const R) rp(rhs); @@ -103,23 +101,31 @@ // Facades. - template <typename L, typename R, typename O> - void and_(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output) + template <typename L, typename R> + mln_concrete(L) and_(const Image<L>& lhs, const Image<R>& rhs) { + trace::entering("logical::and_"); mln_precondition(exact(rhs).domain() = exact(lhs).domain()); - mln_precondition(exact(output).domain() = exact(lhs).domain()); + + mln_concrete(L) output; + initialize(output, lhs); impl::and__(mln_trait_image_speed(L)(), exact(lhs), - mln_trait_image_speed(R)(), exact(rhs), - mln_trait_image_speed(O)(), exact(output)); + mln_trait_image_speed(R)(), exact(rhs), output); + + trace::exiting("logical::and_"); + return output; } template <typename L, typename R> void and_inplace(Image<L>& lhs, const Image<R>& rhs) { - mln_precondition(exact(rhs).domain() <= exact(lhs).domain()); + trace::entering("logical::and_inplace"); + mln_precondition(exact(rhs).domain() >= exact(lhs).domain()); + impl::and__(mln_trait_image_speed(L)(), exact(lhs), - mln_trait_image_speed(R)(), exact(rhs), - mln_trait_image_speed(L)(), exact(lhs)); + mln_trait_image_speed(R)(), exact(rhs), exact(lhs)); + + trace::exiting("logical::and_inplace"); } # endif // ! MLN_INCLUDE_ONLY Index: mln/logical/and_not.hh --- mln/logical/and_not.hh (revision 1405) +++ mln/logical/and_not.hh (working copy) @@ -48,24 +48,24 @@ * * \param[in] lhs First operand image. * \param[in] rhs Second operand image. - * \param[out] output The result image. + * \result The result image. * - * \pre \p output.domain = \p lhs.domain = \p rhs.domain + * \pre \p lhs.domain = \p rhs.domain */ - template <typename L, typename R, typename O> - void and_not(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output); + template <typename L, typename R> + mln_concrete(L) and_not(const Image<L>& lhs, const Image<R>& rhs); /*! Point-wise in-place logical "and not" of image \p rhs in image \p lhs. * - * \param[in] lhs First operand image. - * \param[in,out] rhs Second operand image. + * \param[in,out] lhs First operand image. + * \param[in] rhs Second operand image. * * It performs: \n * for all p of rhs.domain \n * lhs(p) = lhs(p) and not rhs(p) * - * \pre \p rhs.domain <= \p lhs.domain + * \pre \p rhs.domain >= \p lhs.domain */ template <typename L, typename R> void and_not_inplace(Image<L>& lhs, const Image<R>& rhs); @@ -78,8 +78,7 @@ template <typename L, typename R, typename O> void and_not_(trait::image::speed::any, const L& lhs, - trait::image::speed::any, const R& rhs, - trait::image::speed::any, O& output) + trait::image::speed::any, const R& rhs, O& output) { mln_piter(L) p(lhs.domain()); for_all(p) @@ -88,8 +87,7 @@ template <typename L, typename R, typename O> void and_not_(trait::image::speed::fastest, const L& lhs, - trait::image::speed::fastest, const R& rhs, - trait::image::speed::fastest, O& output) + trait::image::speed::fastest, const R& rhs, O& output) { mln_pixter(const L) lp(lhs); mln_pixter(const R) rp(rhs); @@ -103,23 +101,31 @@ // Facades. - template <typename L, typename R, typename O> - void and_not(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output) + template <typename L, typename R> + mln_concrete(L) and_not(const Image<L>& lhs, const Image<R>& rhs) { + trace::entering("logical::and_not"); mln_precondition(exact(rhs).domain() = exact(lhs).domain()); - mln_precondition(exact(output).domain() = exact(lhs).domain()); + + mln_concrete(L) output; + initialize(output, lhs); impl::and_not_(mln_trait_image_speed(L)(), exact(lhs), - mln_trait_image_speed(R)(), exact(rhs), - mln_trait_image_speed(O)(), exact(output)); + mln_trait_image_speed(R)(), exact(rhs), output); + + trace::exiting("logical::and_not"); + return output; } template <typename L, typename R> void and_not_inplace(Image<L>& lhs, const Image<R>& rhs) { - mln_precondition(exact(rhs).domain() <= exact(lhs).domain()); + trace::entering("logical::and_not_inplace"); + mln_precondition(exact(rhs).domain() >= exact(lhs).domain()); + impl::and_not_(mln_trait_image_speed(L)(), exact(lhs), - mln_trait_image_speed(R)(), exact(rhs), - mln_trait_image_speed(L)(), exact(lhs)); + mln_trait_image_speed(R)(), exact(rhs), exact(lhs)); + + trace::exiting("logical::and_not_inplace"); } # endif // ! MLN_INCLUDE_ONLY Index: mln/logical/or.hh --- mln/logical/or.hh (revision 1405) +++ mln/logical/or.hh (working copy) @@ -48,24 +48,24 @@ * * \param[in] lhs First operand image. * \param[in] rhs Second operand image. - * \param[out] output The result image. + * \result The result image. * - * \pre \p output.domain = \p lhs.domain = \p rhs.domain + * \pre \p lhs.domain = \p rhs.domain */ - template <typename L, typename R, typename O> - void or_(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output); + template <typename L, typename R> + mln_concrete(L) or_(const Image<L>& lhs, const Image<R>& rhs); /*! Point-wise in-place "logical or" of image \p rhs in image \p lhs. * - * \param[in] lhs First operand image. - * \param[in,out] rhs Second operand image. + * \param[in,out] lhs First operand image. + * \param[in] rhs Second operand image. * * It performs: \n - * for all p of rhs.domain \n + * for all p of lhs.domain \n * lhs(p) = lhs(p) or rhs(p) * - * \pre \p rhs.domain <= \p lhs.domain + * \pre \p rhs.domain >= \p lhs.domain */ template <typename L, typename R> void or_inplace(Image<L>& lhs, const Image<R>& rhs); @@ -78,8 +78,7 @@ template <typename L, typename R, typename O> void or__(trait::image::speed::any, const L& lhs, - trait::image::speed::any, const R& rhs, - trait::image::speed::any, O& output) + trait::image::speed::any, const R& rhs, O& output) { mln_piter(L) p(lhs.domain()); for_all(p) @@ -88,8 +87,7 @@ template <typename L, typename R, typename O> void or__(trait::image::speed::fastest, const L& lhs, - trait::image::speed::fastest, const R& rhs, - trait::image::speed::fastest, O& output) + trait::image::speed::fastest, const R& rhs, O& output) { mln_pixter(const L) lp(lhs); mln_pixter(const R) rp(rhs); @@ -103,23 +101,31 @@ // Facades. - template <typename L, typename R, typename O> - void or_(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output) + template <typename L, typename R> + mln_concrete(L) or_(const Image<L>& lhs, const Image<R>& rhs) { + trace::entering("logical::or_"); mln_precondition(exact(rhs).domain() = exact(lhs).domain()); - mln_precondition(exact(output).domain() = exact(lhs).domain()); + + mln_concrete(L) output; + initialize(output, lhs); impl::or__(mln_trait_image_speed(L)(), exact(lhs), - mln_trait_image_speed(R)(), exact(rhs), - mln_trait_image_speed(O)(), exact(output)); + mln_trait_image_speed(R)(), exact(rhs), output); + + trace::exiting("logical::or_"); + return output; } template <typename L, typename R> void or_inplace(Image<L>& lhs, const Image<R>& rhs) { - mln_precondition(exact(rhs).domain() <= exact(lhs).domain()); + trace::entering("logical::or_inplace"); + mln_precondition(exact(rhs).domain() >= exact(lhs).domain()); + impl::or__(mln_trait_image_speed(L)(), exact(lhs), - mln_trait_image_speed(R)(), exact(rhs), - mln_trait_image_speed(L)(), exact(lhs)); + mln_trait_image_speed(R)(), exact(rhs), exact(lhs)); + + trace::exiting("logical::or_inplace"); } # endif // ! MLN_INCLUDE_ONLY Index: mln/logical/not.hh --- mln/logical/not.hh (revision 1405) +++ mln/logical/not.hh (working copy) @@ -47,12 +47,12 @@ /*! Point-wise "logical not" of image \p input. * * \param[in] input the input image. - * \param[out] output The result image. + * \result The result image. * - * \pre \p output.domain = \p input.domain + * \pre \p input.has_data */ - template <typename I, typename O> - void not_(const Image<I>& input, Image<O>& output); + template <typename I> + mln_concrete(I) not_(const Image<I>& input); /*! Point-wise in-place "logical not" of image \p input. @@ -73,8 +73,7 @@ { template <typename I, typename O> - void not__(trait::image::speed::any, const I& input, - trait::image::speed::any, O& output) + void not__(trait::image::speed::any, const I& input, O& output) { mln_piter(I) p(input.domain()); for_all(p) @@ -82,8 +81,7 @@ } template <typename I, typename O> - void not__(trait::image::speed::fastest, const I& input, - trait::image::speed::fastest, O& output) + void not__(trait::image::speed::fastest, const I& input, O& output) { mln_pixter(const I) ip(input); mln_pixter(O) op(output); @@ -96,20 +94,27 @@ // Facades. - template <typename I, typename O> - void not_(const Image<I>& input, Image<O>& output) + template <typename I> + mln_concrete(I) not_(const Image<I>& input) { - mln_precondition(exact(output).domain() = exact(input).domain()); - impl::not__(mln_trait_image_speed(I)(), exact(input), - mln_trait_image_speed(O)(), exact(output)); + trace::entering("logical::not"); + mln_precondition(exact(input).has_data()); + + mln_concrete(I) output; + initialize(output, input); + impl::not__(mln_trait_image_speed(I)(), exact(input), output); + + trace::exiting("logical::not"); + return output; } template <typename I> void not_inplace(Image<I>& input) { + trace::entering("logical::not_inplace"); mln_precondition(exact(input).has_data()); - impl::not__(mln_trait_image_speed(I)(), exact(input), - mln_trait_image_speed(I)(), exact(input)); + impl::not__(mln_trait_image_speed(I)(), exact(input), exact(input)); + trace::exiting("logical::not_inplace"); } # endif // ! MLN_INCLUDE_ONLY Index: img/picasso.pbm Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: img/picasso.pbm ___________________________________________________________________ Name: svn:mime-type + application/octet-stream
participants (1)
-
Thierry Geraud