Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

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

Generated on Thu Jan 10 14:40:01 2008 for core/vil by  doxygen 1.4.4