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

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

html generated using doxygen and Python
VIGRA 1.4.0 (21 Dec 2005)