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