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_