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