core/vil/vil_image_view.txx

Go to the documentation of this file.
00001 // This is core/vil/vil_image_view.txx
00002 #ifndef vil_image_view_txx_
00003 #define vil_image_view_txx_
00004 //:
00005 // \file
00006 // \brief Represent images of one or more planes of Ts.
00007 // \author Ian Scott
00008 //
00009 // Note: To keep down size of vil_image_view
00010 // Please think carefully before adding any new methods.
00011 // In particular any methods that provide new views (e.g. vil_plane)
00012 // will be more usefully provided as external functions. - IMS.
00013 // In that case, use the "relates" keyword of Doxygen to link the documentation
00014 // of that function to the vil_image_view class.
00015 //
00016 // \verbatim
00017 //  Modifications
00018 //   23 Oct.2003 - Peter Vanroose - Added support for 64-bit int pixels
00019 // \endvarbatim
00020 
00021 #include "vil_image_view.h"
00022 #include <vcl_string.h>
00023 #include <vcl_cassert.h>
00024 #include <vcl_cstdlib.h>
00025 #include <vcl_cmath.h>
00026 #include <vcl_ostream.h>
00027 #include <vil/vil_pixel_format.h>
00028 #include <vil/vil_exception.h>
00029 #include <vcl_cstring.h>
00030 #include <vcl_algorithm.h>
00031 
00032 //=======================================================================
00033 
00034 
00035 template<class T>
00036 vil_image_view<T>::vil_image_view(unsigned n_i, unsigned n_j, unsigned n_planes,
00037                                   unsigned n_interleaved_planes)
00038 : top_left_(0), istep_(n_interleaved_planes)
00039 {
00040   assert(n_planes==1 || n_interleaved_planes==1);
00041   assert(n_planes * n_interleaved_planes == 1 ||
00042          vil_pixel_format_num_components(vil_pixel_format_of(T())) == 1);
00043   set_size(n_i,n_j,n_planes*n_interleaved_planes);
00044 }
00045 
00046 //: Set this view to look at someone else's memory data.
00047 template<class T>
00048 vil_image_view<T>::vil_image_view(const T* top_left, unsigned n_i, unsigned n_j, unsigned n_planes,
00049                                   vcl_ptrdiff_t i_step, vcl_ptrdiff_t j_step, vcl_ptrdiff_t plane_step)
00050 {
00051   set_to_memory(top_left,n_i,n_j,n_planes,i_step,j_step,plane_step);
00052 }
00053 
00054 //: Set this view to look at another view's data
00055 //  Need to pass the memory chunk to set up the internal smart ptr appropriately
00056 template<class T>
00057 vil_image_view<T>::vil_image_view(vil_memory_chunk_sptr const& mem_chunk,
00058                                   const T* top_left, unsigned n_i, unsigned n_j, unsigned n_planes,
00059                                   vcl_ptrdiff_t i_step, vcl_ptrdiff_t j_step, vcl_ptrdiff_t plane_step)
00060  : vil_image_view_base(n_i, n_j, n_planes)
00061  , top_left_(const_cast<T*>(top_left))
00062  , istep_(i_step), jstep_(j_step)
00063  , planestep_(plane_step)
00064  , ptr_(mem_chunk)
00065 {
00066 #ifndef NDEBUG
00067   // check view and chunk are in rough agreement
00068   if (mem_chunk) // if we are doing a view transform on a non-owned image, then mem_chunk will be 0.
00069   {
00070     if ( mem_chunk->size() < n_planes*n_i*n_j*sizeof(T) )
00071       vcl_cerr << "mem_chunk->size()=" << mem_chunk->size() << '\n'
00072                << "nplanes=" << n_planes << '\n'
00073                << "n_i=" << n_i << '\n'
00074                << "n_j=" << n_j << '\n'
00075                << "sizeof(T)=" << sizeof(T) << '\n'
00076                << "n_planes*n_i*n_j*sizeof(T)=" << n_planes*n_i*n_j*sizeof(T) << '\n';
00077     assert(mem_chunk->size() >= n_planes*n_i*n_j*sizeof(T));
00078     if (top_left  < reinterpret_cast<const T*>(mem_chunk->data()) ||
00079         top_left >= reinterpret_cast<const T*>(reinterpret_cast<const char*>(mem_chunk->data()) + mem_chunk->size()))
00080       vcl_cerr << "top_left at " << static_cast<const void*>(top_left) << ", memory_chunk at "
00081                << reinterpret_cast<const void*>(mem_chunk->data()) << ", size " << mem_chunk->size()
00082                << ", size of data type " << sizeof(T) << '\n';
00083     assert(top_left >= reinterpret_cast<const T*>(mem_chunk->data()) &&
00084            (mem_chunk->size()==0 || top_left  < reinterpret_cast<const T*>(reinterpret_cast<const char*>(mem_chunk->data()) + mem_chunk->size())) );
00085   }
00086 #endif
00087 }
00088 
00089 //: Copy constructor
00090 // If this view cannot set itself to view the other data (e.g. because the
00091 // types are incompatible) it will set itself to empty.
00092 template<class T>
00093 vil_image_view<T>::vil_image_view(const vil_image_view<T>& that)
00094 : vil_image_view_base(that.ni(),that.nj(),that.nplanes()),
00095   top_left_(0), istep_(0), jstep_(0), planestep_(0), ptr_(0)
00096 {
00097   operator=( static_cast<vil_image_view_base const&>(that) );
00098 }
00099 
00100 //: Sort of copy constructor
00101 // If this view cannot set itself to view the other data (e.g. because the
00102 // types are incompatible) it will set itself to empty.
00103 template<class T>
00104 vil_image_view<T>::vil_image_view(const vil_image_view_base& that):
00105 top_left_(0), istep_(0), jstep_(0), planestep_(0), ptr_(0)
00106 {
00107   operator=(that);
00108 }
00109 
00110 //: Sort of copy constructor
00111 // If this view cannot set itself to view the other data (e.g. because the
00112 // types are incompatible) it will set itself to empty.
00113 template <class T>
00114 vil_image_view<T>::vil_image_view(const vil_image_view_base_sptr& that):
00115 top_left_(0), istep_(0), jstep_(0), planestep_(0), ptr_(0)
00116 {
00117   operator=(that);
00118 }
00119 
00120 //: Perform deep copy of the src image, placing in this image
00121 template<class T>
00122 void vil_image_view<T>::deep_copy(const vil_image_view<T>& src)
00123 {
00124   set_size(src.ni(),src.nj(),src.nplanes());
00125 
00126   if (src.is_contiguous() && this->is_contiguous())
00127   {
00128     istep_=src.istep_; jstep_= src.jstep_; planestep_ = src.planestep_;
00129     if (src.istep()>0 && src.jstep()>0 && src.planestep()>=0)
00130     {
00131       vcl_memcpy(top_left_,src.top_left_ptr(),src.size()*sizeof(T));
00132       return;
00133     }
00134     const_iterator s_it = src.begin();
00135     iterator d_it = begin();
00136     const_iterator end_it = src.end();
00137     while (s_it!=end_it) {*d_it = *s_it; ++s_it; ++d_it; }
00138     return;
00139   }
00140 
00141   const vcl_ptrdiff_t s_planestep = src.planestep();
00142   const vcl_ptrdiff_t s_istep = src.istep();
00143   const vcl_ptrdiff_t s_jstep = src.jstep();
00144 
00145   // Do a deep copy
00146   // This is potentially inefficient
00147   const T* src_data = src.top_left_ptr();
00148   T* data = top_left_;
00149   for (unsigned int p=0;p<nplanes_;++p,src_data += s_planestep,data += planestep_)
00150   {
00151     T* row = data;
00152     const T* src_row = src_data;
00153     for (unsigned int j=0;j<nj_;++j,row += jstep_,src_row += s_jstep)
00154     {
00155       T* p = row;
00156       const T* sp = src_row;
00157       for (unsigned int i=0;i<ni_;++i,p+=istep_,sp+=s_istep) *p = *sp;
00158     }
00159   }
00160 }
00161 
00162 // Notes on convert_components_from_planes() and convert_planes_from_components()
00163 // These are used by the operator= to provide the appropriate smart conversion
00164 // behaviour for the various types.
00165 // I don't think that C++ templates support full pattern matching,
00166 // so we have to provide one template instantiation to cover the general
00167 // compound pixel case (the range of which is possibly infinite)
00168 // We then specialise for all the scalar pixel cases (there are only so
00169 // many scalar types).
00170 // I guess someone could merge all the scalar specialisations using
00171 // macros and substantially reduce the length of this code.
00172 
00173 
00174 //: Convert planes to components from planes, or do nothing if types are wrong.
00175 template <class T>
00176 inline bool convert_components_from_planes(vil_image_view<T> &lhs,
00177                                            const vil_image_view_base &rhs_base)
00178 {
00179   typedef typename T::value_type comp_type;
00180 
00181   const int ncomp =
00182     vil_pixel_format_num_components(vil_pixel_format_of(T()));
00183 
00184   vil_pixel_format fmt = vil_pixel_format_of(T());
00185   if (// both sides have equal component types and rhs has scalar pixels and
00186       rhs_base.pixel_format() == vil_pixel_format_component_format(fmt) &&
00187       // lhs has number of components equal to rhs's number of planes.
00188       ncomp == (int)rhs_base.nplanes() )
00189   {
00190     const vil_image_view<comp_type> &rhs = static_cast<const vil_image_view<comp_type>&>(rhs_base);
00191     // Check that the steps are suitable for viewing as components
00192     if (rhs.planestep() != 1 || vcl_abs((int)rhs.istep())<ncomp || vcl_abs((int)rhs.jstep())<ncomp ) return false;
00193     lhs = vil_image_view<T >(rhs.memory_chunk(),
00194                              reinterpret_cast<T const*>(rhs.top_left_ptr()),
00195                              rhs.ni(),rhs.nj(),1,
00196                              rhs.istep()/ncomp,rhs.jstep()/ncomp,1);
00197     return true;
00198   }
00199   else
00200     return false;
00201 }
00202 
00203 
00204 VCL_DEFINE_SPECIALIZATION
00205 inline bool convert_components_from_planes(vil_image_view<float> & /*lhs*/,
00206                                            const vil_image_view_base & /*rhs_base*/)
00207 {return false;}  // when lhs has scalar pixels, don't attempt conversion
00208 
00209 VCL_DEFINE_SPECIALIZATION
00210 inline bool convert_components_from_planes(vil_image_view<double> & /*lhs*/,
00211                                            const vil_image_view_base & /*rhs_base*/)
00212 {return false;}
00213 
00214 VCL_DEFINE_SPECIALIZATION
00215 inline bool convert_components_from_planes(vil_image_view<bool> & /*lhs*/,
00216                                            const vil_image_view_base & /*rhs_base*/)
00217 {return false;}
00218 
00219 VCL_DEFINE_SPECIALIZATION
00220 inline bool convert_components_from_planes(vil_image_view<vxl_sbyte> & /*lhs*/,
00221                                            const vil_image_view_base & /*rhs_base*/)
00222 {return false;}
00223 
00224 VCL_DEFINE_SPECIALIZATION
00225 inline bool convert_components_from_planes(vil_image_view<vxl_byte> & /*lhs*/,
00226                                            const vil_image_view_base & /*rhs_base*/)
00227 {return false;}
00228 
00229 VCL_DEFINE_SPECIALIZATION
00230 inline bool convert_components_from_planes(vil_image_view<vxl_int_16> & /*lhs*/,
00231                                            const vil_image_view_base & /*rhs_base*/)
00232 {return false;}
00233 
00234 VCL_DEFINE_SPECIALIZATION
00235 inline bool convert_components_from_planes(vil_image_view<vxl_uint_16> & /*lhs*/,
00236                                            const vil_image_view_base & /*rhs_base*/)
00237 {return false;}
00238 
00239 VCL_DEFINE_SPECIALIZATION
00240 inline bool convert_components_from_planes(vil_image_view<vxl_int_32> & /*lhs*/,
00241                                            const vil_image_view_base & /*rhs_base*/)
00242 {return false;}
00243 
00244 VCL_DEFINE_SPECIALIZATION
00245 inline bool convert_components_from_planes(vil_image_view<vxl_uint_32> & /*lhs*/,
00246                                            const vil_image_view_base & /*rhs_base*/)
00247 {return false;}
00248 
00249 #if VXL_HAS_INT_64
00250 
00251 VCL_DEFINE_SPECIALIZATION
00252 inline bool convert_components_from_planes(vil_image_view<vxl_int_64> & /*lhs*/,
00253                                            const vil_image_view_base & /*rhs_base*/)
00254 {return false;}
00255 
00256 VCL_DEFINE_SPECIALIZATION
00257 inline bool convert_components_from_planes(vil_image_view<vxl_uint_64> & /*lhs*/,
00258                                            const vil_image_view_base & /*rhs_base*/)
00259 {return false;}
00260 
00261 #endif
00262 
00263 //: Convert components to planes from planes, or do nothing if types are wrong.
00264 template <class T>
00265 inline bool convert_planes_from_components(vil_image_view<T> & /*lhs*/,
00266                                            const vil_image_view_base & /*rhs*/)
00267 { return false;} // when lhs has non-scalar pixels, don't attempt conversion
00268 // except for the following typical cases
00269 VCL_DEFINE_SPECIALIZATION
00270 inline bool convert_planes_from_components(vil_image_view<vil_rgb<vxl_byte> > & lhs,
00271                                            const vil_image_view_base & rhs)
00272 {
00273   if(rhs.nplanes() != 3)
00274     return false;
00275   if(rhs.pixel_format()!=VIL_PIXEL_FORMAT_BYTE)
00276     return false;
00277   unsigned ni = rhs.ni(), nj = rhs.nj();
00278   const vil_image_view<vxl_byte> &rhsv = static_cast<const vil_image_view<vxl_byte>&>(rhs);
00279   lhs= *(new vil_image_view<vil_rgb<vxl_byte> >(ni, nj));
00280   for(unsigned j = 0; j<nj; ++j)
00281     for(unsigned i = 0; i<ni; ++i){
00282       lhs(i,j).r = rhsv(i,j,0); lhs(i, j).g = rhsv(i,j,1); lhs(i, j).b = rhsv(i,j,2);
00283     }
00284   return true;
00285 }
00286 
00287 VCL_DEFINE_SPECIALIZATION
00288 inline bool convert_planes_from_components(vil_image_view<vil_rgba<vxl_uint_16> > & lhs,
00289                                            const vil_image_view_base & rhs)
00290 {
00291   if(rhs.nplanes() != 4)
00292     return false;
00293   if(rhs.pixel_format()!=VIL_PIXEL_FORMAT_UINT_16)
00294     return false;
00295   unsigned ni = rhs.ni(), nj = rhs.nj();
00296   const vil_image_view<vxl_uint_16> &rhsv = static_cast<const vil_image_view<vxl_uint_16>&>(rhs);
00297   lhs = *(new vil_image_view<vil_rgba<vxl_uint_16> >(ni, nj));
00298   for(unsigned j = 0; j<nj; ++j)
00299     for(unsigned i = 0; i<ni; ++i){
00300       lhs(i, j).r = rhsv(i,j,0); lhs(i, j).g = rhsv(i,j,1); lhs(i, j).b = rhsv(i,j,2);
00301       lhs(i, j).a = rhsv(i,j,3);
00302     }
00303  return true;
00304 }
00305 
00306 VCL_DEFINE_SPECIALIZATION
00307 inline bool convert_planes_from_components(vil_image_view<vxl_byte> &lhs,
00308                                            const vil_image_view_base &rhs_base)
00309 {
00310   const unsigned ncomp =
00311     vil_pixel_format_num_components(rhs_base.pixel_format());
00312 
00313   if (// rhs has just 1 plane
00314       rhs_base.nplanes() == 1 &&
00315       // both sides have equal component types
00316       vil_pixel_format_component_format(rhs_base.pixel_format()) == VIL_PIXEL_FORMAT_BYTE)
00317   {
00318     // cheat by casting to component type, not pixel type (because we don't know full pixel type at compile time.)
00319     const vil_image_view<vxl_byte> &rhs = static_cast<const vil_image_view<vxl_byte>&>(rhs_base);
00320 
00321     lhs = vil_image_view<vxl_byte>(rhs.memory_chunk(), rhs.top_left_ptr(),
00322                                    rhs.ni(),rhs.nj(),ncomp,
00323                                    rhs.istep()*ncomp,rhs.jstep()*ncomp,1);
00324     return true;
00325   }
00326   else
00327     return false;
00328 }
00329 
00330 VCL_DEFINE_SPECIALIZATION
00331 inline bool convert_planes_from_components(vil_image_view<vxl_sbyte> &lhs,
00332                                            const vil_image_view_base &rhs_base)
00333 {
00334   const unsigned ncomp =
00335     vil_pixel_format_num_components(rhs_base.pixel_format());
00336 
00337   if (// rhs has just 1 plane
00338       rhs_base.nplanes() == 1 &&
00339       // both sides have equal component types
00340       vil_pixel_format_component_format(rhs_base.pixel_format()) == VIL_PIXEL_FORMAT_SBYTE)
00341   {
00342     // cheat by casting to component type, not pixel type (because we don't know full pixel type at compile time.)
00343     const vil_image_view<vxl_sbyte> &rhs = static_cast<const vil_image_view<vxl_sbyte>&>(rhs_base);
00344 
00345     lhs = vil_image_view<vxl_sbyte>(rhs.memory_chunk(), rhs.top_left_ptr(),
00346                                     rhs.ni(),rhs.nj(),ncomp,
00347                                     rhs.istep()*ncomp,rhs.jstep()*ncomp,1);
00348     return true;
00349   }
00350   else
00351     return false;
00352 }
00353 
00354 VCL_DEFINE_SPECIALIZATION
00355 inline bool convert_planes_from_components(vil_image_view<vxl_uint_16> &lhs,
00356                                            const vil_image_view_base &rhs_base)
00357 {
00358   const unsigned ncomp =
00359     vil_pixel_format_num_components(rhs_base.pixel_format());
00360 
00361   if (// rhs has just 1 plane
00362       rhs_base.nplanes() == 1 &&
00363       // both sides have equal component types
00364       vil_pixel_format_component_format(rhs_base.pixel_format()) == VIL_PIXEL_FORMAT_UINT_16)
00365   {
00366     // cheat by casting to component type, not pixel type (because we don't know full pixel type at compile time.)
00367     const vil_image_view<vxl_uint_16> &rhs = static_cast<const vil_image_view<vxl_uint_16>&>(rhs_base);
00368 
00369     lhs = vil_image_view<vxl_uint_16>(rhs.memory_chunk(), rhs.top_left_ptr(),
00370                                       rhs.ni(),rhs.nj(),ncomp,
00371                                       rhs.istep()*ncomp,rhs.jstep()*ncomp,1);
00372     return true;
00373   }
00374   else
00375     return false;
00376 }
00377 
00378 VCL_DEFINE_SPECIALIZATION
00379 inline bool convert_planes_from_components(vil_image_view<vxl_int_16> &lhs,
00380                                            const vil_image_view_base &rhs_base)
00381 {
00382   const unsigned ncomp =
00383     vil_pixel_format_num_components(rhs_base.pixel_format());
00384 
00385   if (// rhs has just 1 plane
00386       rhs_base.nplanes() == 1 &&
00387       // both sides have equal component types
00388       vil_pixel_format_component_format(rhs_base.pixel_format()) == VIL_PIXEL_FORMAT_INT_16)
00389   {
00390     // cheat by casting to component type, not pixel type (because we don't know full pixel type at compile time.)
00391     const vil_image_view<vxl_int_16> &rhs = static_cast<const vil_image_view<vxl_int_16>&>(rhs_base);
00392 
00393     lhs = vil_image_view<vxl_int_16>(rhs.memory_chunk(), rhs.top_left_ptr(),
00394                                      rhs.ni(),rhs.nj(),ncomp,
00395                                      rhs.istep()*ncomp,rhs.jstep()*ncomp,1);
00396     return true;
00397   }
00398   else
00399     return false;
00400 }
00401 
00402 VCL_DEFINE_SPECIALIZATION
00403 inline bool convert_planes_from_components(vil_image_view<vxl_uint_32> &lhs,
00404                                            const vil_image_view_base &rhs_base)
00405 {
00406   const unsigned ncomp =
00407     vil_pixel_format_num_components(rhs_base.pixel_format());
00408 
00409   if (// rhs has just 1 plane
00410       rhs_base.nplanes() == 1 &&
00411       // both sides have equal component types
00412        vil_pixel_format_component_format(rhs_base.pixel_format()) == VIL_PIXEL_FORMAT_UINT_32)
00413   {
00414     // cheat by casting to component type, not pixel type (because we don't know full pixel type at compile time.)
00415     const vil_image_view<vxl_uint_32> &rhs = static_cast<const vil_image_view<vxl_uint_32>&>(rhs_base);
00416 
00417     lhs = vil_image_view<vxl_uint_32>(rhs.memory_chunk(), rhs.top_left_ptr(),
00418                                       rhs.ni(),rhs.nj(),ncomp,
00419                                       rhs.istep()*ncomp,rhs.jstep()*ncomp,1);
00420     return true;
00421   }
00422   else
00423     return false;
00424 }
00425 
00426 VCL_DEFINE_SPECIALIZATION
00427 inline bool convert_planes_from_components(vil_image_view<vxl_int_32> &lhs,
00428                                            const vil_image_view_base &rhs_base)
00429 {
00430   const unsigned ncomp =
00431     vil_pixel_format_num_components(rhs_base.pixel_format());
00432 
00433   if (// rhs has just 1 plane
00434       rhs_base.nplanes() == 1 &&
00435       // both sides have equal component types
00436       vil_pixel_format_component_format(rhs_base.pixel_format()) == VIL_PIXEL_FORMAT_INT_32)
00437   {
00438     // cheat by casting to component type, not pixel type (because we don't know full pixel type at compile time.)
00439     const vil_image_view<vxl_int_32> &rhs = static_cast<const vil_image_view<vxl_int_32>&>(rhs_base);
00440 
00441     lhs = vil_image_view<vxl_int_32>(rhs.memory_chunk(), rhs.top_left_ptr(),
00442                                      rhs.ni(),rhs.nj(),ncomp,
00443                                      rhs.istep()*ncomp,rhs.jstep()*ncomp,1);
00444     return true;
00445   }
00446   else
00447     return false;
00448 }
00449 
00450 #if VXL_HAS_INT_64
00451 
00452 VCL_DEFINE_SPECIALIZATION
00453 inline bool convert_planes_from_components(vil_image_view<vxl_uint_64> &lhs,
00454                                            const vil_image_view_base &rhs_base)
00455 {
00456   const unsigned ncomp =
00457     vil_pixel_format_num_components(rhs_base.pixel_format());
00458 
00459   if (// rhs has just 1 plane
00460       rhs_base.nplanes() == 1 &&
00461       // both sides have equal component types
00462        vil_pixel_format_component_format(rhs_base.pixel_format()) == VIL_PIXEL_FORMAT_UINT_64)
00463   {
00464     // cheat by casting to component type, not pixel type (because we don't know full pixel type at compile time.)
00465     const vil_image_view<vxl_uint_64> &rhs = static_cast<const vil_image_view<vxl_uint_64>&>(rhs_base);
00466 
00467     lhs = vil_image_view<vxl_uint_64>(rhs.memory_chunk(), rhs.top_left_ptr(),
00468                                       rhs.ni(),rhs.nj(),ncomp,
00469                                       rhs.istep()*ncomp,rhs.jstep()*ncomp,1);
00470     return true;
00471   }
00472   else
00473     return false;
00474 }
00475 
00476 VCL_DEFINE_SPECIALIZATION
00477 inline bool convert_planes_from_components(vil_image_view<vxl_int_64> &lhs,
00478                                            const vil_image_view_base &rhs_base)
00479 {
00480   const unsigned ncomp =
00481     vil_pixel_format_num_components(rhs_base.pixel_format());
00482 
00483   if (// rhs has just 1 plane
00484       rhs_base.nplanes() == 1 &&
00485       // both sides have equal component types
00486       vil_pixel_format_component_format(rhs_base.pixel_format()) == VIL_PIXEL_FORMAT_INT_64)
00487   {
00488     // cheat by casting to component type, not pixel type (because we don't know full pixel type at compile time.)
00489     const vil_image_view<vxl_int_64> &rhs = static_cast<const vil_image_view<vxl_int_64>&>(rhs_base);
00490 
00491     lhs = vil_image_view<vxl_int_64>(rhs.memory_chunk(), rhs.top_left_ptr(),
00492                                      rhs.ni(),rhs.nj(),ncomp,
00493                                      rhs.istep()*ncomp,rhs.jstep()*ncomp,1);
00494     return true;
00495   }
00496   else
00497     return false;
00498 }
00499 
00500 #endif // VXL_HAS_INT_64
00501 
00502 VCL_DEFINE_SPECIALIZATION
00503 inline bool convert_planes_from_components(vil_image_view<float> &lhs,
00504                                            const vil_image_view_base &rhs_base)
00505 {
00506   const unsigned ncomp =
00507     vil_pixel_format_num_components(rhs_base.pixel_format());
00508 
00509   if (// rhs has just 1 plane
00510       rhs_base.nplanes() == 1 &&
00511       // both sides have equal component types
00512       vil_pixel_format_component_format(rhs_base.pixel_format()) == VIL_PIXEL_FORMAT_FLOAT)
00513   {
00514     // cheat by casting to component type, not pixel type (because we don't know full pixel type at compile time.)
00515     const vil_image_view<float> &rhs = static_cast<const vil_image_view<float>&>(rhs_base);
00516 
00517     lhs = vil_image_view<float>(rhs.memory_chunk(), rhs.top_left_ptr(),
00518                                 rhs.ni(),rhs.nj(),ncomp,
00519                                 rhs.istep()*ncomp,rhs.jstep()*ncomp,1);
00520     return true;
00521   }
00522   else
00523     return false;
00524 }
00525 
00526 VCL_DEFINE_SPECIALIZATION
00527 inline bool convert_planes_from_components(vil_image_view<double> &lhs,
00528                                            const vil_image_view_base &rhs_base)
00529 {
00530   const unsigned ncomp =
00531     vil_pixel_format_num_components(rhs_base.pixel_format());
00532 
00533   if (// rhs has just 1 plane
00534       rhs_base.nplanes() == 1 &&
00535       // both sides have equal component types
00536       vil_pixel_format_component_format(rhs_base.pixel_format()) == VIL_PIXEL_FORMAT_DOUBLE)
00537   {
00538     // cheat by casting to component type, not pixel type (because we don't know full pixel type at compile time.)
00539     const vil_image_view<double> &rhs = static_cast<const vil_image_view<double>&>(rhs_base);
00540 
00541     lhs = vil_image_view<double>(rhs.memory_chunk(), rhs.top_left_ptr(),
00542                                  rhs.ni(),rhs.nj(),ncomp,
00543                                  rhs.istep()*ncomp,rhs.jstep()*ncomp,1);
00544     return true;
00545   }
00546   else
00547     return false;
00548 }
00549 
00550 
00551 template<class T>
00552 const vil_image_view<T> & vil_image_view<T>::operator= (const vil_image_view<T> & rhs)
00553 {
00554   return operator=( static_cast<vil_image_view_base const&>(rhs) );
00555 }
00556 
00557 
00558 template<class T>
00559 const vil_image_view<T> & vil_image_view<T>::operator= (const vil_image_view_base & rhs)
00560 {
00561   if (static_cast<const vil_image_view_base*>(this) == &rhs)
00562     return *this;
00563 
00564   if (rhs.pixel_format() == pixel_format())
00565   {
00566     const vil_image_view<T> &that = static_cast<const vil_image_view<T>&>(rhs);
00567     ni_=that.ni_;
00568     nj_=that.nj_;
00569     nplanes_=that.nplanes_;
00570     istep_=that.istep_;
00571     jstep_=that.jstep_;
00572     planestep_=that.planestep_;
00573     top_left_=that.top_left_;
00574     ptr_=that.ptr_;
00575     return *this;
00576   }
00577 
00578   if (convert_components_from_planes(*this, rhs))
00579     return *this;
00580 
00581   if (convert_planes_from_components(*this, rhs))
00582     return *this;
00583 
00584   vil_exception_warning(vil_exception_pixel_formats_incompatible(
00585     rhs.pixel_format(), this->pixel_format(), "vil_image_view::operator =") );
00586   set_to_memory(0, 0, 0, 0, 0, 0, 0);
00587   return *this;
00588 }
00589 
00590 
00591 //=======================================================================
00592 
00593 
00594 template<class T>
00595 void vil_image_view<T>::set_size(unsigned n_i, unsigned n_j)
00596 {
00597   if ( nplanes_ > 0 )
00598     set_size(n_i, n_j, nplanes_);
00599   else
00600     set_size(n_i, n_j, 1);
00601 }
00602 
00603 //: True if data all in one unbroken block and top_left_ptr() is lowest data address
00604 template<class T>
00605 bool vil_image_view<T>::is_contiguous() const
00606 {
00607   // For a contiguous image, the smallest step size should be 1, the
00608   // next step size should be the width of corresponding to the
00609   // smallest step size, and so on. So, sort the step sizes and check
00610   // if this is the case.
00611 
00612   // Sort the step sizes in ascending order, and keep the
00613   // corresponding widths.
00614 
00615   vcl_ptrdiff_t s1, s2, s3;
00616   unsigned n1, n2;
00617   if ( istep_ < jstep_ )
00618     if ( jstep_ < planestep_ )
00619     {
00620       s1 = istep_; s2 = jstep_; s3 = planestep_;
00621       n1 = ni_;    n2 = nj_;  //  n3 = nplanes_;
00622     }
00623     else // planestep_ < jstep_
00624       if ( istep_ < planestep_ )
00625       {
00626         s1 = istep_; s2 = planestep_; s3 = jstep_;
00627         n1 = ni_;    n2 = nplanes_; //  n3 = nj_;
00628       }
00629       else // planestep_ < istep_
00630       {
00631         s1 = planestep_; s2 = istep_; s3 = jstep_;
00632         n1 = nplanes_;   n2 = ni_;  //  n3 = nj_;
00633       }
00634   else // jstep < istep_
00635     if ( jstep_ < planestep_ )
00636       if ( istep_ < planestep_ )
00637       {
00638         s1 = jstep_; s2 = istep_; s3 = planestep_;
00639         n1 = nj_;    n2 = ni_;  //  n3 = nplanes_;
00640       }
00641       else // planestep_ < istep_
00642       {
00643         s1 = jstep_; s2 = planestep_; s3 = istep_;
00644         n1 = nj_;    n2 = nplanes_;  // n3 = ni_;
00645       }
00646     else // planestep_ < jstep_
00647     {
00648       s1 = planestep_; s2 = jstep_; s3 = istep_;
00649       n1 = nplanes_;   n2 = nj_;  //  n3 = ni_;
00650     }
00651 
00652   return s1 == 1 &&
00653          s2 > 0 && unsigned(s2) == n1 &&
00654          s3 > 0 && unsigned(s3) == n1*n2;
00655 }
00656 
00657 //=======================================================================
00658 
00659 template<class T>
00660 void vil_image_view<T>::set_size(unsigned n_i, unsigned n_j, unsigned n_planes)
00661 {
00662   if (n_i==ni_ && n_j==nj_ && n_planes==nplanes_) return;
00663 
00664   release_memory();
00665 
00666   vil_pixel_format fmt = vil_pixel_format_of(T());
00667   ptr_ = new vil_memory_chunk(sizeof(T)*n_planes*n_j*n_i,
00668                               vil_pixel_format_component_format(fmt));
00669 
00670   ni_ = n_i;
00671   nj_ = n_j;
00672   nplanes_ = n_planes;
00673   // When the image view was in interleaved mode before entering this function,
00674   // check whether the new number of planes is the same as the istep_.
00675   // If the two agree, remain in the interleaved mode, which is desired by the constructor.
00676   // Otherwise, make istep_=1 and thus no longer interleaved.
00677   if (istep_==0 || int(istep_) != int(n_planes)) istep_ = 1;
00678   jstep_ = n_i*istep_;
00679   planestep_ = istep_==1 ? n_i*n_j : 1;
00680 
00681   top_left_ = reinterpret_cast<T*>(ptr_->data());
00682   assert( (istep_==1 && (int)planestep_==int(n_i*n_j)) || (planestep_==1 && (int)istep_==(int)n_planes) );
00683 }
00684 
00685 
00686 //: Set this view to look at someone else's memory.
00687 template<class T>
00688 void vil_image_view<T>::set_to_memory(const T* top_left,
00689                                       unsigned n_i, unsigned n_j, unsigned n_planes,
00690                                       vcl_ptrdiff_t i_step, vcl_ptrdiff_t j_step, vcl_ptrdiff_t plane_step)
00691 {
00692   release_memory();
00693   top_left_ = const_cast<T*>(top_left);  // Remove const, as view may end up manipulating data
00694 
00695   ni_ = n_i;
00696   nj_ = n_j;
00697   nplanes_ = n_planes;
00698   istep_ = i_step;
00699   jstep_ = j_step;
00700   planestep_ = plane_step;
00701 }
00702 
00703 
00704 //=======================================================================
00705 //: Fill view with given value
00706 template<class T>
00707 void vil_image_view<T>::fill(T value)
00708 {
00709   T* plane = top_left_;
00710 
00711   if (is_contiguous())
00712   {
00713     vcl_fill(begin(), end(), value);
00714     return;
00715   }
00716 
00717   if (istep_==1)
00718   {
00719     for (unsigned int p=0;p<nplanes_;++p,plane += planestep_)
00720     {
00721       T* row = plane;
00722       for (unsigned int j=0;j<nj_;++j,row += jstep_)
00723       {
00724         int i = ni_;
00725         while (i!=0) { row[--i]=value; }
00726       }
00727     }
00728     return;
00729   }
00730 
00731   if (jstep_==1)
00732   {
00733     for (unsigned int p=0;p<nplanes_;++p,plane += planestep_)
00734     {
00735       T* col = plane;
00736       for (unsigned int i=0;i<ni_;++i,col += istep_)
00737       {
00738         int j = nj_;
00739         while (j!=0) { col[--j]=value; }
00740       }
00741     }
00742     return;
00743   }
00744 
00745   for (unsigned int p=0;p<nplanes_;++p,plane += planestep_)
00746   {
00747     T* row = plane;
00748     for (unsigned int j=0;j<nj_;++j,row += jstep_)
00749     {
00750       T* p = row;
00751       for (unsigned int i=0;i<ni_;++i,p+=istep_) *p = value;
00752     }
00753   }
00754 }
00755 
00756 //=======================================================================
00757 
00758 template<class T>
00759 bool vil_image_view<T>::is_class(vcl_string const& s) const
00760 {
00761   return s==vil_image_view<T>::is_a() || vil_image_view_base::is_class(s);
00762 }
00763 
00764 //=======================================================================
00765 
00766 template<class T>
00767 void vil_image_view<T>::print(vcl_ostream& os) const
00768 {
00769   os<<nplanes_<<" planes, each "<<ni_<<" x "<<nj_;
00770 }
00771 
00772 //=======================================================================
00773 //: True if they share same view of same image data.
00774 //  This does not do a deep equality on image data. If the images point
00775 //  to different image data objects that contain identical images, then
00776 //  the result will still be false.
00777 template<class T>
00778 bool vil_image_view<T>::operator==(const vil_image_view_base &rhs) const
00779 {
00780   if (rhs.pixel_format() != pixel_format()) return false;
00781 
00782   const vil_image_view<T> & other = static_cast<const vil_image_view<T> &>(rhs);
00783 
00784   if (this == &other) return true;
00785 
00786   if (!(bool) *this && !(bool)other) return true;
00787   return ptr_  == other.ptr_ &&
00788     top_left_  == other.top_left_ &&
00789     nplanes_   == other.nplanes_ &&
00790     ni_        == other.ni_ &&
00791     nj_        == other.nj_ &&
00792     (nplanes_ <= 1 || planestep_ == other.planestep_) &&
00793     istep_     == other.istep_ &&
00794     jstep_     == other.jstep_;
00795 }
00796 
00797 //=======================================================================
00798 //: Provides an ordering.
00799 //  Useful for ordered containers.
00800 //  There is no guaranteed meaning to the less than operator, except that
00801 //  (a<b && b<a)  is false and  !(a<b) && !(b<a)  is equivalent to  a==b
00802 template<class T>
00803 bool vil_image_view<T>::operator<(const vil_image_view_base& rhs) const
00804 {
00805   if (rhs.pixel_format() != pixel_format()) return pixel_format() < rhs.pixel_format();
00806 
00807   const vil_image_view<T> & other = static_cast<const vil_image_view<T> &>(rhs);
00808   if (ptr_ != other.ptr_) return ptr_<other.ptr_;
00809   if (!(bool) *this && !(bool)other) return false;
00810   if (nplanes_ != other.nplanes_) return nplanes_ < other.nplanes_;
00811   if (ni_ != other.ni_) return ni_ < other.ni_;
00812   if (nj_ != other.nj_) return nj_ < other.nj_;
00813   if (planestep_ != other.planestep_) return planestep_ < other.planestep_;
00814   if (istep_ != other.istep_) return istep_ < other.istep_;
00815   return jstep_ < other.jstep_;
00816 }
00817 
00818 
00819 //=======================================================================
00820 //: Provides an ordering.
00821 //  Useful for ordered containers.
00822 //  There is no guaranteed meaning to the less than operator, except that
00823 //  (a>b) is equivalent to (b<a)
00824 template<class T>
00825 bool vil_image_view<T>::operator>(const vil_image_view_base& rhs) const
00826 {
00827   if (rhs.pixel_format() != pixel_format()) return pixel_format() > rhs.pixel_format();
00828 
00829   const vil_image_view<T> & other = static_cast<const vil_image_view<T> &>(rhs);
00830 
00831   if (this == &other) return false;
00832 
00833   if (ptr_ != other.ptr_) return ptr_>other.ptr_;
00834   if (!(bool) *this && !(bool)other) return false;
00835   if (nplanes_ != other.nplanes_) return nplanes_ > other.nplanes_;
00836   if (ni_ != other.ni_) return ni_ > other.ni_;
00837   if (nj_ != other.nj_) return nj_ > other.nj_;
00838   if (planestep_ != other.planestep_) return planestep_ > other.planestep_;
00839   if (istep_ != other.istep_) return istep_ > other.istep_;
00840   return jstep_ > other.jstep_;
00841 }
00842 
00843 
00844 //=======================================================================
00845 //: True if the actual images are identical.
00846 // $\bigwedge_{i,j,p} {\textstyle src}(i,j,p) == {\textstyle dest}(i,j,p)$
00847 // The data may be formatted differently in each memory chunk.
00848 //  O(size).
00849 // \relates vil_image_view
00850 template<class T>
00851 bool vil_image_view_deep_equality(const vil_image_view<T> &lhs,
00852                                   const vil_image_view<T> &rhs)
00853 {
00854   if (lhs.nplanes() != rhs.nplanes() ||
00855       lhs.nj() != rhs.nj() ||
00856       lhs.ni() != rhs.ni())
00857     return false;
00858 
00859   for (unsigned p = 0; p < rhs.nplanes(); ++p)
00860     for (unsigned j = 0; j < rhs.nj(); ++j)
00861       for (unsigned i = 0; i < rhs.ni(); ++i)
00862         if (!(rhs(i,j,p) == lhs(i,j,p)))
00863           return false;
00864   return true;
00865 }
00866 
00867 //=======================================================================
00868 
00869 // Specializations must be declared in all translation units where
00870 // they are used.  Since we do not know what instantiations will be
00871 // defined, and each requires a specialization, we define the primary
00872 // template of is_a to call a function that will be declared and
00873 // specialized only in the instantiation translation units.
00874 template <class T> vcl_string vil_image_view_type_name(T*);
00875 
00876 template <class T>
00877 vcl_string vil_image_view<T>::is_a() const
00878 {
00879   return vil_image_view_type_name(static_cast<T*>(0));
00880 }
00881 
00882 #define VIL_IMAGE_VIEW_INSTANTIATE(T) \
00883 VCL_DEFINE_SPECIALIZATION vcl_string vil_image_view_type_name(T*) \
00884 { return vcl_string("vil_image_view<" #T ">"); } \
00885 template class vil_image_view<T >; \
00886 template bool vil_image_view_deep_equality(const vil_image_view<T >&, \
00887                                            const vil_image_view<T >&)
00888 
00889 #endif // vil_image_view_txx_

Generated on Mon Nov 23 05:08:37 2009 for core/vil by  doxygen 1.5.1