vil_resample_nearest.hxx
Go to the documentation of this file.
1 // This is core/vil/vil_resample_nearest.hxx
2 #ifndef vil_resample_nearest_hxx_
3 #define vil_resample_nearest_hxx_
4 //:
5 // \file
6 // \brief Sample image with nearest neighbour interpolation in one image and place in another
7 // \author dac
8 //
9 // The vil nearest neighbour source files were derived from the corresponding
10 // vil bilin files, thus the vil bilin/bicub/nearest source files are very
11 // similar. If you modify something in this file, there is a
12 // corresponding bicub/bilin file that would likely also benefit from
13 // the same change.
14 
15 #include "vil_resample_nearest.h"
16 #include <vil/vil_nearest_interp.h>
17 
18 
19 #ifdef _MSC_VER
20 // Get rid of double to bool conversion warnings
21 #pragma warning( disable : 4800 )
22 #endif
23 
24 //: This function should not be the same in nearest, bicub and bilin
25 inline bool vil_resample_nearest_corner_in_image(double x0, double y0,
26  const vil_image_view_base& image)
27 {
28  return x0 >= 0.0
29  && y0 >= 0.0
30  && x0+1 <= image.ni()
31  && y0+1 <= image.nj();
32 }
33 
34 //: Sample grid of points in one image and place in another, using nearest neighbour interpolation.
35 // dest_image(i,j,p) is sampled from the src_image at
36 // (x0+i.dx1+j.dx2,y0+i.dy1+j.dy2), where i=[0..n1-1], j=[0..n2-1]
37 // dest_image resized to (n1,n2,src_image.nplanes())
38 // Points outside image return zero.
39 // \relatesalso vil_image_view
40 template <class sType, class dType>
42  vil_image_view<dType>& dest_image,
43  double x0, double y0, double dx1, double dy1,
44  double dx2, double dy2, int n1, int n2)
45 {
46  bool all_in_image = vil_resample_nearest_corner_in_image(x0,y0,src_image)
47  && vil_resample_nearest_corner_in_image(x0+(n1-1)*dx1,y0+(n1-1)*dy1,src_image)
48  && vil_resample_nearest_corner_in_image(x0+(n2-1)*dx2,y0+(n2-1)*dy2,src_image)
49  && vil_resample_nearest_corner_in_image(x0+(n1-1)*dx1+(n2-1)*dx2,
50  y0+(n1-1)*dy1+(n2-1)*dy2,src_image);
51 #ifdef DEBUG
52  // corners
53  std::cout<<"src_image= "<<src_image<<std::endl
54  <<"x0="<<x0<<std::endl
55  <<"y0="<<y0<<std::endl
56  <<"x0+(n1-1)*dx1+(n2-1)*dx2="<<x0+(n1-1)*dx1+(n2-1)*dx2<<std::endl
57  <<"y0+(n1-1)*dy1+(n2-1)*dy2="<<y0+(n1-1)*dy1+(n2-1)*dy2<<std::endl;
58 #endif
59 
60  const unsigned ni = src_image.ni();
61  const unsigned nj = src_image.nj();
62  const unsigned np = src_image.nplanes();
63  const std::ptrdiff_t istep = src_image.istep();
64  const std::ptrdiff_t jstep = src_image.jstep();
65  const std::ptrdiff_t pstep = src_image.planestep();
66  const sType* plane0 = src_image.top_left_ptr();
67 
68  dest_image.set_size(n1,n2,np);
69  const std::ptrdiff_t d_istep = dest_image.istep();
70  const std::ptrdiff_t d_jstep = dest_image.jstep();
71  const std::ptrdiff_t d_pstep = dest_image.planestep();
72  dType* d_plane0 = dest_image.top_left_ptr();
73 
74  double x1=x0;
75  double y1=y0;
76 
77  if (all_in_image)
78  {
79  if (np==1)
80  {
81  dType *row = d_plane0;
82  for (int j=0;j<n2;++j,x1+=dx2,y1+=dy2,row+=d_jstep)
83  {
84  double x=x1, y=y1; // Start of j-th row
85  dType *dpt = row;
86  for (int i=0;i<n1;++i,x+=dx1,y+=dy1,dpt+=d_istep)
87  *dpt = (dType) vil_nearest_interp_unsafe(x,y,plane0,ni,nj,istep,jstep);
88  }
89  }
90  else
91  {
92  dType *row = d_plane0;
93  for (int j=0;j<n2;++j,x1+=dx2,y1+=dy2,row+=d_jstep)
94  {
95  double x=x1, y=y1; // Start of j-th row
96  dType *dpt = row;
97  for (int i=0;i<n1;++i,x+=dx1,y+=dy1,dpt+=d_istep)
98  {
99  for (unsigned int p=0;p<np;++p)
100  dpt[p*d_pstep] = (dType) vil_nearest_interp_unsafe(x,y,plane0+p*pstep,ni,nj,istep,jstep);
101  }
102  }
103  }
104  }
105  else
106  {
107  // Use safe interpolation
108  if (np==1)
109  {
110  dType *row = d_plane0;
111  for (int j=0;j<n2;++j,x1+=dx2,y1+=dy2,row+=d_jstep)
112  {
113  double x=x1, y=y1; // Start of j-th row
114  dType *dpt = row;
115  for (int i=0;i<n1;++i,x+=dx1,y+=dy1,dpt+=d_istep)
116  *dpt = (dType) vil_nearest_interp_safe(x,y,plane0,
117  ni,nj,istep,jstep);
118  }
119  }
120  else
121  {
122  dType *row = d_plane0;
123  for (int j=0;j<n2;++j,x1+=dx2,y1+=dy2,row+=d_jstep)
124  {
125  double x=x1, y=y1; // Start of j-th row
126  dType *dpt = row;
127  for (int i=0;i<n1;++i,x+=dx1,y+=dy1,dpt+=d_istep)
128  {
129  for (unsigned int p=0;p<np;++p)
130  dpt[p*d_pstep] = (dType) vil_nearest_interp_safe(x,y,plane0+p*pstep,
131  ni,nj,istep,jstep);
132  }
133  }
134  }
135  }
136 }
137 
138 
139 //: Resample image to a specified width (n1) and height (n2)
140 template <class sType, class dType>
142  vil_image_view<dType>& dest_image,
143  int n1, int n2)
144 {
145  double f= 0.9999999; // so sampler doesn't go off edge of image
146  double x0=0;
147  double y0=0;
148  double dx1=f*(src_image.ni()-1)*1.0/(n1-1);
149  double dy1=0;
150  double dx2=0;
151  double dy2=f*(src_image.nj()-1)*1.0/(n2-1);
152  vil_resample_nearest( src_image, dest_image, x0, y0, dx1, dy1, dx2, dy2, n1, n2 );
153 }
154 
155 
156 //: Sample grid of points in one image and place in another, using bilinear interpolation.
157 // dest_image(i,j,p) is sampled from the src_image at
158 // (x0+i.dx1+j.dx2,y0+i.dy1+j.dy2), where i=[0..n1-1], j=[0..n2-1]
159 // dest_image resized to (n1,n2,src_image.nplanes())
160 // Points outside image return zero.
161 // \relatesalso vil_image_view
162 template <class sType, class dType>
164  const vil_image_view<sType>& src_image,
165  vil_image_view<dType>& dest_image,
166  double x0, double y0, double dx1, double dy1,
167  double dx2, double dy2, int n1, int n2)
168 {
169  bool all_in_image = vil_resample_nearest_corner_in_image(x0,y0,src_image)
170  && vil_resample_nearest_corner_in_image(x0+(n1-1)*dx1,y0+(n1-1)*dy1,src_image)
171  && vil_resample_nearest_corner_in_image(x0+(n2-1)*dx2,y0+(n2-1)*dy2,src_image)
172  && vil_resample_nearest_corner_in_image(x0+(n1-1)*dx1+(n2-1)*dx2,
173  y0+(n1-1)*dy1+(n2-1)*dy2,src_image);
174 #ifdef DEBUG
175  // corners
176  std::cout<<"src_image= "<<src_image<<std::endl
177  <<"x0="<<x0<<std::endl
178  <<"y0="<<y0<<std::endl
179  <<"x0+(n1-1)*dx1+(n2-1)*dx2="<<x0+(n1-1)*dx1+(n2-1)*dx2<<std::endl
180  <<"y0+(n1-1)*dy1+(n2-1)*dy2="<<y0+(n1-1)*dy1+(n2-1)*dy2<<std::endl;
181 #endif
182 
183  const unsigned ni = src_image.ni();
184  const unsigned nj = src_image.nj();
185  const unsigned np = src_image.nplanes();
186  const std::ptrdiff_t istep = src_image.istep();
187  const std::ptrdiff_t jstep = src_image.jstep();
188  const std::ptrdiff_t pstep = src_image.planestep();
189  const sType* plane0 = src_image.top_left_ptr();
190 
191  dest_image.set_size(n1,n2,np);
192  const std::ptrdiff_t d_istep = dest_image.istep();
193  const std::ptrdiff_t d_jstep = dest_image.jstep();
194  const std::ptrdiff_t d_pstep = dest_image.planestep();
195  dType* d_plane0 = dest_image.top_left_ptr();
196 
197  double x1=x0;
198  double y1=y0;
199 
200  if (all_in_image)
201  {
202  if (np==1)
203  {
204  dType *row = d_plane0;
205  for (int j=0;j<n2;++j,x1+=dx2,y1+=dy2,row+=d_jstep)
206  {
207  double x=x1, y=y1; // Start of j-th row
208  dType *dpt = row;
209  for (int i=0;i<n1;++i,x+=dx1,y+=dy1,dpt+=d_istep)
210  *dpt = (dType) vil_nearest_interp(x,y,plane0,ni,nj,istep,jstep);
211  }
212  }
213  else
214  {
215  dType *row = d_plane0;
216  for (int j=0;j<n2;++j,x1+=dx2,y1+=dy2,row+=d_jstep)
217  {
218  double x=x1, y=y1; // Start of j-th row
219  dType *dpt = row;
220  for (int i=0;i<n1;++i,x+=dx1,y+=dy1,dpt+=d_istep)
221  {
222  for (unsigned int p=0;p<np;++p)
223  dpt[p*d_pstep] = (dType) vil_nearest_interp(x,y,plane0+p*pstep,ni,nj,istep,jstep);
224  }
225  }
226  }
227  }
228  else
229  {
230  // Use safe interpolation
231  if (np==1)
232  {
233  dType *row = d_plane0;
234  for (int j=0;j<n2;++j,x1+=dx2,y1+=dy2,row+=d_jstep)
235  {
236  double x=x1, y=y1; // Start of j-th row
237  dType *dpt = row;
238  for (int i=0;i<n1;++i,x+=dx1,y+=dy1,dpt+=d_istep)
239  *dpt = (dType) vil_nearest_interp_safe_extend(
240  x,y,plane0,ni,nj,istep,jstep);
241  }
242  }
243  else
244  {
245  dType *row = d_plane0;
246  for (int j=0;j<n2;++j,x1+=dx2,y1+=dy2,row+=d_jstep)
247  {
248  double x=x1, y=y1; // Start of j-th row
249  dType *dpt = row;
250  for (int i=0;i<n1;++i,x+=dx1,y+=dy1,dpt+=d_istep)
251  {
252  for (unsigned int p=0;p<np;++p)
253  dpt[p*d_pstep] = (dType) vil_nearest_interp_safe_extend(
254  x,y,plane0+p*pstep,ni,nj,istep,jstep);
255  }
256  }
257  }
258  }
259 }
260 
261 
262 //: Resample image to a specified width (n1) and height (n2)
263 template <class sType, class dType>
265  vil_image_view<dType>& dest_image,
266  int n1, int n2)
267 {
268  double f= 0.9999999; // so sampler doesn't go off edge of image
269  double x0=0;
270  double y0=0;
271  double dx1=f*(src_image.ni()-1)*1.0/(n1-1);
272  double dy1=0;
273  double dx2=0;
274  double dy2=f*(src_image.nj()-1)*1.0/(n2-1);
276  src_image, dest_image, x0, y0, dx1, dy1, dx2, dy2, n1, n2 );
277 }
278 #define VIL_RESAMPLE_NEAREST_INSTANTIATE( sType, dType ) \
279 template void vil_resample_nearest(const vil_image_view<sType >& src_image, \
280  vil_image_view<dType >& dest_image, \
281  double x0, double y0, double dx1, double dy1, \
282  double dx2, double dy2, int n1, int n2); \
283 template void vil_resample_nearest(const vil_image_view<sType >& src_image, \
284  vil_image_view<dType >& dest_image, \
285  int n1, int n2); \
286 template void vil_resample_nearest_edge_extend(const vil_image_view<sType >& src_image, \
287  vil_image_view<dType >& dest_image, \
288  double x0, double y0, double dx1, double dy1, \
289  double dx2, double dy2, int n1, int n2); \
290 template void vil_resample_nearest_edge_extend(const vil_image_view<sType >& src_image, \
291  vil_image_view<dType >& dest_image, \
292  int n1, int n2)
293 
294 #endif // vil_resample_nearest_hxx_
An abstract base class of smart pointers to actual image data in memory.
Concrete view of image data of type T held in memory.
Definition: vil_fwd.h:13
void vil_resample_nearest(const vil_image_view< sType > &src_image, vil_image_view< dType > &dest_image, double x0, double y0, double dx1, double dy1, double dx2, double dy2, int n1, int n2)
Sample grid of points in one image and place in another, using nearest neighbour interpolation.
void set_size(unsigned ni, unsigned nj) override
resize current planes to ni x nj.
Sample image with nearest neighbour interpolation in one image and place in another.
T vil_nearest_interp_unsafe(const vil_image_view< T > &view, double x, double y, unsigned p=0)
Compute nearest neighbour interpolation at (x,y), no bound checks. Requires -0.5<=x<ni-0....
std::ptrdiff_t jstep() const
Add this to your pixel pointer to get next j pixel.
unsigned ni() const
Width.
unsigned nj() const
Height.
bool vil_resample_nearest_corner_in_image(double x0, double y0, const vil_image_view_base &image)
This function should not be the same in nearest, bicub and bilin.
std::ptrdiff_t planestep() const
Add this to your pixel pointer to get pixel on next plane.
T vil_nearest_interp_safe_extend(const vil_image_view< T > &view, double x, double y, unsigned p=0)
Compute nearest neighbour interpolation at (x,y), with bound checks.
T vil_nearest_interp(const vil_image_view< T > &view, double x, double y, unsigned p=0)
Compute nearest neighbour interpolation at (x,y), with minimal bound checks.
void vil_resample_nearest_edge_extend(const vil_image_view< sType > &src_image, vil_image_view< dType > &dest_image, double x0, double y0, double dx1, double dy1, double dx2, double dy2, int n1, int n2)
Sample grid of points in one image and place in another, using nearest neighbour interpolation.
T * top_left_ptr()
Pointer to the first (top left in plane 0) pixel.
unsigned nplanes() const
Number of planes.
nearest neighbour interpolation functions for 2D images
T vil_nearest_interp_safe(const vil_image_view< T > &view, double x, double y, unsigned p=0)
Compute nearest neighbour interpolation at (x,y), with bound checks.
std::ptrdiff_t istep() const
Add this to your pixel pointer to get next i pixel.