VIGRA - VIGRA: vigra/multi_pointoperators.hxx Source File

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