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