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