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