contrib/mul/vil3d/vil3d_image_view.h
Go to the documentation of this file.
00001 // This is mul/vil3d/vil3d_image_view.h
00002 #ifndef vil3d_image_view_h_
00003 #define vil3d_image_view_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \brief A base class reference-counting view of some image data.
00010 // \author Tim Cootes, Ian Scott - Manchester
00011 
00012 #include <vcl_iosfwd.h>
00013 #include <vcl_string.h>
00014 #include <vcl_cassert.h>
00015 #include <vcl_cstddef.h>
00016 #include <vil3d/vil3d_image_view_base.h>
00017 #include <vil/vil_memory_chunk.h>
00018 #include <vil/vil_pixel_format.h>
00019 
00020 //: Concrete view of image data of type T held in memory
00021 //  Views nplanes() planes of data each of size ni() x nj() x nk().
00022 //  The (i,j,k) element of the p'th plane is given by
00023 //  im.origin_ptr()[i*im.istep() + j*im.jstep()+ k*im.kstep() + p*im.planestep]
00024 //  The actual image data is either allocated by the class
00025 //  (using set_size), in which case it is deleted
00026 //  only when it has no views observing it, or is allocated outside (and is not
00027 //  deleted on destruction).  This allows external images to be accessed
00028 //  without a deep copy.
00029 //
00030 //  Note that copying one vil3d_image_view<T> to another takes a shallow
00031 //  copy by default - it copies the view, not the raw image data.
00032 //  Use the explicit deep_copy() call to take a deep copy.
00033 
00034 template <class T>
00035 class vil3d_image_view : public vil3d_image_view_base
00036 {
00037  private:
00038   VCL_SAFE_BOOL_DEFINE;
00039  protected:
00040   //: Pointer to pixel at origin.
00041   T * top_left_;
00042   //: Add this to a pixel pointer to move one column left.
00043   vcl_ptrdiff_t istep_;
00044   //: Add this to a pixel pointer to move one row down.
00045   vcl_ptrdiff_t jstep_;
00046   //: Add this to a pixel pointer to move one slice down.
00047   vcl_ptrdiff_t kstep_;
00048   //: Add this to a pixel pointer to move one plane back.
00049   vcl_ptrdiff_t planestep_;
00050 
00051   //: Reference to actual image data.
00052   vil_memory_chunk_sptr ptr_;
00053 
00054   //: Disconnect this view from the underlying data,
00055   void release_memory() { ptr_ = 0; }
00056 
00057  public:
00058 
00059   //: Dflt ctor
00060   //  Creates an empty one-plane image.
00061   vil3d_image_view();
00062 
00063   //: Create an n_plane plane image of ni x nj x nk pixels
00064   vil3d_image_view(unsigned ni, unsigned nj, unsigned nk, unsigned n_planes=1);
00065 
00066   //: Set this view to look at someone else's memory data.
00067   //  If the data goes out of scope then this view could be invalid, and
00068   //  there's no way of knowing until it's too late - so take care!
00069   vil3d_image_view(const T* top_left,
00070                    unsigned ni, unsigned nj, unsigned nk, unsigned nplanes,
00071                    vcl_ptrdiff_t i_step, vcl_ptrdiff_t j_step,
00072                    vcl_ptrdiff_t k_step, vcl_ptrdiff_t plane_step);
00073 
00074   //: Set this view to look at another view's data
00075   //  Typically used by functions which generate a manipulated view of
00076   //  another's image data.
00077   //  Need to pass the memory chunk to set up the internal smart ptr appropriately
00078   vil3d_image_view(const vil_memory_chunk_sptr& mem_chunk,
00079                    const T* top_left,
00080                    unsigned ni, unsigned nj, unsigned nk, unsigned nplanes,
00081                    vcl_ptrdiff_t i_step, vcl_ptrdiff_t j_step,
00082                    vcl_ptrdiff_t k_step, vcl_ptrdiff_t plane_step);
00083 
00084   //: Copy construct.
00085   // The new object will point to the same underlying image as the rhs.
00086   vil3d_image_view(const vil3d_image_view<T>& rhs);
00087 
00088   //: Create shallow copy of image with given base reference
00089   //  Sets to empty image if target is of different pixel type
00090   vil3d_image_view(const vil3d_image_view_base& base_ref);
00091 
00092   //: Create shallow copy of image with given base reference
00093   //  Sets to empty image if target is of different pixel type
00094   vil3d_image_view(const vil3d_image_view_base_sptr& base_sptr);
00095 
00096   //: Copy a view. The rhs and lhs will point to the same image data.
00097   const vil3d_image_view<T>& operator=(const vil3d_image_view<T>& rhs);
00098 
00099 
00100   //: Create shallow copy of image with given base reference
00101   //  Sets to empty image if target is of different pixel type
00102   const vil3d_image_view& operator=(const vil3d_image_view_base& base_ref);
00103 
00104   //: Copy a view. The rhs and lhs will point to the same image data.
00105   // If the view types are not compatible this object will be set to empty.
00106   // If the pointer is null, this object will be set to empty.
00107   inline const vil3d_image_view<T>& operator=(const vil3d_image_view_base_sptr& rhs)
00108   {
00109     if (!rhs) clear();
00110     else *this = *rhs;
00111     return *this;
00112   }
00113 
00114   //  Destructor
00115   virtual ~vil3d_image_view();
00116 
00117   // Standard container stuff
00118   // This assumes that the data is arranged contiguously.
00119   // Is this assumption good?
00120 
00121   //: The pixel type of this image
00122   typedef T pixel_type;
00123 
00124   //: True if data all in one unbroken block and origin_ptr() is lowest data address
00125   bool is_contiguous() const;
00126 
00127   // iterators
00128   typedef T *iterator;
00129   inline iterator begin() { assert(is_contiguous()); return top_left_; }
00130   inline iterator end  () { assert(is_contiguous()); return top_left_ + size(); }
00131 
00132   typedef T const *const_iterator;
00133   inline const_iterator begin() const { assert(is_contiguous()); return top_left_; }
00134   inline const_iterator end  () const { assert(is_contiguous()); return top_left_ + size(); }
00135 
00136   // arithmetic indexing stuff
00137 
00138   //: Pointer to the first (top left in plane 0) pixel.
00139   //  Note that this is not necessarily the lowest data memory address.
00140   inline T * origin_ptr() { return top_left_; }  // Make origin explicit
00141   //: Pointer to the first (top left in plane 0) pixel.
00142   //  Note that this is not necessarily the lowest data memory address.
00143   inline const T * origin_ptr() const { return top_left_; }
00144 
00145   //: Add this to your pixel pointer to get next i pixel.
00146   //  Note that istep() may well be negative;
00147   inline vcl_ptrdiff_t istep() const { return istep_; }
00148   //: Add this to your pixel pointer to get next j pixel.
00149   //  Note that jstep() may well be negative;
00150   inline vcl_ptrdiff_t jstep() const { return jstep_; }
00151   //: Add this to your pixel pointer to get next k pixel.
00152   //  Note that kstep() may well be negative;
00153   inline vcl_ptrdiff_t kstep() const { return kstep_; }
00154   //: Add this to your pixel pointer to get pixel on next plane.
00155   //  Note that planestep() may well be negative, e.g. with BMP file images
00156   inline vcl_ptrdiff_t planestep() const { return planestep_; }
00157 
00158   //: Cast to bool is true if pointing at some data.
00159   operator safe_bool () const
00160     { return (top_left_ != (T*)0)? VCL_SAFE_BOOL_TRUE : 0; }
00161 
00162   //: Return false if pointing at some data.
00163   bool operator!() const
00164     { return (top_left_ != (T*)0)? false : true; }
00165 
00166   //: The number of bytes in the data
00167   inline vcl_size_t size_bytes() const { return size() * sizeof(T); }
00168 
00169   //: Smart pointer to the object holding the data for this view
00170   // Will be a null pointer if this view looks at `third-party' data,
00171   // e.g. using set_to_memory.
00172   //
00173   // Typically used when creating new views of the data
00174   inline const vil_memory_chunk_sptr& memory_chunk() const { return ptr_; }
00175 
00176   //: Smart pointer to the object holding the data for this view
00177   // Will be a null pointer if this view looks at `third-party' data,
00178   // e.g. using set_to_memory
00179   //
00180   // Typically used when creating new views of the data
00181   inline vil_memory_chunk_sptr& memory_chunk() { return ptr_; }
00182 
00183   // Ordinary image indexing stuff.
00184 
00185   //: Return read-only reference to pixel at (i,j,k) in plane 0.
00186   inline const T& operator()(unsigned i, unsigned j, unsigned k) const {
00187     assert(i<ni_); assert(j<nj_); assert(k<nk_);
00188     return top_left_[kstep_*k+jstep_*j+i*istep_]; }
00189 
00190   //: Return read/write reference to pixel at (i,j,k) in plane 0.
00191   inline T&       operator()(unsigned i, unsigned j, unsigned k) {
00192     assert(i<ni_); assert(j<nj_); assert(k<nk_);
00193     return top_left_[istep_*i+j*jstep_+kstep_*k]; }
00194 
00195   //: Return read-only reference to pixel at (i,j,k) in plane p.
00196   inline const T& operator()(unsigned i, unsigned j, unsigned k, unsigned p) const {
00197     assert(i<ni_); assert(j<nj_); assert(k<nk_); assert(p<nplanes_);
00198     return top_left_[p*planestep_ + kstep_*k + j*jstep_ + i*istep_]; }
00199 
00200   //: Return read-only reference to pixel at (i,j,k) in plane p.
00201   inline T&       operator()(unsigned i, unsigned j, unsigned k, unsigned p) {
00202     assert(i<ni_); assert(j<nj_); assert(k<nk_); assert(p<nplanes_);
00203     return top_left_[p*planestep_ + kstep_*k + j*jstep_ + i*istep_]; }
00204 
00205   // image stuff
00206 
00207   //: resize current planes to ni x nj x nk
00208   // If already correct size, this function returns quickly
00209   virtual void set_size(unsigned ni, unsigned nj, unsigned nk);
00210 
00211   //: resize to ni x nj x nk x nplanes
00212   // If already correct size, this function returns quickly
00213   virtual void set_size(unsigned ni, unsigned nj, unsigned nk, unsigned nplanes);
00214 
00215   //: Make a copy of the data in src and set this to view it
00216   void deep_copy(const vil3d_image_view<T>& src);
00217 
00218   //: Make empty.
00219   // Disconnects view from underlying data.
00220   inline void clear() { release_memory(); ni_=nj_=nk_=nplanes_=0; top_left_=0; }
00221 
00222   //: Set this view to look at someone else's memory data.
00223   //  If the data goes out of scope then this view could be invalid, and
00224   //  there's no way of knowing until it's too late -- so take care!
00225   //
00226   //  Note that though top_left is passed in as const, the data may be manipulated
00227   //  through the view.
00228   void set_to_memory(const T* top_left,
00229                      unsigned ni, unsigned nj, unsigned nk, unsigned nplanes,
00230                      vcl_ptrdiff_t i_step, vcl_ptrdiff_t j_step,
00231                      vcl_ptrdiff_t k_step, vcl_ptrdiff_t plane_step);
00232 
00233   //: Fill view with given value
00234   void fill(T value);
00235 
00236   //: Print a 1-line summary of contents
00237   virtual void print(vcl_ostream&) const;
00238 
00239   //: Return class name
00240   virtual vcl_string is_a() const;
00241 
00242   //: True if this is (or is derived from) class s
00243   virtual bool is_class(vcl_string const& s) const;
00244 
00245   //: Return a description of the concrete data pixel type.
00246   // The value corresponds directly to pixel_type.
00247   inline vil_pixel_format pixel_format() const { return vil_pixel_format_of(T()); }
00248 
00249   //: True if they share same view of same image data.
00250   //  This does not do a deep equality on image data. If the images point
00251   //  to different image data objects that contain identical images, then
00252   //  the result will still be false.
00253   bool operator==(const vil3d_image_view<T>& other) const;
00254 
00255   //: True if they do not share same view of same image data.
00256   //  This does not do a deep inequality on image data. If the images point
00257   //  to different image data objects that contain identical images, then
00258   //  the result will still be true.
00259   inline bool operator!=(const vil3d_image_view<T>& rhs) const { return !operator==(rhs); }
00260 
00261   //: Provides an ordering.
00262   //  Useful for ordered containers.
00263   //  There is no guaranteed meaning to the less than operator, except that
00264   //  (a<b && b<a)  is false and  !(a<b) && !(b<a)  is equivalent to  a==b
00265   bool operator<(const vil3d_image_view<T>& other) const;
00266 
00267   //: Provides an ordering.
00268   inline bool operator>=(const vil3d_image_view<T>& other) const { return !operator<(other); }
00269 
00270   //: Provides an ordering.
00271   inline bool operator>(const vil3d_image_view<T>& other) const { return other<(*this); }
00272 
00273   //: Provides an ordering.
00274   inline bool operator<=(const vil3d_image_view<T>& other) const { return !operator>(other); }
00275 };
00276 
00277 //: Print a 1-line summary of contents
00278 template <class T>
00279 inline
00280 vcl_ostream& operator<<(vcl_ostream& s, vil3d_image_view<T> const& im)
00281 {
00282   im.print(s); return s;
00283 }
00284 
00285 //: True if the actual images are identical.
00286 // $\bigwedge_{i,j,k,p} {\textstyle src}(i,j,k,p) == {\textstyle dest}(i,j,k,p)$
00287 // The data may be formatted differently in each memory chunk.
00288 //  O(size).
00289 // \relatesalso vil3d_image_view
00290 template<class T>
00291 bool vil3d_image_view_deep_equality(const vil3d_image_view<T> &lhs,
00292                                     const vil3d_image_view<T> &rhs);
00293 
00294 #endif // vil3d_image_view_h_