1 // This is core/vil/vil_transform.h
2 #ifndef vil_transform_h_
3 #define vil_transform_h_
4 //:
5 // \file
6 // \brief STL algorithm like methods.
7 // \author Ian Scott.
8 
9 #include <cassert>
10 #ifdef _MSC_VER
11 #  include <vcl_msvc_warnings.h>
12 #endif
13 #include "vil_image_view.h"
14 
15 //: Apply a unary operation to each pixel in image.
16 // \param functor should take a value of type T and return same type
17 // \relatesalso vil_image_view
18 template <class T, class F >
vil_transform(vil_image_view<T> & image,F functor)19 inline void vil_transform(vil_image_view<T >& image, F functor)
20 {
21   const unsigned ni = image.ni(), nj= image.nj(), np = image.nplanes();
22 
23   std::ptrdiff_t istep=image.istep(),jstep=image.jstep(),pstep = image.planestep();
24   T* plane = image.top_left_ptr();
25 
26   if (istep==1)
27   {
28     // Optimise special case
29     for (unsigned p=0;p<np;++p,plane += pstep)
30     {
31       T* row = plane;
32       for (unsigned j=0;j<nj;++j,row += jstep)
33       {
34         T *pixel = row, *end_row = row+ni;
35         for (;pixel!=end_row;++pixel) *pixel = functor(*pixel);
36       }
37     }
38   }
39   else
40   if (jstep==1)
41   {
42     // Optimise special case
43     for (unsigned p=0;p<np;++p,plane += pstep)
44     {
45       T* col = plane;
46       for (unsigned i=0;i<ni;++i,col += istep)
47       {
48         T *pixel = col, *end_col=col+nj;
49         for (;pixel!=end_col;++pixel) *pixel = functor(*pixel);
50       }
51     }
52   }
53   else
54   {
55     // General case
56     for (unsigned p=0;p<np;++p,plane += pstep)
57     {
58       T* row = plane;
59       for (unsigned j=0;j<nj;++j,row += jstep)
60       {
61         T* pixel = row;
62         for (unsigned i=0;i<ni;++i,pixel+=istep)
63           *pixel = functor(*pixel);
64       }
65     }
66   }
67 }
68 
69 
70 //: Apply a unary operation to each pixel in src to get dest.
71 // \param functor should take a value of type inP, and return a value of type outP
72 // \relatesalso vil_image_view
73 template <class inP, class outP, class Op >
vil_transform(const vil_image_view<inP> & src,vil_image_view<outP> & dest,Op functor)74 inline void vil_transform(const vil_image_view<inP >&src, vil_image_view<outP >&dest, Op functor)
75 {
76   const unsigned ni = src.ni(), nj= src.nj(), np = src.nplanes();
77 
78   dest.set_size(ni, nj, np);
79 
80   // Optimise special case;
81   if (dest.istep()==1 && src.istep()==1)
82   {
83     for (unsigned p = 0; p < np; ++p)
84       for (unsigned j = 0; j < nj; ++j)
85       {
86         const inP* src_row = &src(0,j,p);
87         outP* dest_row = &dest(0,j,p);
88         for (unsigned i = 0; i < ni; ++i)
89           dest_row[i] = functor(src_row[i]);
90       }
91     return;
92   }
93 
94   for (unsigned p = 0; p < np; ++p)
95     for (unsigned j = 0; j < nj; ++j)
96       for (unsigned i = 0; i < ni; ++i)
97         dest(i,j,p) = functor(src(i,j,p));
98 }
99 
100 //: Apply a binary function to each pixel in src and dest that modifies dest.
101 // \param functor should take two parameters (inP src, outP &dest);
102 // \relatesalso vil_image_view
103 template <class inP, class outP, class Op >
vil_transform2(const vil_image_view<inP> & src,vil_image_view<outP> & dest,Op functor)104 inline void vil_transform2(const vil_image_view<inP >&src, vil_image_view<outP >&dest, Op functor)
105 {
106   const unsigned ni = src.ni(), nj= src.nj(), np = src.nplanes();
107 
108   dest.set_size(ni, nj, np);
109 
110   // Optimise special case;
111   if (dest.istep()==1 && src.istep()==1)
112   {
113     for (unsigned p = 0; p < np; ++p)
114       for (unsigned j = 0; j < nj; ++j)
115       {
116         const inP* src_row = &src(0,j,p);
117         outP* dest_row = &dest(0,j,p);
118         for (unsigned i = 0; i < ni; ++i)
119           functor(src_row[i],dest_row[i]);
120       }
121     return;
122   }
123 
124   for (unsigned p = 0; p < np; ++p)
125     for (unsigned j = 0; j < nj; ++j)
126       for (unsigned i = 0; i < ni; ++i)
127          functor(src(i,j,p), dest(i,j,p));
128 }
129 
130 
131 //: Apply a binary operation to each pixel in srcA and srcB to get dest.
132 // \relatesalso vil_image_view
133 template <class inA, class inB, class outP, class BinOp >
vil_transform(const vil_image_view<inA> & srcA,const vil_image_view<inB> & srcB,vil_image_view<outP> & dest,BinOp functor)134 inline void vil_transform(const vil_image_view<inA >&srcA,
135                           const vil_image_view<inB >&srcB,
136                           vil_image_view<outP >&dest,
137                           BinOp functor)
138 {
139   assert(srcB.ni() == srcA.ni() && srcA.nj() == srcB.nj() && srcA.nplanes() == srcB.nplanes());
140   dest.set_size(srcA.ni(), srcA.nj(), srcA.nplanes());
141   for (unsigned p = 0; p < srcA.nplanes(); ++p)
142     for (unsigned j = 0; j < srcA.nj(); ++j)
143       for (unsigned i = 0; i < srcA.ni(); ++i)
144         dest(i,j,p) = functor(srcA(i,j,p),srcB(i,j,p));
145 }
146 
147 //: Apply a binary operation to each pixel in srcA and srcB to get dest.
148 // non-const dest version, assumes dest is already correct size.
149 // \relatesalso vil_image_view
150 template <class inA, class inB, class outP, class BinOp >
vil_transform(const vil_image_view<inA> & srcA,const vil_image_view<inB> & srcB,const vil_image_view<outP> & dest,BinOp functor)151 inline void vil_transform(const vil_image_view<inA >&srcA,
152                           const vil_image_view<inB >&srcB,
153                           const vil_image_view<outP >&dest,
154                           BinOp functor)
155 {
156   assert(dest.ni() == srcA.ni() && srcA.nj() == dest.nj() && srcA.nplanes() == dest.nplanes());
157   assert(srcB.ni() == srcA.ni() && srcA.nj() == srcB.nj() && srcA.nplanes() == srcB.nplanes());
158   vil_image_view<outP >& nc_dest = const_cast<vil_image_view<outP >&>(dest);
159   for (unsigned p = 0; p < srcA.nplanes(); ++p)
160     for (unsigned j = 0; j < srcA.nj(); ++j)
161       for (unsigned i = 0; i < srcA.ni(); ++i)
162         nc_dest(i,j,p) = functor(srcA(i,j,p),srcB(i,j,p));
163 }
164 
165 
166 #endif // vil_transform_h_
167