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

vigra/multi_pointoperators.hxx

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

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
VIGRA 1.6.0 (13 Aug 2008)