[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]
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) |
html generated using doxygen and Python
|