[ VIGRA Homepage | Class Index | Function Index | File Index | Main Page ]

| vigra/multi_pointoperators.hxx |
--- | --- | ---

    00001 //-- -*- c++ -*-
    00002 /************************************************************************/
    00003 /*                                                                      */
    00004 /*               Copyright 2003 by Ullrich Koethe                       */
    00005 /*       Cognitive Systems Group, University of Hamburg, Germany        */
    00006 /*                                                                      */
    00007 /*    This file is part of the VIGRA computer vision library.           */
    00008 /*    ( Version 1.3.2, Jan 27 2005 )                                    */
    00009 /*    You may use, modify, and distribute this software according       */
    00010 /*    to the terms stated in the LICENSE file included in               */
    00011 /*    the VIGRA distribution.                                           */
    00012 /*                                                                      */
    00013 /*    The VIGRA Website is                                              */
    00014 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
    00015 /*    Please direct questions, bug reports, and contributions to        */
    00016 /*        koethe@informatik.uni-hamburg.de                              */
    00017 /*                                                                      */
    00018 /*  THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR          */
    00019 /*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED      */
    00020 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
    00021 /*                                                                      */
    00022 /************************************************************************/
    00023
    00024 #ifndef VIGRA_MULTI_POINTOPERATORS_H
    00025 #define VIGRA_MULTI_POINTOPERATORS_H
    00026
    00027 #include <vigra/initimage.hxx>
    00028 #include <vigra/copyimage.hxx>
    00029 #include <vigra/transformimage.hxx>
    00030 #include <vigra/combineimages.hxx>
    00031 #include <vigra/inspectimage.hxx>
    00032 #include <vigra/multi_array.hxx>
    00033 #include <vigra/metaprogramming.hxx>
    00034
    00035
    00036
    00037 namespace vigra
    00038 {
    00039
    00040 /** \addtogroup MultiPointoperators Point operators for multi-dimensional arrays.
    00041
    00042     Copy, transform, and inspect arbitrary dimensional arrays which are represented
    00043     by iterators compatible to \ref MultiIteratorPage. Note that are range is here
    00044     specified by a pair: an iterator referring to the first point of the array
    00045     and a shape object specifying the size of the (rectangular) ROI.
    00046
    00047     <b>\#include</b> "<a href="multi__pointoperators_8hxx-source.html">vigra/multi_pointoperators.hxx</a>"
    00048 */
    00049 //@{
    00050
    00051 /********************************************************/
    00052 /*                                                      */
    00053 /*                    initMultiArray                    */
    00054 /*                                                      */
    00055 /********************************************************/
    00056
    00057 template <class Iterator, class Shape, class Accessor,
    00058           class VALUETYPE>
    00059 inline void
    00060 initMultiArrayImpl(Iterator s, Shape const & shape, Accessor a,  VALUETYPE v, MetaInt<0>)
    00061 {
    00062     initLine(s, s + shape[0], a, v);
    00063 }
    00064
    00065 template <class Iterator, class Shape, class Accessor,
    00066           class VALUETYPE, int N>
    00067 void
    00068 initMultiArrayImpl(Iterator s, Shape const & shape, Accessor a,
    00069                    VALUETYPE v, MetaInt<N>)
    00070 {
    00071     Iterator send = s + shape[N];
    00072     for(; s != send; ++s)
    00073     {
    00074         initMultiArrayImpl(s.begin(), shape, a, v, MetaInt<N-1>());
    00075     }
    00076 }
    00077
    00078 /** \brief Write a value to every pixel in a multi-dimensional array.
    00079
    00080     This function can be used to init the array which must be represented by
    00081     a pair of iterators compatible to \ref vigra::MultiIterator.
    00082     It uses an accessor to access the data alements. Note that the iterator range
    00083     must be specified by a shape object, because otherwise we could not control
    00084     the range simultaneously in all dimensions (this is a necessary consequence
    00085     of the \ref vigra::MultiIterator design).
    00086
    00087     <b> Declarations:</b>
    00088
    00089     pass arguments explicitly:
    00090     \code
    00091     namespace vigra {
    00092         template <class Iterator, class Shape, class Accessor, class VALUETYPE>
    00093         void
    00094         initMultiArray(Iterator s, Shape const & shape, Accessor a,  VALUETYPE v);
    00095
    00096
    00097         template <class Iterator, class Shape, class Accessor, class FUNCTOR>
    00098         void
    00099         initMultiArray(Iterator s, Shape const & shape, Accessor a,  FUNCTOR const & f);
    00100     }
    00101     \endcode
    00102
    00103     use argument objects in conjunction with \ref ArgumentObjectFactories:
    00104     \code
    00105     namespace vigra {
    00106         template <class Iterator, class Shape, class Accessor, class VALUETYPE>
    00107         void
    00108         initMultiArray(triple<Iterator, Shape, Accessor> const & s, VALUETYPE v);
    00109
    00110
    00111         template <class Iterator, class Shape, class Accessor, class FUNCTOR>
    00112         void
    00113         initMultiArray(triple<Iterator, Shape, Accessor> const & s, FUNCTOR const & f);
    00114     }
    00115     \endcode
    00116
    00117     <b> Usage:</b>
    00118
    00119     <b>\#include</b> "<a href="multi__pointoperators_8hxx-source.html">vigra/multi_pointoperators.hxx</a>"<br>
    00120     Namespace: vigra
    00121
    00122     \code
    00123     typedef vigra::MultiArray<3, int> Array;
    00124     Array array(Array::size_type(100, 200, 50));
    00125
    00126     // zero the array
    00127     vigra::initMultiArray(destMultiArrayRange(array), 0);
    00128     \endcode
    00129
    00130     <b> Required Interface:</b>
    00131
    00132     The function accepts either a value that is copied into every destination element:
    00133
    00134     \code
    00135     MultiIterator begin;
    00136
    00137     Accessor accessor;
    00138     VALUETYPE v;
    00139
    00140     accessor.set(v, begin);
    00141     \endcode
    00142
    00143     or a functor that is called (without argument) at every location,
    00144     and the result is written into the current element. Internally,
    00145     functors are recognized by the meta function
    00146     <tt>FunctorTraits&lt;FUNCTOR&gt;::</tt><tt>isInitializer</tt> yielding <tt>VigraTrueType</tt>.
    00147     Make sure that your functor correctly defines <tt>FunctorTraits</tt> because
    00148     otherwise the code will not compile.
    00149
    00150     \code
    00151     MultiIterator begin;
    00152     Accessor accessor;
    00153
    00154     FUNCTOR f;
    00155     assert(typeid(FunctorTraits<FUNCTOR>::isInitializer) == typeid(VigraTrueType));
    00156
    00157     accessor.set(f(), begin);
    00158     \endcode
    00159
    00160
    00161 */
    00162 template <class Iterator, class Shape, class Accessor, class VALUETYPE>
    00163 inline void
    00164 initMultiArray(Iterator s, Shape const & shape, Accessor a,  VALUETYPE v)
    00165 {
    00166     initMultiArrayImpl(s, shape, a, v, MetaInt<Iterator::level>());
    00167 }
    00168
    00169 template <class Iterator, class Shape, class Accessor, class VALUETYPE>
    00170 inline
    00171 void
    00172 initMultiArray(triple<Iterator, Shape, Accessor> const & s, VALUETYPE v)
    00173 {
    00174     initMultiArray(s.first, s.second, s.third, v);
    00175 }
    00176
    00177 /********************************************************/
    00178 /*                                                      */
    00179 /*                    copyMultiArray                    */
    00180 /*                                                      */
    00181 /********************************************************/
    00182
    00183 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00184           class DestIterator, class DestShape, class DestAccessor>
    00185 void
    00186 copyMultiArrayImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00187                DestIterator d, DestShape const & dshape, DestAccessor dest, MetaInt<0>)
    00188 {
    00189     if(sshape[0] == 1)
    00190     {
    00191         initLine(d, d + dshape[0], dest, src(s));
    00192     }
    00193     else
    00194     {
    00195         copyLine(s, s + sshape[0], src, d, dest);
    00196     }
    00197 }
    00198
    00199 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00200           class DestIterator, class DestShape, class DestAccessor, int N>
    00201 void
    00202 copyMultiArrayImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00203                    DestIterator d, DestShape const & dshape, DestAccessor dest, MetaInt<N>)
    00204 {
    00205     DestIterator dend = d + dshape[N];
    00206     if(sshape[N] == 1)
    00207     {
    00208         for(; d != dend; ++d)
    00209         {
    00210             copyMultiArrayImpl(s.begin(), sshape, src, d.begin(), dshape, dest, MetaInt<N-1>());
    00211         }
    00212     }
    00213     else
    00214     {
    00215         for(; d != dend; ++s, ++d)
    00216         {
    00217             copyMultiArrayImpl(s.begin(), sshape, src, d.begin(), dshape, dest, MetaInt<N-1>());
    00218         }
    00219     }
    00220 }
    00221
    00222 /** \brief Copy a multi-dimensional array.
    00223
    00224     This function can be applied in two modes:
    00225
    00226     <DL>
    00227     <DT><b>Standard Mode:</b>
    00228         <DD>If the source and destination arrays have the same size,
    00229         the corresponding array elements are simply copied.
    00230         If necessary, type conversion takes place.
    00231     <DT><b>Expanding Mode:</b>
    00232         <DD>If the source array has length 1 along some (or even all) dimensions,
    00233         the source value at index 0 is used for all destination
    00234         elements in those dimensions. For example, if we have single row of data
    00235         (column length is 1), we can copy it into a 2D image of the same width:
    00236         The given row is automatically repeated for every row of the destination image.
    00237         Again, type conversion os performed if necessary.
    00238     </DL>
    00239
    00240     The arrays must be represented by
    00241     iterators compatible with \ref vigra::MultiIterator, and the iteration range
    00242     is specified by means of shape objects. If only the source shape is given
    00243     the destination array is assumed to have the same shape, and standard mode
    00244     is applied. If two shapes are given, the size of corresponding dimensions
    00245     must be either equal (standard copy), or the source length must be 1
    00246     (expanding copy). The function uses accessors to access the data elements.
    00247
    00248     <b> Declarations:</b>
    00249
    00250     <b>\#include</b> "<a href="multi__pointoperators_8hxx-source.html">vigra/multi_pointoperators.hxx</a>"<br>
    00251     Namespace: vigra
    00252
    00253     pass arguments explicitly:
    00254     \code
    00255     namespace vigra {
    00256         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00257                   class DestIterator, class DestAccessor>
    00258         void
    00259         copyMultiArray(SrcIterator s,
    00260                        SrcShape const & shape, SrcAccessor src,
    00261                        DestIterator d, DestAccessor dest);
    00262
    00263
    00264         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00265                   class DestIterator, class DestShape, class DestAccessor>
    00266         void
    00267         copyMultiArray(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00268                        DestIterator d, DestShape const & dshape, DestAccessor dest);
    00269     }
    00270     \endcode
    00271
    00272
    00273     use argument objects in conjunction with \ref ArgumentObjectFactories:
    00274     \code
    00275     namespace vigra {
    00276         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00277                   class DestIterator, class DestAccessor>
    00278         void
    00279         copyMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
    00280                        pair<DestIterator, DestAccessor> const & dest);
    00281
    00282
    00283         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00284                   class DestIterator, class DestShape, class DestAccessor>
    00285         void
    00286         copyMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
    00287                        triple<DestIterator, DestShape, DestAccessor> const & dest);
    00288     }
    00289     \endcode
    00290
    00291     <b> Usage - Standard Mode:</b>
    00292
    00293     \code
    00294     typedef vigra::MultiArray<3, int> Array;
    00295     Array src(Array::size_type(100, 200, 50)),
    00296           dest(Array::size_type(100, 200, 50));
    00297     ...
    00298
    00299     vigra::copyMultiArray(srcMultiArrayRange(src), destMultiArray(dest));
    00300     \endcode
    00301
    00302     <b> Usage - Expanding Mode:</b>
    00303
    00304     The source array is only 2D (it has depth 1). Thus, the destination
    00305     will contain 50 identical copies of this image. Note that the destination shape
    00306     must be passed to the algorithm for the expansion to work, so we use
    00307     <tt>destMultiArrayRange()</tt> rather than <tt>destMultiArray()</tt>.
    00308
    00309     \code
    00310     typedef vigra::MultiArray<3, int> Array;
    00311     Array src(Array::size_type(100, 200, 1)),
    00312           dest(Array::size_type(100, 200, 50));
    00313     ...
    00314
    00315     vigra::copyMultiArray(srcMultiArrayRange(src), destMultiArrayRange(dest));
    00316     \endcode
    00317
    00318     <b> Required Interface:</b>
    00319
    00320     \code
    00321     MultiIterator src_begin, dest_begin;
    00322
    00323     SrcAccessor src_accessor;
    00324     DestAccessor dest_accessor;
    00325
    00326     dest_accessor.set(src_accessor(src_begin), dest_begin);
    00327
    00328     \endcode
    00329
    00330 */
    00331 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00332           class DestIterator, class DestAccessor>
    00333 inline void
    00334 copyMultiArray(SrcIterator s,
    00335                SrcShape const & shape, SrcAccessor src,
    00336                DestIterator d, DestAccessor dest)
    00337 {
    00338     copyMultiArrayImpl(s, shape, src, d, shape, dest, MetaInt<SrcIterator::level>());
    00339 }
    00340
    00341 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00342           class DestIterator, class DestAccessor>
    00343 inline void
    00344 copyMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
    00345                pair<DestIterator, DestAccessor> const & dest)
    00346 {
    00347
    00348     copyMultiArray(src.first, src.second, src.third, dest.first, dest.second);
    00349 }
    00350
    00351 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00352           class DestIterator, class DestShape, class DestAccessor>
    00353 void
    00354 copyMultiArray(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00355                DestIterator d, DestShape const & dshape, DestAccessor dest)
    00356 {
    00357     vigra_precondition(sshape.size() == dshape.size(),
    00358         "copyMultiArray(): dimensionality of source and destination array differ");
    00359     for(unsigned int i=0; i<sshape.size(); ++i)
    00360         vigra_precondition(sshape[i] == 1 || sshape[i] == dshape[i],
    00361             "copyMultiArray(): mismatch between source and destination shapes:\n"
    00362             "length of each source dimension must either be 1 or equal to the corresponding "
    00363             "destination length.");
    00364     copyMultiArrayImpl(s, sshape, src, d, dshape, dest, MetaInt<SrcIterator::level>());
    00365 }
    00366
    00367 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00368           class DestIterator, class DestShape, class DestAccessor>
    00369 inline void
    00370 copyMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
    00371                triple<DestIterator, DestShape, DestAccessor> const & dest)
    00372 {
    00373
    00374     copyMultiArray(src.first, src.second, src.third, dest.first, dest.second, dest.third);
    00375 }
    00376
    00377 /********************************************************/
    00378 /*                                                      */
    00379 /*                 transformMultiArray                  */
    00380 /*                                                      */
    00381 /********************************************************/
    00382
    00383 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00384           class DestIterator, class DestShape, class DestAccessor,
    00385           class Functor>
    00386 void
    00387 transformMultiArrayReduceImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00388                DestIterator d, DestShape const & dshape, DestAccessor dest,
    00389                SrcShape const & reduceShape,
    00390                Functor const & ff, MetaInt<0>)
    00391 {
    00392     DestIterator dend = d + dshape[0];
    00393     for(; d != dend; ++s.template dim<0>(), ++d)
    00394     {
    00395         Functor f = ff;
    00396         inspectMultiArray(s, reduceShape, src, f);
    00397         dest.set(f(), d);
    00398     }
    00399 }
    00400
    00401 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00402           class DestIterator, class DestShape, class DestAccessor,
    00403           class Functor, int N>
    00404 void
    00405 transformMultiArrayReduceImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00406                    DestIterator d, DestShape const & dshape, DestAccessor dest,
    00407                    SrcShape const & reduceShape,
    00408                    Functor const & f, MetaInt<N>)
    00409 {
    00410     DestIterator dend = d + dshape[N];
    00411     for(; d != dend; ++s.template dim<N>(), ++d)
    00412     {
    00413         transformMultiArrayReduceImpl(s, sshape, src, d.begin(), dshape, dest,
    00414                                       reduceShape, f, MetaInt<N-1>());
    00415     }
    00416 }
    00417
    00418 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00419           class DestIterator, class DestShape, class DestAccessor,
    00420           class Functor>
    00421 void
    00422 transformMultiArrayImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00423                DestIterator d, DestShape const & dshape, DestAccessor dest,
    00424                Functor const & f, VigraTrueType)
    00425 {
    00426     // reduce mode
    00427     SrcShape reduceShape = sshape;
    00428     for(unsigned int i=0; i<dshape.size(); ++i)
    00429     {
    00430         vigra_precondition(dshape[i] == 1 || sshape[i] == dshape[i],
    00431             "transformMultiArray(): mismatch between source and destination shapes:\n"
    00432             "In 'reduce'-mode, the length of each destination dimension must either be 1\n"
    00433             "or equal to the corresponding source length.");
    00434         if(dshape[i] != 1)
    00435             reduceShape[i] = 1;
    00436     }
    00437     transformMultiArrayReduceImpl(s, sshape, src, d, dshape, dest, reduceShape,
    00438                                   f, MetaInt<SrcIterator::level>());
    00439 }
    00440
    00441 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00442           class DestIterator, class DestShape, class DestAccessor,
    00443           class Functor>
    00444 void
    00445 transformMultiArrayExpandImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00446                DestIterator d, DestShape const & dshape, DestAccessor dest,
    00447                Functor const & f, MetaInt<0>)
    00448 {
    00449     if(sshape[0] == 1)
    00450     {
    00451         initLine(d, d + dshape[0], dest, f(src(s)));
    00452     }
    00453     else
    00454     {
    00455         transformLine(s, s + sshape[0], src, d, dest, f);
    00456     }
    00457 }
    00458
    00459 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00460           class DestIterator, class DestShape, class DestAccessor,
    00461           class Functor, int N>
    00462 void
    00463 transformMultiArrayExpandImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00464                    DestIterator d, DestShape const & dshape, DestAccessor dest,
    00465                    Functor const & f, MetaInt<N>)
    00466 {
    00467     DestIterator dend = d + dshape[N];
    00468     if(sshape[N] == 1)
    00469     {
    00470         for(; d != dend; ++d)
    00471         {
    00472             transformMultiArrayExpandImpl(s.begin(), sshape, src, d.begin(), dshape, dest,
    00473                                           f, MetaInt<N-1>());
    00474         }
    00475     }
    00476     else
    00477     {
    00478         for(; d != dend; ++s, ++d)
    00479         {
    00480             transformMultiArrayExpandImpl(s.begin(), sshape, src, d.begin(), dshape, dest,
    00481                                           f, MetaInt<N-1>());
    00482         }
    00483     }
    00484 }
    00485
    00486 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00487           class DestIterator, class DestShape, class DestAccessor,
    00488           class Functor>
    00489 void
    00490 transformMultiArrayImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00491                DestIterator d, DestShape const & dshape, DestAccessor dest,
    00492                Functor const & f, VigraFalseType)
    00493 {
    00494     // expand mode
    00495     for(unsigned int i=0; i<sshape.size(); ++i)
    00496         vigra_precondition(sshape[i] == 1 || sshape[i] == dshape[i],
    00497             "transformMultiArray(): mismatch between source and destination shapes:\n"
    00498             "In 'expand'-mode, the length of each source dimension must either be 1\n"
    00499             "or equal to the corresponding destination length.");
    00500     transformMultiArrayExpandImpl(s, sshape, src, d, dshape, dest,
    00501                                   f, MetaInt<SrcIterator::level>());
    00502 }
    00503
    00504 /** \brief Transform a multi-dimensional array with a unary function or functor.
    00505
    00506     This function can be applied in three modes:
    00507
    00508     <DL>
    00509     <DT><b>Standard Mode:</b>
    00510         <DD>If the source and destination arrays have the same size,
    00511         the transformation given by the functor is applied to every source
    00512         element and the result written into the corresponding destination element.
    00513         Unary functions, unary functors from the STL and the functors specifically
    00514         defined in \ref TransformFunctor can be used in standard mode.
    00515         Creation of new functors is easiest by using \ref FunctorExpressions.
    00516     <DT><b>Expanding Mode:</b>
    00517         <DD>If the source array has length 1 along some (or even all) dimensions,
    00518         the source value at index 0 is used for all destination
    00519         elements in those dimensions. In other words, the source index is not
    00520         incremented along these dimensions, but the transformation functor
    00521         is applied as usual. So, we can expand a small array (e.g. a single row of data,
    00522         column length is 1), into a larger one (e.g. a 2D image with the same width):
    00523         the given values are simply reused as necessary (e.g. for every row of the
    00524         destination image). The same functors as in standard mode can be applied.
    00525     <DT><b>Reducing Mode:</b>
    00526         <DD>If the destination array has length 1 along some (or even all) dimensions,
    00527         the source values in these dimensions are reduced to single values by means
    00528         of a suitable functor (e.g. \ref vigra::ReduceFunctor), which supports two
    00529         function call operators: one
    00530         with a single argument to collect the values, and without argument to
    00531         obtain the final (reduced) result. This behavior is a multi-dimensional
    00532         generalization of the C++ standard function <tt>std::accumulate()</tt>.
    00533     </DL>
    00534
    00535     The arrays must be represented by
    00536     iterators compatible with \ref vigra::MultiIterator, and the iteration range
    00537     is specified by means of shape objects. If only the source shape is given
    00538     the destination array is assumed to have the same shape, and standard mode
    00539     is applied. If two shapes are given, the size of corresponding dimensions
    00540     must be either equal (standard copy), or the source length must be 1
    00541     (expand mode), or the destination length must be 1 (reduce mode). However,
    00542     reduction and expansion cannot be executed at the same time, so the latter
    00543     conditions are mutual exclusive, even if they apply to different dimensions.
    00544
    00545     The function uses accessors to access the data elements.
    00546
    00547     <b> Declarations:</b>
    00548
    00549     <b>\#include</b> "<a href="multi__pointoperators_8hxx-source.html">vigra/multi_pointoperators.hxx</a>"<br>
    00550     Namespace: vigra
    00551
    00552     pass arguments explicitly:
    00553     \code
    00554     namespace vigra {
    00555         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00556                   class DestIterator, class DestAccessor,
    00557                   class Functor>
    00558         void
    00559         transformMultiArray(SrcIterator s, SrcShape const & shape, SrcAccessor src,
    00560                             DestIterator d, DestAccessor dest, Functor const & f);
    00561
    00562
    00563         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00564                   class DestIterator, class DestShape, class DestAccessor,
    00565                   class Functor>
    00566         void
    00567         transformMultiArray(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00568                             DestIterator d, DestShape const & dshape, DestAccessor dest,
    00569                             Functor const & f);
    00570     }
    00571     \endcode
    00572
    00573
    00574     use argument objects in conjunction with \ref ArgumentObjectFactories:
    00575     \code
    00576     namespace vigra {
    00577         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00578                   class DestIterator, class DestAccessor,
    00579                   class Functor>
    00580         void
    00581         transformMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
    00582                             pair<DestIterator, DestAccessor> const & dest, Functor const & f);
    00583
    00584
    00585         template <class SrcIterator, class SrcShape, class SrcAccessor,
    00586                   class DestIterator, class DestShape, class DestAccessor,
    00587                   class Functor>
    00588         void
    00589         transformMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
    00590                             triple<DestIterator, DestShape, DestAccessor> const & dest,
    00591                             Functor const & f)
    00592     }
    00593     \endcode
    00594
    00595     <b> Usage - Standard Mode:</b>
    00596
    00597     Source and destination array have the same size.
    00598
    00599     \code
    00600     #include <cmath>         // for sqrt()
    00601
    00602     typedef vigra::MultiArray<3, float> Array;
    00603     Array src(Array::size_type(100, 200, 50)),
    00604           dest(Array::size_type(100, 200, 50));
    00605     ...
    00606
    00607     vigra::transformMultiArray(srcMultiArrayRange(src),
    00608                                destMultiArray(dest),
    00609                                &std::sqrt );
    00610
    00611     \endcode
    00612
    00613     <b> Usage - Expand Mode:</b>
    00614
    00615     The source array is only 2D (it has depth 1). Thus, the destination
    00616     will contain 50 identical copies of the transformed source array.
    00617     Note that the destination shape must be passed to the algorithm for
    00618     the expansion to work, so we use <tt>destMultiArrayRange()</tt>
    00619     rather than <tt>destMultiArray()</tt>.
    00620
    00621     \code
    00622     #include <cmath>         // for sqrt()
    00623
    00624     typedef vigra::MultiArray<3, float> Array;
    00625     Array src(Array::size_type(100, 200, 1)),
    00626           dest(Array::size_type(100, 200, 50));
    00627     ...
    00628
    00629     vigra::transformMultiArray(srcMultiArrayRange(src),
    00630                                destMultiArrayRange(dest),
    00631                                &std::sqrt );
    00632
    00633     \endcode
    00634
    00635     <b> Usage - Reduce Mode:</b>
    00636
    00637     The destination array is only 1D (it's width and height are 1).
    00638     Thus, it will contain accumulated data for every slice of the source volume
    00639     (or for every frame, if the source is intepreted as an image sequence).
    00640     In the example, we use the functor \ref vigra::FindAverage to calculate
    00641     the average gray value of every slice. Note that the destination shape
    00642     must also be passed for the reduction to work, so we use
    00643     <tt>destMultiArrayRange()</tt> rather than <tt>destMultiArray()</tt>.
    00644
    00645     \code
    00646     typedef vigra::MultiArray<3, float> Array;
    00647     Array src(Array::size_type(100, 200, 50)),
    00648           dest(Array::size_type(1, 1, 50));
    00649     ...
    00650
    00651     vigra::transformMultiArray(srcMultiArrayRange(src),
    00652                                destMultiArrayRange(dest),
    00653                                vigra::FindAverage<float>() );
    00654
    00655     \endcode
    00656
    00657     <b> Required Interface:</b>
    00658
    00659     In standard and expand mode, the functor must be a model of UnaryFunction
    00660     (i.e. support function call with one argument and a return value
    00661     <tt>res = functor(arg)</tt>):
    00662
    00663     \code
    00664     MultiIterator src_begin, src_end, dest_begin;
    00665
    00666     SrcAccessor src_accessor;
    00667     DestAccessor dest_accessor;
    00668     Functor functor;
    00669
    00670     dest_accessor.set(functor(src_accessor(src_begin)), dest_begin);
    00671     \endcode
    00672
    00673     In reduce mode, it must be a model of UnaryAnalyser (i.e. support function call
    00674     with one argument and no return vakue <tt>functor(arg)</tt>) and Initializer
    00675     (i.e. support function call with no argument, but return value
    00676     <tt>res = functor()</tt>). Internally, such functors are recognized by the
    00677     meta functions <tt>FunctorTraits&lt;FUNCTOR&gt;::</tt><tt>isUnaryAnalyser</tt> and
    00678     <tt>FunctorTraits&lt;FUNCTOR&gt;::</tt><tt>isInitializer</tt> which must both yield
    00679     <tt>VigraTrueType</tt>. Make sure that your functor correctly defines
    00680     <tt>FunctorTraits</tt> because otherwise reduce mode will not work. In addition,
    00681     the functor must be copy constructible in order to start each reduction
    00682     with a fresh functor.
    00683
    00684     \code
    00685     MultiIterator src_begin, src_end, dest_begin;
    00686
    00687     SrcAccessor src_accessor;
    00688     DestAccessor dest_accessor;
    00689
    00690     FUNCTOR initial_functor, functor(initial_functor);
    00691     assert(typeid(FunctorTraits<FUNCTOR>::isInitializer) == typeid(VigraTrueType));
    00692     assert(typeid(FunctorTraits<FUNCTOR>::isUnaryAnalyser) == typeid(VigraTrueType));
    00693
    00694     functor(src_accessor(src_begin));
    00695     dest_accessor.set(functor(), dest_begin);
    00696     \endcode
    00697
    00698 */
    00699 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00700           class DestIterator, class DestAccessor,
    00701           class Functor>
    00702 inline void
    00703 transformMultiArray(SrcIterator s, SrcShape const & shape, SrcAccessor src,
    00704                     DestIterator d, DestAccessor dest, Functor const & f)
    00705 {
    00706     transformMultiArrayExpandImpl(s, shape, src, d, shape, dest,
    00707                                   f, MetaInt<SrcIterator::level>());
    00708 }
    00709
    00710 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00711           class DestIterator, class DestAccessor,
    00712           class Functor>
    00713 inline void
    00714 transformMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
    00715                pair<DestIterator, DestAccessor> const & dest, Functor const & f)
    00716 {
    00717
    00718     transformMultiArray(src.first, src.second, src.third,
    00719                         dest.first, dest.second, f);
    00720 }
    00721
    00722 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00723           class DestIterator, class DestShape, class DestAccessor,
    00724           class Functor>
    00725 void
    00726 transformMultiArray(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
    00727                DestIterator d, DestShape const & dshape, DestAccessor dest,
    00728                Functor const & f)
    00729 {
    00730     vigra_precondition(sshape.size() == dshape.size(),
    00731         "transformMultiArray(): dimensionality of source and destination array differ");
    00732     typedef FunctorTraits<Functor> FT;
    00733     typedef typename
    00734         And<typename FT::isInitializer, typename FT::isUnaryAnalyser>::result
    00735         isAnalyserInitializer;
    00736     transformMultiArrayImpl(s, sshape, src, d, dshape, dest,
    00737                             f, isAnalyserInitializer());
    00738 }
    00739
    00740 template <class SrcIterator, class SrcShape, class SrcAccessor,
    00741           class DestIterator, class DestShape, class DestAccessor,
    00742           class Functor>
    00743 inline void
    00744 transformMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
    00745                triple<DestIterator, DestShape, DestAccessor> const & dest,
    00746                Functor const & f)
    00747 {
    00748     transformMultiArray(src.first, src.second, src.third,
    00749                         dest.first, dest.second, dest.third, f);
    00750 }
    00751
    00752 /********************************************************/
    00753 /*                                                      */
    00754 /*                combineTwoMultiArrays                 */
    00755 /*                                                      */
    00756 /********************************************************/
    00757
    00758 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    00759           class SrcIterator2, class SrcAccessor2,
    00760           class DestIterator, class DestShape, class DestAccessor,
    00761           class Functor>
    00762 void
    00763 combineTwoMultiArraysReduceImpl(
    00764                SrcIterator1 s1, SrcShape const & sshape, SrcAccessor1 src1,
    00765                SrcIterator2 s2, SrcAccessor2 src2,
    00766                DestIterator d,  DestShape const & dshape, DestAccessor dest,
    00767                SrcShape const & reduceShape,
    00768                Functor const & ff, MetaInt<0>)
    00769 {
    00770     DestIterator dend = d + dshape[0];
    00771     for(; d != dend; ++s1.template dim<0>(), ++s2.template dim<0>(), ++d)
    00772     {
    00773         Functor f = ff;
    00774         inspectTwoMultiArrays(s1, reduceShape, src1, s2, src2, f);
    00775         dest.set(f(), d);
    00776     }
    00777 }
    00778
    00779 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    00780           class SrcIterator2, class SrcAccessor2,
    00781           class DestIterator, class DestShape, class DestAccessor,
    00782           class Functor, int N>
    00783 void
    00784 combineTwoMultiArraysReduceImpl(
    00785                SrcIterator1 s1, SrcShape const & sshape, SrcAccessor1 src1,
    00786                SrcIterator2 s2, SrcAccessor2 src2,
    00787                DestIterator d,  DestShape const & dshape, DestAccessor dest,
    00788                SrcShape const & reduceShape,
    00789                Functor const & f, MetaInt<N>)
    00790 {
    00791     DestIterator dend = d + dshape[N];
    00792     for(; d != dend; ++s1.template dim<N>(), ++s2.template dim<N>(), ++d)
    00793     {
    00794         combineTwoMultiArraysReduceImpl(s1, sshape, src1, s2, src2,
    00795                                         d.begin(), dshape, dest,
    00796                                         reduceShape, f, MetaInt<N-1>());
    00797     }
    00798 }
    00799
    00800 template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
    00801           class SrcIterator2, class SrcShape2, class SrcAccessor2,
    00802           class DestIterator, class DestShape, class DestAccessor,
    00803           class Functor>
    00804 void
    00805 combineTwoMultiArraysImpl(
    00806                SrcIterator1 s1, SrcShape1 const & sshape1, SrcAccessor1 src1,
    00807                SrcIterator2 s2, SrcShape2 const & sshape2, SrcAccessor2 src2,
    00808                DestIterator d, DestShape const & dshape, DestAccessor dest,
    00809                Functor const & f, VigraTrueType)
    00810 {
    00811     // reduce mode
    00812     SrcShape1 reduceShape = sshape1;
    00813     for(unsigned int i=0; i<dshape.size(); ++i)
    00814     {
    00815         vigra_precondition(sshape1[i] == sshape2[i] &&
    00816                            (dshape[i] == 1 || sshape1[i] == dshape[i]),
    00817             "combineTwoMultiArrays(): mismatch between source and destination shapes:\n"
    00818             "In 'reduce'-mode, the two source shapes must be equal, and\n"
    00819             "the length of each destination dimension must either be 1\n"
    00820             "or equal to the corresponding source length.");
    00821         if(dshape[i] != 1)
    00822             reduceShape[i] = 1;
    00823     }
    00824     combineTwoMultiArraysReduceImpl(s1, sshape1, src1, s2, src2,
    00825                                     d, dshape, dest, reduceShape,
    00826                                     f, MetaInt<SrcIterator1::level>());
    00827 }
    00828
    00829 template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
    00830           class SrcIterator2, class SrcShape2, class SrcAccessor2,
    00831           class DestIterator, class DestShape, class DestAccessor,
    00832           class Functor>
    00833 void
    00834 combineTwoMultiArraysExpandImpl(
    00835                SrcIterator1 s1, SrcShape1 const & sshape1, SrcAccessor1 src1,
    00836                SrcIterator2 s2, SrcShape2 const & sshape2, SrcAccessor2 src2,
    00837                DestIterator d, DestShape const & dshape, DestAccessor dest,
    00838                Functor const & f, MetaInt<0>)
    00839 {
    00840     DestIterator dend = d + dshape[0];
    00841     if(sshape1[0] == 1 && sshape2[0] == 1)
    00842     {
    00843         initLine(d, dend, dest, f(src1(s1), src2(s2)));
    00844     }
    00845     else if(sshape1[0] == 1)
    00846     {
    00847         typename SrcAccessor1::value_type sv1 = src1(s1);
    00848         for(; d != dend; ++d, ++s2)
    00849             dest.set(f(sv1, src2(s2)), d);
    00850     }
    00851     else if(sshape2[0] == 1)
    00852     {
    00853         typename SrcAccessor2::value_type sv2 = src2(s2);
    00854         for(; d != dend; ++d, ++s1)
    00855             dest.set(f(src1(s1), sv2), d);
    00856     }
    00857     else
    00858     {
    00859         combineTwoLines(s1, s1 + sshape1[0], src1, s2, src2, d, dest, f);
    00860     }
    00861 }
    00862
    00863 template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
    00864           class SrcIterator2, class SrcShape2, class SrcAccessor2,
    00865           class DestIterator, class DestShape, class DestAccessor,
    00866           class Functor, int N>
    00867 void
    00868 combineTwoMultiArraysExpandImpl(
    00869                SrcIterator1 s1, SrcShape1 const & sshape1, SrcAccessor1 src1,
    00870                SrcIterator2 s2, SrcShape2 const & sshape2, SrcAccessor2 src2,
    00871                DestIterator d, DestShape const & dshape, DestAccessor dest,
    00872                Functor const & f, MetaInt<N>)
    00873 {
    00874     DestIterator dend = d + dshape[N];
    00875     int s1inc = sshape1[N] == 1
    00876                     ? 0
    00877                     : 1;
    00878     int s2inc = sshape2[N] == 1
    00879                     ? 0
    00880                     : 1;
    00881     for(; d != dend; ++d, s1 += s1inc, s2 += s2inc)
    00882     {
    00883         combineTwoMultiArraysExpandImpl(s1.begin(), sshape1, src1,
    00884                                         s2.begin(), sshape2, src2,
    00885                                         d.begin(), dshape, dest,
    00886                                         f, MetaInt<N-1>());
    00887     }
    00888 }
    00889
    00890 template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
    00891           class SrcIterator2, class SrcShape2, class SrcAccessor2,
    00892           class DestIterator, class DestShape, class DestAccessor,
    00893           class Functor>
    00894 void
    00895 combineTwoMultiArraysImpl(
    00896                SrcIterator1 s1, SrcShape1 const & sshape1, SrcAccessor1 src1,
    00897                SrcIterator2 s2, SrcShape2 const & sshape2, SrcAccessor2 src2,
    00898                DestIterator d, DestShape const & dshape, DestAccessor dest,
    00899                Functor const & f, VigraFalseType)
    00900 {
    00901     // expand mode
    00902     for(unsigned int i=0; i<sshape1.size(); ++i)
    00903         vigra_precondition((sshape1[i] == 1 || sshape1[i] == dshape[i]) &&
    00904                            (sshape2[i] == 1 || sshape2[i] == dshape[i]),
    00905             "combineTwoMultiArrays(): mismatch between source and destination shapes:\n"
    00906             "In 'expand'-mode, the length of each source dimension must either be 1\n"
    00907             "or equal to the corresponding destination length.");
    00908     combineTwoMultiArraysExpandImpl(s1, sshape1, src1, s2, sshape2, src2,
    00909                                     d, dshape, dest,
    00910                                     f, MetaInt<SrcIterator1::level>());
    00911 }
    00912
    00913 /** \brief Combine two multi-dimensional arrays into one using a binary function or functor.
    00914
    00915     This function can be applied in three modes:
    00916
    00917     <DL>
    00918     <DT><b>Standard Mode:</b>
    00919         <DD>If the source and destination arrays have the same size,
    00920         the transformation given by the functor is applied to every pair of
    00921         corresponding source elements and the result written into the corresponding
    00922         destination element.
    00923         Binary functions, binary functors from the STL and the functors specifically
    00924         defined in \ref CombineFunctor can be used in standard mode.
    00925         Creation of new functors is easiest by using \ref FunctorExpressions.
    00926     <DT><b>Expanding Mode:</b>
    00927         <DD>If the source arrays have length 1 along some (or even all) dimensions,
    00928         the source values at index 0 are used for all destination
    00929         elements in those dimensions. In other words, the source index is not
    00930         incremented along those dimensions, but the transformation functor
    00931         is applied as usual. So, we can expand small arrays (e.g. a single row of data,
    00932         column length is 1), into larger ones (e.g. a 2D image with the same width):
    00933         the given values are simply reused as necessary (e.g. for every row of the
    00934         destination image). It is not even necessary that the source array shapes
    00935         are equal. For example, we can combine a small array with one that
    00936         hase the same size as the destination array.
    00937         The same functors as in standard mode can be applied.
    00938     <DT><b>Reducing Mode:</b>
    00939         <DD>If the destination array has length 1 along some (or even all) dimensions,
    00940         the source values in these dimensions are reduced to single values by means
    00941         of a suitable functor which supports two function call operators: one
    00942         with two arguments to collect the values, and one without argument to
    00943         obtain the final (reduced) result. This behavior is a multi-dimensional
    00944         generalization of the C++ standard function <tt>std::accumulate()</tt>.
    00945     </DL>
    00946
    00947     The arrays must be represented by
    00948     iterators compatible with \ref vigra::MultiIterator, and the iteration range
    00949     is specified by means of shape objects. If only a single source shape is given
    00950     the destination array is assumed to have the same shape, and standard mode
    00951     is applied. If three shapes are given, the size of corresponding dimensions
    00952     must be either equal (standard copy), or the length of this dimension must
    00953     be 1 in one or both source arrays
    00954     (expand mode), or the destination length must be 1 (reduce mode). However,
    00955     reduction and expansion cannot be executed at the same time, so the latter
    00956     conditions are mutual exclusive, even if they apply to different dimensions.
    00957
    00958     The function uses accessors to access the data elements.
    00959
    00960     <b> Declarations:</b>
    00961
    00962     <b>\#include</b> "<a href="multi__pointoperators_8hxx-source.html">vigra/multi_pointoperators.hxx</a>"<br>
    00963     Namespace: vigra
    00964
    00965     pass arguments explicitly:
    00966     \code
    00967     namespace vigra {
    00968         template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    00969                   class SrcIterator2, class SrcAccessor2,
    00970                   class DestIterator, class DestAccessor,
    00971                   class Functor>
    00972         void combineTwoMultiArrays(
    00973                        SrcIterator1 s1, SrcShape const & shape, SrcAccessor1 src1,
    00974                        SrcIterator2 s2, SrcAccessor2 src2,
    00975                        DestIterator d, DestAccessor dest, Functor const & f);
    00976
    00977
    00978         template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
    00979                   class SrcIterator2, class SrcShape2, class SrcAccessor2,
    00980                   class DestIterator, class DestShape, class DestAccessor,
    00981                   class Functor>
    00982         void combineTwoMultiArrays(
    00983                        SrcIterator1 s1, SrcShape1 const & sshape1, SrcAccessor1 src1,
    00984                        SrcIterator2 s2, SrcShape2 const & sshape2, SrcAccessor2 src2,
    00985                        DestIterator d, DestShape const & dshape, DestAccessor dest,
    00986                        Functor const & f);
    00987             }
    00988     \endcode
    00989
    00990
    00991     use argument objects in conjunction with \ref ArgumentObjectFactories:
    00992     \code
    00993     namespace vigra {
    00994         template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    00995                   class SrcIterator2, class SrcAccessor2,
    00996                   class DestIterator, class DestAccessor, class Functor>
    00997         void combineTwoMultiArrays(
    00998                        triple<SrcIterator1, SrcShape, SrcAccessor1> const & src1,
    00999                        pair<SrcIterator2, SrcAccessor2> const & src2,
    01000                        pair<DestIterator, DestAccessor> const & dest, Functor const & f);
    01001
    01002
    01003         template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
    01004                   class SrcIterator2, class SrcShape2, class SrcAccessor2,
    01005                   class DestIterator, class DestShape, class DestAccessor,
    01006                   class Functor>
    01007         void combineTwoMultiArrays(
    01008                        triple<SrcIterator1, SrcShape1, SrcAccessor1> const & src1,
    01009                        triple<SrcIterator2, SrcShape2, SrcAccessor2> const & src2,
    01010                        triple<DestIterator, DestShape, DestAccessor> const & dest,
    01011                        Functor const & f);
    01012     }
    01013     \endcode
    01014
    01015     <b> Usage - Standard Mode:</b>
    01016
    01017     Source and destination arrays have the same size.
    01018
    01019     \code
    01020     #include <functional>     // for std::plus
    01021
    01022     typedef vigra::MultiArray<3, int> Array;
    01023     Array src1(Array::size_type(100, 200, 50)),
    01024           src2(Array::size_type(100, 200, 50)),
    01025           dest(Array::size_type(100, 200, 50));
    01026     ...
    01027
    01028     vigra::combineTwoMultiArrays(
    01029                 srcMultiArrayRange(src1),
    01030                 srcMultiArray(src2),
    01031                 destMultiArray(dest),
    01032                 std::plus<int>());
    01033
    01034     \endcode
    01035
    01036     <b> Usage - Expand Mode:</b>
    01037
    01038     One source array is only 2D (it has depth 1). This image will be added
    01039     to every slice of the other source array, and the result
    01040     if written into the corresponding destination slice. Note that the shapes
    01041     of all arrays must be passed to the algorithm, so we use
    01042     <tt>srcMultiArrayRange()</tt> and <tt>destMultiArrayRange()</tt>
    01043     rather than <tt>srcMultiArray()</tt> and <tt>destMultiArray()</tt>.
    01044
    01045     \code
    01046     #include <functional>     // for std::plus
    01047
    01048     typedef vigra::MultiArray<3, int> Array;
    01049     Array src1(Array::size_type(100, 200, 1)),
    01050           src2(Array::size_type(100, 200, 50)),
    01051           dest(Array::size_type(100, 200, 50));
    01052     ...
    01053
    01054     vigra::combineTwoMultiArrays(
    01055                 srcMultiArrayRange(src1),
    01056                 srcMultiArray(src2),
    01057                 destMultiArray(dest),
    01058                 std::plus<int>());
    01059
    01060     \endcode
    01061
    01062     <b> Usage - Reduce Mode:</b>
    01063
    01064     The destination array is only 1D (it's width and height are 1).
    01065     Thus, it will contain accumulated data for every slice of the source volumes
    01066     (or for every frame, if the sources are intepreted as image sequences).
    01067     In the example, we use \ref vigra::ReduceFunctor together with a functor
    01068     expression (see \ref FunctorExpressions)
    01069     to calculate the total absolute difference of the gray values in every pair of
    01070     source slices. Note that the shapes of all arrays must be passed
    01071     to the algorithm in order for the reduction to work, so we use
    01072     <tt>srcMultiArrayRange()</tt> and <tt>destMultiArrayRange()</tt>
    01073     rather than <tt>srcMultiArray()</tt> and <tt>destMultiArray()</tt>.
    01074
    01075     \code
    01076     #include <vigra/functorexpression.hxx>
    01077     using namespace vigra::functor;
    01078
    01079     typedef vigra::MultiArray<3, int> Array;
    01080     Array src1(Array::size_type(100, 200, 50)),
    01081           src2(Array::size_type(100, 200, 50)),
    01082           dest(Array::size_type(1, 1, 50));
    01083     ...
    01084
    01085     vigra::combineTwoMultiArrays(
    01086                 srcMultiArrayRange(src1),
    01087                 srcMultiArray(src2),
    01088                 destMultiArray(dest),
    01089                 reduceFunctor(Arg1() + abs(Arg2() - Arg3()), 0) );
    01090                 // Arg1() is the sum accumulated so far, initialzed with 0
    01091
    01092     \endcode
    01093
    01094     <b> Required Interface:</b>
    01095
    01096     In standard and expand mode, the functor must be a model of BinaryFunction
    01097     (i.e. support function call with two arguments and a return value
    01098     <tt>res = functor(arg1, arg2)</tt>):
    01099
    01100     \code
    01101     MultiIterator src1_begin, src2_begin, dest_begin;
    01102
    01103     SrcAccessor1 src1_accessor;
    01104     SrcAccessor2 src2_accessor;
    01105     DestAccessor dest_accessor;
    01106
    01107     Functor functor;
    01108
    01109     dest_accessor.set(
    01110           functor(src1_accessor(src1_begin), src2_accessor(src2_begin)),
    01111           dest_begin);
    01112
    01113     \endcode
    01114
    01115     In reduce mode, it must be a model of BinaryAnalyser (i.e. support function call
    01116     with two arguments and no return vakue <tt>functor(arg1, arg2)</tt>) and Initializer
    01117     (i.e. support function call with no argument, but return value
    01118     <tt>res = functor()</tt>). Internally, such functors are recognized by the
    01119     meta functions <tt>FunctorTraits&lt;FUNCTOR&gt;::</tt><tt>isBinaryAnalyser</tt> and
    01120     <tt>FunctorTraits&lt;FUNCTOR&gt;::</tt><tt>isInitializer</tt> which must both yield
    01121     <tt>VigraTrueType</tt>. Make sure that your functor correctly defines
    01122     <tt>FunctorTraits</tt> because otherwise reduce mode will not work. In addition,
    01123     the functor must be copy constructible in order to start each reduction
    01124     with a fresh functor.
    01125
    01126     \code
    01127     MultiIterator src1_begin, src2_begin, dest_begin;
    01128
    01129     SrcAccessor1 src1_accessor;
    01130     SrcAccessor2 src2_accessor;
    01131     DestAccessor dest_accessor;
    01132
    01133     FUNCTOR initial_functor, functor(initial_functor);
    01134     assert(typeid(FunctorTraits<FUNCTOR>::isInitializer) == typeid(VigraTrueType));
    01135     assert(typeid(FunctorTraits<FUNCTOR>::isBinaryAnalyser) == typeid(VigraTrueType));
    01136
    01137     functor(src1_accessor(src1_begin), src2_accessor(src2_begin));
    01138     dest_accessor.set(functor(), dest_begin);
    01139     \endcode
    01140
    01141 */
    01142 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    01143           class SrcIterator2, class SrcAccessor2,
    01144           class DestIterator, class DestAccessor,
    01145           class Functor>
    01146 inline void
    01147 combineTwoMultiArrays(SrcIterator1 s1, SrcShape const & shape, SrcAccessor1 src1,
    01148                SrcIterator2 s2, SrcAccessor2 src2,
    01149                DestIterator d, DestAccessor dest, Functor const & f)
    01150 {
    01151     combineTwoMultiArraysExpandImpl(s1, shape, src1, s2, shape, src2, d, shape, dest, f,
    01152                                     MetaInt<SrcIterator1::level>());
    01153 }
    01154
    01155 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    01156           class SrcIterator2, class SrcAccessor2,
    01157           class DestIterator, class DestAccessor, class Functor>
    01158 inline void
    01159 combineTwoMultiArrays(triple<SrcIterator1, SrcShape, SrcAccessor1> const & src1,
    01160                pair<SrcIterator2, SrcAccessor2> const & src2,
    01161                pair<DestIterator, DestAccessor> const & dest, Functor const & f)
    01162 {
    01163
    01164     combineTwoMultiArrays(
    01165            src1.first, src1.second, src1.third,
    01166            src2.first, src2.second, dest.first, dest.second, f);
    01167 }
    01168
    01169 template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
    01170           class SrcIterator2, class SrcShape2, class SrcAccessor2,
    01171           class DestIterator, class DestShape, class DestAccessor,
    01172           class Functor>
    01173 void
    01174 combineTwoMultiArrays(
    01175                SrcIterator1 s1, SrcShape1 const & sshape1, SrcAccessor1 src1,
    01176                SrcIterator2 s2, SrcShape2 const & sshape2, SrcAccessor2 src2,
    01177                DestIterator d, DestShape const & dshape, DestAccessor dest,
    01178                Functor const & f)
    01179 {
    01180     vigra_precondition(sshape1.size() == dshape.size() && sshape2.size() == dshape.size(),
    01181         "combineTwoMultiArrays(): dimensionality of source and destination arrays differ");
    01182
    01183     typedef FunctorTraits<Functor> FT;
    01184     typedef typename
    01185         And<typename FT::isInitializer, typename FT::isBinaryAnalyser>::result
    01186         isAnalyserInitializer;
    01187     combineTwoMultiArraysImpl(s1, sshape1, src1, s2, sshape2, src2, d, dshape, dest,
    01188                               f, isAnalyserInitializer());
    01189 }
    01190
    01191 template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
    01192           class SrcIterator2, class SrcShape2, class SrcAccessor2,
    01193           class DestIterator, class DestShape, class DestAccessor,
    01194           class Functor>
    01195 inline void
    01196 combineTwoMultiArrays(
    01197                triple<SrcIterator1, SrcShape1, SrcAccessor1> const & src1,
    01198                triple<SrcIterator2, SrcShape2, SrcAccessor2> const & src2,
    01199                triple<DestIterator, DestShape, DestAccessor> const & dest,
    01200                Functor const & f)
    01201 {
    01202     combineTwoMultiArrays(src1.first, src1.second, src1.third,
    01203                           src2.first, src2.second, src2.third,
    01204                           dest.first, dest.second, dest.third, f);
    01205 }
    01206
    01207 /********************************************************/
    01208 /*                                                      */
    01209 /*               combineThreeMultiArrays                */
    01210 /*                                                      */
    01211 /********************************************************/
    01212
    01213 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    01214           class SrcIterator2, class SrcAccessor2,
    01215           class SrcIterator3, class SrcAccessor3,
    01216           class DestIterator, class DestAccessor,
    01217           class Functor>
    01218 inline void
    01219 combineThreeMultiArraysImpl(SrcIterator1 s1, SrcShape const & shape, SrcAccessor1 src1,
    01220                SrcIterator2 s2, SrcAccessor2 src2,
    01221                SrcIterator3 s3, SrcAccessor3 src3,
    01222                DestIterator d, DestAccessor dest, Functor const & f, MetaInt<0>)
    01223 {
    01224     combineThreeLines(s1, s1 + shape[0], src1, s2, src2, s3, src3, d, dest, f);
    01225 }
    01226
    01227 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    01228           class SrcIterator2, class SrcAccessor2,
    01229           class SrcIterator3, class SrcAccessor3,
    01230           class DestIterator, class DestAccessor,
    01231           class Functor, int N>
    01232 void
    01233 combineThreeMultiArraysImpl(SrcIterator1 s1, SrcShape const & shape, SrcAccessor1 src1,
    01234                SrcIterator2 s2, SrcAccessor2 src2,
    01235                SrcIterator3 s3, SrcAccessor3 src3,
    01236                DestIterator d, DestAccessor dest,
    01237                    Functor const & f, MetaInt<N>)
    01238 {
    01239     SrcIterator1 s1end = s1 + shape[N];
    01240     for(; s1 != s1end; ++s1, ++s2, ++s3, ++d)
    01241     {
    01242         combineThreeMultiArraysImpl(s1.begin(), shape, src1,
    01243                                   s2.begin(), src2, s3.begin(), src3, d.begin(), dest,
    01244                                   f, MetaInt<N-1>());
    01245     }
    01246 }
    01247
    01248
    01249 /** \brief Combine three multi-dimensional arrays into one using a
    01250            ternary function or functor.
    01251
    01252     Except for the fact that it operates on three input arrays, this function is
    01253     identical to \ref combineTwoMultiArrays().
    01254
    01255     <b> Declarations:</b>
    01256
    01257     pass arguments explicitly:
    01258     \code
    01259     namespace vigra {
    01260         template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    01261                   class SrcIterator2, class SrcAccessor2,
    01262                   class SrcIterator3, class SrcAccessor3,
    01263                   class DestIterator, class DestAccessor,
    01264                   class Functor>
    01265         void
    01266         combineThreeMultiArrays(SrcIterator1 s1, SrcShape const & shape, SrcAccessor1 src1,
    01267                        SrcIterator2 s2, SrcAccessor2 src2,
    01268                        SrcIterator3 s3, SrcAccessor3 src3,
    01269                        DestIterator d, DestAccessor dest, Functor const & f);
    01270                     }
    01271     \endcode
    01272
    01273
    01274     use argument objects in conjunction with \ref ArgumentObjectFactories:
    01275     \code
    01276     namespace vigra {
    01277         template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    01278                   class SrcIterator2, class SrcAccessor2,
    01279                   class SrcIterator3, class SrcAccessor3,
    01280                   class DestIterator, class DestAccessor,
    01281                   class Functor>
    01282         inline void
    01283         combineThreeMultiArrays(triple<SrcIterator1, SrcShape, SrcAccessor1> const & src1,
    01284                        pair<SrcIterator2, SrcAccessor2> const & src2,
    01285                        pair<SrcIterator3, SrcAccessor3> const & src3,
    01286                        pair<DestIterator, DestAccessor> const & dest, Functor const & f);
    01287     }
    01288     \endcode
    01289
    01290     <b> Usage:</b>
    01291
    01292     <b>\#include</b> "<a href="multi__pointoperators_8hxx-source.html">vigra/multi_pointoperators.hxx</a>"<br>
    01293     Namespace: vigra
    01294
    01295     \code
    01296     #include <functional>     // for plus
    01297
    01298     typedef vigra::MultiArray<3, int> Array;
    01299     Array src1(Array::size_type(100, 200, 50)),
    01300           src2(Array::size_type(100, 200, 50)),
    01301           src3(Array::size_type(100, 200, 50)),
    01302           dest(Array::size_type(100, 200, 50));
    01303     ...
    01304
    01305     vigra::combineThreeMultiArrays(
    01306                 srcMultiArrayRange(src1),
    01307                 srcMultiArray(src2),
    01308                 srcMultiArray(src3),
    01309                 destMultiArray(dest),
    01310                 SomeThreeArgumentFunctor());
    01311
    01312     \endcode
    01313 */
    01314 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    01315           class SrcIterator2, class SrcAccessor2,
    01316           class SrcIterator3, class SrcAccessor3,
    01317           class DestIterator, class DestAccessor,
    01318           class Functor>
    01319 inline void
    01320 combineThreeMultiArrays(SrcIterator1 s1, SrcShape const & shape, SrcAccessor1 src1,
    01321                SrcIterator2 s2, SrcAccessor2 src2,
    01322                SrcIterator3 s3, SrcAccessor3 src3,
    01323                DestIterator d, DestAccessor dest, Functor const & f)
    01324 {
    01325     combineThreeMultiArraysImpl(s1, shape, src1, s2, src2, s3, src3, d, dest, f,
    01326                               MetaInt<SrcIterator1::level>());
    01327 }
    01328
    01329 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
    01330           class SrcIterator2, class SrcAccessor2,
    01331           class SrcIterator3, class SrcAccessor3,
    01332           class DestIterator, class DestAccessor,
    01333           class Functor>
    01334 inline void
    01335 combineThreeMultiArrays(triple<SrcIterator1, SrcShape, SrcAccessor1> const & src1,
    01336                pair<SrcIterator2, SrcAccessor2> const & src2,
    01337                pair<SrcIterator3, SrcAccessor3> const & src3,
    01338                pair<DestIterator, DestAccessor> const & dest, Functor const & f)
    01339 {
    01340
    01341     combineThreeMultiArrays(
    01342            src1.first, src1.second, src1.third,
    01343            src2.first, src2.second, src3.first, src3.second, dest.first, dest.second, f);
    01344 }
    01345
    01346 /********************************************************/
    01347 /*                                                      */
    01348 /*                  inspectMultiArray                   */
    01349 /*                                                      */
    01350 /********************************************************/
    01351
    01352 template <class Iterator, class Shape, class Accessor, class Functor>
    01353 inline void
    01354 inspectMultiArrayImpl(Iterator s, Shape const & shape, Accessor a,  Functor & f, MetaInt<0>)
    01355 {
    01356     inspectLine(s, s + shape[0], a, f);
    01357 }
    01358
    01359 template <class Iterator, class Shape, class Accessor, class Functor, int N>
    01360 void
    01361 inspectMultiArrayImpl(Iterator s, Shape const & shape, Accessor a,  Functor & f, MetaInt<N>)
    01362 {
    01363     Iterator send = s + shape[N];
    01364     for(; s != send; ++s)
    01365     {
    01366         inspectMultiArrayImpl(s.begin(), shape, a, f, MetaInt<N-1>());
    01367     }
    01368 }
    01369
    01370 /** \brief Call an analyzing functor at every element of a multi-dimensional array.
    01371
    01372     This function can be used to collect statistics of the array etc.
    01373     The results must be stored in the functor, which serves as a return
    01374     value. The arrays must be represented by
    01375     iterators compatible with \ref vigra::MultiIterator.
    01376     The function uses an accessor to access the pixel data. Note that the iterator range
    01377     must be specified by a shape object, because otherwise we could not control
    01378     the range simultaneously in all dimensions (this is a necessary consequence
    01379     of the \ref vigra::MultiIterator design).
    01380
    01381     <b> Declarations:</b>
    01382
    01383     pass arguments explicitly:
    01384     \code
    01385     namespace vigra {
    01386         template <class Iterator, class Shape, class Accessor, class Functor>
    01387         void
    01388         inspectMultiArray(Iterator s, Shape const & shape, Accessor a,  Functor & f);
    01389     }
    01390     \endcode
    01391
    01392     use argument objects in conjunction with \ref ArgumentObjectFactories:
    01393     \code
    01394     namespace vigra {
    01395         template <class Iterator, class Shape, class Accessor, class Functor>
    01396         void
    01397         inspectMultiArray(triple<Iterator, Shape, Accessor> const & s, Functor & f);
    01398     }
    01399     \endcode
    01400
    01401     <b> Usage:</b>
    01402
    01403     <b>\#include</b> "<a href="multi__pointoperators_8hxx-source.html">vigra/multi_pointoperators.hxx</a>"<br>
    01404     Namespace: vigra
    01405
    01406     \code
    01407     typedef vigra::MultiArray<3, int> Array;
    01408     Array array(Array::size_type(100, 200, 50));
    01409
    01410     // init functor
    01411     vigra::FindMinMax<int> minmax;
    01412
    01413     vigra::inspectMultiArray(srcMultiArrayRange(array), minmax);
    01414
    01415     cout << "Min: " << minmax.min << " Max: " << minmax.max;
    01416
    01417     \endcode
    01418
    01419     <b> Required Interface:</b>
    01420
    01421     \code
    01422     MultiIterator src_begin;
    01423
    01424     Accessor accessor;
    01425     Functor functor;
    01426
    01427     functor(accessor(src_begin));
    01428     \endcode
    01429
    01430 */
    01431 template <class Iterator, class Shape, class Accessor, class Functor>
    01432 inline void
    01433 inspectMultiArray(Iterator s, Shape const & shape, Accessor a,  Functor & f)
    01434 {
    01435     inspectMultiArrayImpl(s, shape, a, f, MetaInt<Iterator::level>());
    01436 }
    01437
    01438 template <class Iterator, class Shape, class Accessor, class Functor>
    01439 inline void
    01440 inspectMultiArray(triple<Iterator, Shape, Accessor> const & s, Functor & f)
    01441 {
    01442     inspectMultiArray(s.first, s.second, s.third, f);
    01443 }
    01444
    01445 /********************************************************/
    01446 /*                                                      */
    01447 /*                  inspectTwoMultiArrays               */
    01448 /*                                                      */
    01449 /********************************************************/
    01450
    01451 template <class Iterator1, class Shape, class Accessor1,
    01452           class Iterator2, class Accessor2,
    01453           class Functor>
    01454 inline void
    01455 inspectTwoMultiArraysImpl(Iterator1 s1, Shape const & shape, Accessor1 a1,
    01456                           Iterator2 s2, Accessor2 a2,
    01457                           Functor & f, MetaInt<0>)
    01458 {
    01459     inspectTwoLines(s1, s1 + shape[0], a1, s2, a2, f);
    01460 }
    01461
    01462 template <class Iterator1, class Shape, class Accessor1,
    01463           class Iterator2, class Accessor2,
    01464           class Functor, int N>
    01465 void
    01466 inspectTwoMultiArraysImpl(Iterator1 s1, Shape const & shape, Accessor1 a1,
    01467                           Iterator2 s2, Accessor2 a2,
    01468                           Functor & f, MetaInt<N>)
    01469 {
    01470     Iterator1 s1end = s1 + shape[N];
    01471     for(; s1 != s1end; ++s1, ++s2)
    01472     {
    01473         inspectTwoMultiArraysImpl(s1.begin(), shape, a1,
    01474                                   s2.begin(), a2, f, MetaInt<N-1>());
    01475     }
    01476 }
    01477
    01478 /** \brief Call an analyzing functor at all corresponding elements of
    01479            two multi-dimensional arrays.
    01480
    01481     This function can be used to collect statistics of the array etc.
    01482     The results must be stored in the functor, which serves as a return
    01483     value. The arrays must be represented by
    01484     iterators compatible with \ref vigra::MultiIterator.
    01485     The function uses an accessor to access the pixel data. Note that the iterator range
    01486     must be specified by a shape object, because otherwise we could not control
    01487     the range simultaneously in all dimensions (this is a necessary consequence
    01488     of the \ref vigra::MultiIterator design).
    01489
    01490     <b> Declarations:</b>
    01491
    01492     pass arguments explicitly:
    01493     \code
    01494     namespace vigra {
    01495         template <class Iterator1, class Shape, class Accessor1,
    01496                   class Iterator2, class Accessor2,
    01497                   class Functor>
    01498         void
    01499         inspectTwoMultiArrays(Iterator1 s1, Shape const & shape, Accessor1 a1,
    01500                               Iterator2 s2, Accessor2 a2, Functor & f);
    01501     }
    01502     \endcode
    01503
    01504     use argument objects in conjunction with \ref ArgumentObjectFactories:
    01505     \code
    01506     namespace vigra {
    01507         template <class Iterator1, class Shape1, class Accessor1,
    01508                   class Iterator2, class Accessor2,
    01509                   class Functor>
    01510         void
    01511         inspectTwoMultiArrays(triple<Iterator1, Shape1, Accessor1> const & s1,
    01512                               pair<Iterator2, Accessor2> const & s2, Functor & f);
    01513     }
    01514     \endcode
    01515
    01516     <b> Usage:</b>
    01517
    01518     <b>\#include</b> "<a href="multi__pointoperators_8hxx-source.html">vigra/multi_pointoperators.hxx</a>"<br>
    01519     Namespace: vigra
    01520
    01521     \code
    01522     typedef vigra::MultiArray<3, int> Array;
    01523     Array array1(Array::size_type(100, 200, 50)),
    01524           array2(Array::size_type(100, 200, 50));
    01525
    01526     // init functor
    01527     SomeStatisticsFunctor stats(..);
    01528
    01529     vigra::inspectTwoMultiArrays(srcMultiArrayRange(array1), srcMultiArray(array2), stats);
    01530
    01531     \endcode
    01532
    01533     <b> Required Interface:</b>
    01534
    01535     \code
    01536     MultiIterator src1_begin, src2_begin;
    01537
    01538     Accessor a1, a2;
    01539     Functor functor;
    01540
    01541     functor(a1(src1_begin), a2(src2_begin));
    01542     \endcode
    01543
    01544 */
    01545 template <class Iterator1, class Shape, class Accessor1,
    01546           class Iterator2, class Accessor2,
    01547           class Functor>
    01548 inline void
    01549 inspectTwoMultiArrays(Iterator1 s1, Shape const & shape, Accessor1 a1,
    01550                       Iterator2 s2, Accessor2 a2, Functor & f)
    01551 {
    01552     inspectTwoMultiArraysImpl(s1, shape, a1, s2, a2, f, MetaInt<Iterator1::level>());
    01553 }
    01554
    01555 template <class Iterator1, class Shape, class Accessor1,
    01556           class Iterator2, class Accessor2,
    01557           class Functor>
    01558 inline
    01559 void
    01560 inspectTwoMultiArrays(triple<Iterator1, Shape, Accessor1> const & s1,
    01561                       pair<Iterator2, Accessor2> const & s2, Functor & f)
    01562 {
    01563     inspectTwoMultiArrays(s1.first, s1.second, s1.third,
    01564                           s2.first, s2.second, f);
    01565 }
    01566
    01567 //@}
    01568
    01569 };  //-- namespace vigra
    01570
    01571
    01572 #endif  //-- VIGRA_MULTI_POINTOPERATORS_H

© Ullrich Köthe (koethe@informatik.uni-hamburg.de) Cognitive Systems Group, University of Hamburg, Germany | html generated using doxygen and Python VIGRA 1.3.2 (27 Jan 2005)