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