vil_image_view.h
Go to the documentation of this file.
1 // This is core/vil/vil_image_view.h
2 #ifndef vil_image_view_h_
3 #define vil_image_view_h_
4 //:
5 // \file
6 // \brief A base class reference-counting view of some image data.
7 // \author Ian Scott - Manchester
8 // \verbatim
9 // Modifications
10 // Peter Vanroose - 21 Aug.2003 - support added for interleaved planes
11 // \endverbatim
12 
13 #include <iosfwd>
14 #include <string>
15 #include <cstddef>
16 #ifdef _MSC_VER
17 # include <vcl_msvc_warnings.h>
18 #endif
19 #include <cassert>
21 #include <vil/vil_memory_chunk.h>
22 #include <vil/vil_pixel_format.h>
23 
24 
25 //: Concrete view of image data of type T held in memory
26 // Views nplanes() planes of data each of size ni() x nj().
27 // The (i,j) element of the p'th plane is given by
28 // im.top_left_ptr()[i*im.istep() + j*im.jstep() + p*im.planestep]
29 // The actual image data is either allocated by the class
30 // (using set_size), in which case it is deleted
31 // only when it has no views observing it, or is allocated outside (and is not
32 // deleted on destruction). This allows external images to be accessed
33 // without a deep copy.
34 //
35 // Note that copying one vil_image_view<T> to another takes a shallow
36 // copy by default - it copies the view, not the raw image data.
37 // Use the explicit deep_copy() call to take a deep copy.
38 
39 template <class T>
41 {
42  private:
43 
44  protected:
45  //: Pointer to pixel at origin.
46  T * top_left_;
47  //: Add this to a pixel pointer to move one column left.
48  std::ptrdiff_t istep_;
49  //: Add this to a pixel pointer to move one row down.
50  std::ptrdiff_t jstep_;
51  //: Add this to a pixel pointer to move one plane back.
52  std::ptrdiff_t planestep_;
53 
54  //: Reference to actual image data.
56 
57  //: Disconnect this view from the underlying data,
58  void release_memory() { ptr_ = nullptr; }
59 
60  public:
61  //: Dflt ctor
62  // Creates an empty one-plane image.
64 
65  //: Create an image of ni x nj pixels in (n_planes * n_interleaved_planes) planes
66  // If n_interleaved_planes > 1, the planes are interleaved.
67  // If n_planes > 1, each plane of pixels is stored contiguously.
68  // n_planes and n_interleaved_planes should not be both different from 1.
69  // n_planes * n_interleaved_planes should be 1 unless T is scalar.
70  vil_image_view(unsigned ni, unsigned nj, unsigned n_planes=1, unsigned n_interleaved_planes=1);
71 
72  //: Set this view to look at someone else's memory data.
73  // If the data goes out of scope then this view could be invalid, and
74  // there's no way of knowing until it's too late - so take care!
75  vil_image_view(const T* top_left, unsigned ni, unsigned nj, unsigned nplanes,
76  std::ptrdiff_t i_step, std::ptrdiff_t j_step, std::ptrdiff_t plane_step);
77 
78  //: Set this view to look at another view's data
79  // Typically used by functions which generate a manipulated view of
80  // another's image data.
81  // Need to pass the memory chunk to set up the internal smart ptr appropriately
82  vil_image_view(const vil_memory_chunk_sptr& mem_chunk,
83  const T* top_left, unsigned ni, unsigned nj, unsigned nplanes,
84  std::ptrdiff_t i_step, std::ptrdiff_t j_step, std::ptrdiff_t plane_step);
85 
86  //: Copy constructor.
87  // The new object will point to the same underlying image as the rhs.
89 
90  //: Construct from various vil_image_view types.
91  // The new object will point to the same underlying image as the rhs
92  // You can assign a vil_image_view<compound_type<T>> to a vil_image_view<T>
93  // in all reasonable cases - the lhs will have as many planes as the rhs has
94  // components. You can assign a vil_image_view<T> to a vil_image_view<compound_type<T>>
95  // when the underlying data is formatted appropriately and the lhs has
96  // as many components as the rhs has planes. O(1).
97  // If the view types are not compatible this object will be set to empty.
99 
100  //: Construct from various vil_image_view types.
101  // The new object will point to the same underlying image as the rhs.
102  //
103  // You can assign a vil_image_view<compound_type<T>> to a vil_image_view<T>
104  // in all reasonable cases - the lhs will have as many planes as the rhs has
105  // components. You can assign a vil_image_view<T> to a vil_image_view<compound_type<T>>
106  // when the underlying data is formatted appropriately and the lhs has
107  // as many components as the rhs has planes. O(1).
108  // \throws vil_exception_pixel_formats_incompatible if view types are not compatible. Or
109  // returns a null image if exceptions are disabled.
111 
112  // Destructor
113  ~vil_image_view() override = default;
114 
115  // === Standard container stuff ===
116  // This assumes that the data is arranged contiguously.
117  // Is this assumption good?
118 
119  //: The pixel type of this image
120  typedef T pixel_type;
121 
122  //: True if data all in one unbroken block and top_left_ptr() is lowest data address
123  bool is_contiguous() const;
124 
125  // === iterators ===
126 
127  typedef T *iterator;
128  inline iterator begin() { assert(is_contiguous()); return top_left_; }
129  inline iterator end () { assert(is_contiguous()); return top_left_ + size(); }
130 
131  typedef T const *const_iterator;
132  inline const_iterator begin() const { assert(is_contiguous()); return top_left_; }
133  inline const_iterator end () const { assert(is_contiguous()); return top_left_ + size(); }
134 
135  // === arithmetic indexing stuff ===
136 
137  //: Pointer to the first (top left in plane 0) pixel.
138  // Note that this is not necessarily the lowest data memory address.
139  inline T * top_left_ptr() { return top_left_; } // Make origin explicit
140  //: Pointer to the first (top left in plane 0) pixel.
141  // Note that this is not necessarily the lowest data memory address.
142  inline const T * top_left_ptr() const { return top_left_; }
143 
144  //: Add this to your pixel pointer to get next i pixel.
145  // Note that istep() may well be negative; see e.g. vil_flip_lr
146  inline std::ptrdiff_t istep() const { return istep_; }
147  //: Add this to your pixel pointer to get next j pixel.
148  // Note that jstep() may well be negative; see e.g. vil_flip_ud
149  inline std::ptrdiff_t jstep() const { return jstep_; }
150  //: Add this to your pixel pointer to get pixel on next plane.
151  // Note that planestep() may well be negative, e.g. with BMP file images
152  inline std::ptrdiff_t planestep() const { return planestep_; }
153 
154  //: Cast to bool is true if pointing at some data.
155  /* The old 'safe_bool' did implicit conversions, best practice would be to use explicit operator bool */
156  operator bool() const
157  { return (top_left_ != nullptr)? true : false; }
158 
159  //: Return false if pointing at some data.
160  bool operator!() const
161  { return (top_left_ != nullptr)? false : true; }
162 
163  //: The number of bytes in the data
164  inline unsigned size_bytes() const { return size() * sizeof(T); }
165 
166  //: Smart pointer to the object holding the data for this view
167  // Will be a null pointer if this view looks at `third-party' data,
168  // e.g. using set_to_memory.
169  //
170  // Typically used when creating new views of the data
171  inline const vil_memory_chunk_sptr& memory_chunk() const { return ptr_; }
172 
173  //: Smart pointer to the object holding the data for this view
174  // Will be a null pointer if this view looks at `third-party' data,
175  // e.g. using set_to_memory
176  //
177  // Typically used when creating new views of the data
179 
180  // === Ordinary image indexing stuff. ===
181 
182  //: Return true if (i,j) is a valid index into this buffer.
183  inline bool in_range(int i, int j) const
184  { return (i>-1) && (i<(int)ni_) && (j>-1) && (j<(int)nj_); }
185 
186  //: Return true if (i,j,p) is a valid index into this buffer.
187  inline bool in_range(int i, int j, int p) const
188  { return (i>-1) && (i<(int)ni_) && (j>-1) && (j<(int)nj_)
189  && (p>-1) && (p<(int)nplanes_); }
190 
191  //: Return read-only reference to pixel at (i,j) in plane 0.
192  inline const T& operator()(unsigned i, unsigned j) const {
193  assert(i<ni_); assert(j<nj_);
194  return top_left_[jstep_*j+i*istep_]; }
195 
196  //: Return read/write reference to pixel at (i,j) in plane 0.
197  inline T& operator()(unsigned i, unsigned j) {
198  assert(i<ni_); assert(j<nj_);
199  return top_left_[istep_*i+j*jstep_]; }
200 
201  //: Return read-only reference to pixel at (i,j) in plane p.
202  inline const T& operator()(unsigned i, unsigned j, unsigned p) const {
203  assert(i<ni_); assert(j<nj_); assert(p<nplanes_);
204  return top_left_[p*planestep_ + j*jstep_ + i*istep_]; }
205 
206  //: Return read-only reference to pixel at (i,j) in plane p.
207  inline T& operator()(unsigned i, unsigned j, unsigned p) {
208  assert(i<ni_); assert(j<nj_); assert(p<nplanes_);
209  return top_left_[p*planestep_ + j*jstep_ + i*istep_]; }
210 
211  // === image stuff ===
212 
213  //: resize current planes to ni x nj
214  // If already correct size, this function returns quickly
215  void set_size(unsigned ni, unsigned nj) override;
216 
217  //: resize to ni x nj x nplanes
218  // If already correct size, this function returns quickly
219  void set_size(unsigned ni, unsigned nj, unsigned nplanes) override;
220 
221  //: Make a copy of the data in src and set this to view it
222  void deep_copy(const vil_image_view<T>& src);
223 
224  //: Make empty.
225  // Disconnects view from underlying data.
226  inline void clear() { release_memory(); ni_=nj_=nplanes_=0; top_left_=nullptr; istep_=jstep_=planestep_=0; }
227 
228  //: Set this view to look at someone else's memory data.
229  // If the data goes out of scope then this view could be invalid, and
230  // there's no way of knowing until it's too late -- so take care!
231  //
232  // Note that though top_left is passed in as const, the data may be manipulated
233  // through the view.
234  void set_to_memory(const T* top_left, unsigned ni, unsigned nj, unsigned nplanes,
235  std::ptrdiff_t i_step, std::ptrdiff_t j_step, std::ptrdiff_t plane_step);
236 
237  //: Fill view with given value
238  void fill(T value);
239 
240  //: Print a 1-line summary of contents
241  void print(std::ostream&) const override;
242 
243  //: Return class name
244  std::string is_a() const override;
245 
246  //: True if this is (or is derived from) class s
247  bool is_class(std::string const& s) const override;
248 
249  //: Return a description of the concrete data pixel type.
250  // The value corresponds directly to pixel_type.
251  inline vil_pixel_format pixel_format() const override { return vil_pixel_format_of(T()); }
252 
253  //: True if they share same view of same image data.
254  // This does not do a deep equality on image data. If the images point
255  // to different image data objects that contain identical images, then
256  // the result will still be false.
257  bool operator==(const vil_image_view_base& other) const;
258 
259  //: True if they do not share same view of same image data.
260  // This does not do a deep inequality on image data. If the images point
261  // to different image data objects that contain identical images, then
262  // the result will still be true.
263  inline bool operator!=(const vil_image_view_base& rhs) const { return !operator==(rhs); }
264 
265  //: Provides an ordering.
266  // Useful for ordered containers.
267  // There is no guaranteed meaning to the less than operator, except that
268  // (a<b && b<a) is false and !(a<b) && !(b<a) is equivalent to a==b
269  bool operator<(const vil_image_view_base& rhs) const;
270 
271  //: Provides an ordering.
272  inline bool operator>=(const vil_image_view_base& rhs) const { return !operator<(rhs); }
273 
274  //: Provides an ordering.
275  bool operator>(const vil_image_view_base& rhs) const;
276 
277  //: Provides an ordering.
278  inline bool operator<=(const vil_image_view_base & rhs) const { return !operator>(rhs); }
279 
280  //: Copy a view. The rhs and lhs will point to the same image data.
281  const vil_image_view<T>& operator=(const vil_image_view<T>& rhs);
282 
283  //: Copy a view. The rhs and lhs will point to the same image data.
284  // You can assign a vil_image_view<compound_type<T>> to a vil_image_view<T>
285  // in all reasonable cases - the lhs will have as many planes as the rhs has
286  // components. You can assign a vil_image_view<T> to a vil_image_view<compound_type<T>>
287  // when the underlying data is formatted appropriately and the lhs has
288  // as many components as the rhs has planes. O(1).
289  // If the view types are not compatible this object will be set to empty.
290  const vil_image_view<T>& operator=(const vil_image_view_base & rhs);
291 
292  //: Copy a view. The rhs and lhs will point to the same image data.
293  // You can assign a vil_image_view<compound_type<T>> to a vil_image_view<T>
294  // in all reasonable cases - the lhs will have as many planes as the rhs has
295  // components. You can assign a vil_image_view<T> to a vil_image_view<compound_type<T>>
296  // when the underlying data is formatted appropriately and the lhs has
297  // as many components as the rhs has planes. O(1).
298  // If the view types are not compatible this object will be set to empty.
299  // If the pointer is null, this object will be set to empty.
300  // See also vil_convert_to_component_order().
302  {
303  if (!rhs) clear();
304  else *this = *rhs;
305  return *this;
306  }
307 };
308 
309 //: Print a 1-line summary of contents
310 template <class T>
311 inline
312 std::ostream& operator<<(std::ostream& s, vil_image_view<T> const& im)
313 {
314  im.print(s); return s;
315 }
316 
317 //: True if the actual images are identical.
318 // $\bigwedge_{i,j,p} {\textstyle src}(i,j,p) == {\textstyle dest}(i,j,p)$
319 // The data may be formatted differently in each memory chunk.
320 // O(size).
321 // \relatesalso vil_image_view
322 template<class T>
324 
325 #endif // vil_image_view_h_
unsigned ni_
Number of columns.
An abstract base class of smart pointers to actual image data in memory.
vil_pixel_format
Describes the type of the concrete data.
unsigned size_bytes() const
The number of bytes in the data.
bool operator>=(const vil_image_view_base &rhs) const
Provides an ordering.
std::ptrdiff_t istep_
Add this to a pixel pointer to move one column left.
const T & operator()(unsigned i, unsigned j) const
Return read-only reference to pixel at (i,j) in plane 0.
T & operator()(unsigned i, unsigned j)
Return read/write reference to pixel at (i,j) in plane 0.
A base class reference-counting view of some image data.
Concrete view of image data of type T held in memory.
Definition: vil_fwd.h:13
void fill(T value)
Fill view with given value.
std::ostream & operator<<(std::ostream &s, vil_image_view< T > const &im)
Print a 1-line summary of contents.
const vil_image_view< T > & operator=(const vil_image_view_base_sptr &rhs)
Copy a view. The rhs and lhs will point to the same image data.
bool is_contiguous() const
True if data all in one unbroken block and top_left_ptr() is lowest data address.
bool operator<=(const vil_image_view_base &rhs) const
Provides an ordering.
void set_size(unsigned ni, unsigned nj) override
resize current planes to ni x nj.
bool in_range(int i, int j, int p) const
Return true if (i,j,p) is a valid index into this buffer.
std::ptrdiff_t planestep_
Add this to a pixel pointer to move one plane back.
std::ptrdiff_t jstep() const
Add this to your pixel pointer to get next j pixel.
bool vil_image_view_deep_equality(const vil_image_view< T > &lhs, const vil_image_view< T > &rhs)
True if the actual images are identical.
bool in_range(int i, int j) const
Return true if (i,j) is a valid index into this buffer.
bool operator<(const vil_image_view_base &rhs) const
Provides an ordering.
vil_memory_chunk_sptr ptr_
Reference to actual image data.
unsigned ni() const
Width.
bool operator!=(const vil_image_view_base &rhs) const
True if they do not share same view of same image data.
iterator end()
unsigned nj() const
Height.
std::ptrdiff_t planestep() const
Add this to your pixel pointer to get pixel on next plane.
const T & operator()(unsigned i, unsigned j, unsigned p) const
Return read-only reference to pixel at (i,j) in plane p.
iterator begin()
bool operator!() const
Return false if pointing at some data.
bool operator>(const vil_image_view_base &rhs) const
Provides an ordering.
void deep_copy(const vil_image_view< T > &src)
Make a copy of the data in src and set this to view it.
void print(std::ostream &) const override
Print a 1-line summary of contents.
const_iterator end() const
~vil_image_view() override=default
unsigned nplanes_
Number of planes.
vil_memory_chunk_sptr & memory_chunk()
Smart pointer to the object holding the data for this view.
T const * const_iterator
unsigned long size() const
The number of pixels.
std::string is_a() const override
Return class name.
T pixel_type
The pixel type of this image.
std::ptrdiff_t jstep_
Add this to a pixel pointer to move one row down.
T * top_left_ptr()
Pointer to the first (top left in plane 0) pixel.
unsigned nplanes() const
Number of planes.
vil_pixel_format pixel_format() const override
Return a description of the concrete data pixel type.
void set_to_memory(const T *top_left, unsigned ni, unsigned nj, unsigned nplanes, std::ptrdiff_t i_step, std::ptrdiff_t j_step, std::ptrdiff_t plane_step)
Set this view to look at someone else's memory data.
const vil_memory_chunk_sptr & memory_chunk() const
Smart pointer to the object holding the data for this view.
unsigned nj_
Number of rasters.
vil_image_view()
Dflt ctor.
bool is_class(std::string const &s) const override
True if this is (or is derived from) class s.
T * top_left_
Pointer to pixel at origin.
const vil_image_view< T > & operator=(const vil_image_view< T > &rhs)
Copy a view. The rhs and lhs will point to the same image data.
const T * top_left_ptr() const
Pointer to the first (top left in plane 0) pixel.
bool operator==(const vil_image_view_base &other) const
True if they share same view of same image data.
std::ptrdiff_t istep() const
Add this to your pixel pointer to get next i pixel.
vil_pixel_format vil_pixel_format_of(T)
The pixel format enumeration corresponding to the C++ type.
const_iterator begin() const
void release_memory()
Disconnect this view from the underlying data,.
T & operator()(unsigned i, unsigned j, unsigned p)
Return read-only reference to pixel at (i,j) in plane p.
void clear()
Make empty.