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_base*/)
00267 { return false;} // when lhs has non-scalar pixels, don't attempt conversion
00268 
00269 VCL_DEFINE_SPECIALIZATION
00270 inline bool convert_planes_from_components(vil_image_view<vxl_byte> &lhs,
00271                                            const vil_image_view_base &rhs_base)
00272 {
00273   const unsigned ncomp =
00274     vil_pixel_format_num_components(rhs_base.pixel_format());
00275 
00276   if (// rhs has just 1 plane
00277       rhs_base.nplanes() == 1 &&
00278       // both sides have equal component types
00279       vil_pixel_format_component_format(rhs_base.pixel_format()) == VIL_PIXEL_FORMAT_BYTE)
00280   {
00281     // cheat by casting to component type, not pixel type (because we don't know full pixel type at compile time.)
00282     const vil_image_view<vxl_byte> &rhs = static_cast<const vil_image_view<vxl_byte>&>(rhs_base);
00283 
00284     lhs = vil_image_view<vxl_byte>(rhs.memory_chunk(), rhs.top_left_ptr(),
00285                                    rhs.ni(),rhs.nj(),ncomp,
00286                                    rhs.istep()*ncomp,rhs.jstep()*ncomp,1);
00287     return true;
00288   }
00289   else
00290     return false;
00291 }
00292 
00293 VCL_DEFINE_SPECIALIZATION
00294 inline bool convert_planes_from_components(vil_image_view<vxl_sbyte> &lhs,
00295                                            const vil_image_view_base &rhs_base)
00296 {
00297   const unsigned ncomp =
00298     vil_pixel_format_num_components(rhs_base.pixel_format());
00299 
00300   if (// rhs has just 1 plane
00301       rhs_base.nplanes() == 1 &&
00302       // both sides have equal component types
00303       vil_pixel_format_component_format(rhs_base.pixel_format()) == VIL_PIXEL_FORMAT_SBYTE)
00304   {
00305     // cheat by casting to component type, not pixel type (because we don't know full pixel type at compile time.)
00306     const vil_image_view<vxl_sbyte> &rhs = static_cast<const vil_image_view<vxl_sbyte>&>(rhs_base);
00307 
00308     lhs = vil_image_view<vxl_sbyte>(rhs.memory_chunk(), rhs.top_left_ptr(),
00309                                     rhs.ni(),rhs.nj(),ncomp,
00310                                     rhs.istep()*ncomp,rhs.jstep()*ncomp,1);
00311     return true;
00312   }
00313   else
00314     return false;
00315 }
00316 
00317 VCL_DEFINE_SPECIALIZATION
00318 inline bool convert_planes_from_components(vil_image_view<vxl_uint_16> &lhs,
00319                                            const vil_image_view_base &rhs_base)
00320 {
00321   const unsigned ncomp =
00322     vil_pixel_format_num_components(rhs_base.pixel_format());
00323 
00324   if (// rhs has just 1 plane
00325       rhs_base.nplanes() == 1 &&
00326       // both sides have equal component types
00327       vil_pixel_format_component_format(rhs_base.pixel_format()) == VIL_PIXEL_FORMAT_UINT_16)
00328   {
00329     // cheat by casting to component type, not pixel type (because we don't know full pixel type at compile time.)
00330     const vil_image_view<vxl_uint_16> &rhs = static_cast<const vil_image_view<vxl_uint_16>&>(rhs_base);
00331 
00332     lhs = vil_image_view<vxl_uint_16>(rhs.memory_chunk(), rhs.top_left_ptr(),
00333                                       rhs.ni(),rhs.nj(),ncomp,
00334                                       rhs.istep()*ncomp,rhs.jstep()*ncomp,1);
00335     return true;
00336   }
00337   else
00338     return false;
00339 }
00340 
00341 VCL_DEFINE_SPECIALIZATION
00342 inline bool convert_planes_from_components(vil_image_view<vxl_int_16> &lhs,
00343                                            const vil_image_view_base &rhs_base)
00344 {
00345   const unsigned ncomp =
00346     vil_pixel_format_num_components(rhs_base.pixel_format());
00347 
00348   if (// rhs has just 1 plane
00349       rhs_base.nplanes() == 1 &&
00350       // both sides have equal component types
00351       vil_pixel_format_component_format(rhs_base.pixel_format()) == VIL_PIXEL_FORMAT_INT_16)
00352   {
00353     // cheat by casting to component type, not pixel type (because we don't know full pixel type at compile time.)
00354     const vil_image_view<vxl_int_16> &rhs = static_cast<const vil_image_view<vxl_int_16>&>(rhs_base);
00355 
00356     lhs = vil_image_view<vxl_int_16>(rhs.memory_chunk(), rhs.top_left_ptr(),
00357                                      rhs.ni(),rhs.nj(),ncomp,
00358                                      rhs.istep()*ncomp,rhs.jstep()*ncomp,1);
00359     return true;
00360   }
00361   else
00362     return false;
00363 }
00364 
00365 VCL_DEFINE_SPECIALIZATION
00366 inline bool convert_planes_from_components(vil_image_view<vxl_uint_32> &lhs,
00367                                            const vil_image_view_base &rhs_base)
00368 {
00369   const unsigned ncomp =
00370     vil_pixel_format_num_components(rhs_base.pixel_format());
00371 
00372   if (// rhs has just 1 plane
00373       rhs_base.nplanes() == 1 &&
00374       // both sides have equal component types
00375        vil_pixel_format_component_format(rhs_base.pixel_format()) == VIL_PIXEL_FORMAT_UINT_32)
00376   {
00377     // cheat by casting to component type, not pixel type (because we don't know full pixel type at compile time.)
00378     const vil_image_view<vxl_uint_32> &rhs = static_cast<const vil_image_view<vxl_uint_32>&>(rhs_base);
00379 
00380     lhs = vil_image_view<vxl_uint_32>(rhs.memory_chunk(), rhs.top_left_ptr(),
00381                                       rhs.ni(),rhs.nj(),ncomp,
00382                                       rhs.istep()*ncomp,rhs.jstep()*ncomp,1);
00383     return true;
00384   }
00385   else
00386     return false;
00387 }
00388 
00389 VCL_DEFINE_SPECIALIZATION
00390 inline bool convert_planes_from_components(vil_image_view<vxl_int_32> &lhs,
00391                                            const vil_image_view_base &rhs_base)
00392 {
00393   const unsigned ncomp =
00394     vil_pixel_format_num_components(rhs_base.pixel_format());
00395 
00396   if (// rhs has just 1 plane
00397       rhs_base.nplanes() == 1 &&
00398       // both sides have equal component types
00399       vil_pixel_format_component_format(rhs_base.pixel_format()) == VIL_PIXEL_FORMAT_INT_32)
00400   {
00401     // cheat by casting to component type, not pixel type (because we don't know full pixel type at compile time.)
00402     const vil_image_view<vxl_int_32> &rhs = static_cast<const vil_image_view<vxl_int_32>&>(rhs_base);
00403 
00404     lhs = vil_image_view<vxl_int_32>(rhs.memory_chunk(), rhs.top_left_ptr(),
00405                                      rhs.ni(),rhs.nj(),ncomp,
00406                                      rhs.istep()*ncomp,rhs.jstep()*ncomp,1);
00407     return true;
00408   }
00409   else
00410     return false;
00411 }
00412 
00413 #if VXL_HAS_INT_64
00414 
00415 VCL_DEFINE_SPECIALIZATION
00416 inline bool convert_planes_from_components(vil_image_view<vxl_uint_64> &lhs,
00417                                            const vil_image_view_base &rhs_base)
00418 {
00419   const unsigned ncomp =
00420     vil_pixel_format_num_components(rhs_base.pixel_format());
00421 
00422   if (// rhs has just 1 plane
00423       rhs_base.nplanes() == 1 &&
00424       // both sides have equal component types
00425        vil_pixel_format_component_format(rhs_base.pixel_format()) == VIL_PIXEL_FORMAT_UINT_64)
00426   {
00427     // cheat by casting to component type, not pixel type (because we don't know full pixel type at compile time.)
00428     const vil_image_view<vxl_uint_64> &rhs = static_cast<const vil_image_view<vxl_uint_64>&>(rhs_base);
00429 
00430     lhs = vil_image_view<vxl_uint_64>(rhs.memory_chunk(), rhs.top_left_ptr(),
00431                                       rhs.ni(),rhs.nj(),ncomp,
00432                                       rhs.istep()*ncomp,rhs.jstep()*ncomp,1);
00433     return true;
00434   }
00435   else
00436     return false;
00437 }
00438 
00439 VCL_DEFINE_SPECIALIZATION
00440 inline bool convert_planes_from_components(vil_image_view<vxl_int_64> &lhs,
00441                                            const vil_image_view_base &rhs_base)
00442 {
00443   const unsigned ncomp =
00444     vil_pixel_format_num_components(rhs_base.pixel_format());
00445 
00446   if (// rhs has just 1 plane
00447       rhs_base.nplanes() == 1 &&
00448       // both sides have equal component types
00449       vil_pixel_format_component_format(rhs_base.pixel_format()) == VIL_PIXEL_FORMAT_INT_64)
00450   {
00451     // cheat by casting to component type, not pixel type (because we don't know full pixel type at compile time.)
00452     const vil_image_view<vxl_int_64> &rhs = static_cast<const vil_image_view<vxl_int_64>&>(rhs_base);
00453 
00454     lhs = vil_image_view<vxl_int_64>(rhs.memory_chunk(), rhs.top_left_ptr(),
00455                                      rhs.ni(),rhs.nj(),ncomp,
00456                                      rhs.istep()*ncomp,rhs.jstep()*ncomp,1);
00457     return true;
00458   }
00459   else
00460     return false;
00461 }
00462 
00463 #endif // VXL_HAS_INT_64
00464 
00465 VCL_DEFINE_SPECIALIZATION
00466 inline bool convert_planes_from_components(vil_image_view<float> &lhs,
00467                                            const vil_image_view_base &rhs_base)
00468 {
00469   const unsigned ncomp =
00470     vil_pixel_format_num_components(rhs_base.pixel_format());
00471 
00472   if (// rhs has just 1 plane
00473       rhs_base.nplanes() == 1 &&
00474       // both sides have equal component types
00475       vil_pixel_format_component_format(rhs_base.pixel_format()) == VIL_PIXEL_FORMAT_FLOAT)
00476   {
00477     // cheat by casting to component type, not pixel type (because we don't know full pixel type at compile time.)
00478     const vil_image_view<float> &rhs = static_cast<const vil_image_view<float>&>(rhs_base);
00479 
00480     lhs = vil_image_view<float>(rhs.memory_chunk(), rhs.top_left_ptr(),
00481                                 rhs.ni(),rhs.nj(),ncomp,
00482                                 rhs.istep()*ncomp,rhs.jstep()*ncomp,1);
00483     return true;
00484   }
00485   else
00486     return false;
00487 }
00488 
00489 VCL_DEFINE_SPECIALIZATION
00490 inline bool convert_planes_from_components(vil_image_view<double> &lhs,
00491                                            const vil_image_view_base &rhs_base)
00492 {
00493   const unsigned ncomp =
00494     vil_pixel_format_num_components(rhs_base.pixel_format());
00495 
00496   if (// rhs has just 1 plane
00497       rhs_base.nplanes() == 1 &&
00498       // both sides have equal component types
00499       vil_pixel_format_component_format(rhs_base.pixel_format()) == VIL_PIXEL_FORMAT_DOUBLE)
00500   {
00501     // cheat by casting to component type, not pixel type (because we don't know full pixel type at compile time.)
00502     const vil_image_view<double> &rhs = static_cast<const vil_image_view<double>&>(rhs_base);
00503 
00504     lhs = vil_image_view<double>(rhs.memory_chunk(), rhs.top_left_ptr(),
00505                                  rhs.ni(),rhs.nj(),ncomp,
00506                                  rhs.istep()*ncomp,rhs.jstep()*ncomp,1);
00507     return true;
00508   }
00509   else
00510     return false;
00511 }
00512 
00513 
00514 template<class T>
00515 const vil_image_view<T> & vil_image_view<T>::operator= (const vil_image_view<T> & rhs)
00516 {
00517   return operator=( static_cast<vil_image_view_base const&>(rhs) );
00518 }
00519 
00520 
00521 template<class T>
00522 const vil_image_view<T> & vil_image_view<T>::operator= (const vil_image_view_base & rhs)
00523 {
00524   if (static_cast<const vil_image_view_base*>(this) == &rhs)
00525     return *this;
00526 
00527   if (rhs.pixel_format() == pixel_format())
00528   {
00529     const vil_image_view<T> &that = static_cast<const vil_image_view<T>&>(rhs);
00530     ni_=that.ni_;
00531     nj_=that.nj_;
00532     nplanes_=that.nplanes_;
00533     istep_=that.istep_;
00534     jstep_=that.jstep_;
00535     planestep_=that.planestep_;
00536     top_left_=that.top_left_;
00537     ptr_=that.ptr_;
00538     return *this;
00539   }
00540 
00541   if (convert_components_from_planes(*this, rhs))
00542     return *this;
00543 
00544   if (convert_planes_from_components(*this, rhs))
00545     return *this;
00546 
00547   vil_exception_warning(vil_exception_pixel_formats_incompatible(
00548     rhs.pixel_format(), this->pixel_format(), "vil_image_view::operator =") );
00549   set_to_memory(0, 0, 0, 0, 0, 0, 0);
00550   return *this;
00551 }
00552 
00553 
00554 //=======================================================================
00555 
00556 
00557 template<class T>
00558 void vil_image_view<T>::set_size(unsigned n_i, unsigned n_j)
00559 {
00560   if ( nplanes_ > 0 )
00561     set_size(n_i, n_j, nplanes_);
00562   else
00563     set_size(n_i, n_j, 1);
00564 }
00565 
00566 //: True if data all in one unbroken block and top_left_ptr() is lowest data address
00567 template<class T>
00568 bool vil_image_view<T>::is_contiguous() const
00569 {
00570   // For a contiguous image, the smallest step size should be 1, the
00571   // next step size should be the width of corresponding to the
00572   // smallest step size, and so on. So, sort the step sizes and check
00573   // if this is the case.
00574 
00575   // Sort the step sizes in ascending order, and keep the
00576   // corresponding widths.
00577 
00578   vcl_ptrdiff_t s1, s2, s3;
00579   unsigned n1, n2;
00580   if ( istep_ < jstep_ )
00581     if ( jstep_ < planestep_ )
00582     {
00583       s1 = istep_; s2 = jstep_; s3 = planestep_;
00584       n1 = ni_;    n2 = nj_;  //  n3 = nplanes_;
00585     }
00586     else // planestep_ < jstep_
00587       if ( istep_ < planestep_ )
00588       {
00589         s1 = istep_; s2 = planestep_; s3 = jstep_;
00590         n1 = ni_;    n2 = nplanes_; //  n3 = nj_;
00591       }
00592       else // planestep_ < istep_
00593       {
00594         s1 = planestep_; s2 = istep_; s3 = jstep_;
00595         n1 = nplanes_;   n2 = ni_;  //  n3 = nj_;
00596       }
00597   else // jstep < istep_
00598     if ( jstep_ < planestep_ )
00599       if ( istep_ < planestep_ )
00600       {
00601         s1 = jstep_; s2 = istep_; s3 = planestep_;
00602         n1 = nj_;    n2 = ni_;  //  n3 = nplanes_;
00603       }
00604       else // planestep_ < istep_
00605       {
00606         s1 = jstep_; s2 = planestep_; s3 = istep_;
00607         n1 = nj_;    n2 = nplanes_;  // n3 = ni_;
00608       }
00609     else // planestep_ < jstep_
00610     {
00611       s1 = planestep_; s2 = jstep_; s3 = istep_;
00612       n1 = nplanes_;   n2 = nj_;  //  n3 = ni_;
00613     }
00614 
00615   return s1 == 1 &&
00616          s2 > 0 && unsigned(s2) == n1 &&
00617          s3 > 0 && unsigned(s3) == n1*n2;
00618 }
00619 
00620 //=======================================================================
00621 
00622 template<class T>
00623 void vil_image_view<T>::set_size(unsigned n_i, unsigned n_j, unsigned n_planes)
00624 {
00625   if (n_i==ni_ && n_j==nj_ && n_planes==nplanes_) return;
00626 
00627   release_memory();
00628 
00629   vil_pixel_format fmt = vil_pixel_format_of(T());
00630   ptr_ = new vil_memory_chunk(sizeof(T)*n_planes*n_j*n_i,
00631                               vil_pixel_format_component_format(fmt));
00632 
00633   ni_ = n_i;
00634   nj_ = n_j;
00635   nplanes_ = n_planes;
00636   if (istep_==0) istep_ = 1;
00637   jstep_ = n_i*istep_;
00638   planestep_ = istep_==1 ? n_i*n_j : 1;
00639 
00640   top_left_ = reinterpret_cast<T*>(ptr_->data());
00641 }
00642 
00643 
00644 //: Set this view to look at someone else's memory.
00645 template<class T>
00646 void vil_image_view<T>::set_to_memory(const T* top_left,
00647                                       unsigned n_i, unsigned n_j, unsigned n_planes,
00648                                       vcl_ptrdiff_t i_step, vcl_ptrdiff_t j_step, vcl_ptrdiff_t plane_step)
00649 {
00650   release_memory();
00651   top_left_ = const_cast<T*>(top_left);  // Remove const, as view may end up manipulating data
00652 
00653   ni_ = n_i;
00654   nj_ = n_j;
00655   nplanes_ = n_planes;
00656   istep_ = i_step;
00657   jstep_ = j_step;
00658   planestep_ = plane_step;
00659 }
00660 
00661 
00662 //=======================================================================
00663 //: Fill view with given value
00664 template<class T>
00665 void vil_image_view<T>::fill(T value)
00666 {
00667   T* plane = top_left_;
00668 
00669   if (is_contiguous())
00670   {
00671     vcl_fill(begin(), end(), value);
00672     return;
00673   }
00674 
00675   if (istep_==1)
00676   {
00677     for (unsigned int p=0;p<nplanes_;++p,plane += planestep_)
00678     {
00679       T* row = plane;
00680       for (unsigned int j=0;j<nj_;++j,row += jstep_)
00681       {
00682         int i = ni_;
00683         while (i!=0) { row[--i]=value; }
00684       }
00685     }
00686     return;
00687   }
00688 
00689   if (jstep_==1)
00690   {
00691     for (unsigned int p=0;p<nplanes_;++p,plane += planestep_)
00692     {
00693       T* col = plane;
00694       for (unsigned int i=0;i<ni_;++i,col += istep_)
00695       {
00696         int j = nj_;
00697         while (j!=0) { col[--j]=value; }
00698       }
00699     }
00700     return;
00701   }
00702 
00703   for (unsigned int p=0;p<nplanes_;++p,plane += planestep_)
00704   {
00705     T* row = plane;
00706     for (unsigned int j=0;j<nj_;++j,row += jstep_)
00707     {
00708       T* p = row;
00709       for (unsigned int i=0;i<ni_;++i,p+=istep_) *p = value;
00710     }
00711   }
00712 }
00713 
00714 //=======================================================================
00715 
00716 template<class T>
00717 bool vil_image_view<T>::is_class(vcl_string const& s) const
00718 {
00719   return s==vil_image_view<T>::is_a() || vil_image_view_base::is_class(s);
00720 }
00721 
00722 //=======================================================================
00723 
00724 template<class T>
00725 void vil_image_view<T>::print(vcl_ostream& os) const
00726 {
00727   os<<nplanes_<<" planes, each "<<ni_<<" x "<<nj_;
00728 }
00729 
00730 //=======================================================================
00731 //: True if they share same view of same image data.
00732 //  This does not do a deep equality on image data. If the images point
00733 //  to different image data objects that contain identical images, then
00734 //  the result will still be false.
00735 template<class T>
00736 bool vil_image_view<T>::operator==(const vil_image_view_base &rhs) const
00737 {
00738   if (rhs.pixel_format() != pixel_format()) return false;
00739 
00740   const vil_image_view<T> & other = static_cast<const vil_image_view<T> &>(rhs);
00741 
00742   if (this == &other) return true;
00743 
00744   if (!(bool) *this && !(bool)other) return true;
00745   return ptr_  == other.ptr_ &&
00746     top_left_  == other.top_left_ &&
00747     nplanes_   == other.nplanes_ &&
00748     ni_        == other.ni_ &&
00749     nj_        == other.nj_ &&
00750     (nplanes_ <= 1 || planestep_ == other.planestep_) &&
00751     istep_     == other.istep_ &&
00752     jstep_     == other.jstep_;
00753 }
00754 
00755 //=======================================================================
00756 //: Provides an ordering.
00757 //  Useful for ordered containers.
00758 //  There is no guaranteed meaning to the less than operator, except that
00759 //  (a<b && b<a)  is false and  !(a<b) && !(b<a)  is equivalent to  a==b
00760 template<class T>
00761 bool vil_image_view<T>::operator<(const vil_image_view_base& rhs) const
00762 {
00763   if (rhs.pixel_format() != pixel_format()) return pixel_format() < rhs.pixel_format();
00764 
00765   const vil_image_view<T> & other = static_cast<const vil_image_view<T> &>(rhs);
00766   if (ptr_ != other.ptr_) return ptr_<other.ptr_;
00767   if (!(bool) *this && !(bool)other) return false;
00768   if (nplanes_ != other.nplanes_) return nplanes_ < other.nplanes_;
00769   if (ni_ != other.ni_) return ni_ < other.ni_;
00770   if (nj_ != other.nj_) return nj_ < other.nj_;
00771   if (planestep_ != other.planestep_) return planestep_ < other.planestep_;
00772   if (istep_ != other.istep_) return istep_ < other.istep_;
00773   return jstep_ < other.jstep_;
00774 }
00775 
00776 
00777 //=======================================================================
00778 //: Provides an ordering.
00779 //  Useful for ordered containers.
00780 //  There is no guaranteed meaning to the less than operator, except that
00781 //  (a>b) is equivalent to (b<a)
00782 template<class T>
00783 bool vil_image_view<T>::operator>(const vil_image_view_base& rhs) const
00784 {
00785   if (rhs.pixel_format() != pixel_format()) return pixel_format() > rhs.pixel_format();
00786 
00787   const vil_image_view<T> & other = static_cast<const vil_image_view<T> &>(rhs);
00788 
00789   if (this == &other) return false;
00790 
00791   if (ptr_ != other.ptr_) return ptr_>other.ptr_;
00792   if (!(bool) *this && !(bool)other) return false;
00793   if (nplanes_ != other.nplanes_) return nplanes_ > other.nplanes_;
00794   if (ni_ != other.ni_) return ni_ > other.ni_;
00795   if (nj_ != other.nj_) return nj_ > other.nj_;
00796   if (planestep_ != other.planestep_) return planestep_ > other.planestep_;
00797   if (istep_ != other.istep_) return istep_ > other.istep_;
00798   return jstep_ > other.jstep_;
00799 }
00800 
00801 
00802 //=======================================================================
00803 //: True if the actual images are identical.
00804 // $\bigwedge_{i,j,p} {\textstyle src}(i,j,p) == {\textstyle dest}(i,j,p)$
00805 // The data may be formatted differently in each memory chunk.
00806 //  O(size).
00807 // \relates vil_image_view
00808 template<class T>
00809 bool vil_image_view_deep_equality(const vil_image_view<T> &lhs,
00810                                   const vil_image_view<T> &rhs)
00811 {
00812   if (lhs.nplanes() != rhs.nplanes() ||
00813       lhs.nj() != rhs.nj() ||
00814       lhs.ni() != rhs.ni())
00815     return false;
00816 
00817   for (unsigned p = 0; p < rhs.nplanes(); ++p)
00818     for (unsigned j = 0; j < rhs.nj(); ++j)
00819       for (unsigned i = 0; i < rhs.ni(); ++i)
00820         if (!(rhs(i,j,p) == lhs(i,j,p)))
00821           return false;
00822   return true;
00823 }
00824 
00825 //=======================================================================
00826 
00827 // Specializations must be declared in all translation units where
00828 // they are used.  Since we do not know what instantiations will be
00829 // defined, and each requires a specialization, we define the primary
00830 // template of is_a to call a function that will be declared and
00831 // specialized only in the instantiation translation units.
00832 template <class T> vcl_string vil_image_view_type_name(T*);
00833 
00834 template <class T>
00835 vcl_string vil_image_view<T>::is_a() const
00836 {
00837   return vil_image_view_type_name(static_cast<T*>(0));
00838 }
00839 
00840 #define VIL_IMAGE_VIEW_INSTANTIATE(T) \
00841 VCL_DEFINE_SPECIALIZATION vcl_string vil_image_view_type_name(T*) \
00842 { return vcl_string("vil_image_view<" #T ">"); } \
00843 template class vil_image_view<T >; \
00844 template bool vil_image_view_deep_equality(const vil_image_view<T >&, \
00845                                            const vil_image_view<T >&)
00846 
00847 #endif // vil_image_view_txx_

Generated on Sun Sep 7 05:07:47 2008 for core/vil by  doxygen 1.5.1