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