1 /************************************************************************/
2 /* */
3 /* Copyright 1998-2002 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35
36
37 #ifndef VIGRA_COMBINEIMAGES_HXX
38 #define VIGRA_COMBINEIMAGES_HXX
39
40 #include "utilities.hxx"
41 #include "numerictraits.hxx"
42 #include "functortraits.hxx"
43 #include "multi_shape.hxx"
44
45 #include <cmath>
46
47 namespace vigra {
48
49 /** \addtogroup CombineAlgo Algorithms to Combine Images
50
51 Apply functor to calculate a pixelwise transformation depending on multiple images.
52 Note that the binary functors of the STL may be used with these functions.
53 */
54 //@{
55
56 /********************************************************/
57 /* */
58 /* combine...Lines */
59 /* */
60 /********************************************************/
61
62 template <class SrcIterator1, class SrcAccessor1,
63 class SrcIterator2, class SrcAccessor2,
64 class DestIterator, class DestAccessor, class Functor>
65 void
combineTwoLines(SrcIterator1 s1,SrcIterator1 s1end,SrcAccessor1 src1,SrcIterator2 s2,SrcAccessor2 src2,DestIterator d,DestAccessor dest,Functor const & f)66 combineTwoLines(SrcIterator1 s1,
67 SrcIterator1 s1end, SrcAccessor1 src1,
68 SrcIterator2 s2, SrcAccessor2 src2,
69 DestIterator d, DestAccessor dest,
70 Functor const & f)
71 {
72 for(; s1 != s1end; ++s1, ++s2, ++d)
73 dest.set(f(src1(s1), src2(s2)), d);
74 }
75
76 template <class SrcIterator1, class SrcAccessor1,
77 class SrcIterator2, class SrcAccessor2,
78 class MaskIterator, class MaskAccessor,
79 class DestIterator, class DestAccessor, class Functor>
80 void
combineTwoLinesIf(SrcIterator1 s1,SrcIterator1 s1end,SrcAccessor1 src1,SrcIterator2 s2,SrcAccessor2 src2,MaskIterator m,MaskAccessor mask,DestIterator d,DestAccessor dest,Functor const & f)81 combineTwoLinesIf(SrcIterator1 s1,
82 SrcIterator1 s1end, SrcAccessor1 src1,
83 SrcIterator2 s2, SrcAccessor2 src2,
84 MaskIterator m, MaskAccessor mask,
85 DestIterator d, DestAccessor dest,
86 Functor const & f)
87 {
88 for(; s1 != s1end; ++s1, ++s2, ++m, ++d)
89 if(mask(m))
90 dest.set(f(src1(s1), src2(s2)), d);
91 }
92
93 template <class SrcIterator1, class SrcAccessor1,
94 class SrcIterator2, class SrcAccessor2,
95 class SrcIterator3, class SrcAccessor3,
96 class DestIterator, class DestAccessor, class Functor>
97 void
combineThreeLines(SrcIterator1 s1,SrcIterator1 s1end,SrcAccessor1 src1,SrcIterator2 s2,SrcAccessor2 src2,SrcIterator3 s3,SrcAccessor3 src3,DestIterator d,DestAccessor dest,Functor const & f)98 combineThreeLines(SrcIterator1 s1,
99 SrcIterator1 s1end, SrcAccessor1 src1,
100 SrcIterator2 s2, SrcAccessor2 src2,
101 SrcIterator3 s3, SrcAccessor3 src3,
102 DestIterator d, DestAccessor dest,
103 Functor const & f)
104 {
105 for(; s1 != s1end; ++s1, ++s2, ++s3, ++d)
106 dest.set(f(src1(s1), src2(s2), src3(s3)), d);
107 }
108
109 /********************************************************/
110 /* */
111 /* combineTwoImages */
112 /* */
113 /********************************************************/
114
115 /** \brief Combine two source images into destination image.
116
117 After the introduction of arithmetic and algebraic \ref MultiMathModule "array expressions",
118 this function is rarely needed. Moreover, \ref combineTwoMultiArrays() provides the
119 same functionality for arbitrary dimensional arrays.
120
121 The transformation given by the functor is applied to the source
122 pixels and the result written into the corresponding destination pixel.
123 This is typically used for operations like add and subtract.
124 Note that the binary functors of the STL can be used in addition to
125 the functors specifically defined in \ref CombineFunctor.
126 Creation of new functors is easiest by using \ref FunctorExpressions.
127
128 <b> Declarations:</b>
129
130 pass 2D array views:
131 \code
132 namespace vigra {
133 template <class T11, class S11,
134 class T12, class S12,
135 class T2, class S2,
136 class Functor>
137 void
138 combineTwoImages(MultiArrayView<2, T11, S11> const & src1,
139 MultiArrayView<2, T12, S12> const & src2,
140 MultiArrayView<2, T2, S2> dest,
141 Functor const & f);
142 }
143 \endcode
144
145 \deprecatedAPI{combineTwoImages}
146 pass \ref ImageIterators and \ref DataAccessors :
147 \code
148 namespace vigra {
149 template <class SrcImageIterator1, class SrcAccessor1,
150 class SrcImageIterator2, class SrcAccessor2,
151 class DestImageIterator, class DestAccessor,
152 class Functor>
153 void
154 combineTwoImages(SrcImageIterator1 src1_upperleft,
155 SrcImageIterator1 src1_lowerright, SrcAccessor1 sa1,
156 SrcImageIterator2 src2_upperleft, SrcAccessor2 sa2,
157 DestImageIterator dest_upperleft, DestAccessor da,
158 Functor const & f)
159 }
160 \endcode
161 use argument objects in conjunction with \ref ArgumentObjectFactories :
162 \code
163 namespace vigra {
164 template <class SrcImageIterator1, class SrcAccessor1,
165 class SrcImageIterator2, class SrcAccessor2,
166 class DestImageIterator, class DestAccessor,
167 class Functor>
168 void
169 combineTwoImages(triple<SrcImageIterator1, SrcImageIterator1, SrcAccessor1> src1,
170 pair<SrcImageIterator2, SrcAccessor2> src2,
171 pair<DestImageIterator, DestAccessor> dest,
172 Functor const & f)
173 }
174 \endcode
175 \deprecatedEnd
176
177 <b> Usage:</b>
178
179 <b>\#include</b> \<vigra/combineimages.hxx\><br>
180 Namespace: vigra
181
182 \code
183 #include <functional> // for plus
184 MultiArray<2, float> src1(width, height), src2(width, height),
185 dest(width, height);
186 ... // fill source images
187
188 combineTwoImages(src1, src2, dest,
189 std::plus<float>());
190 \endcode
191
192 \deprecatedUsage{combineTwoImages}
193 \code
194 #include <functional> // for plus
195 FImage src1(width, height), src2(width, height),
196 dest(width, height);
197 ... // fill source images
198
199 vigra::combineTwoImages(
200 srcIterRange(src1.upperLeft(), src1.lowerRight()),
201 srcIter(src2.upperLeft()),
202 destIter(dest.upperLeft()),
203 std::plus<float>());
204 \endcode
205 <b> Required Interface:</b>
206 \code
207 SrcImageIterator1 src1_upperleft, src1_lowerright;
208 SrcImageIterator2 src2_upperleft;
209 DestImageIterator dest_upperleft;
210 SrcImageIterator1::row_iterator sx1 = src1_upperleft.rowIterator();
211 SrcImageIterator2::row_iterator sx2 = src2_upperleft.rowIterator();
212 DestImageIterator::row_iterator dx = dest_upperleft.rowIterator();
213
214 SrcAccessor1 src1_accessor;
215 SrcAccessor2 src2_accessor;
216 DestAccessor dest_accessor;
217
218 Functor functor;
219
220 dest_accessor.set(
221 functor(src1_accessor(sx1), src2_accessor(sx2)),
222 dx);
223
224 \endcode
225 \deprecatedEnd
226
227 \see TransformFunctor, MultiMathModule, \ref FunctorExpressions
228 */
doxygen_overloaded_function(template<...> void combineTwoImages)229 doxygen_overloaded_function(template <...> void combineTwoImages)
230
231 template <class SrcImageIterator1, class SrcAccessor1,
232 class SrcImageIterator2, class SrcAccessor2,
233 class DestImageIterator, class DestAccessor,
234 class Functor>
235 void
236 combineTwoImages(SrcImageIterator1 src1_upperleft,
237 SrcImageIterator1 src1_lowerright, SrcAccessor1 sa1,
238 SrcImageIterator2 src2_upperleft, SrcAccessor2 sa2,
239 DestImageIterator dest_upperleft, DestAccessor da,
240 Functor const & f)
241 {
242 int w = src1_lowerright.x - src1_upperleft.x;
243
244 for(; src1_upperleft.y < src1_lowerright.y;
245 ++src1_upperleft.y, ++src2_upperleft.y, ++dest_upperleft.y)
246 {
247 combineTwoLines(src1_upperleft.rowIterator(),
248 src1_upperleft.rowIterator() + w, sa1,
249 src2_upperleft.rowIterator(), sa2,
250 dest_upperleft.rowIterator(), da, f);
251 }
252 }
253
254 template <class SrcImageIterator1, class SrcAccessor1,
255 class SrcImageIterator2, class SrcAccessor2,
256 class DestImageIterator, class DestAccessor,
257 class Functor>
258 inline
259 void
combineTwoImages(triple<SrcImageIterator1,SrcImageIterator1,SrcAccessor1> src1,pair<SrcImageIterator2,SrcAccessor2> src2,pair<DestImageIterator,DestAccessor> dest,Functor const & f)260 combineTwoImages(triple<SrcImageIterator1, SrcImageIterator1, SrcAccessor1> src1,
261 pair<SrcImageIterator2, SrcAccessor2> src2,
262 pair<DestImageIterator, DestAccessor> dest,
263 Functor const & f)
264 {
265 combineTwoImages(src1.first, src1.second, src1.third,
266 src2.first, src2.second,
267 dest.first, dest.second, f);
268 }
269
270 template <class T11, class S11,
271 class T12, class S12,
272 class T2, class S2,
273 class Functor>
274 inline void
combineTwoImages(MultiArrayView<2,T11,S11> const & src1,MultiArrayView<2,T12,S12> const & src2,MultiArrayView<2,T2,S2> dest,Functor const & f)275 combineTwoImages(MultiArrayView<2, T11, S11> const & src1,
276 MultiArrayView<2, T12, S12> const & src2,
277 MultiArrayView<2, T2, S2> dest,
278 Functor const & f)
279 {
280 vigra_precondition(src1.shape() == src2.shape() && src1.shape() == dest.shape(),
281 "combineTwoImages(): shape mismatch between inputs and/or output.");
282 combineTwoImages(srcImageRange(src1),
283 srcImage(src2),
284 destImage(dest), f);
285 }
286
287 /********************************************************/
288 /* */
289 /* combineTwoImagesIf */
290 /* */
291 /********************************************************/
292
293 /** \brief Combine ROI of two source images into destination image.
294
295 The transformation given by the functor is applied to all source
296 pixels in the ROI (i.e. whenever the corresponding value of the mask array
297 is non-zero)
298 and the result written into the corresponding destination pixel.
299 This is typically used for operations like add and subtract.
300 Note that the binary functors of the STL can be used in addition to
301 the functors specifically defined in \ref CombineFunctor.
302 Creation of new functors is easiest by using \ref FunctorExpressions.
303
304 <b> Declarations:</b>
305
306 pass 2D array views:
307 \code
308 namespace vigra {
309 template <class T11, class S11,
310 class T12, class S12,
311 class TM, class SM,
312 class T2, class S2,
313 class Functor>
314 void
315 combineTwoImagesIf(MultiArrayView<2, T11, S11> const & src1,
316 MultiArrayView<2, T12, S12> const & src2,
317 MultiArrayView<2, TM, SM> const & mask,
318 MultiArrayView<2, T2, S2> dest,
319 Functor const & f);
320 }
321 \endcode
322
323 \deprecatedAPI{combineTwoImagesIf}
324 pass \ref ImageIterators and \ref DataAccessors :
325 \code
326 namespace vigra {
327 template <class SrcImageIterator1, class SrcAccessor1,
328 class SrcImageIterator2, class SrcAccessor2,
329 class MaskImageIterator, class MaskAccessor,
330 class DestImageIterator, clas DestAccessor,
331 class Functor>
332 void
333 combineTwoImagesIf(SrcImageIterator1 src1_upperleft,
334 SrcImageIterator1 src1_lowerright, SrcAccessor1 sa1,
335 SrcImageIterator2 src2_upperleft, SrcAccessor2 sa2,
336 MaskImageIterator mask_upperleft, MaskAccessor ma,
337 DestImageIterator dest_upperleft, DestAccessor da,
338 Functor const & f)
339 }
340 \endcode
341 use argument objects in conjunction with \ref ArgumentObjectFactories :
342 \code
343 namespace vigra {
344 template <class SrcImageIterator1, class SrcAccessor1,
345 class SrcImageIterator2, class SrcAccessor2,
346 class MaskImageIterator, class MaskAccessor,
347 class DestImageIterator, clas DestAccessor,
348 class Functor>
349 void
350 combineTwoImagesIf(triple<SrcImageIterator1, SrcImageIterator1, SrcAccessor1> src1,
351 pair<SrcImageIterator2, SrcAccessor2> src2,
352 pair<MaskImageIterator, MaskAccessor> mask,
353 pair<DestImageIterator, DestAccessor> dest,
354 Functor const & f)
355 }
356 \endcode
357 \deprecatedEnd
358
359 <b> Usage:</b>
360
361 <b>\#include</b> \<vigra/combineimages.hxx\><br>
362 Namespace: vigra
363
364 \code
365 #include <functional> // for plus
366 MultiArray<2, float> src1(width, height), src2(width, height), mask(width, height),
367 dest(width, height);
368 ... // fill source and mask images
369
370 combineTwoImagesIf(src1, src2, mask, dest,
371 std::plus<float>());
372 \endcode
373
374 \deprecatedUsage{combineTwoImagesIf}
375 \code
376 #include <functional> // for plus
377 FImage src1(width, height), src2(width, height), mask(width, height),
378 dest(width, height);
379 ... // fill source and mask images
380
381 vigra::combineTwoImagesIf(
382 srcIterRange(src1.upperLeft(), src1.lowerRight()),
383 srcIter(src2.upperLeft()),
384 maskIter(mask.upperLeft()),
385 destIter(dest.upperLeft()),
386 std::plus<SrcValueType>());
387
388 \endcode
389 <b> Required Interface:</b>
390 \code
391 SrcImageIterator1 src1_upperleft, src1_lowerright;
392 SrcImageIterator2 src2_upperleft;
393 MaskImageIterator mask_upperleft;
394 DestImageIterator dest_upperleft;
395 SrcImageIterator1::row_iterator sx1 = src1_upperleft.rowIterator();
396 SrcImageIterator2::row_iterator sx2 = src2_upperleft.rowIterator();
397 MaskImageIterator::row_iterator mx = mask_upperleft.rowIterator();
398 DestImageIterator::row_iterator dx = dest_upperleft.rowIterator();
399
400
401 SrcAccessor1 src1_accessor;
402 SrcAccessor2 src2_accessor;
403 MaskAccessor mask_accessor;
404 DestAccessor dest_accessor;
405
406 Functor functor;
407
408 if(mask_accessor(mx))
409 dest_accessor.set(
410 functor(src1_accessor(sx1), src2_accessor(sx2)),
411 dx);
412
413 \endcode
414 \deprecatedEnd
415
416 \see TransformFunctor, MultiMathModule, \ref FunctorExpressions
417 */
doxygen_overloaded_function(template<...> void combineTwoImagesIf)418 doxygen_overloaded_function(template <...> void combineTwoImagesIf)
419
420 template <class SrcImageIterator1, class SrcAccessor1,
421 class SrcImageIterator2, class SrcAccessor2,
422 class MaskImageIterator, class MaskAccessor,
423 class DestImageIterator, class DestAccessor,
424 class Functor>
425 void
426 combineTwoImagesIf(SrcImageIterator1 src1_upperleft,
427 SrcImageIterator1 src1_lowerright, SrcAccessor1 sa1,
428 SrcImageIterator2 src2_upperleft, SrcAccessor2 sa2,
429 MaskImageIterator mask_upperleft, MaskAccessor ma,
430 DestImageIterator dest_upperleft, DestAccessor da,
431 Functor const & f)
432 {
433 int w = src1_lowerright.x - src1_upperleft.x;
434
435 for(; src1_upperleft.y < src1_lowerright.y;
436 ++src1_upperleft.y, ++src2_upperleft.y,
437 ++dest_upperleft.y, ++mask_upperleft.y)
438 {
439 combineTwoLinesIf(src1_upperleft.rowIterator(),
440 src1_upperleft.rowIterator() + w, sa1,
441 src2_upperleft.rowIterator(), sa2,
442 mask_upperleft.rowIterator(), ma,
443 dest_upperleft.rowIterator(), da, f);
444 }
445 }
446
447 template <class SrcImageIterator1, class SrcAccessor1,
448 class SrcImageIterator2, class SrcAccessor2,
449 class MaskImageIterator, class MaskAccessor,
450 class DestImageIterator, class DestAccessor,
451 class Functor>
452 inline
453 void
combineTwoImagesIf(triple<SrcImageIterator1,SrcImageIterator1,SrcAccessor1> src1,pair<SrcImageIterator2,SrcAccessor2> src2,pair<MaskImageIterator,MaskAccessor> mask,pair<DestImageIterator,DestAccessor> dest,Functor const & f)454 combineTwoImagesIf(triple<SrcImageIterator1, SrcImageIterator1, SrcAccessor1> src1,
455 pair<SrcImageIterator2, SrcAccessor2> src2,
456 pair<MaskImageIterator, MaskAccessor> mask,
457 pair<DestImageIterator, DestAccessor> dest,
458 Functor const & f)
459 {
460 combineTwoImagesIf(src1.first, src1.second, src1.third,
461 src2.first, src2.second,
462 mask.first, mask.second,
463 dest.first, dest.second, f);
464 }
465
466 template <class T11, class S11,
467 class T12, class S12,
468 class TM, class SM,
469 class T2, class S2,
470 class Functor>
471 inline void
combineTwoImagesIf(MultiArrayView<2,T11,S11> const & src1,MultiArrayView<2,T12,S12> const & src2,MultiArrayView<2,TM,SM> const & mask,MultiArrayView<2,T2,S2> dest,Functor const & f)472 combineTwoImagesIf(MultiArrayView<2, T11, S11> const & src1,
473 MultiArrayView<2, T12, S12> const & src2,
474 MultiArrayView<2, TM, SM> const & mask,
475 MultiArrayView<2, T2, S2> dest,
476 Functor const & f)
477 {
478 vigra_precondition(src1.shape() == src2.shape() && src1.shape() == mask.shape() && src1.shape() == dest.shape(),
479 "combineTwoImagesIf(): shape mismatch between inputs and/or output.");
480 combineTwoImagesIf(srcImageRange(src1),
481 srcImage(src2),
482 maskImage(mask),
483 destImage(dest), f);
484 }
485
486 /********************************************************/
487 /* */
488 /* combineThreeImages */
489 /* */
490 /********************************************************/
491
492 /** \brief Combine three source images into destination image.
493
494 After the introduction of arithmetic and algebraic \ref MultiMathModule "array expressions",
495 this function is rarely needed. Moreover, \ref combineThreeMultiArrays() provides the
496 same functionality for arbitrary dimensional arrays.
497
498 The transformation given by the functor is applied to the source
499 pixels and the result written into the corresponding destination pixel.
500 Creation of new functors is easiest by using \ref FunctorExpressions.
501
502 <b> Declarations:</b>
503
504 pass 2D array views:
505 \code
506 namespace vigra {
507 template <class T11, class S11,
508 class T12, class S12,
509 class T13, class S13,
510 class T2, class S2,
511 class Functor>
512 void
513 combineThreeImages(MultiArrayView<2, T11, S11> const & src1,
514 MultiArrayView<2, T12, S12> const & src2,
515 MultiArrayView<2, T13, S13> const & src3,
516 MultiArrayView<2, T2, S2> dest,
517 Functor const & f);
518 }
519 \endcode
520
521 \deprecatedAPI{combineThreeImages}
522 pass \ref ImageIterators and \ref DataAccessors :
523 \code
524 namespace vigra {
525 template <class SrcImageIterator1, class SrcAccessor1,
526 class SrcImageIterator2, class SrcAccessor2,
527 class SrcImageIterator3, class SrcAccessor3,
528 class DestImageIterator, class DestAccessor,
529 class Functor>
530 void
531 combineThreeImages(SrcImageIterator1 src1_upperleft,
532 SrcImageIterator1 src1_lowerright, SrcAccessor1 sa1,
533 SrcImageIterator2 src2_upperleft, SrcAccessor2 sa2,
534 SrcImageIterator3 src2_upperleft, SrcAccessor3 sa3,
535 DestImageIterator dest_upperleft, DestAccessor da,
536 Functor const & f)
537 }
538 \endcode
539 use argument objects in conjunction with \ref ArgumentObjectFactories :
540 \code
541 namespace vigra {
542 template <class SrcImageIterator1, class SrcAccessor1,
543 class SrcImageIterator2, class SrcAccessor2,
544 class SrcImageIterator3, class SrcAccessor3,
545 class DestImageIterator, class DestAccessor,
546 class Functor>
547 void
548 combineThreeImages(triple<SrcImageIterator1, SrcImageIterator1, SrcAccessor1> src1,
549 pair<SrcImageIterator2, SrcAccessor2> src2,
550 pair<SrcImageIterator3, SrcAccessor3> src3,
551 pair<DestImageIterator, DestAccessor> dest,
552 Functor const & f)
553 }
554 \endcode
555 \deprecatedEnd
556
557 <b> Usage:</b>
558
559 <b>\#include</b> \<vigra/combineimages.hxx\><br>
560 Namespace: vigra
561
562 \code
563 #include <vigra/functorexpression.hxx>
564
565 MultiArray<2, float> src1(width, height), src2(width, height), src3(width, height),
566 dest(width, height);
567 ... // fill source images
568
569 using namespace vigra::functor; // activate VIGRA's lambda library
570
571 combineThreeImages(src1, src2, src3, dest,
572 Arg1()*exp(-abs(Arg2()-Arg3())));
573 \endcode
574
575 \deprecatedUsage{combineThreeImages}
576 \code
577 FImage src1(width, height), src2(width, height), src3(width, height),
578 dest(width, height);
579 ... // fill source images
580
581 vigra::combineThreeImages(
582 srcIterRange(src1.upperLeft(), src1.lowerRight()),
583 srcIter(src2.upperLeft()),
584 srcIter(src3.upperLeft()),
585 destIter(dest.upperLeft()),
586 SomeThreeArgumentFunctor());
587
588 \endcode
589 <b> Required Interface:</b>
590 \code
591 SrcImageIterator1 src1_upperleft, src1_lowerright;
592 SrcImageIterator2 src2_upperleft;
593 SrcImageIterator3 src3_upperleft;
594 DestImageIterator dest_upperleft;
595 SrcImageIterator1::row_iterator sx1 = src1_upperleft.rowIterator();
596 SrcImageIterator2::row_iterator sx2 = src2_upperleft.rowIterator();
597 SrcImageIterator3::row_iterator sx3 = src3_upperleft.rowIterator();
598 DestImageIterator::row_iterator dx = dest_upperleft.rowIterator();
599
600 SrcAccessor1 src1_accessor;
601 SrcAccessor2 src2_accessor;
602 SrcAccessor3 src3_accessor;
603 DestAccessor dest_accessor;
604
605 Functor functor;
606
607 dest_accessor.set(
608 functor(src1_accessor(sx1),
609 src2_accessor(sx2),
610 src3_accessor(sx3)),
611 dx);
612
613 \endcode
614 \deprecatedEnd
615
616 \see TransformFunctor, MultiMathModule, \ref FunctorExpressions
617 */
doxygen_overloaded_function(template<...> void combineThreeImages)618 doxygen_overloaded_function(template <...> void combineThreeImages)
619
620 template <class SrcImageIterator1, class SrcAccessor1,
621 class SrcImageIterator2, class SrcAccessor2,
622 class SrcImageIterator3, class SrcAccessor3,
623 class DestImageIterator, class DestAccessor,
624 class Functor>
625 void
626 combineThreeImages(SrcImageIterator1 src1_upperleft,
627 SrcImageIterator1 src1_lowerright, SrcAccessor1 sa1,
628 SrcImageIterator2 src2_upperleft, SrcAccessor2 sa2,
629 SrcImageIterator3 src3_upperleft, SrcAccessor3 sa3,
630 DestImageIterator dest_upperleft, DestAccessor da,
631 Functor const & f)
632 {
633 int w = src1_lowerright.x - src1_upperleft.x;
634
635 for(; src1_upperleft.y < src1_lowerright.y;
636 ++src1_upperleft.y, ++src2_upperleft.y, ++src3_upperleft.y,
637 ++dest_upperleft.y)
638 {
639 combineThreeLines(src1_upperleft.rowIterator(),
640 src1_upperleft.rowIterator() + w, sa1,
641 src2_upperleft.rowIterator(), sa2,
642 src3_upperleft.rowIterator(), sa3,
643 dest_upperleft.rowIterator(), da, f);
644 }
645 }
646
647 template <class SrcImageIterator1, class SrcAccessor1,
648 class SrcImageIterator2, class SrcAccessor2,
649 class SrcImageIterator3, class SrcAccessor3,
650 class DestImageIterator, class DestAccessor,
651 class Functor>
652 inline
653 void
combineThreeImages(triple<SrcImageIterator1,SrcImageIterator1,SrcAccessor1> src1,pair<SrcImageIterator2,SrcAccessor2> src2,pair<SrcImageIterator3,SrcAccessor3> src3,pair<DestImageIterator,DestAccessor> dest,Functor const & f)654 combineThreeImages(triple<SrcImageIterator1, SrcImageIterator1, SrcAccessor1> src1,
655 pair<SrcImageIterator2, SrcAccessor2> src2,
656 pair<SrcImageIterator3, SrcAccessor3> src3,
657 pair<DestImageIterator, DestAccessor> dest,
658 Functor const & f)
659 {
660 combineThreeImages(src1.first, src1.second, src1.third,
661 src2.first, src2.second,
662 src3.first, src3.second,
663 dest.first, dest.second, f);
664 }
665
666 template <class T11, class S11,
667 class T12, class S12,
668 class T13, class S13,
669 class T2, class S2,
670 class Functor>
671 inline void
combineThreeImages(MultiArrayView<2,T11,S11> const & src1,MultiArrayView<2,T12,S12> const & src2,MultiArrayView<2,T13,S13> const & src3,MultiArrayView<2,T2,S2> dest,Functor const & f)672 combineThreeImages(MultiArrayView<2, T11, S11> const & src1,
673 MultiArrayView<2, T12, S12> const & src2,
674 MultiArrayView<2, T13, S13> const & src3,
675 MultiArrayView<2, T2, S2> dest,
676 Functor const & f)
677 {
678 vigra_precondition(src1.shape() == src2.shape() && src1.shape() == src3.shape() && src1.shape() == dest.shape(),
679 "combineThreeImages(): shape mismatch between inputs and/or output.");
680 combineThreeImages(srcImageRange(src1),
681 srcImage(src2),
682 srcImage(src3),
683 destImage(dest), f);
684 }
685
686
687 //@}
688
689 /** \addtogroup CombineFunctor Functors to Combine Images
690
691 Common functors with several arguments
692 */
693 //@{
694
695 /********************************************************/
696 /* */
697 /* MagnitudeFunctor */
698 /* */
699 /********************************************************/
700
701 /** Calculate the magnitude from two arguments.
702 Can be used in conjunction with \ref gradientBasedTransform().
703
704 If the gradient is represented by a vector-valued image instead of
705 a pair of scalar images, use \ref vigra::VectorNormFunctor.
706
707 <b> Traits defined:</b>
708
709 <tt>FunctorTraits::isBinaryFunctor</tt> are true (<tt>VigraTrueType</tt>)
710 */
711 template <class ValueType>
712 class MagnitudeFunctor
713 {
714 public:
715 /** the functor's first argument type
716 */
717 typedef ValueType first_argument_type;
718
719 /** the functor's second argument type
720 */
721 typedef ValueType second_argument_type;
722
723 /** the functor's result type
724 */
725 typedef typename SquareRootTraits<typename NormTraits<ValueType>::SquaredNormType>::SquareRootResult result_type;
726
727 /** \deprecated use first_argument_type, second_argument_type, result_type
728 */
729 typedef ValueType value_type;
730
731 /** calculate transform '<TT>sqrt(squaredNorm(v1) + squaredNorm(v2))</TT>'.
732
733 */
operator ()(first_argument_type const & v1,second_argument_type const & v2) const734 result_type operator()(first_argument_type const & v1, second_argument_type const & v2) const
735 {
736 return VIGRA_CSTD::sqrt(squaredNorm(v1) + squaredNorm(v2));
737 }
738 };
739
740 template <class T>
741 class FunctorTraits<MagnitudeFunctor<T> >
742 : public FunctorTraitsBase<MagnitudeFunctor<T> >
743 {
744 public:
745 typedef VigraTrueType isBinaryFunctor;
746 };
747
748 /********************************************************/
749 /* */
750 /* RGBGradientMagnitudeFunctor */
751 /* */
752 /********************************************************/
753
754
755 /** Calculate the gradient magnitude from RGB arguments.
756 Can be used in conjunction with \ref gradientBasedTransform().
757
758 <b> Traits defined:</b>
759
760 <tt>FunctorTraits::isBinaryFunctor</tt> are true (<tt>VigraTrueType</tt>)
761 */
762 template <class ValueType>
763 class RGBGradientMagnitudeFunctor
764 {
765 public:
766 /** the functor's first argument type
767 */
768 typedef RGBValue<ValueType> first_argument_type;
769
770 /** the functor's second argument type
771 */
772 typedef RGBValue<ValueType> second_argument_type;
773
774 /** the functor's result type
775 */
776 typedef typename NumericTraits<ValueType>::RealPromote result_type;
777
778 /** \deprecated use first_argument_type, second_argument_type, result_type
779 */
780 typedef ValueType value_type;
781
782 /** Calculate the gradient magnitude form given RGB components.
783 The function returns
784
785 \f[ \sqrt{|\nabla red|^2 + |\nabla green|^2 + |\nabla blue|^2}
786 \f]
787
788 where \f$|\nabla red|^2\f$ is defined by <TT>gx.red()*gx.red() + gy.red()*gy.red()</TT>.
789
790 <TT>ValueType</TT> (the RGB's component type) must support addition, multiplication,
791 abd <TT>sqrt()</TT>.
792 */
793 result_type
operator ()(first_argument_type const & gx,second_argument_type const & gy) const794 operator()(first_argument_type const & gx, second_argument_type const & gy) const
795 {
796 return VIGRA_CSTD::sqrt(gx.red()*gx.red() + gx.green()*gx.green() +
797 gx.blue()*gx.blue() + gy.red()*gy.red() +
798 gy.green()*gy.green() + gy.blue()*gy.blue());
799 }
800 };
801
802 template <class T>
803 class FunctorTraits<RGBGradientMagnitudeFunctor<T> >
804 : public FunctorTraitsBase<RGBGradientMagnitudeFunctor<T> >
805 {
806 public:
807 typedef VigraTrueType isBinaryFunctor;
808 };
809
810 //@}
811
812 } // namespace vigra
813
814 #endif // VIGRA_COMBINEIMAGES_HXX
815