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

details vigra/multi_pointoperators.hxx VIGRA

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

© Ullrich Köthe (koethe@informatik.uni-hamburg.de)
Cognitive Systems Group, University of Hamburg, Germany

html generated using doxygen and Python
VIGRA 1.3.3 (18 Aug 2005)