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