00001
00002 #ifndef vil_convolve_1d_h_
00003 #define vil_convolve_1d_h_
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <vcl_compiler.h>
00017 #include <vcl_algorithm.h>
00018 #include <vcl_cstdlib.h>
00019 #include <vcl_cstring.h>
00020 #include <vcl_cassert.h>
00021 #include <vcl_iostream.h>
00022 #include <vil/vil_image_view.h>
00023 #include <vil/vil_image_resource.h>
00024 #include <vil/vil_property.h>
00025
00026
00027
00028
00029
00030
00031 enum vil_convolve_boundary_option
00032 {
00033
00034
00035 vil_convolve_ignore_edge,
00036
00037
00038
00039
00040
00041
00042
00043
00044 vil_convolve_no_extend,
00045
00046
00047
00048
00049
00050
00051
00052
00053 vil_convolve_zero_extend,
00054
00055
00056
00057
00058
00059
00060
00061
00062 vil_convolve_constant_extend,
00063
00064
00065
00066
00067
00068
00069
00070
00071 vil_convolve_periodic_extend,
00072
00073
00074
00075
00076
00077
00078
00079
00080 vil_convolve_reflect_extend,
00081
00082
00083
00084
00085
00086
00087
00088 vil_convolve_trim
00089 };
00090
00091
00092
00093 template <class srcT, class destT, class kernelT, class accumT>
00094 inline void vil_convolve_edge_1d(const srcT* src, unsigned n, vcl_ptrdiff_t s_step,
00095 destT* dest, vcl_ptrdiff_t d_step,
00096 const kernelT* kernel,
00097 vcl_ptrdiff_t k_lo, vcl_ptrdiff_t k_hi,
00098 vcl_ptrdiff_t kstep, accumT,
00099 vil_convolve_boundary_option option)
00100 {
00101 switch (option)
00102 {
00103 case vil_convolve_ignore_edge:
00104 return;
00105 case vil_convolve_no_extend:
00106
00107 for (vcl_ptrdiff_t i=-k_hi;i<0;++i,dest+=d_step)
00108 *dest = 0;
00109 return;
00110 case vil_convolve_zero_extend:
00111
00112
00113 for (vcl_ptrdiff_t i=0;i<k_hi;++i,dest+=d_step)
00114 {
00115 accumT sum = 0;
00116 const srcT* s = src;
00117 const kernelT* k = kernel+i*kstep;
00118 for (vcl_ptrdiff_t j=i;j>=k_lo;--j,s+=s_step,k-=kstep)
00119 sum+= (accumT)((*s)*(*k));
00120 *dest=(destT)sum;
00121 }
00122 return;
00123 case vil_convolve_constant_extend:
00124 {
00125
00126 vcl_ptrdiff_t i_max = k_hi-1;
00127 for (vcl_ptrdiff_t i=0;i<=i_max;++i)
00128 {
00129 accumT sum=0;
00130 for (vcl_ptrdiff_t j=-k_hi;j<=-k_lo;++j)
00131 {
00132 if ((i+j)<0) sum+=(accumT)(src[0]*kernel[j*(-kstep)]);
00133 else sum+=(accumT)(src[(i+j)*s_step]*kernel[j*(-kstep)]);
00134 }
00135 dest[i*d_step]=(destT)sum;
00136 }
00137 return;
00138 }
00139 case vil_convolve_reflect_extend:
00140 {
00141
00142 vcl_ptrdiff_t i_max = k_hi-1;
00143 for (vcl_ptrdiff_t i=0;i<=i_max;++i)
00144 {
00145 accumT sum=0;
00146 for (vcl_ptrdiff_t j=-k_hi;j<=-k_lo;++j)
00147 {
00148 if ((i+j)<0) sum+=(accumT)(src[-(i+j)*s_step]*kernel[j*(-kstep)]);
00149 else sum+=(accumT)(src[(i+j)*s_step]*kernel[j*(-kstep)]);
00150 }
00151 dest[i*d_step]=(destT)sum;
00152 }
00153 return;
00154 }
00155 case vil_convolve_periodic_extend:
00156 {
00157
00158 vcl_ptrdiff_t i_max = k_hi-1;
00159 for (int i=0;i<=i_max;++i)
00160 {
00161 accumT sum=0;
00162 for (vcl_ptrdiff_t j=k_hi;j>=k_lo;--j)
00163 sum+=(accumT)(src[((i-j+n)%n)*s_step]*kernel[j*kstep]);
00164 dest[i*d_step]=(destT)sum;
00165 }
00166 return;
00167 }
00168 case vil_convolve_trim:
00169 {
00170
00171 accumT k_sum_all=0;
00172 for (vcl_ptrdiff_t j=-k_hi;j<=-k_lo;++j) k_sum_all+=(accumT)(kernel[j*(-kstep)]);
00173
00174 vcl_ptrdiff_t i_max = k_hi-1;
00175 for (vcl_ptrdiff_t i=0;i<=i_max;++i)
00176 {
00177 accumT sum=0;
00178 accumT k_sum=0;
00179
00180
00181 for (vcl_ptrdiff_t j=-i;j<=-k_lo;++j)
00182 {
00183 sum+=(accumT)(src[(i+j)*s_step]*kernel[j*(-kstep)]);
00184 k_sum += (accumT)(kernel[j*(-kstep)]);
00185 }
00186 dest[i*d_step]=(destT)(sum*k_sum_all/k_sum);
00187 }
00188 return;
00189 }
00190 default:
00191 vcl_cout<<"ERROR: vil_convolve_edge_1d: "
00192 <<"Sorry, can't deal with supplied edge option.\n";
00193 vcl_abort();
00194 }
00195 }
00196
00197
00198
00199
00200 template <class srcT, class destT, class kernelT, class accumT>
00201 inline void vil_convolve_1d(const srcT* src0, unsigned nx, vcl_ptrdiff_t s_step,
00202 destT* dest0, vcl_ptrdiff_t d_step,
00203 const kernelT* kernel,
00204 vcl_ptrdiff_t k_lo, vcl_ptrdiff_t k_hi,
00205 accumT ac,
00206 vil_convolve_boundary_option start_option,
00207 vil_convolve_boundary_option end_option)
00208 {
00209 assert(k_hi - k_lo < int(nx));
00210
00211
00212 vil_convolve_edge_1d(src0,nx,s_step,dest0,d_step,kernel,k_lo,k_hi,1,ac,start_option);
00213
00214 const kernelT* k_rbegin = kernel+k_hi;
00215 const kernelT* k_rend = kernel+k_lo-1;
00216 assert(k_rbegin >= k_rend);
00217 const srcT* src = src0;
00218
00219 for (destT * dest = dest0 + d_step*k_hi,
00220 * const end_dest = dest0 + d_step*(int(nx)+k_lo);
00221 dest!=end_dest;
00222 dest+=d_step,src+=s_step)
00223 {
00224 accumT sum = 0;
00225 const srcT* s= src;
00226 for (const kernelT *k = k_rbegin;k!=k_rend;--k,s+=s_step)
00227 sum+= (accumT)((*k)*(*s));
00228 *dest = destT(sum);
00229 }
00230
00231
00232 vil_convolve_edge_1d(src0+(nx-1)*s_step,nx,-s_step,
00233 dest0+(nx-1)*d_step,-d_step,
00234 kernel,-k_hi,-k_lo,-1,ac,end_option);
00235 }
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 template <class srcT, class destT, class kernelT, class accumT>
00246 inline void vil_convolve_1d(const vil_image_view<srcT>& src_im,
00247 vil_image_view<destT>& dest_im,
00248 const kernelT* kernel,
00249 vcl_ptrdiff_t k_lo, vcl_ptrdiff_t k_hi,
00250 accumT ac,
00251 vil_convolve_boundary_option start_option,
00252 vil_convolve_boundary_option end_option)
00253 {
00254 unsigned n_i = src_im.ni();
00255 unsigned n_j = src_im.nj();
00256 assert(k_hi - k_lo +1 <= (int) n_i);
00257 vcl_ptrdiff_t s_istep = src_im.istep(), s_jstep = src_im.jstep();
00258
00259 dest_im.set_size(n_i,n_j,src_im.nplanes());
00260 vcl_ptrdiff_t d_istep = dest_im.istep(),d_jstep = dest_im.jstep();
00261
00262 for (unsigned int p=0;p<src_im.nplanes();++p)
00263 {
00264
00265 const srcT* src_row = src_im.top_left_ptr()+p*src_im.planestep();
00266 destT* dest_row = dest_im.top_left_ptr()+p*dest_im.planestep();
00267
00268
00269
00270
00271 if (s_istep == 1)
00272 {
00273 if (d_istep == 1)
00274 for (unsigned int j=0;j<n_j;++j,src_row+=s_jstep,dest_row+=d_jstep)
00275 vil_convolve_1d(src_row,n_i,1, dest_row,1,
00276 kernel,k_lo,k_hi,ac,start_option,end_option);
00277 else
00278 for (unsigned int j=0;j<n_j;++j,src_row+=s_jstep,dest_row+=d_jstep)
00279 vil_convolve_1d(src_row,n_i,1, dest_row,d_istep,
00280 kernel,k_lo,k_hi,ac,start_option,end_option);
00281 }
00282 else
00283 {
00284 if (d_istep == 1)
00285 for (unsigned int j=0;j<n_j;++j,src_row+=s_jstep,dest_row+=d_jstep)
00286 vil_convolve_1d(src_row,n_i,s_istep, dest_row,1,
00287 kernel,k_lo,k_hi,ac,start_option,end_option);
00288 else
00289 for (unsigned int j=0;j<n_j;++j,src_row+=s_jstep,dest_row+=d_jstep)
00290 vil_convolve_1d(src_row,n_i,s_istep, dest_row,d_istep,
00291 kernel,k_lo,k_hi,ac,start_option,end_option);
00292 }
00293 }
00294 }
00295
00296 template <class destT, class kernelT, class accumT>
00297 vil_image_resource_sptr vil_convolve_1d(
00298 const vil_image_resource_sptr& src_im,
00299 const destT dt,
00300 const kernelT* kernel, int k_lo, int k_hi,
00301 const accumT ac,
00302 vil_convolve_boundary_option start_option,
00303 vil_convolve_boundary_option end_option);
00304
00305
00306 template <class kernelT, class accumT, class destT>
00307 class vil_convolve_1d_resource : public vil_image_resource
00308 {
00309
00310
00311 vil_convolve_1d_resource(const vil_image_resource_sptr& src,
00312 const kernelT* kernel, int k_lo, int k_hi,
00313 vil_convolve_boundary_option start_option,
00314 vil_convolve_boundary_option end_option) :
00315 src_(src), kernel_(kernel), klo_(k_lo), khi_(k_hi),
00316 start_option_(start_option), end_option_(end_option)
00317 {
00318
00319 assert (start_option != vil_convolve_periodic_extend ||
00320 end_option != vil_convolve_periodic_extend);
00321 }
00322
00323 friend vil_image_resource_sptr vil_convolve_1d VCL_NULL_TMPL_ARGS (
00324 const vil_image_resource_sptr& src_im, const destT dt, const kernelT* kernel,
00325 int k_lo, int k_hi, const accumT ac,
00326 vil_convolve_boundary_option start_option,
00327 vil_convolve_boundary_option end_option);
00328
00329 public:
00330 virtual vil_image_view_base_sptr get_copy_view(unsigned i0, unsigned n_i,
00331 unsigned j0, unsigned n_j) const
00332 {
00333 if (i0 + n_i > src_->ni() || j0 + n_j > src_->nj()) return 0;
00334 const unsigned lsrc = (unsigned) vcl_max(0,(int)i0 + klo_);
00335 const unsigned hsrc = vcl_min(src_->ni(),i0 + n_i - klo_ + khi_);
00336 const unsigned lboundary = vcl_min((unsigned) -klo_, i0);
00337 assert (hsrc > lsrc);
00338 vil_image_view_base_sptr vs = src_->get_view(lsrc, hsrc-lsrc, j0, n_j);
00339 vil_image_view<destT> dest(vs->ni(), vs->nj(), vs->nplanes());
00340 switch (vs->pixel_format())
00341 {
00342 #define macro( F , T ) \
00343 case F : \
00344 vil_convolve_1d(static_cast<vil_image_view<T >&>(*vs),dest, \
00345 kernel_, klo_, khi_, accumT(), start_option_, end_option_); \
00346 return new vil_image_view<destT>(vil_crop(dest, lboundary, n_i, 0, n_j));
00347
00348 macro(VIL_PIXEL_FORMAT_BYTE , vxl_byte )
00349 macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00350 macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00351 macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00352 macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00353 macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00354 macro(VIL_PIXEL_FORMAT_BOOL , bool )
00355 macro(VIL_PIXEL_FORMAT_FLOAT , float )
00356 macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00357
00358
00359 #undef macro
00360 default:
00361 return 0;
00362 }
00363 }
00364
00365 virtual unsigned nplanes() const { return src_->nplanes(); }
00366 virtual unsigned ni() const { return src_->ni(); }
00367 virtual unsigned nj() const { return src_->nj(); }
00368
00369 virtual enum vil_pixel_format pixel_format() const
00370 { return vil_pixel_format_of(accumT()); }
00371
00372
00373
00374 virtual bool put_view(const vil_image_view_base& , unsigned , unsigned )
00375 {
00376 vcl_cerr << "WARNING: vil_convolve_1d_resource::put_back\n"
00377 << "\tYou can't push data back into a convolve filter.\n";
00378 return false;
00379 }
00380
00381
00382 virtual bool get_property(char const* tag, void* property_value = 0) const
00383 {
00384 if (0==vcl_strcmp(tag, vil_property_read_only))
00385 return property_value ? (*static_cast<bool*>(property_value)) = true : true;
00386
00387 return src_->get_property(tag, property_value);
00388 }
00389
00390 protected:
00391 vil_image_resource_sptr src_;
00392 const kernelT* kernel_;
00393 int klo_, khi_;
00394 vil_convolve_boundary_option start_option_, end_option_;
00395 };
00396
00397
00398
00399
00400
00401
00402 template <class destT, class kernelT, class accumT>
00403 vil_image_resource_sptr vil_convolve_1d(
00404 const vil_image_resource_sptr& src_im,
00405 const destT ,
00406 const kernelT* kernel, int k_lo, int k_hi,
00407 const accumT,
00408 vil_convolve_boundary_option start_option,
00409 vil_convolve_boundary_option end_option)
00410 {
00411 return new vil_convolve_1d_resource<kernelT, accumT, destT>(src_im, kernel, k_lo, k_hi, start_option, end_option);
00412 }
00413
00414 #endif // vil_convolve_1d_h_
00415