vigra - vigra/multi_pointoperators.hxx Source File

[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

multi_pointoperators.hxx |

1 //-- -*- c++ -*-
2 /************************************************************************/
3 /* */
4 /* Copyright 2003 by Ullrich Koethe, B. Seppke, F. Heinrich */
5 /* */
6 /* This file is part of the VIGRA computer vision library. */
7 /* The VIGRA Website is */
8 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
9 /* Please direct questions, bug reports, and contributions to */
10 /* ullrich.koethe@iwr.uni-heidelberg.de or */
11 /* vigra@informatik.uni-hamburg.de */
12 /* */
13 /* Permission is hereby granted, free of charge, to any person */
14 /* obtaining a copy of this software and associated documentation */
15 /* files (the "Software"), to deal in the Software without */
16 /* restriction, including without limitation the rights to use, */
17 /* copy, modify, merge, publish, distribute, sublicense, and/or */
18 /* sell copies of the Software, and to permit persons to whom the */
19 /* Software is furnished to do so, subject to the following */
20 /* conditions: */
21 /* */
22 /* The above copyright notice and this permission notice shall be */
23 /* included in all copies or substantial portions of the */
24 /* Software. */
25 /* */
26 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
27 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
28 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
29 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
30 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
31 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
32 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
33 /* OTHER DEALINGS IN THE SOFTWARE. */
34 /* */
35 /************************************************************************/
36
37 #ifndef VIGRA_MULTI_POINTOPERATORS_H
38 #define VIGRA_MULTI_POINTOPERATORS_H
39
40 #include "initimage.hxx"
41 #include "copyimage.hxx"
42 #include "transformimage.hxx"
43 #include "combineimages.hxx"
44 #include "inspectimage.hxx"
45 #include "multi_array.hxx"
46 #include "metaprogramming.hxx"
47 #include "inspector_passes.hxx"
48
49
50
51 namespace vigra
52 {
53
54 /** \addtogroup MultiPointoperators Point operators for multi-dimensional arrays.
55
56 Copy, transform, and inspect arbitrary dimensional arrays which are represented
57 by iterators compatible to \ref MultiIteratorPage. Note that are range is here
58 specified by a pair: an iterator referring to the first point of the array
59 and a shape object specifying the size of the (rectangular) ROI.
60
61 <b>\#include</b> <vigra/multi_pointoperators.hxx><br/>
62 Namespace: vigra
63 */
64 //@{
65
66 /********************************************************/
67 /* */
68 /* initMultiArray */
69 /* */
70 /********************************************************/
71
72 template <class Iterator, class Shape, class Accessor,
73 class VALUETYPE>
74 inline void
75 initMultiArrayImpl(Iterator s, Shape const & shape, Accessor a, VALUETYPE const & v, MetaInt<0>)
76 {
77 initLine(s, s + shape[0], a, v);
78 }
79
80 template <class Iterator, class Shape, class Accessor,
81 class VALUETYPE, int N>
82 void
83 initMultiArrayImpl(Iterator s, Shape const & shape, Accessor a,
84 VALUETYPE const & v, MetaInt<N>)
85 {
86 Iterator send = s + shape[N];
87 for(; s < send; ++s)
88 {
89 initMultiArrayImpl(s.begin(), shape, a, v, MetaInt<N-1>());
90 }
91 }
92
93 /** \brief Write a value to every element in a multi-dimensional array.
94
95 The initial value can either be a constant of appropriate type (compatible with
96 the destination's value_type), or a functor with compatible result_type. These two
97 cases are automatically distinguished when <tt>FunctorTraits<FUNCTOR>::isInitializer</tt>
98 yields <tt>VigraTrueType</tt>. Since the functor is passed by <tt>const</tt> reference, its
99 <tt>operator()</tt> must be const, and its internal state may need to be <tt>mutable</tt>.
100
101 <b> Declarations:</b>
102
103 pass arbitrary-dimensional array views:
104 \code
105 namespace vigra {
106 template <unsigned int N, class T, class S, class VALUETYPE>
107 void
108 initMultiArray(MultiArrayView<N, T, S> s, VALUETYPE const & v);
109
110 template <unsigned int N, class T, class S, class FUNCTOR>
111 void
112 initMultiArray(MultiArrayView<N, T, S> s, FUNCTOR const & f);
113 }
114 \endcode
115
116 \deprecatedAPI{initMultiArray}
117 pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors :
118 \code
119 namespace vigra {
120 template <class Iterator, class Shape, class Accessor, class VALUETYPE>
121 void
122 initMultiArray(Iterator s, Shape const & shape, Accessor a, VALUETYPE const & v);
123
124 template <class Iterator, class Shape, class Accessor, class FUNCTOR>
125 void
126 initMultiArray(Iterator s, Shape const & shape, Accessor a, FUNCTOR const & f);
127 }
128 \endcode
129 use argument objects in conjunction with \ref ArgumentObjectFactories :
130 \code
131 namespace vigra {
132 template <class Iterator, class Shape, class Accessor, class VALUETYPE>
133 void
134 initMultiArray(triple<Iterator, Shape, Accessor> const & s, VALUETYPE const & v);
135
136
137 template <class Iterator, class Shape, class Accessor, class FUNCTOR>
138 void
139 initMultiArray(triple<Iterator, Shape, Accessor> const & s, FUNCTOR const & f);
140 }
141 \endcode
142 \deprecatedEnd
143
144 <b> Usage:</b>
145
146 <b>\#include</b> <vigra/multi_pointoperators.hxx><br>
147 Namespace: vigra
148
149 \code
150 MultiArray<3, unsigned int> array(Shape3(100, 200, 50));
151
152 // make an array of all ones
153 initMultiArray(array, 1);
154
155 // equivalent calls:
156 array = 1;
157 array.init(1);
158
159 // fill the array with random numbers
160 #include <vigra/random.hxx>
161
162 initMultiArray(array, MersenneTwister());
163 \endcode
164
165 \deprecatedUsage{initMultiArray}
166 \code
167 MultiArray<3, int> array(Shape3(100, 200, 50));
168
169 // make an array of all twos
170 vigra::initMultiArray(destMultiArrayRange(array), 2);
171 \endcode
172 <b> Required Interface:</b>
173 The function accepts either a value that is copied into every destination element:
174 \code
175 MultiIterator begin;
176
177 Accessor accessor;
178 VALUETYPE v;
179
180 accessor.set(v, begin);
181 \endcode
182 or a functor that is called (without argument) at every location,
183 and the result is written into the current element. Internally,
184 functors are recognized by the meta function
185 <tt>FunctorTraits<FUNCTOR>::isInitializer</tt> yielding <tt>VigraTrueType</tt>.
186 Make sure that your functor correctly defines <tt>FunctorTraits</tt> because
187 otherwise the code will not compile.
188 \code
189 MultiIterator begin;
190 Accessor accessor;
191
192 FUNCTOR f;
193 assert(typeid(FunctorTraits<FUNCTOR>::isInitializer) == typeid(VigraTrueType));
194
195 accessor.set(f(), begin);
196 \endcode
197 \deprecatedEnd
198 */
199 doxygen_overloaded_function(template <...> void initMultiArray)
200
201 template <class Iterator, class Shape, class Accessor, class VALUETYPE>
202 inline void
203 initMultiArray(Iterator s, Shape const & shape, Accessor a, VALUETYPE const & v)
204 {
205 initMultiArrayImpl(s, shape, a, v, MetaInt<Iterator::level>());
206 }
207
208 template <class Iterator, class Shape, class Accessor, class VALUETYPE>
209 inline void
210 initMultiArray(triple<Iterator, Shape, Accessor> const & s, VALUETYPE const & v)
211 {
212 initMultiArrayImpl(s.first, s.second, s.third, v, MetaInt<Iterator::level>());
213 }
214
215 template <unsigned int N, class T, class S, class VALUETYPE>
216 inline void
217 initMultiArray(MultiArrayView<N, T, S> s, VALUETYPE const & v)
218 {
219 initMultiArray(destMultiArrayRange(s), v);
220 }
221
222 /********************************************************/
223 /* */
224 /* initMultiArrayBorder */
225 /* */
226 /********************************************************/
227
228 /** \brief Write values to the specified border values in the array.
229
230 This functions is similar to \ref initMultiArray(), but it initializes only
231 the array elements whose distance from any array border is at most \a border_width.
232
233 <b> Declarations:</b>
234
235 pass arbitrary-dimensional array views:
236 \code
237 namespace vigra {
238 // init equal borders on all array sides
239 template <unsigned int N, class T, class S,
240 class VALUETYPE>
241 void
242 initMultiArrayBorder( MultiArrayView<N, T, S> array,
243 MultiArrayIndex border_width, VALUETYPE const & v);
244
245 template <unsigned int N, class T, class S,
246 class FUNCTOR>
247 void
248 initMultiArrayBorder( MultiArrayView<N, T, S> array,
249 MultiArrayIndex border_width, FUNCTOR const & v);
250
251 // specify border width individually for all array sides
252 template <unsigned int N, class T, class S,
253 class VALUETYPE>
254 void
255 initMultiArrayBorder( MultiArrayView<N, T, S> array,
256 typename MultiArrayShape<N>::type const & lower_border,
257 typename MultiArrayShape<N>::type const & upper_border,
258 VALUETYPE const & v);
259 }
260 \endcode
261
262 \deprecatedAPI{initMultiArrayBorder}
263 pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors :
264 \code
265 namespace vigra {
266 template <class Iterator, class Diff_type, class Accessor,
267 class VALUETYPE>
268 void
269 initMultiArrayBorder(Iterator upperleft, Diff_type shape, Accessor a,
270 MultiArrayIndex border_width, VALUETYPE const & v);
271 }
272 \endcode
273 use argument objects in conjunction with \ref ArgumentObjectFactories :
274 \code
275 namespace vigra {
276 template <class Iterator, class Diff_type, class Accessor,
277 class VALUETYPE>
278 inline void
279 initMultiArrayBorder( triple<Iterator, Diff_type, Accessor> multiArray,
280 MultiArrayIndex border_width, VALUETYPE const & v);
281 }
282 \endcode
283 \deprecatedEnd
284
285 <b> Usage:</b>
286
287 <b>\#include</b> <vigra/multi_pointoperators.hxx><br>
288 Namespace: vigra
289
290 \code
291 MultiArray<3, unsigned int> array(Shape3(100, 200, 50));
292
293 int border_width = 5;
294
295 // init the array interior to 1, the border to 2
296 initMultiArray(array.subarray(Shape3(border_width), Shape3(-border_width)), 1);
297 initMultiArrayBorder(array, border_width, 2);
298 \endcode
299 */
300 doxygen_overloaded_function(template <...> void initMultiArrayBorder)
301
302 template <class Iterator, class Diff_type, class Accessor,
303 class VALUETYPE>
304 void
305 initMultiArrayBorder(Iterator upperleft, Diff_type shape, Accessor a,
306 Diff_type lower_border, Diff_type upper_border,
307 VALUETYPE const & v)
308 {
309 for(unsigned int dim=0; dim<shape.size(); dim++)
310 {
311 lower_border[dim] = (lower_border[dim] > shape[dim]) ? shape[dim] : lower_border[dim];
312 upper_border[dim] = (upper_border[dim] > shape[dim]) ? shape[dim] : upper_border[dim];
313 }
314
315 for(unsigned int dim=0; dim<shape.size(); dim++)
316 {
317 Diff_type start,
318 offset(shape);
319 offset[dim] = lower_border[dim];
320
321 initMultiArray(upperleft+start, offset, a, v);
322
323 start[dim] = shape[dim] - upper_border[dim];
324 offset[dim] = upper_border[dim];
325 initMultiArray(upperleft+start, offset, a, v);
326 }
327 }
328
329 template <class Iterator, class Diff_type, class Accessor,
330 class VALUETYPE>
331 inline void
332 initMultiArrayBorder(Iterator upperleft, Diff_type shape, Accessor a,
333 MultiArrayIndex border_width, VALUETYPE const & v)
334 {
335 initMultiArrayBorder(upperleft, shape, a,
336 Diff_type(border_width), Diff_type(border_width), v);
337 }
338
339 template <class Iterator, class Diff_type, class Accessor,
340 class VALUETYPE>
341 inline void
342 initMultiArrayBorder( triple<Iterator, Diff_type, Accessor> multiArray,
343 MultiArrayIndex border_width, VALUETYPE const & v)
344 {
345 initMultiArrayBorder(multiArray.first, multiArray.second, multiArray.third, border_width, v);
346 }
347
348 template <class Iterator, class Diff_type, class Accessor,
349 class VALUETYPE>
350 inline void
351 initMultiArrayBorder( triple<Iterator, Diff_type, Accessor> multiArray,
352 Diff_type const & lower_border, Diff_type const & upper_border,
353 VALUETYPE const & v)
354 {
355 initMultiArrayBorder(multiArray.first, multiArray.second, multiArray.third,
356 lower_border, upper_border, v);
357 }
358
359 template <unsigned int N, class T, class S,
360 class VALUETYPE>
361 inline void
362 initMultiArrayBorder( MultiArrayView<N, T, S> array,
363 MultiArrayIndex border_width, VALUETYPE const & v)
364 {
365 initMultiArrayBorder(destMultiArrayRange(array), border_width, v);
366 }
367
368 template <unsigned int N, class T, class S,
369 class VALUETYPE>
370 inline void
371 initMultiArrayBorder( MultiArrayView<N, T, S> array,
372 typename MultiArrayShape<N>::type const & lower_border,
373 typename MultiArrayShape<N>::type const & upper_border,
374 VALUETYPE const & v)
375 {
376 initMultiArrayBorder(destMultiArrayRange(array), lower_border, upper_border, v);
377 }
378
379 /********************************************************/
380 /* */
381 /* copyMultiArray */
382 /* */
383 /********************************************************/
384
385 template <class SrcIterator, class SrcShape, class SrcAccessor,
386 class DestIterator, class DestShape, class DestAccessor>
387 void
388 copyMultiArrayImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
389 DestIterator d, DestShape const & dshape, DestAccessor dest, MetaInt<0>)
390 {
391 if(sshape[0] == 1)
392 {
393 initLine(d, d + dshape[0], dest, src(s));
394 }
395 else
396 {
397 copyLine(s, s + sshape[0], src, d, dest);
398 }
399 }
400
401 template <class SrcIterator, class SrcShape, class SrcAccessor,
402 class DestIterator, class DestShape, class DestAccessor, int N>
403 void
404 copyMultiArrayImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
405 DestIterator d, DestShape const & dshape, DestAccessor dest, MetaInt<N>)
406 {
407 DestIterator dend = d + dshape[N];
408 if(sshape[N] == 1)
409 {
410 for(; d < dend; ++d)
411 {
412 copyMultiArrayImpl(s.begin(), sshape, src, d.begin(), dshape, dest, MetaInt<N-1>());
413 }
414 }
415 else
416 {
417 for(; d < dend; ++s, ++d)
418 {
419 copyMultiArrayImpl(s.begin(), sshape, src, d.begin(), dshape, dest, MetaInt<N-1>());
420 }
421 }
422 }
423
424 /** \brief Copy a multi-dimensional array.
425
426 This function can be applied in two modes:
427
428 <DL>
429 <DT><b>Standard Mode:</b>
430 <DD>If the source and destination arrays have the same size,
431 the corresponding array elements are simply copied.
432 If necessary, type conversion takes place.
433 <DT><b>Expanding Mode:</b>
434 <DD>If the source array has length 1 along some (or even all) dimensions,
435 the source value at index 0 is used for all destination
436 elements in those dimensions. For example, if we have single row of data
437 (column length is 1), we can copy it into a 2D image of the same width:
438 The given row is automatically repeated for every row of the destination image.
439 Again, type conversion os performed if necessary.
440 </DL>
441
442 The arrays must be represented by
443 iterators compatible with \ref vigra::MultiIterator, and the iteration range
444 is specified by means of shape objects. If only the source shape is given
445 the destination array is assumed to have the same shape, and standard mode
446 is applied. If two shapes are given, the size of corresponding dimensions
447 must be either equal (standard copy), or the source length must be 1
448 (expanding copy).
449
450 <b> Declarations:</b>
451
452 <b>\#include</b> <vigra/multi_pointoperators.hxx><br>
453 Namespace: vigra
454
455 pass arbitrary-dimensional array views:
456 \code
457 namespace vigra {
458 template <unsigned int N, class T1, class S1,
459 class T2, class S2>
460 void
461 copyMultiArray(MultiArrayView<N, T1, S1> const & source,
462 MultiArrayView<N, T2, S2> dest);
463 }
464 \endcode
465
466 \deprecatedAPI{copyMultiArray}
467 pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors :
468 \code
469 namespace vigra {
470 template <class SrcIterator, class SrcShape, class SrcAccessor,
471 class DestIterator, class DestAccessor>
472 void
473 copyMultiArray(SrcIterator s,
474 SrcShape const & shape, SrcAccessor src,
475 DestIterator d, DestAccessor dest);
476
477
478 template <class SrcIterator, class SrcShape, class SrcAccessor,
479 class DestIterator, class DestShape, class DestAccessor>
480 void
481 copyMultiArray(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
482 DestIterator d, DestShape const & dshape, DestAccessor dest);
483 }
484 \endcode
485 use argument objects in conjunction with \ref ArgumentObjectFactories :
486 \code
487 namespace vigra {
488 template <class SrcIterator, class SrcShape, class SrcAccessor,
489 class DestIterator, class DestAccessor>
490 void
491 copyMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
492 pair<DestIterator, DestAccessor> const & dest);
493
494
495 template <class SrcIterator, class SrcShape, class SrcAccessor,
496 class DestIterator, class DestShape, class DestAccessor>
497 void
498 copyMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
499 triple<DestIterator, DestShape, DestAccessor> const & dest);
500 }
501 \endcode
502 \deprecatedEnd
503
504 <b> Usage - Standard Mode:</b>
505
506 \code
507 MultiArray<3, int> src(Shape3(100, 200, 50)),
508 dest(Shape3(100, 200, 50));
509 ...
510
511 copyMultiArray(src, dest);
512
513 // equivalent to
514 dest = src;
515
516 // copy only the red channel (i.e. channl 0) of an RGB array
517 MultiArray<3, RGBValue<int> > rgb_src(Shape3(100, 200, 50));
518
519 copyMultiArray(rgb_src.bindElementChannel(0), dest);
520
521 // equivalent to
522 dest = rgb_src.bindElementChannel(0);
523 \endcode
524
525 <b> Usage - Expanding Mode:</b>
526
527 The source array is effectively only a 2D image (it has a 3D shape, but 'depth' is a
528 singleton dimension with length 1). Thus, the destination will contain 50 identical
529 copies of this image:
530
531 \code
532 MultiArray<3, int> src(Shape2(100, 200)),
533 dest(Shape3(100, 200, 50));
534 ...
535
536 copyMultiArray(src.insertSingletonDimension(2), dest);
537
538 // create an RGB image with three identical color bands
539 MultiArray<3, RGBValue<int> > rgb_dest(Shape2(100, 200));
540
541 copyMultiArray(src.insertSingletonDimension(2), rgb_dest.expandElements(2));
542 \endcode
543
544 \deprecatedUsage{copyMultiArray}
545 \code
546 typedef vigra::MultiArray<3, int> Array;
547 Array src(Array::size_type(100, 200, 50)),
548 dest(Array::size_type(100, 200, 50));
549 ...
550
551 vigra::copyMultiArray(srcMultiArrayRange(src), destMultiArray(dest));
552 \endcode
553 <b> Required Interface:</b>
554 \code
555 MultiIterator src_begin, dest_begin;
556
557 SrcAccessor src_accessor;
558 DestAccessor dest_accessor;
559
560 dest_accessor.set(src_accessor(src_begin), dest_begin);
561 \endcode
562 \deprecatedEnd
563 */
564 doxygen_overloaded_function(template <...> void copyMultiArray)
565
566 template <class SrcIterator, class SrcShape, class SrcAccessor,
567 class DestIterator, class DestAccessor>
568 inline void
569 copyMultiArray(SrcIterator s,
570 SrcShape const & shape, SrcAccessor src,
571 DestIterator d, DestAccessor dest)
572 {
573 copyMultiArrayImpl(s, shape, src, d, shape, dest, MetaInt<SrcIterator::level>());
574 }
575
576 template <class SrcIterator, class SrcShape, class SrcAccessor,
577 class DestIterator, class DestShape, class DestAccessor>
578 void
579 copyMultiArray(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
580 DestIterator d, DestShape const & dshape, DestAccessor dest)
581 {
582 vigra_precondition(sshape.size() == dshape.size(),
583 "copyMultiArray(): dimensionality of source and destination array differ");
584 for(unsigned int i=0; i<sshape.size(); ++i)
585 vigra_precondition(sshape[i] == 1 || sshape[i] == dshape[i],
586 "copyMultiArray(): mismatch between source and destination shapes:\n"
587 "length of each source dimension must either be 1 or equal to the corresponding "
588 "destination length.");
589 copyMultiArrayImpl(s, sshape, src, d, dshape, dest, MetaInt<SrcIterator::level>());
590 }
591
592 template <class SrcIterator, class SrcShape, class SrcAccessor,
593 class DestIterator, class DestAccessor>
594 inline void
595 copyMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
596 pair<DestIterator, DestAccessor> const & dest)
597 {
598
599 copyMultiArray(src.first, src.second, src.third, dest.first, dest.second);
600 }
601
602 template <class SrcIterator, class SrcShape, class SrcAccessor,
603 class DestIterator, class DestShape, class DestAccessor>
604 inline void
605 copyMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
606 triple<DestIterator, DestShape, DestAccessor> const & dest)
607 {
608
609 copyMultiArray(src.first, src.second, src.third, dest.first, dest.second, dest.third);
610 }
611
612 template <unsigned int N, class T1, class S1,
613 class T2, class S2>
614 inline void
615 copyMultiArray(MultiArrayView<N, T1, S1> const & source,
616 MultiArrayView<N, T2, S2> dest)
617 {
618 for(unsigned k=0; k<N; ++k)
619 vigra_precondition(source.shape(k) == dest.shape(k) || source.shape(k) == 1 || 1 == dest.shape(k),
620 "copyMultiArray(): shape mismatch between input and output.");
621 if(source.shape() == dest.shape())
622 copyMultiArray(srcMultiArrayRange(source), destMultiArray(dest));
623 else
624 copyMultiArray(srcMultiArrayRange(source), destMultiArrayRange(dest));
625 }
626
627 /********************************************************/
628 /* */
629 /* transformMultiArray */
630 /* */
631 /********************************************************/
632
633 template <class SrcIterator, class SrcShape, class SrcAccessor,
634 class DestIterator, class DestShape, class DestAccessor,
635 class Functor>
636 void
637 transformMultiArrayReduceImpl(SrcIterator s, SrcShape const &, SrcAccessor src,
638 DestIterator d, DestShape const & dshape, DestAccessor dest,
639 SrcShape const & reduceShape,
640 Functor const & ff, MetaInt<0>)
641 {
642 DestIterator dend = d + dshape[0];
643 for(; d < dend; ++s.template dim<0>(), ++d)
644 {
645 Functor f = ff;
646 inspectMultiArray(s, reduceShape, src, f);
647 dest.set(f(), d);
648 }
649 }
650
651 template <class SrcIterator, class SrcShape, class SrcAccessor,
652 class DestIterator, class DestShape, class DestAccessor,
653 class Functor, int N>
654 void
655 transformMultiArrayReduceImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
656 DestIterator d, DestShape const & dshape, DestAccessor dest,
657 SrcShape const & reduceShape,
658 Functor const & f, MetaInt<N>)
659 {
660 DestIterator dend = d + dshape[N];
661 for(; d < dend; ++s.template dim<N>(), ++d)
662 {
663 transformMultiArrayReduceImpl(s, sshape, src, d.begin(), dshape, dest,
664 reduceShape, f, MetaInt<N-1>());
665 }
666 }
667
668 template <class SrcIterator, class SrcShape, class SrcAccessor,
669 class DestIterator, class DestShape, class DestAccessor,
670 class Functor>
671 void
672 transformMultiArrayImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
673 DestIterator d, DestShape const & dshape, DestAccessor dest,
674 Functor const & f, VigraTrueType)
675 {
676 // reduce mode
677 SrcShape reduceShape = sshape;
678 for(unsigned int i=0; i<dshape.size(); ++i)
679 {
680 vigra_precondition(dshape[i] == 1 || sshape[i] == dshape[i],
681 "transformMultiArray(): mismatch between source and destination shapes:\n"
682 "In 'reduce'-mode, the length of each destination dimension must either be 1\n"
683 "or equal to the corresponding source length.");
684 if(dshape[i] != 1)
685 reduceShape[i] = 1;
686 }
687 transformMultiArrayReduceImpl(s, sshape, src, d, dshape, dest, reduceShape,
688 f, MetaInt<SrcIterator::level>());
689 }
690
691 template <class SrcIterator, class SrcShape, class SrcAccessor,
692 class DestIterator, class DestShape, class DestAccessor,
693 class Functor>
694 void
695 transformMultiArrayExpandImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
696 DestIterator d, DestShape const & dshape, DestAccessor dest,
697 Functor const & f, MetaInt<0>)
698 {
699 if(sshape[0] == 1)
700 {
701 initLine(d, d + dshape[0], dest, f(src(s)));
702 }
703 else
704 {
705 transformLine(s, s + sshape[0], src, d, dest, f);
706 }
707 }
708
709 template <class SrcIterator, class SrcShape, class SrcAccessor,
710 class DestIterator, class DestShape, class DestAccessor,
711 class Functor, int N>
712 void
713 transformMultiArrayExpandImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
714 DestIterator d, DestShape const & dshape, DestAccessor dest,
715 Functor const & f, MetaInt<N>)
716 {
717 DestIterator dend = d + dshape[N];
718 if(sshape[N] == 1)
719 {
720 for(; d < dend; ++d)
721 {
722 transformMultiArrayExpandImpl(s.begin(), sshape, src, d.begin(), dshape, dest,
723 f, MetaInt<N-1>());
724 }
725 }
726 else
727 {
728 for(; d < dend; ++s, ++d)
729 {
730 transformMultiArrayExpandImpl(s.begin(), sshape, src, d.begin(), dshape, dest,
731 f, MetaInt<N-1>());
732 }
733 }
734 }
735
736 template <class SrcIterator, class SrcShape, class SrcAccessor,
737 class DestIterator, class DestShape, class DestAccessor,
738 class Functor>
739 void
740 transformMultiArrayImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
741 DestIterator d, DestShape const & dshape, DestAccessor dest,
742 Functor const & f, VigraFalseType)
743 {
744 // expand mode
745 for(unsigned int i=0; i<sshape.size(); ++i)
746 vigra_precondition(sshape[i] == 1 || sshape[i] == dshape[i],
747 "transformMultiArray(): mismatch between source and destination shapes:\n"
748 "In 'expand'-mode, the length of each source dimension must either be 1\n"
749 "or equal to the corresponding destination length.");
750 transformMultiArrayExpandImpl(s, sshape, src, d, dshape, dest,
751 f, MetaInt<SrcIterator::level>());
752 }
753
754 /** \brief Transform a multi-dimensional array with a unary function or functor.
755
756 Note: The effect of this function can often be achieved in a simpler and
757 more readable way by means of \ref MultiMathModule "array expressions".
758
759 This function can be applied in three modes:
760
761 <DL>
762 <DT><b>Standard Mode:</b>
763 <DD>If the source and destination arrays have the same size,
764 the transformation given by the functor is applied to every source
765 element and the result written into the corresponding destination element.
766 Unary functions, unary functors from the STL and the functors specifically
767 defined in \ref TransformFunctor can be used in standard mode.
768 Creation of new functors is easiest by using \ref FunctorExpressions.
769 <DT><b>Expanding Mode:</b>
770 <DD>If the source array has length 1 along some (or even all) dimensions,
771 the source value at index 0 is used for all destination
772 elements in those dimensions. In other words, the source index is not
773 incremented along these dimensions, but the transformation functor
774 is applied as usual. So, we can expand a small array (e.g. a single row of data,
775 column length is 1), into a larger one (e.g. a 2D image with the same width):
776 the given values are simply reused as necessary (e.g. for every row of the
777 destination image). The same functors as in standard mode can be applied.
778 <DT><b>Reducing Mode:</b>
779 <DD>If the destination array has length 1 along some (or even all) dimensions,
780 the source values in these dimensions are reduced to single values by means
781 of a suitable functor (e.g. \ref vigra::ReduceFunctor), which supports two
782 function call operators: one
783 with a single argument to collect the values, and without argument to
784 obtain the final (reduced) result. This behavior is a multi-dimensional
785 generalization of the C++ standard function <tt>std::accumulate()</tt>.
786 </DL>
787
788 The arrays must be represented by MultiArrayViews. If source and destination shapes
789 match, standard mode is applied. If the shapes differ, the size of corresponding
790 dimensions must either be equal, or the source length must be 1
791 (expand mode), or the destination length must be 1 (reduce mode). However,
792 reduction and expansion cannot be executed at the same time, so the latter
793 conditions are mutual exclusive, even if they apply to different dimensions.
794
795 <b> Declarations:</b>
796
797 <b>\#include</b> <vigra/multi_pointoperators.hxx><br>
798 Namespace: vigra
799
800 pass arbitrary-dimensional array views:
801 \code
802 namespace vigra {
803 template <unsigned int N, class T1, class S1,
804 class T2, class S2,
805 class Functor>
806 void
807 transformMultiArray(MultiArrayView<N, T1, S1> const & source,
808 MultiArrayView<N, T2, S2> dest, Functor const & f);
809 }
810 \endcode
811
812 \deprecatedAPI{transformMultiArray}
813 pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors :
814 \code
815 namespace vigra {
816 template <class SrcIterator, class SrcShape, class SrcAccessor,
817 class DestIterator, class DestAccessor,
818 class Functor>
819 void
820 transformMultiArray(SrcIterator s, SrcShape const & shape, SrcAccessor src,
821 DestIterator d, DestAccessor dest, Functor const & f);
822
823
824 template <class SrcIterator, class SrcShape, class SrcAccessor,
825 class DestIterator, class DestShape, class DestAccessor,
826 class Functor>
827 void
828 transformMultiArray(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
829 DestIterator d, DestShape const & dshape, DestAccessor dest,
830 Functor const & f);
831 }
832 \endcode
833 use argument objects in conjunction with \ref ArgumentObjectFactories :
834 \code
835 namespace vigra {
836 template <class SrcIterator, class SrcShape, class SrcAccessor,
837 class DestIterator, class DestAccessor,
838 class Functor>
839 void
840 transformMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
841 pair<DestIterator, DestAccessor> const & dest, Functor const & f);
842
843
844 template <class SrcIterator, class SrcShape, class SrcAccessor,
845 class DestIterator, class DestShape, class DestAccessor,
846 class Functor>
847 void
848 transformMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
849 triple<DestIterator, DestShape, DestAccessor> const & dest,
850 Functor const & f)
851 }
852 \endcode
853 \deprecatedEnd
854
855 <b> Usage - Standard Mode:</b>
856
857 Source and destination array have the same size.
858
859 \code
860 #include <cmath> // for sqrt()
861
862 MultiArray<3, float> src(Shape3(100, 200, 50)),
863 dest(Shape3(100, 200, 50));
864 ...
865
866 transformMultiArray(src, dest, &std::sqrt );
867 \endcode
868
869 <b> Usage - Expand Mode:</b>
870
871 The source array is effectively only a 2D image(it has a 3D shape, but depth is a singleton dimension
872 with length 1). Thus, the destination will contain 50 identical copies of the transformed source image.
873
874 \code
875 #include <cmath> // for sqrt()
876
877 MultiArray<3, float> src(Shape3(100, 200, 1)),
878 dest(Shape3(100, 200, 50));
879 ...
880
881 transformMultiArray(src, dest, &std::sqrt );
882 \endcode
883
884 <b> Usage - Reduce Mode:</b>
885
886 The destination array is effectively only 1D (it's width and height are singleton dimensions).
887 Thus, it will contain accumulated data for every slice of the source volume
888 (or for every frame, if the source is interpreted as an image sequence).
889 In the example, we use the functor \ref vigra::FindAverage to calculate
890 the average gray value of every slice.
891
892 \code
893 MultiArray<3, float> src(Shape3(100, 200, 50)),
894 dest(Shape3(1, 1, 50));
895 ...
896
897 transformMultiArray(src, dest,
898 FindAverage<float>() );
899 \endcode
900
901 Note that the functor must define the appropriate traits described below in order to be
902 recognized as a reduce functor. This is most easily achieved by deriving from
903 <tt>UnaryReduceFunctorTag</tt> (see \ref vigra::FunctorTraits).
904
905 \deprecatedUsage{transformMultiArray}
906 \code
907 #include <cmath> // for sqrt()
908
909 typedef vigra::MultiArray<3, float> Array;
910 Array src(Shape3(100, 200, 50)),
911 dest(Shape3(100, 200, 50));
912 ...
913
914 vigra::transformMultiArray(srcMultiArrayRange(src),
915 destMultiArray(dest),
916 (float(*)(float))&std::sqrt );
917
918 \endcode
919 \deprecatedEnd
920
921 <b> Required Interface:</b>
922
923 In standard and expand mode, the functor must be a model of UnaryFunction
924 (i.e. support one-argument function call which accepts values of type
925 <tt>T1</tt> and a return value that is convertible into <tt>T2</tt>.
926
927 In reduce mode, it must be a model of UnaryAnalyser (i.e. support function call
928 with one argument and no return value <tt>functor(arg)</tt>) and Initializer
929 (i.e. support function call with no argument, but return value
930 <tt>res = functor()</tt>). Internally, such functors are recognized by the
931 meta functions <tt>FunctorTraits<FUNCTOR>::isUnaryAnalyser</tt> and
932 <tt>FunctorTraits<FUNCTOR>::isInitializer</tt> which must both yield
933 <tt>VigraTrueType</tt>. Make sure that your functor correctly defines
934 <tt>FunctorTraits</tt> because otherwise reduce mode will not work.
935 This is most easily achieved by deriving the functor from
936 <tt>UnaryReduceFunctorTag</tt> (see \ref vigra::FunctorTraits).
937 In addition, the functor must be copy constructible in order to start each reduction
938 with a fresh functor.
939
940 \see TransformFunctor, MultiMathModule, \ref FunctorExpressions
941 */
942 doxygen_overloaded_function(template <...> void transformMultiArray)
943
944 template <class SrcIterator, class SrcShape, class SrcAccessor,
945 class DestIterator, class DestAccessor,
946 class Functor>
947 inline void
948 transformMultiArray(SrcIterator s, SrcShape const & shape, SrcAccessor src,
949 DestIterator d, DestAccessor dest, Functor const & f)
950 {
951 transformMultiArrayExpandImpl(s, shape, src, d, shape, dest,
952 f, MetaInt<SrcIterator::level>());
953 }
954
955 template <class SrcIterator, class SrcShape, class SrcAccessor,
956 class DestIterator, class DestShape, class DestAccessor,
957 class Functor>
958 void
959 transformMultiArray(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
960 DestIterator d, DestShape const & dshape, DestAccessor dest,
961 Functor const & f)
962 {
963 vigra_precondition(sshape.size() == dshape.size(),
964 "transformMultiArray(): dimensionality of source and destination array differ");
965 typedef FunctorTraits<Functor> FT;
966 typedef typename
967 And<typename FT::isInitializer, typename FT::isUnaryAnalyser>::result
968 isAnalyserInitializer;
969 transformMultiArrayImpl(s, sshape, src, d, dshape, dest,
970 f, isAnalyserInitializer());
971 }
972
973 template <class SrcIterator, class SrcShape, class SrcAccessor,
974 class DestIterator, class DestAccessor,
975 class Functor>
976 inline void
977 transformMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
978 pair<DestIterator, DestAccessor> const & dest, Functor const & f)
979 {
980
981 transformMultiArray(src.first, src.second, src.third,
982 dest.first, dest.second, f);
983 }
984
985 template <class SrcIterator, class SrcShape, class SrcAccessor,
986 class DestIterator, class DestShape, class DestAccessor,
987 class Functor>
988 inline void
989 transformMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
990 triple<DestIterator, DestShape, DestAccessor> const & dest,
991 Functor const & f)
992 {
993 transformMultiArray(src.first, src.second, src.third,
994 dest.first, dest.second, dest.third, f);
995 }
996
997 template <unsigned int N, class T1, class S1,
998 class T2, class S2,
999 class Functor>
1000 inline void
1001 transformMultiArrayImpl(MultiArrayView<N, T1, S1> const & source,
1002 MultiArrayView<N, T2, S2> dest,
1003 Functor const & f, VigraFalseType)
1004 {
1005 if(source.shape() == dest.shape())
1006 transformMultiArray(srcMultiArrayRange(source), destMultiArray(dest), f);
1007 else
1008 transformMultiArray(srcMultiArrayRange(source), destMultiArrayRange(dest), f);
1009 }
1010
1011 template <unsigned int N, class T1, class S1,
1012 class T2, class S2,
1013 class Functor>
1014 inline void
1015 transformMultiArrayImpl(MultiArrayView<N, T1, S1> const & source,
1016 MultiArrayView<N, T2, S2> dest,
1017 Functor const & f, VigraTrueType)
1018 {
1019 transformMultiArray(srcMultiArrayRange(source), destMultiArrayRange(dest), f);
1020 }
1021
1022 template <unsigned int N, class T1, class S1,
1023 class T2, class S2,
1024 class Functor>
1025 inline void
1026 transformMultiArray(MultiArrayView<N, T1, S1> const & source,
1027 MultiArrayView<N, T2, S2> dest, Functor const & f)
1028 {
1029 for(unsigned int k=0; k<N; ++k)
1030 vigra_precondition(source.shape(k) == dest.shape(k) || source.shape(k) == 1 || 1 == dest.shape(k),
1031 "transformMultiArray(): shape mismatch between input and output.");
1032
1033 typedef FunctorTraits<Functor> FT;
1034 typedef typename
1035 And<typename FT::isInitializer, typename FT::isUnaryAnalyser>::result
1036 isAnalyserInitializer;
1037 transformMultiArrayImpl(source, dest, f, isAnalyserInitializer());
1038 }
1039
1040 /********************************************************/
1041 /* */
1042 /* combineTwoMultiArrays */
1043 /* */
1044 /********************************************************/
1045
1046 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
1047 class SrcIterator2, class SrcAccessor2,
1048 class DestIterator, class DestShape, class DestAccessor,
1049 class Functor>
1050 void
1051 combineTwoMultiArraysReduceImpl(
1052 SrcIterator1 s1, SrcShape const & , SrcAccessor1 src1,
1053 SrcIterator2 s2, SrcAccessor2 src2,
1054 DestIterator d, DestShape const & dshape, DestAccessor dest,
1055 SrcShape const & reduceShape,
1056 Functor const & ff, MetaInt<0>)
1057 {
1058 DestIterator dend = d + dshape[0];
1059 for(; d < dend; ++s1.template dim<0>(), ++s2.template dim<0>(), ++d)
1060 {
1061 Functor f = ff;
1062 inspectTwoMultiArrays(s1, reduceShape, src1, s2, src2, f);
1063 dest.set(f(), d);
1064 }
1065 }
1066
1067 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
1068 class SrcIterator2, class SrcAccessor2,
1069 class DestIterator, class DestShape, class DestAccessor,
1070 class Functor, int N>
1071 void
1072 combineTwoMultiArraysReduceImpl(
1073 SrcIterator1 s1, SrcShape const & sshape, SrcAccessor1 src1,
1074 SrcIterator2 s2, SrcAccessor2 src2,
1075 DestIterator d, DestShape const & dshape, DestAccessor dest,
1076 SrcShape const & reduceShape,
1077 Functor const & f, MetaInt<N>)
1078 {
1079 DestIterator dend = d + dshape[N];
1080 for(; d < dend; ++s1.template dim<N>(), ++s2.template dim<N>(), ++d)
1081 {
1082 combineTwoMultiArraysReduceImpl(s1, sshape, src1, s2, src2,
1083 d.begin(), dshape, dest,
1084 reduceShape, f, MetaInt<N-1>());
1085 }
1086 }
1087
1088 template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
1089 class SrcIterator2, class SrcShape2, class SrcAccessor2,
1090 class DestIterator, class DestShape, class DestAccessor,
1091 class Functor>
1092 void
1093 combineTwoMultiArraysImpl(
1094 SrcIterator1 s1, SrcShape1 const & sshape1, SrcAccessor1 src1,
1095 SrcIterator2 s2, SrcShape2 const & sshape2, SrcAccessor2 src2,
1096 DestIterator d, DestShape const & dshape, DestAccessor dest,
1097 Functor const & f, VigraTrueType)
1098 {
1099 // reduce mode
1100 SrcShape1 reduceShape = sshape1;
1101 for(unsigned int i=0; i<dshape.size(); ++i)
1102 {
1103 vigra_precondition(sshape1[i] == sshape2[i] &&
1104 (dshape[i] == 1 || sshape1[i] == dshape[i]),
1105 "combineTwoMultiArrays(): mismatch between source and destination shapes:\n"
1106 "In 'reduce'-mode, the two source shapes must be equal, and\n"
1107 "the length of each destination dimension must either be 1\n"
1108 "or equal to the corresponding source length.");
1109 if(dshape[i] != 1)
1110 reduceShape[i] = 1;
1111 }
1112 combineTwoMultiArraysReduceImpl(s1, sshape1, src1, s2, src2,
1113 d, dshape, dest, reduceShape,
1114 f, MetaInt<SrcIterator1::level>());
1115 }
1116
1117 template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
1118 class SrcIterator2, class SrcShape2, class SrcAccessor2,
1119 class DestIterator, class DestShape, class DestAccessor,
1120 class Functor>
1121 void
1122 combineTwoMultiArraysExpandImpl(
1123 SrcIterator1 s1, SrcShape1 const & sshape1, SrcAccessor1 src1,
1124 SrcIterator2 s2, SrcShape2 const & sshape2, SrcAccessor2 src2,
1125 DestIterator d, DestShape const & dshape, DestAccessor dest,
1126 Functor const & f, MetaInt<0>)
1127 {
1128 DestIterator dend = d + dshape[0];
1129 if(sshape1[0] == 1 && sshape2[0] == 1)
1130 {
1131 initLine(d, dend, dest, f(src1(s1), src2(s2)));
1132 }
1133 else if(sshape1[0] == 1)
1134 {
1135 typename SrcAccessor1::value_type sv1 = src1(s1);
1136 for(; d < dend; ++d, ++s2)
1137 dest.set(f(sv1, src2(s2)), d);
1138 }
1139 else if(sshape2[0] == 1)
1140 {
1141 typename SrcAccessor2::value_type sv2 = src2(s2);
1142 for(; d < dend; ++d, ++s1)
1143 dest.set(f(src1(s1), sv2), d);
1144 }
1145 else
1146 {
1147 combineTwoLines(s1, s1 + sshape1[0], src1, s2, src2, d, dest, f);
1148 }
1149 }
1150
1151 template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
1152 class SrcIterator2, class SrcShape2, class SrcAccessor2,
1153 class DestIterator, class DestShape, class DestAccessor,
1154 class Functor, int N>
1155 void
1156 combineTwoMultiArraysExpandImpl(
1157 SrcIterator1 s1, SrcShape1 const & sshape1, SrcAccessor1 src1,
1158 SrcIterator2 s2, SrcShape2 const & sshape2, SrcAccessor2 src2,
1159 DestIterator d, DestShape const & dshape, DestAccessor dest,
1160 Functor const & f, MetaInt<N>)
1161 {
1162 DestIterator dend = d + dshape[N];
1163 int s1inc = sshape1[N] == 1
1164 ? 0
1165 : 1;
1166 int s2inc = sshape2[N] == 1
1167 ? 0
1168 : 1;
1169 for(; d < dend; ++d, s1 += s1inc, s2 += s2inc)
1170 {
1171 combineTwoMultiArraysExpandImpl(s1.begin(), sshape1, src1,
1172 s2.begin(), sshape2, src2,
1173 d.begin(), dshape, dest,
1174 f, MetaInt<N-1>());
1175 }
1176 }
1177
1178 template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
1179 class SrcIterator2, class SrcShape2, class SrcAccessor2,
1180 class DestIterator, class DestShape, class DestAccessor,
1181 class Functor>
1182 void
1183 combineTwoMultiArraysImpl(
1184 SrcIterator1 s1, SrcShape1 const & sshape1, SrcAccessor1 src1,
1185 SrcIterator2 s2, SrcShape2 const & sshape2, SrcAccessor2 src2,
1186 DestIterator d, DestShape const & dshape, DestAccessor dest,
1187 Functor const & f, VigraFalseType)
1188 {
1189 // expand mode
1190 for(unsigned int i=0; i<sshape1.size(); ++i)
1191 vigra_precondition((sshape1[i] == 1 || sshape1[i] == dshape[i]) &&
1192 (sshape2[i] == 1 || sshape2[i] == dshape[i]),
1193 "combineTwoMultiArrays(): mismatch between source and destination shapes:\n"
1194 "In 'expand'-mode, the length of each source dimension must either be 1\n"
1195 "or equal to the corresponding destination length.");
1196 combineTwoMultiArraysExpandImpl(s1, sshape1, src1, s2, sshape2, src2,
1197 d, dshape, dest,
1198 f, MetaInt<SrcIterator1::level>());
1199 }
1200
1201 /** \brief Combine two multi-dimensional arrays into one using a binary function or functor.
1202
1203 Note: The effect of this function can often be achieved in a simpler and
1204 more readable way by means of \ref MultiMathModule "array expressions".
1205
1206 This function can be applied in three modes:
1207
1208 <DL>
1209 <DT><b>Standard Mode:</b>
1210 <DD>If the source and destination arrays have the same size,
1211 the transformation given by the functor is applied to every pair of
1212 corresponding source elements and the result written into the corresponding
1213 destination element.
1214 Binary functions, binary functors from the STL and the functors specifically
1215 defined in \ref CombineFunctor can be used in standard mode.
1216 Creation of new functors is easiest by using \ref FunctorExpressions.
1217 <DT><b>Expanding Mode:</b>
1218 <DD>If the source arrays have length 1 along some (or even all) dimensions,
1219 the source values at index 0 are used for all destination
1220 elements in those dimensions. In other words, the source index is not
1221 incremented along those dimensions, but the transformation functor
1222 is applied as usual. So, we can expand small arrays (e.g. a single row of data,
1223 column length is 1), into larger ones (e.g. a 2D image with the same width):
1224 the given values are simply reused as necessary (e.g. for every row of the
1225 destination image). It is not even necessary that the source array shapes
1226 are equal. For example, we can combine a small array with one that
1227 hase the same size as the destination array.
1228 The same functors as in standard mode can be applied.
1229 <DT><b>Reducing Mode:</b>
1230 <DD>If the destination array has length 1 along some (or even all) dimensions,
1231 the source values in these dimensions are reduced to single values by means
1232 of a suitable functor which supports two function call operators: one
1233 with two arguments to collect the values, and one without argument to
1234 obtain the final (reduced) result. This behavior is a multi-dimensional
1235 generalization of the C++ standard function <tt>std::accumulate()</tt>.
1236 </DL>
1237
1238 The arrays must be represented by MultiArrayViews. If all shapes are identical,
1239 standard mode is applied. If the shapes differ, the size of corresponding dimensions
1240 must either be equal, or the length of this dimension must be 1 in one or both source
1241 arrays (expand mode), or the destination length must be 1 (reduce mode). However,
1242 reduction and expansion cannot be executed at the same time, so the latter
1243 conditions are mutual exclusive, even if they apply to different dimensions.
1244
1245 <b> Declarations:</b>
1246
1247 <b>\#include</b> <vigra/multi_pointoperators.hxx><br>
1248 Namespace: vigra
1249
1250 pass arbitrary-dimensional array views:
1251 \code
1252 namespace vigra {
1253 template <unsigned int N, class T11, class S11,
1254 class T12, class S12,
1255 class T2, class S2,
1256 class Functor>
1257 void
1258 combineTwoMultiArrays(MultiArrayView<N, T11, S11> const & source1,
1259 MultiArrayView<N, T12, S12> const & source2,
1260 MultiArrayView<N, T2, S2> dest,
1261 Functor const & f);
1262 }
1263 \endcode
1264
1265 \deprecatedAPI{combineTwoMultiArrays}
1266 pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors :
1267 \code
1268 namespace vigra {
1269 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
1270 class SrcIterator2, class SrcAccessor2,
1271 class DestIterator, class DestAccessor,
1272 class Functor>
1273 void combineTwoMultiArrays(
1274 SrcIterator1 s1, SrcShape const & shape, SrcAccessor1 src1,
1275 SrcIterator2 s2, SrcAccessor2 src2,
1276 DestIterator d, DestAccessor dest, Functor const & f);
1277
1278
1279 template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
1280 class SrcIterator2, class SrcShape2, class SrcAccessor2,
1281 class DestIterator, class DestShape, class DestAccessor,
1282 class Functor>
1283 void combineTwoMultiArrays(
1284 SrcIterator1 s1, SrcShape1 const & sshape1, SrcAccessor1 src1,
1285 SrcIterator2 s2, SrcShape2 const & sshape2, SrcAccessor2 src2,
1286 DestIterator d, DestShape const & dshape, DestAccessor dest,
1287 Functor const & f);
1288 }
1289 \endcode
1290 use argument objects in conjunction with \ref ArgumentObjectFactories :
1291 \code
1292 namespace vigra {
1293 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
1294 class SrcIterator2, class SrcAccessor2,
1295 class DestIterator, class DestAccessor, class Functor>
1296 void combineTwoMultiArrays(
1297 triple<SrcIterator1, SrcShape, SrcAccessor1> const & src1,
1298 pair<SrcIterator2, SrcAccessor2> const & src2,
1299 pair<DestIterator, DestAccessor> const & dest, Functor const & f);
1300
1301
1302 template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
1303 class SrcIterator2, class SrcShape2, class SrcAccessor2,
1304 class DestIterator, class DestShape, class DestAccessor,
1305 class Functor>
1306 void combineTwoMultiArrays(
1307 triple<SrcIterator1, SrcShape1, SrcAccessor1> const & src1,
1308 triple<SrcIterator2, SrcShape2, SrcAccessor2> const & src2,
1309 triple<DestIterator, DestShape, DestAccessor> const & dest,
1310 Functor const & f);
1311 }
1312 \endcode
1313 \deprecatedEnd
1314
1315 <b> Usage - Standard Mode:</b>
1316
1317 Source and destination arrays have the same size.
1318
1319 \code
1320 #include <functional> // for std::plus
1321
1322 MultiArray<3, int> src1(Shape3(100, 200, 50)),
1323 src2(Shape3(100, 200, 50)),
1324 dest(Shape3(100, 200, 50));
1325 ...
1326
1327 combineTwoMultiArrays(src1, src2, dest,
1328 std::plus<int>());
1329 \endcode
1330
1331 <b> Usage - Expand Mode:</b>
1332
1333 One source array is effectively only a 2D image (it has depth 1). This image will be added
1334 to every slice of the other source array, and the result is written into the
1335 corresponding destination slice.
1336
1337 \code
1338 #include <functional> // for std::plus
1339
1340 MultiArray<3, int> src1(Shape3(100, 200, 1)),
1341 src2(Shape3(100, 200, 50)),
1342 dest(Shape3(100, 200, 50));
1343 ...
1344
1345 combineTwoMultiArrays(src1, src2, dest,
1346 std::plus<int>());
1347 \endcode
1348
1349 <b> Usage - Reduce Mode:</b>
1350
1351 The destination array is only 1D (it's width and height are singleton dimensions).
1352 Thus, it will contain accumulated data for every slice of the source volumes
1353 (or for every frame, if the sources are interpreted as image sequences).
1354 In the example, we use \ref vigra::ReduceFunctor together with a functor
1355 expression (see \ref FunctorExpressions) to calculate the total absolute difference
1356 of the gray values in every pair of source slices.
1357
1358 \code
1359 #include <vigra/functorexpression.hxx>
1360 using namespace vigra::functor;
1361
1362 MultiArray<3, int> src1(Shape3(100, 200, 50)),
1363 src2(Shape3(100, 200, 50)),
1364 dest(Shape3(1, 1, 50));
1365 ...
1366
1367 combineTwoMultiArrays(src1, src2, dest,
1368 reduceFunctor(Arg1() + abs(Arg2() - Arg3()), 0) );
1369 // Arg1() is the sum accumulated so far, initialized with 0
1370 \endcode
1371
1372 Note that the functor must define the appropriate traits described below in order to be
1373 recognized as a reduce functor. This is most easily achieved by deriving from
1374 <tt>BinaryReduceFunctorTag</tt> (see \ref vigra::FunctorTraits).
1375
1376 \deprecatedUsage{combineTwoMultiArrays}
1377 \code
1378 #include <functional> // for std::plus
1379
1380 typedef vigra::MultiArray<3, int> Array;
1381 Array src1(Shape3(100, 200, 50)),
1382 src2(Shape3(100, 200, 50)),
1383 dest(Shape3(100, 200, 50));
1384 ...
1385
1386 vigra::combineTwoMultiArrays(
1387 srcMultiArrayRange(src1),
1388 srcMultiArray(src2),
1389 destMultiArray(dest),
1390 std::plus<int>());
1391 \endcode
1392 \deprecatedEnd
1393
1394 <b> Required Interface:</b>
1395
1396 In standard and expand mode, the functor must be a model of BinaryFunction
1397 (i.e. support function call with two arguments and a return value which is convertible
1398 into <tt>T2</tt>: <tt>T2 res = functor(arg1, arg2)</tt>):
1399
1400 In reduce mode, it must be a model of BinaryAnalyser (i.e. support function call
1401 with two arguments and no return value <tt>functor(arg1, arg2)</tt>) and Initializer
1402 (i.e. support function call with no argument, but return value
1403 <tt>res = functor()</tt>). Internally, such functors are recognized by the
1404 meta functions <tt>FunctorTraits<FUNCTOR>::isBinaryAnalyser</tt> and
1405 <tt>FunctorTraits<FUNCTOR>::isInitializer</tt> which must both yield
1406 <tt>VigraTrueType</tt>. Make sure that your functor correctly defines
1407 <tt>FunctorTraits</tt> because otherwise reduce mode will not work.
1408 This is most easily achieved by deriving the functor from
1409 <tt>BinaryReduceFunctorTag</tt> (see \ref vigra::FunctorTraits).
1410 In addition, the functor must be copy constructible in order to start each reduction
1411 with a fresh functor.
1412
1413 \see TransformFunctor, MultiMathModule, \ref FunctorExpressions
1414 */
1415 doxygen_overloaded_function(template <...> void combineTwoMultiArrays)
1416
1417 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
1418 class SrcIterator2, class SrcAccessor2,
1419 class DestIterator, class DestAccessor,
1420 class Functor>
1421 inline void
1422 combineTwoMultiArrays(SrcIterator1 s1, SrcShape const & shape, SrcAccessor1 src1,
1423 SrcIterator2 s2, SrcAccessor2 src2,
1424 DestIterator d, DestAccessor dest, Functor const & f)
1425 {
1426 combineTwoMultiArraysExpandImpl(s1, shape, src1, s2, shape, src2, d, shape, dest, f,
1427 MetaInt<SrcIterator1::level>());
1428 }
1429
1430 template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
1431 class SrcIterator2, class SrcShape2, class SrcAccessor2,
1432 class DestIterator, class DestShape, class DestAccessor,
1433 class Functor>
1434 void
1435 combineTwoMultiArrays(
1436 SrcIterator1 s1, SrcShape1 const & sshape1, SrcAccessor1 src1,
1437 SrcIterator2 s2, SrcShape2 const & sshape2, SrcAccessor2 src2,
1438 DestIterator d, DestShape const & dshape, DestAccessor dest,
1439 Functor const & f)
1440 {
1441 vigra_precondition(sshape1.size() == dshape.size() && sshape2.size() == dshape.size(),
1442 "combineTwoMultiArrays(): dimensionality of source and destination arrays differ");
1443
1444 typedef FunctorTraits<Functor> FT;
1445 typedef typename
1446 And<typename FT::isInitializer, typename FT::isBinaryAnalyser>::result
1447 isAnalyserInitializer;
1448 combineTwoMultiArraysImpl(s1, sshape1, src1, s2, sshape2, src2, d, dshape, dest,
1449 f, isAnalyserInitializer());
1450 }
1451
1452 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
1453 class SrcIterator2, class SrcAccessor2,
1454 class DestIterator, class DestAccessor, class Functor>
1455 inline void
1456 combineTwoMultiArrays(triple<SrcIterator1, SrcShape, SrcAccessor1> const & src1,
1457 pair<SrcIterator2, SrcAccessor2> const & src2,
1458 pair<DestIterator, DestAccessor> const & dest,
1459 Functor const & f)
1460 {
1461
1462 combineTwoMultiArrays(
1463 src1.first, src1.second, src1.third,
1464 src2.first, src2.second, dest.first, dest.second, f);
1465 }
1466
1467 template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
1468 class SrcIterator2, class SrcShape2, class SrcAccessor2,
1469 class DestIterator, class DestShape, class DestAccessor,
1470 class Functor>
1471 inline void
1472 combineTwoMultiArrays(triple<SrcIterator1, SrcShape1, SrcAccessor1> const & src1,
1473 triple<SrcIterator2, SrcShape2, SrcAccessor2> const & src2,
1474 triple<DestIterator, DestShape, DestAccessor> const & dest,
1475 Functor const & f)
1476 {
1477 combineTwoMultiArrays(src1.first, src1.second, src1.third,
1478 src2.first, src2.second, src2.third,
1479 dest.first, dest.second, dest.third, f);
1480 }
1481
1482 template <unsigned int N, class T11, class S11,
1483 class T12, class S12,
1484 class T2, class S2,
1485 class Functor>
1486 inline void
1487 combineTwoMultiArraysImpl(MultiArrayView<N, T11, S11> const & source1,
1488 MultiArrayView<N, T12, S12> const & source2,
1489 MultiArrayView<N, T2, S2> dest,
1490 Functor const & f, VigraFalseType)
1491 {
1492
1493 if(source1.shape() == source2.shape() && source1.shape() == dest.shape())
1494 combineTwoMultiArrays(srcMultiArrayRange(source1),
1495 srcMultiArray(source2), destMultiArray(dest), f);
1496 else
1497 combineTwoMultiArrays(srcMultiArrayRange(source1),
1498 srcMultiArrayRange(source2),
1499 destMultiArrayRange(dest), f);
1500 }
1501
1502 template <unsigned int N, class T11, class S11,
1503 class T12, class S12,
1504 class T2, class S2,
1505 class Functor>
1506 inline void
1507 combineTwoMultiArraysImpl(MultiArrayView<N, T11, S11> const & source1,
1508 MultiArrayView<N, T12, S12> const & source2,
1509 MultiArrayView<N, T2, S2> dest,
1510 Functor const & f, VigraTrueType)
1511 {
1512
1513 combineTwoMultiArrays(srcMultiArrayRange(source1),
1514 srcMultiArrayRange(source2),
1515 destMultiArrayRange(dest), f);
1516 }
1517
1518 template <unsigned int N, class T11, class S11,
1519 class T12, class S12,
1520 class T2, class S2,
1521 class Functor>
1522 inline void
1523 combineTwoMultiArrays(MultiArrayView<N, T11, S11> const & source1,
1524 MultiArrayView<N, T12, S12> const & source2,
1525 MultiArrayView<N, T2, S2> dest,
1526 Functor const & f)
1527 {
1528 for(unsigned int k=0; k<N; ++k)
1529 vigra_precondition((source1.shape(k) == source2.shape(k) || source1.shape(k) == 1 || 1 == source2.shape(k)) &&
1530 (source1.shape(k) == dest.shape(k) || source1.shape(k) == 1 || 1 == dest.shape(k)),
1531 "combineTwoMultiArrays(): shape mismatch between inputs and/or output.");
1532
1533 typedef FunctorTraits<Functor> FT;
1534 typedef typename
1535 And<typename FT::isInitializer, typename FT::isBinaryAnalyser>::result
1536 isAnalyserInitializer;
1537 combineTwoMultiArraysImpl(source1, source2, dest, f, isAnalyserInitializer());
1538 }
1539
1540 /********************************************************/
1541 /* */
1542 /* combineThreeMultiArrays */
1543 /* */
1544 /********************************************************/
1545
1546 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
1547 class SrcIterator2, class SrcAccessor2,
1548 class SrcIterator3, class SrcAccessor3,
1549 class DestIterator, class DestAccessor,
1550 class Functor>
1551 inline void
1552 combineThreeMultiArraysImpl(SrcIterator1 s1, SrcShape const & shape, SrcAccessor1 src1,
1553 SrcIterator2 s2, SrcAccessor2 src2,
1554 SrcIterator3 s3, SrcAccessor3 src3,
1555 DestIterator d, DestAccessor dest, Functor const & f, MetaInt<0>)
1556 {
1557 combineThreeLines(s1, s1 + shape[0], src1, s2, src2, s3, src3, d, dest, f);
1558 }
1559
1560 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
1561 class SrcIterator2, class SrcAccessor2,
1562 class SrcIterator3, class SrcAccessor3,
1563 class DestIterator, class DestAccessor,
1564 class Functor, int N>
1565 void
1566 combineThreeMultiArraysImpl(SrcIterator1 s1, SrcShape const & shape, SrcAccessor1 src1,
1567 SrcIterator2 s2, SrcAccessor2 src2,
1568 SrcIterator3 s3, SrcAccessor3 src3,
1569 DestIterator d, DestAccessor dest,
1570 Functor const & f, MetaInt<N>)
1571 {
1572 SrcIterator1 s1end = s1 + shape[N];
1573 for(; s1 < s1end; ++s1, ++s2, ++s3, ++d)
1574 {
1575 combineThreeMultiArraysImpl(s1.begin(), shape, src1,
1576 s2.begin(), src2, s3.begin(), src3, d.begin(), dest,
1577 f, MetaInt<N-1>());
1578 }
1579 }
1580
1581
1582 /** \brief Combine three multi-dimensional arrays into one using a
1583 ternary function or functor.
1584
1585 Note: The effect of this function can often be achieved in a simpler and
1586 more readable way by means of \ref MultiMathModule "array expressions".
1587
1588 Except for the fact that it operates on three input arrays, this function is
1589 identical to the standard mode of \ref combineTwoMultiArrays() (reduce and expand
1590 modes are not supported).
1591
1592 <b> Declarations:</b>
1593
1594 pass arbitrary-dimensional array views:
1595 \code
1596 namespace vigra {
1597 template <unsigned int N, class T11, class S11,
1598 class T12, class S12,
1599 class T13, class S13,
1600 class T2, class S2,
1601 class Functor>
1602 void
1603 combineThreeMultiArrays(MultiArrayView<N, T11, S11> const & source1,
1604 MultiArrayView<N, T12, S12> const & source2,
1605 MultiArrayView<N, T13, S13> const & source3,
1606 MultiArrayView<N, T2, S2> dest,
1607 Functor const & f);
1608 }
1609 \endcode
1610
1611 \deprecatedAPI{combineThreeMultiArrays}
1612 pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors :
1613 \code
1614 namespace vigra {
1615 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
1616 class SrcIterator2, class SrcAccessor2,
1617 class SrcIterator3, class SrcAccessor3,
1618 class DestIterator, class DestAccessor,
1619 class Functor>
1620 void
1621 combineThreeMultiArrays(SrcIterator1 s1, SrcShape const & shape, SrcAccessor1 src1,
1622 SrcIterator2 s2, SrcAccessor2 src2,
1623 SrcIterator3 s3, SrcAccessor3 src3,
1624 DestIterator d, DestAccessor dest, Functor const & f);
1625 }
1626 \endcode
1627 use argument objects in conjunction with \ref ArgumentObjectFactories :
1628 \code
1629 namespace vigra {
1630 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
1631 class SrcIterator2, class SrcAccessor2,
1632 class SrcIterator3, class SrcAccessor3,
1633 class DestIterator, class DestAccessor,
1634 class Functor>
1635 inline void
1636 combineThreeMultiArrays(triple<SrcIterator1, SrcShape, SrcAccessor1> const & src1,
1637 pair<SrcIterator2, SrcAccessor2> const & src2,
1638 pair<SrcIterator3, SrcAccessor3> const & src3,
1639 pair<DestIterator, DestAccessor> const & dest, Functor const & f);
1640 }
1641 \endcode
1642 \deprecatedEnd
1643
1644 <b> Usage:</b>
1645
1646 <b>\#include</b> <vigra/multi_pointoperators.hxx><br>
1647 Namespace: vigra
1648
1649 \code
1650 #include <vigra/functorexpression.hxx>
1651
1652 MultiArray<3, int> src1(Shape3(100, 200, 50)),
1653 src2(Shape3(100, 200, 50)),
1654 src3(Shape3(100, 200, 50)),
1655 dest(Shape3(100, 200, 50));
1656 ...
1657
1658 using namespace vigra::functor; // activate VIGRA's lambda library
1659
1660 combineThreeMultiArrays(src1, src2, src3, dest,
1661 Arg1()*exp(-abs(Arg2()-Arg3())));
1662 \endcode
1663
1664 \deprecatedUsage{combineThreeMultiArrays}
1665 \code
1666 #include <functional> // for plus
1667
1668 typedef vigra::MultiArray<3, int> Array;
1669 Array src1(Shape3(100, 200, 50)),
1670 src2(Shape3(100, 200, 50)),
1671 src3(Shape3(100, 200, 50)),
1672 dest(Shape3(100, 200, 50));
1673 ...
1674
1675 vigra::combineThreeMultiArrays(
1676 srcMultiArrayRange(src1),
1677 srcMultiArray(src2),
1678 srcMultiArray(src3),
1679 destMultiArray(dest),
1680 SomeThreeArgumentFunctor());
1681 \endcode
1682 \deprecatedEnd
1683
1684 \see TransformFunctor, MultiMathModule, \ref FunctorExpressions
1685 */
1686 doxygen_overloaded_function(template <...> void combineThreeMultiArrays)
1687
1688 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
1689 class SrcIterator2, class SrcAccessor2,
1690 class SrcIterator3, class SrcAccessor3,
1691 class DestIterator, class DestAccessor,
1692 class Functor>
1693 inline void
1694 combineThreeMultiArrays(SrcIterator1 s1, SrcShape const & shape, SrcAccessor1 src1,
1695 SrcIterator2 s2, SrcAccessor2 src2,
1696 SrcIterator3 s3, SrcAccessor3 src3,
1697 DestIterator d, DestAccessor dest, Functor const & f)
1698 {
1699 combineThreeMultiArraysImpl(s1, shape, src1, s2, src2, s3, src3, d, dest, f,
1700 MetaInt<SrcIterator1::level>());
1701 }
1702
1703 template <class SrcIterator1, class SrcShape, class SrcAccessor1,
1704 class SrcIterator2, class SrcAccessor2,
1705 class SrcIterator3, class SrcAccessor3,
1706 class DestIterator, class DestAccessor,
1707 class Functor>
1708 inline void
1709 combineThreeMultiArrays(triple<SrcIterator1, SrcShape, SrcAccessor1> const & src1,
1710 pair<SrcIterator2, SrcAccessor2> const & src2,
1711 pair<SrcIterator3, SrcAccessor3> const & src3,
1712 pair<DestIterator, DestAccessor> const & dest, Functor const & f)
1713 {
1714
1715 combineThreeMultiArrays(
1716 src1.first, src1.second, src1.third,
1717 src2.first, src2.second, src3.first, src3.second, dest.first, dest.second, f);
1718 }
1719
1720 template <unsigned int N, class T11, class S11,
1721 class T12, class S12,
1722 class T13, class S13,
1723 class T2, class S2,
1724 class Functor>
1725 inline void
1726 combineThreeMultiArrays(MultiArrayView<N, T11, S11> const & source1,
1727 MultiArrayView<N, T12, S12> const & source2,
1728 MultiArrayView<N, T13, S13> const & source3,
1729 MultiArrayView<N, T2, S2> dest, Functor const & f)
1730 {
1731 vigra_precondition(source1.shape() == source2.shape() && source1.shape() == source3.shape() && source1.shape() == dest.shape(),
1732 "combineThreeMultiArrays(): shape mismatch between inputs and/or output.");
1733
1734 combineThreeMultiArrays(
1735 srcMultiArrayRange(source1),
1736 srcMultiArray(source2), srcMultiArray(source3), destMultiArray(dest), f);
1737 }
1738
1739 /********************************************************/
1740 /* */
1741 /* inspectMultiArray */
1742 /* */
1743 /********************************************************/
1744
1745 template <class Iterator, class Shape, class Accessor, class Functor>
1746 inline void
1747 inspectMultiArrayImpl(Iterator s, Shape const & shape, Accessor a, Functor & f, MetaInt<0>)
1748 {
1749 inspectLine(s, s + shape[0], a, f);
1750 }
1751
1752 template <class Iterator, class Shape, class Accessor, class Functor, int N>
1753 void
1754 inspectMultiArrayImpl(Iterator s, Shape const & shape, Accessor a, Functor & f, MetaInt<N>)
1755 {
1756 Iterator send = s + shape[N];
1757 for(; s < send; ++s)
1758 {
1759 inspectMultiArrayImpl(s.begin(), shape, a, f, MetaInt<N-1>());
1760 }
1761 }
1762
1763 /** \brief Call an analyzing functor at every element of a multi-dimensional array.
1764
1765 This function can be used to collect statistics of the array etc.
1766 The results must be stored in the functor, which serves as a return
1767 value (therefore, it is passed to the function by reference). The array must be
1768 represented as a MultiArrayView.
1769
1770 For many common statistics, the use of \ref vigra::acc::extractFeatures() in combination with
1771 \ref FeatureAccumulators is more convenient.
1772
1773 <b> Declarations:</b>
1774
1775 pass arbitrary-dimensional array views:
1776 \code
1777 namespace vigra {
1778 template <unsigned int N, class T, class S,
1779 class Functor>
1780 void
1781 inspectMultiArray(MultiArrayView<N, T, S> const & s,
1782 Functor & f);
1783 }
1784 \endcode
1785
1786 \deprecatedAPI{inspectMultiArray}
1787 pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors :
1788 \code
1789 namespace vigra {
1790 template <class Iterator, class Shape, class Accessor, class Functor>
1791 void
1792 inspectMultiArray(Iterator s, Shape const & shape, Accessor a, Functor & f);
1793 }
1794 \endcode
1795 use argument objects in conjunction with \ref ArgumentObjectFactories :
1796 \code
1797 namespace vigra {
1798 template <class Iterator, class Shape, class Accessor, class Functor>
1799 void
1800 inspectMultiArray(triple<Iterator, Shape, Accessor> const & s, Functor & f);
1801 }
1802 \endcode
1803 \deprecatedEnd
1804
1805 <b> Usage:</b>
1806
1807 <b>\#include</b> <vigra/multi_pointoperators.hxx><br>
1808 Namespace: vigra
1809
1810 \code
1811 MultiArray<3, int> array(Shape3(100, 200, 50));
1812 ... // fill array
1813
1814 // init functor
1815 FindMinMax<int> minmax;
1816
1817 inspectMultiArray(array, minmax);
1818
1819 cout << "Min: " << minmax.min << " Max: " << minmax.max;
1820 \endcode
1821 The functor must support function call with one argument.
1822
1823 \deprecatedUsage{inspectMultiArray}
1824 \code
1825 typedef vigra::MultiArray<3, int> Array;
1826 Array array(Shape3(100, 200, 50));
1827
1828 // init functor
1829 vigra::FindMinMax<int> minmax;
1830
1831 vigra::inspectMultiArray(srcMultiArrayRange(array), minmax);
1832
1833 cout << "Min: " << minmax.min << " Max: " << minmax.max;
1834
1835 \endcode
1836 <b> Required Interface:</b>
1837 \code
1838 MultiIterator src_begin;
1839
1840 Accessor accessor;
1841 Functor functor;
1842
1843 functor(accessor(src_begin));
1844 \endcode
1845 \deprecatedEnd
1846 */
1847 doxygen_overloaded_function(template <...> void inspectMultiArray)
1848
1849 template <class Iterator, class Shape, class Accessor>
1850 struct inspectMultiArray_binder
1851 {
1852 Iterator s;
1853 const Shape & shape;
1854 Accessor a;
1855 inspectMultiArray_binder(Iterator s_, const Shape & shape_, Accessor a_)
1856 : s(s_), shape(shape_), a(a_) {}
1857 template <class Functor>
1858 void operator()(Functor & f)
1859 {
1860 inspectMultiArrayImpl(s, shape, a, f, MetaInt<Iterator::level>());
1861 }
1862 };
1863
1864 template <class Iterator, class Shape, class Accessor, class Functor>
1865 inline void
1866 inspectMultiArray(Iterator s, Shape const & shape, Accessor a, Functor & f)
1867 {
1868 inspectMultiArray_binder<Iterator, Shape, Accessor> g(s, shape, a);
1869 detail::extra_passes_select(g, f);
1870 }
1871
1872 template <class Iterator, class Shape, class Accessor, class Functor>
1873 inline void
1874 inspectMultiArray(triple<Iterator, Shape, Accessor> const & s, Functor & f)
1875 {
1876 inspectMultiArray(s.first, s.second, s.third, f);
1877 }
1878
1879 template <unsigned int N, class T, class S, class Functor>
1880 inline void
1881 inspectMultiArray(MultiArrayView<N, T, S> const & s, Functor & f)
1882 {
1883 inspectMultiArray(srcMultiArrayRange(s), f);
1884 }
1885
1886 /********************************************************/
1887 /* */
1888 /* inspectTwoMultiArrays */
1889 /* */
1890 /********************************************************/
1891
1892 template <class Iterator1, class Shape, class Accessor1,
1893 class Iterator2, class Accessor2,
1894 class Functor>
1895 inline void
1896 inspectTwoMultiArraysImpl(Iterator1 s1, Shape const & shape, Accessor1 a1,
1897 Iterator2 s2, Accessor2 a2,
1898 Functor & f, MetaInt<0>)
1899 {
1900 inspectTwoLines(s1, s1 + shape[0], a1, s2, a2, f);
1901 }
1902
1903 template <class Iterator1, class Shape, class Accessor1,
1904 class Iterator2, class Accessor2,
1905 class Functor, int N>
1906 void
1907 inspectTwoMultiArraysImpl(Iterator1 s1, Shape const & shape, Accessor1 a1,
1908 Iterator2 s2, Accessor2 a2,
1909 Functor & f, MetaInt<N>)
1910 {
1911 Iterator1 s1end = s1 + shape[N];
1912 for(; s1 < s1end; ++s1, ++s2)
1913 {
1914 inspectTwoMultiArraysImpl(s1.begin(), shape, a1,
1915 s2.begin(), a2, f, MetaInt<N-1>());
1916 }
1917 }
1918
1919 /** \brief Call an analyzing functor at all corresponding elements of
1920 two multi-dimensional arrays.
1921
1922 This function can be used to collect statistics over tow arrays.
1923 For example, one can holde data, and the other region labels or weights.
1924 The results must be stored in the functor, which serves as a return
1925 value (and is therefore passed by reference). The arrays must be represented by
1926 MultiArrayViews.
1927
1928 For many common statistics, the use of \ref vigra::acc::extractFeatures() in combination with
1929 \ref FeatureAccumulators is more convenient.
1930
1931 <b> Declarations:</b>
1932
1933 pass arbitrary-dimensional array views:
1934 \code
1935 namespace vigra {
1936 template <unsigned int N, class T1, class S1,
1937 class T2, class S2,
1938 class Functor>
1939 void
1940 inspectTwoMultiArrays(MultiArrayView<N, T1, S1> const & s1,
1941 MultiArrayView<N, T2, S2> const & s2,
1942 Functor & f);
1943 }
1944 \endcode
1945
1946 \deprecatedAPI{inspectTwoMultiArrays}
1947 pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors :
1948 \code
1949 namespace vigra {
1950 template <class Iterator1, class Shape, class Accessor1,
1951 class Iterator2, class Accessor2,
1952 class Functor>
1953 void
1954 inspectTwoMultiArrays(Iterator1 s1, Shape const & shape, Accessor1 a1,
1955 Iterator2 s2, Accessor2 a2, Functor & f);
1956 }
1957 \endcode
1958 use argument objects in conjunction with \ref ArgumentObjectFactories :
1959 \code
1960 namespace vigra {
1961 template <class Iterator1, class Shape1, class Accessor1,
1962 class Iterator2, class Accessor2,
1963 class Functor>
1964 void
1965 inspectTwoMultiArrays(triple<Iterator1, Shape1, Accessor1> const & s1,
1966 pair<Iterator2, Accessor2> const & s2, Functor & f);
1967 }
1968 \endcode
1969 \deprecatedEnd
1970
1971 <b> Usage:</b>
1972
1973 <b>\#include</b> <vigra/multi_pointoperators.hxx><br>
1974 Namespace: vigra
1975
1976 \code
1977 MultiArray<3, int> array1(Shape3(100, 200, 50)),
1978 array2(Shape3(100, 200, 50));
1979
1980 // init functor
1981 SomeStatisticsFunctor stats(..);
1982
1983 inspectTwoMultiArrays(array1, array2, stats);
1984 \endcode
1985 The functor must support function call with two arguments.
1986
1987 \deprecatedUsage{inspectTwoMultiArrays}
1988 \code
1989 MultiArray<3, int> array1(Shape3(100, 200, 50)),
1990 array2(Shape3(100, 200, 50));
1991
1992 // init functor
1993 SomeStatisticsFunctor stats(..);
1994
1995 vigra::inspectTwoMultiArrays(srcMultiArrayRange(array1), srcMultiArray(array2), stats);
1996 \endcode
1997 <b> Required Interface:</b>
1998 \code
1999 MultiIterator src1_begin, src2_begin;
2000
2001 Accessor a1, a2;
2002 Functor functor;
2003
2004 functor(a1(src1_begin), a2(src2_begin));
2005 \endcode
2006 \deprecatedEnd
2007 */
2008 doxygen_overloaded_function(template <...> void inspectTwoMultiArrays)
2009
2010 template <class Iterator1, class Shape, class Accessor1,
2011 class Iterator2, class Accessor2>
2012 struct inspectTwoMultiArrays_binder
2013 {
2014 Iterator1 s1;
2015 const Shape & shape;
2016 Accessor1 a1;
2017 Iterator2 s2;
2018 Accessor2 a2;
2019 inspectTwoMultiArrays_binder(Iterator1 s1_, const Shape & shape_,
2020 Accessor1 a1_, Iterator2 s2_, Accessor2 a2_)
2021 : s1(s1_), shape(shape_), a1(a1_), s2(s2_), a2(a2_) {}
2022 template <class Functor>
2023 void operator()(Functor & f)
2024 {
2025 inspectTwoMultiArraysImpl(s1, shape, a1, s2, a2, f,
2026 MetaInt<Iterator1::level>());
2027 }
2028 };
2029
2030 template <class Iterator1, class Shape, class Accessor1,
2031 class Iterator2, class Accessor2,
2032 class Functor>
2033 inline void
2034 inspectTwoMultiArrays(Iterator1 s1, Shape const & shape, Accessor1 a1,
2035 Iterator2 s2, Accessor2 a2, Functor & f)
2036 {
2037 inspectTwoMultiArrays_binder<Iterator1, Shape, Accessor1,
2038 Iterator2, Accessor2>
2039 g(s1, shape, a1, s2, a2);
2040 detail::extra_passes_select(g, f);
2041 }
2042
2043 template <class Iterator1, class Shape, class Accessor1,
2044 class Iterator2, class Accessor2,
2045 class Functor>
2046 inline void
2047 inspectTwoMultiArrays(triple<Iterator1, Shape, Accessor1> const & s1,
2048 pair<Iterator2, Accessor2> const & s2, Functor & f)
2049 {
2050 inspectTwoMultiArrays(s1.first, s1.second, s1.third,
2051 s2.first, s2.second, f);
2052 }
2053
2054 template <unsigned int N, class T1, class S1,
2055 class T2, class S2,
2056 class Functor>
2057 inline void
2058 inspectTwoMultiArrays(MultiArrayView<N, T1, S1> const & s1,
2059 MultiArrayView<N, T2, S2> const & s2, Functor & f)
2060 {
2061 vigra_precondition(s1.shape() == s2.shape(),
2062 "inspectTwoMultiArrays(): shape mismatch between inputs.");
2063
2064 inspectTwoMultiArrays(srcMultiArrayRange(s1),
2065 srcMultiArray(s2), f);
2066 }
2067
2068 //@}
2069
2070 } //-- namespace vigra
2071
2072
2073 #endif //-- VIGRA_MULTI_POINTOPERATORS_H
vigra::inspectTwoMultiArrays
void inspectTwoMultiArrays(...)
Call an analyzing functor at all corresponding elements of two multi-dimensional arrays.
vigra::initMultiArrayBorder
void initMultiArrayBorder(...)
Write values to the specified border values in the array.
vigra::combineThreeMultiArrays
void combineThreeMultiArrays(...)
Combine three multi-dimensional arrays into one using a ternary function or functor.
vigra::MultiArrayIndex
std::ptrdiff_t MultiArrayIndex
Definition: multi_fwd.hxx:60
vigra::initMultiArray
void initMultiArray(...)
Write a value to every element in a multi-dimensional array.
vigra::boost_graph::source
vigra::GridGraph< N, DirectedTag >::vertex_descriptor source(typename vigra::GridGraph< N, DirectedTag >::edge_descriptor const &e, vigra::GridGraph< N, DirectedTag > const &g)
Get a vertex descriptor for the start vertex of edge e in graph g (API: boost).
Definition: multi_gridgraph.hxx:2943
vigra::doxygen_overloaded_function
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
vigra::copyMultiArray
void copyMultiArray(...)
Copy a multi-dimensional array.
vigra::combineTwoMultiArrays
void combineTwoMultiArrays(...)
Combine two multi-dimensional arrays into one using a binary function or functor. ...
vigra::transformMultiArray
void transformMultiArray(...)
Transform a multi-dimensional array with a unary function or functor.
vigra::inspectMultiArray
void inspectMultiArray(...)
Call an analyzing functor at every element of a multi-dimensional array.

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python vigra 1.11.0 (Thu Mar 17 2016)