core/vil/vil_decimate.cxx
Go to the documentation of this file.
00001 // This is core/vil/vil_decimate.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \author Ian Scott.
00008 //
00009 // \verbatim
00010 //  Modifications
00011 //   23 Oct.2003 - Peter Vanroose - Added support for 64-bit int pixels
00012 // \endverbatim
00013 //
00014 //-----------------------------------------------------------------------------
00015 
00016 #include "vil_decimate.h"
00017 #include <vcl_cassert.h>
00018 #include <vil/vil_copy.h>
00019 #include <vil/vil_crop.h>
00020 #include <vil/vil_exception.h>
00021 
00022 static const unsigned long large_image_limit = 1024ul * 1024ul * 8ul; //8M Pixels
00023 
00024 vil_image_resource_sptr vil_decimate(const vil_image_resource_sptr &src,
00025                                      unsigned i_factor,
00026                                      unsigned j_factor)
00027 {
00028   return new vil_decimate_image_resource(src, i_factor, j_factor);
00029 }
00030 
00031 
00032 vil_decimate_image_resource::vil_decimate_image_resource(vil_image_resource_sptr const& src,
00033                                                          unsigned i_factor, unsigned j_factor):
00034   src_(src),
00035   i_factor_(i_factor),
00036   j_factor_(j_factor)
00037 {
00038   assert (i_factor > 0 && j_factor > 0);
00039 }
00040 
00041 
00042 vil_image_view_base_sptr vil_decimate_image_resource::get_copy_view(unsigned i0, unsigned ni,
00043                                                                     unsigned j0, unsigned nj) const
00044 {
00045   if ((unsigned long)i_factor_ * (unsigned long)ni *
00046       (unsigned long)j_factor_ * (unsigned long)nj < large_image_limit)
00047   {
00048     vil_image_view_base_sptr vs = src_->get_copy_view(i0*i_factor_, ni*i_factor_,
00049                                                       j0*j_factor_, nj*j_factor_);
00050     if (!vs) return 0;
00051 
00052     return vil_decimate( vs, i_factor_, j_factor_ );
00053   }
00054   else // do large image case.
00055   {
00056     if ((i0+ni)*i_factor_ > src_->ni() || (j0+nj)*j_factor_ > src_->nj())
00057     {
00058       vil_exception_warning(vil_exception_out_of_bounds(
00059         "vil_decimate_image_resource::get_copy_view") );
00060       return 0;
00061     }
00062 
00063     switch (src_->pixel_format())
00064     {
00065 #define macro( F , T ) \
00066     case F : { \
00067       vil_image_view<T > view(ni,nj,src_->nplanes()); \
00068       for (unsigned j = 0; j < nj; ++j) \
00069         for (unsigned i = 0; i < ni; ++i) { \
00070           vil_image_view<T > pixel=src_->get_view((i+i0)*i_factor_,1,(j+j0)*j_factor_,1); \
00071           assert ((bool)pixel); \
00072           vil_copy_to_window(pixel, view, i, j); } \
00073       return new vil_image_view<T >(view); }
00074 
00075       macro(VIL_PIXEL_FORMAT_BYTE , vxl_byte )
00076       macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00077 #if VXL_HAS_INT_64
00078       macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
00079       macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
00080 #endif
00081       macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00082       macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00083       macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00084       macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00085       macro(VIL_PIXEL_FORMAT_BOOL , bool )
00086       macro(VIL_PIXEL_FORMAT_FLOAT , float )
00087       macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00088       macro(VIL_PIXEL_FORMAT_COMPLEX_FLOAT ,  vcl_complex<float>)
00089       macro(VIL_PIXEL_FORMAT_COMPLEX_DOUBLE , vcl_complex<double>)
00090 #undef macro
00091     default:
00092       vil_exception_warning(vil_exception_unsupported_pixel_format(
00093         src_->pixel_format(), "vil_decimate_image_resource::get_copy_view") );
00094       return 0;
00095     }
00096   }
00097 }
00098 
00099 vil_image_view_base_sptr vil_decimate_image_resource::get_view(unsigned i0, unsigned ni,
00100                                                                unsigned j0, unsigned nj) const
00101 {
00102   if ((unsigned long)i_factor_ * (unsigned long)ni *
00103       (unsigned long)j_factor_ * (unsigned long)nj < large_image_limit)
00104   {
00105     vil_image_view_base_sptr vs = src_->get_view(i0*i_factor_, ni*i_factor_,
00106                                                  j0*j_factor_, nj*j_factor_);
00107     if (!vs) return 0;
00108 
00109     return vil_decimate( vs, i_factor_, j_factor_ );
00110   }
00111   else // do large image case.
00112     return get_copy_view(i0, ni, j0, nj);
00113 }
00114 
00115 vil_image_view_base_sptr vil_decimate(const vil_image_view_base_sptr im, unsigned i_factor,
00116                                       unsigned j_factor)
00117 {
00118   if (j_factor==0) j_factor=i_factor;
00119   switch (im->pixel_format())
00120   {
00121 #define macro( F , T ) \
00122   case F : \
00123     return new vil_image_view<T >(vil_decimate(static_cast<vil_image_view<T >&>(*im), \
00124                                   i_factor, j_factor));
00125 
00126     macro(VIL_PIXEL_FORMAT_BYTE , vxl_byte )
00127     macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00128 #if VXL_HAS_INT_64
00129     macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
00130     macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
00131 #endif
00132     macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00133     macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00134     macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00135     macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00136     macro(VIL_PIXEL_FORMAT_BOOL , bool )
00137     macro(VIL_PIXEL_FORMAT_FLOAT , float )
00138     macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00139     macro(VIL_PIXEL_FORMAT_COMPLEX_FLOAT ,  vcl_complex<float>)
00140     macro(VIL_PIXEL_FORMAT_COMPLEX_DOUBLE , vcl_complex<double>)
00141 #undef macro
00142   default:
00143     vil_exception_warning(vil_exception_unsupported_pixel_format(
00144       im->pixel_format(), "vil_decimate") );
00145     return 0;
00146   }
00147 }
00148 
00149 //: Put the data in this view back into the image source.
00150 #if 1
00151 bool vil_decimate_image_resource::put_view(const vil_image_view_base&, unsigned, unsigned)
00152 {
00153   vil_exception_warning(vil_exception_unsupported_operation(
00154       "vil_decimate_image_resource::put_view") );
00155   return false;
00156 }
00157 #else // disable put_view, because current implementation
00158       // does something really stupid.
00159       // This put_view, should not just modify the pixels
00160       // selected by the decimation, but all the unselected
00161       // pixels around it as well.
00162 bool vil_decimate_image_resource::put_view(const vil_image_view_base& im, unsigned i0,
00163                                            unsigned j0)
00164 {
00165   if ((unsigned long)i_factor_ * (unsigned long)im.ni() *
00166       (unsigned long)j_factor_ * (unsigned long)im.nj() < large_image_limit)
00167   {
00168     vil_image_view_base_sptr vs = src_->get_view(i0*i_factor_, im.ni()*i_factor_,
00169                                                  j0*j_factor_, im.nj()*j_factor_);
00170     if (!vs || im.pixel_format() != vs->pixel_format() ||
00171         im.nplanes() != vs->nplanes())
00172       return false;
00173 
00174     switch (vs->pixel_format())
00175     {
00176   #define macro( F , T ) \
00177     case F : { \
00178       const vil_image_view<T > view = static_cast<const vil_image_view<T >&>(im); \
00179       vil_image_view<T > decimated = \
00180         vil_decimate(static_cast<vil_image_view<T >&>(*vs), i_factor_, j_factor_); \
00181       if (view == decimated) return true; /* If we have already modified the data, do nothing */ \
00182       assert(view.ni() == decimated.ni() && view.nj() == decimated.nj()); \
00183       vil_copy_reformat(view, decimated); \
00184       return src_->put_view(*vs, i0, j0); }
00185 
00186       macro(VIL_PIXEL_FORMAT_BYTE , vxl_byte )
00187       macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00188 #if VXL_HAS_INT_64
00189       macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
00190       macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
00191 #endif
00192       macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00193       macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00194       macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00195       macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00196       macro(VIL_PIXEL_FORMAT_FLOAT , float )
00197       macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00198       macro(VIL_PIXEL_FORMAT_COMPLEX_FLOAT ,  vcl_complex<float>)
00199       macro(VIL_PIXEL_FORMAT_COMPLEX_DOUBLE , vcl_complex<double>)
00200 #undef macro
00201     default:
00202       return false;
00203     }
00204   }
00205   else // do large image case.
00206   {
00207     if ((i0+im.ni())*i_factor_ > src_->ni() || (j0+im.nj())*j_factor_ > src_->nj())
00208       return 0;
00209 
00210     switch (src_->pixel_format())
00211     {
00212 #define macro( F , T )  \
00213     case F : { \
00214       const vil_image_view<T > &view = static_cast<const vil_image_view<T > &>(im); \
00215       for (unsigned j = 0; j < im.nj(); ++j) \
00216         for (unsigned i = 0; i < im.ni(); ++i) { \
00217           vil_image_view<T > pixel=vil_crop(view,i,1,j,1); \
00218           assert ((bool)pixel); \
00219           if (!src_->put_view(pixel, (i0+i)*i_factor_, (j0+j)*j_factor_)) \
00220             return false; } \
00221       return true; }
00222 
00223       macro(VIL_PIXEL_FORMAT_BYTE ,   vxl_byte )
00224       macro(VIL_PIXEL_FORMAT_SBYTE ,  vxl_sbyte )
00225 #if VXL_HAS_INT_64
00226       macro(VIL_PIXEL_FORMAT_UINT_64 ,vxl_uint_64 )
00227       macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
00228 #endif
00229       macro(VIL_PIXEL_FORMAT_UINT_32 ,vxl_uint_32 )
00230       macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00231       macro(VIL_PIXEL_FORMAT_UINT_16 ,vxl_uint_16 )
00232       macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00233       macro(VIL_PIXEL_FORMAT_FLOAT ,  float )
00234       macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00235       macro(VIL_PIXEL_FORMAT_COMPLEX_FLOAT ,  vcl_complex<float>)
00236       macro(VIL_PIXEL_FORMAT_COMPLEX_DOUBLE , vcl_complex<double>)
00237 #undef macro
00238     default:
00239       return false;
00240     }
00241   }
00242 }
00243 #endif // 1