VIGRA - vigra/multi_pointoperators.hxx Source File

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