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

vigra/multi_pointoperators.hxx |

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

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python vigra 1.7.1 (3 Dec 2010)