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

© 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.10.0 (Mon Nov 18 2013)