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