iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Image.H
Go to the documentation of this file.
1 /*! @file
2  @author Randolph Voorhies
3  @copyright GNU Public License (GPL v3)
4  @section License
5  @verbatim
6  // ////////////////////////////////////////////////////////////////////////
7  // The iLab Neuromorphic Robotics Toolkit (NRT) //
8  // Copyright 2010-2012 by the University of Southern California (USC) //
9  // and the iLab at USC. //
10  // //
11  // iLab - University of Southern California //
12  // Hedco Neurociences Building, Room HNB-10 //
13  // Los Angeles, Ca 90089-2520 - USA //
14  // //
15  // See http://ilab.usc.edu for information about this project. //
16  // ////////////////////////////////////////////////////////////////////////
17  // This file is part of The iLab Neuromorphic Robotics Toolkit. //
18  // //
19  // The iLab Neuromorphic Robotics Toolkit is free software: you can //
20  // redistribute it and/or modify it under the terms of the GNU General //
21  // Public License as published by the Free Software Foundation, either //
22  // version 3 of the License, or (at your option) any later version. //
23  // //
24  // The iLab Neuromorphic Robotics Toolkit is distributed in the hope //
25  // that it will be useful, but WITHOUT ANY WARRANTY; without even the //
26  // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
27  // PURPOSE. See the GNU General Public License for more details. //
28  // //
29  // You should have received a copy of the GNU General Public License //
30  // along with The iLab Neuromorphic Robotics Toolkit. If not, see //
31  // <http://www.gnu.org/licenses/>. //
32  // ////////////////////////////////////////////////////////////////////////
33  @endverbatim */
34 
35 
36 #ifndef INCLUDE_NRT_CORE_IMAGE_IMAGE_H
37 #define INCLUDE_NRT_CORE_IMAGE_IMAGE_H
38 
39 #include <nrt/config.h>
42 
43 #include <boost/iterator/iterator_facade.hpp>
44 
46 #include <nrt/Core/Geometry/Rectangle.H> // for rect_iterator
47 #include <nrt/Core/Geometry/Polygon.H> // for convex_poly_iterator
48 #include <nrt/Core/Typing/Range.H>
50 #include <nrt/Core/Typing/Macros.H>
51 
52 #include <initializer_list>
53 
54 namespace nrt
55 {
56  // ######################################################################
57  //! Initialization policy for the pixels inside an Image, used during construction of the Image
58  /*! \relates Image */
59  enum class ImageInitPolicy
60  {
61  Zeros, //!< Fill the image with all zeros. This costs some CPU.
62  None //!< No initialization of each pixel. This saves some CPU.
63  };
64 
65  // ######################################################################
66  //! Flags to control the behavior of Images
67  /*! You can pass combinations of flags to an Image using the bitwise 'or' operator:
68  @code
69  // Construct an Image that will check for out-of-bounds pixel access, but won't check for shared memory.
70  Image<PixGray<byte>, SafeAccess | UniqueAccess> myImage;
71  @endcode
72 
73  \relates Image */
74  enum ImageFlags : uint32
75  {
76  SafeAccess = 1, /*!< Image coordinate access will be checked, and an exception will be thrown if you try to access a
77  pixel which is out of bounds. If you don't set this flag, then you will be on your own to
78  ensure that you don't try to access pixels outside of the Image (as doing so may result in a
79  segfault). However, SafeAccess comes with a big performance hit, so we recommend you only use
80  it when debugging*/
81 
82  UniqueAccess = 2 /*!< Image reference counting will not be checked during pixel level access. If you are <i>sure</i>
83  that you have the only copy of your image data (and have full understanding of the
84  copy-on-write behavior!), then you can declare your Image with the UniqueAccess flag. A good
85  practice is to always call Image::deepCopy() before making a UniqueAccess alias of an Image.
86 
87  For Example:
88  @code
89  Image<PixRGB<byte>> myImage;
90 
91  // ... Do some processing ...
92 
93  // Make a UniqueAccess alias of myImage. Notice that we make a deep-copy of myImage before we do this,
94  // ensuring that we hold a unique reference to the underlying memory.
95  myImage.deepCopy();
96  Image<PixRGB<byte>, UniqueAccess> myUniqueImage = myImage;
97 
98  // Now, we can mess around with myUniqueImage and all pixel operations will be very fast, as they won't perform
99  // any checks to ensure that we aren't sharing our memory with any other Images.
100  for(int y=0; y<myUniqueImage.height(); y++)
101  for(int x=0; x<myUniqueImage.width(); x++)
102  myUniqueImage(x,y) = ...
103  @endcode
104 
105  */
106 
107  };
108 
109  // ######################################################################
110  /*! \defgroup image Image class template and related classes and functions
111 
112  The NRT Image class template provides a powerful class for processing images. The pixel type is determined by a
113  template parameter. Image uses copy-on-write and ref-counting internally, so that passing images to functions or
114  returning images from functions is inexpensive (similar to passing shared pointers). This allows for a very
115  natural yet powerful syntax (similar to, for example, manipulating matrices in Matlab).
116 
117  For example code using the Image class see \link test-Image.C \endlink
118 
119  \ingroup core */
120 
121  /*! @{ */ // **********************************************************************
122 
123  //! The standard Image class used to store pixel data
124  /*! The Image class is used (not surprisingly!) to hold image data in memory. The class has a number of features
125  which make is easy to use and high-performance. It is a thin wrapper around the nrt::Array2D class, which is a
126  copy-on-write ref-counting memory storage class. This means that copying an Image is a nearly instant operation
127  that essentially equates to just a pointer copy. Whenever the Image data is modified, the class will check to see
128  if its memory pointer is shared with another Image, and if so will create a unique copy of that data for
129  itself. It is therefore up to the user to use read-only methods of Image whenever possible to avoid having to
130  unecessarily copy the Image. Follow these guidelines to ensure high-performance:
131 
132  1) Use the \link Image::at() myImage.at(x,y) \endlink method to read pixel values - this is guaranteed to never
133  cause a copy. Use \link Image::operator()(int32 x, int32 y) myImage(x,y) \endlink only when you actually need
134  to modify the pixel value, e.g.
135 
136  @code
137  // Retrieve a pixel value (no copy here)
138  myPixel = myImage.at(0, 0);
139 
140  // Assign a pixel value (this may copy the image data if it is shared with another Image)
141  yourImage(0, 0) = myPixel;
142  @endcode
143 
144  2) Follow the same guidelines as above when iterating through the Image using begin() / const_begin() and
145  end() / const_end(). Also use cref().
146 
147  3) Feel free to return Images from functions - this can lead to very natural syntax of Image filters and will be
148  essentially free. e.g.
149 
150  @code
151  Image<PixGray<byte>> MyImage = filter3(filter2(filter1(YourImage)));
152  @endcode
153 
154  4) Basic math operators (+,-,*,/,+=,*=,/=,-=) are defined as well as several overloaded wrappers around
155  \c std::accumulate(...), \c std::transform(...), \c std::foreach(...). Instead of chaining
156  operators together it is more efficient to use nrt::transform(...) for per-pixel operations that are more
157  complex than a single operator:
158 
159  @code
160  Image<PixGray<float>> im1, im2;
161  im1 += im2 //ok only one operation
162  im2 = (im1 - im2) / (im1 + im2) //pretty, but wrong!
163 
164  //efficiently apply the operation with a lamda (alternatively a functor, functional, function or function ptr)
165  im2 = transform(im1, im2,
166  [](PixGray<float>> const & v1, PixGray<float>> const & v2) { return (v1 - v2)/(v1 + v2); });
167  @endcode
168 
169  Note: The operators accept arguments by const &, which is efficient but not entirely thread-safe due to the
170  ref-counting mechanism in the Image class. This would only present a problem if you spawned the operator or an
171  accumulate or a transform function in a new thread passing in a non-unique image.
172 
173  @tparam T The pixel type of this Image. T must be a class which derives from nrt::PixelBase
174 
175  @tparam Flags A bitfield which describes various flags to control the behavior or the Image. See \ref ImageFlags
176  for more info. */
177  template <class T, uint32 Flags = 0>
178  class Image : public Array2D<T>
179  {
180  public:
181 
182  //! Convenient typedef for the POD type stored by our Pixel type
184 
185  //! Convenient typedef for our Pixel type
186  typedef T PixelType;
187 
188  //! Convenent typedef for our Dims type
190 
191  //! Construct an empty (0 by 0) Image
192  Image();
193 
194  //! Construct an Image of size dims using the given ImageInitPolicy
195  /*! If you need to construct a blank image filled with 0's then this method is the way to go,
196  as it is faster than the standard value constructor. */
198 
199  //! Construct an Image of size width and height using given InitPolicy
200  /*! \overload */
202 
203  //! Construct an Image of size Dims filled with val
204  Image(DimsType const& dims, T const val);
205 
206  //! Copy constructor
207  template<uint32 OtherFlags>
208  Image(Image<T, OtherFlags> const& other);
209 
210  //! Construct from a 2D initializer list
211  /*! This constructs an image from the passed initializer data, for example:
212  @code
213  Image<int> img1 = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 } }; // image with width=4, height=2. The "=" is optional.
214  Image<int> img2 = { { 1, 2, 3 } }; // image with width=3, height=1 (row vector)
215  Image<int> img3 = { { 1 }, { 2 }, { 3 } }; // image with width=1, height=3 (column vector)
216  @endcode */
217  Image(std::initializer_list<std::initializer_list<T>> vals);
218 
219  //! Color space conversion copy constructor
220  /*! This constructor will convert an Image from one color space to another. It is made explicit to avoid possibly
221  expensive pixel type conversions without the user being aware that it is happening.
222 
223  Example:
224  @code
225  Image<PixHSV<byte>> hsvImage;
226  Image<PixLAB<float>> labImage(hsvImage);
227  @endcode
228 
229  This method works through the toRGB and fromRGB methods required for any deriver of PixelBase. In the above
230  example, the Image<PixRGB<float>> constructor is essentially equivalent to:
231 
232  @code
233  for (size_t i=0; i<labImage.size(); i++)
234  labImage(i) = PixLAB<float>::fromRGB(hsvImage.at(i).toRGB());
235  @endcode
236  */
237  template <class U, uint32 OtherFlags> explicit
238  Image(Image<U, OtherFlags> const& other);
239 
240  //! Construct an Image from a raw array
241  /*! This constructor simply drops the data pointer into the Image's underlying nrt::Array, which has the following
242  important effects:
243  -# This constructor does <I>not</I> copy data, so be aware that data will be shared between this
244  Image and whoever created data.
245  -# The constructed Image will believe that it <I>owns</I> data, and will thus attempt to free it when the
246  Image goes out of scope. */
247  Image(T* data, DimsType const& dims);
248 
249  //! Assignment operator
250  template<uint32 OtherFlags>
252 
253  //! Color space conversion assignment operator
254  /*! \see Image(Image<U> const& other); */
255  template <class U, uint32 OtherFlags>
257 
258  //! Clear contents (or set to given value) without changing the size of the Image
259  void clear(T const & val = T());
260 
261  //! Get the range (min,max) of pixel values contained in the image. If the image is empty then range is [0 .. 0]
262  /*! Note that we do not cache the range, as this would incur the cost of having to invalidate it each time the
263  image contents are modified in some way. So you should consider that calling range() is an "expensive"
264  operation that performs a loop over all pixels in the image each time it is called. If your pixel type T does
265  not support std::min(T, T) and std::max(T, T) then you will not be able to compile. */
266  nrt::Range<T> const range() const;
267 
268  //! Draw the given color onto the Image pixel at point p.
269  /*! This method is for safely drawing onto Images. Bounds checking is performed internally, and this method will
270  have no effect if the Point p lies outside of the Image.
271 
272  The compiler will automatically choose which version of draw() to use based on whether or not ColorType
273  contains an alpha channel. If so, then draw() will correctly mix the new color with the old one. */
274  template <class U, template<typename> class ColorType>
275  typename std::enable_if<std::is_base_of<PixelWithAlpha<U>, ColorType<U>>::value, void>::type
276  draw(Point2D<int32> const& p, ColorType<U> color);
277 
278  //! Draw the given color onto the Image pixel at point p.
279  /*! This method is for safely drawing onto Images. Bounds checking is performed internally, and this method will
280  have no effect if the Point p lies outside of the Image.
281 
282  The compiler will automatically choose which version of draw() to use based on whether or not ColorType
283  contains an alpha channel. If so, then draw() will correctly mix the new color with the old one. */
284  template <class U>
285  void draw(Point2D<int32> const& p, U color);
286 
287  //! Read the pixel value at position (x, y)
288  /*! Use this method to read elements of your Image, e.g.
289  @code
290  PixRGB<byte> val = myImage.at(5, 2);
291  @endcode
292  This method can be much faster than operator() because it will never make a copy of the Image. */
293  T const & at(int32 x, int32 y) const;
294 
295  //! A convenient overload of at(int32 x, int32 y) const
296  T const & at(Point2D<int32> p) const;
297 
298  //! A convenient overload of at(int32 x, int32 y) const for linear read-only access to the Image
299  T const & at(uint32 idx) const;
300 
301  //! Read the bilinearly interpolated value at position (x, y)
302  T interpolate(float x, float y) const;
303 
304  //! A convenient overload of interpolate(float x, float y) const
305  T interpolate(Point2D<float> p) const;
306 
307  //! Get a mutable reference to the value at position (x, y)
308  /*! Use this method to set elements of your Image, e.g.
309  @code
310  myImage(5, 2) = PixGray<byte>(17);
311  @endcode
312  Note that this method can be much slower than the .at() method when just reading values because it
313  may make a deep-copy of the underlying memory if it is shared with another Image. */
314  T& operator()(int32 x, int32 y);
315  T const& operator()(int32 x, int32 y) const;
316 
317  //! A convenient overload of operator()(int32 x, int32 y)
319  T const& operator()(Point2D<int32> p) const;
320 
321  //! A convenient overload of operator()(int32 x, int32 y) for linear write access to the Image
322  T& operator()(uint32 idx);
323  T const& operator()(uint32 idx) const;
324 
325  //! Test whether point falls inside array boundaries
326  template<class U> bool coordsOk(const U x, const U y) const;
327 
328  //! Test whether a rectangle falls inside array boundaries
329  template<class U> bool rectangleOk(const Rectangle<U> rect) const;
330 
331  //! Convenient overload of coordsOk(int32 x, int32 y)
332  template<class U> bool coordsOk(const Point2D<U>& P) const;
333 
334  //! Get the dimensions of the Image
335  DimsType const & dims() const;
336 
337  //! Get the bounding rectangle of the Image
338  Rectangle<int32> const bounds() const;
339 
340  //! Get the width of the Image
341  int32 const width() const;
342 
343  //! Get the height of the Image
344  int32 const height() const;
345 
346  //! Get the total number of pixels in the Image; if it is zero then the image is un-initialized
347  int32 const size() const;
348 
349  //! Let the caller know whether the image is empty (0x0 dimensions)
350  /*! This is equivalent to (size() == 0) */
351  bool const empty() const;
352 
353  //! Reshape an image to new dims without changing the underlying data
354  /*! This just changes the Dims but does not affect the pixel array. The new dims must have a size() equal to the
355  old image size(), otherwise this throws BadDimsImageException. */
356  void reshape(Dims<int32> const & newDims);
357 
358  //! Reshape an image to new dims without changing the underlying data
359  /*! \see reshape(Dims<int32>) */
360  void reshape(int32 newWidth, int32 newHeight);
361 
362  //! Create a new single-channel Image from the chan'th channel of this Image
363  /*! Note that this will make a deep copy of the data and is an expensive operation. */
364  nrt::Image<nrt::PixGray<PODType>> channel(size_t chan) const;
365 
366  //! Get a const reference to a (potentially non-const) Image
367  /*! The main purpose of this method is to allow easy and efficient read-only access via C++0x's range-based for
368  loop. Beware that if you just call begin() on an Image that is not instantiated as a const Image, then the
369  non-const begin() will be called, potentially triggering an (expensive) deep copy. This would occur in the
370  following cases:
371 
372  @code
373  Image<PixGray<int>> img1 = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 } }, img2 = img1;
374  for (auto const & pix : img1) { ... } // Deep copy here because img1 non const and data shared with img2
375  @endcode
376 
377  So the image has to be non-const and shared for this problem to surface, if it is const, then the const
378  version of begin() will be called by our for() loop, or if it is not shared, then the non-const begin() is
379  called but no deep copy will occur anyway. To avoid the deep copy, just use:
380 
381  @code
382  for (auto const & pix : img1.cref()) { ... } // no deep copy, const begin() used
383  @endcode
384 
385  See the examples in \link test-ImageCopy.C \endlink */
386  Image<T, Flags> const & cref() const;
387 
388  //! @name Image Iterator Types
389  /*! The following methods and types provide various ways to iterate over Image data. */
390  //! @{
391 
392  //! Read-write iterator over image pixels, scans in standard raster fashion (x varies fastest, then y)
393  typedef T* iterator;
394 
395  //! Constant iterator over image pixels, scans in standard raster fashion (x varies fastest, then y)
396  typedef T const* const_iterator;
397 
398  //! Read-write iterator over the raw POD data stored in the Image.
399  /*! By iterating over the PODType using a pod_iterator, you can have direct access to the underlying
400  plain-old-data (POD) type stored by your pixels.
401 
402  For example:
403  @code
404  Image<PixRGB<byte>> img(640,480);
405 
406  Image<PixRGB<byte>>::pod_iterator iter; // Create a pod_iterator, which in this case
407  // is just a typedef for byte*
408 
409  iter = img.pod_begin(); // iter now points to the 'red' channel of the first pixel.
410  ++iter; // iter now points to the 'green' channel of the first pixel.
411  ++iter; // iter now points to the 'blue' channel of the first pixel.
412  ++iter; // iter now points to the 'red' channel of the second pixel.
413  @endcode */
415 
416  //! Constant iterator over the raw POD data stored in the Image.
417  typedef PODType const* const_pod_iterator;
418 
419  //! Read-Write iterator onto a given row of the image
421 
422  //! Constant iterator onto a given row of the image
424 
425  //! Read-wite iterator over a given column of the image
426  /*! Each time you increment a col_iterator, the underlying pointer will be incremented by the width of the Image
427  so that you can easily loop over all of the pixels in the column of an Image. */
428  class col_iterator;
429 
430  //! Constant iterator over a given column of the image
431  class const_col_iterator;
432 
433  //! Iterator over a given Rectangle within the Image using the inner coordinates of a Rectangle
434  class rect_iterator;
435 
436  //! Constant iterator over a given Rectangle within the Image using the inner coordinates of a Rectangle
437  class const_rect_iterator;
438 
439  //! Read-write iterator over a given rectangle within the image, iterator uses inner coordinates of Rectangle
440  class convex_poly_iterator;
441 
442  class const_convex_poly_iterator;
443 
444  /*! @} */
445 
446  //! @name Image Iterator Accessors
447  /*! The following methods and types provide various ways to iterate over Image data. */
448  //! @{
449 
450  //! Get constant (read-only) iterators to the beginning of the Image
451  /*! If you only need to inspect elements of an Image, then this is the very fastest way to do so. */
452  const_iterator const_begin() const;
453 
454  //! Get constant (read-only) iterators to the beginning of the Image
455  /*! If you only need to inspect elements of a known-to-be-const Image, then this is the very fastest way to do so,
456  but see cref() for caveats. */
457  const_iterator begin() const;
458 
459  //! Get constant (read-only) iterators to the end of the Image
460  /*! If you only need to inspect elements of an Image, then this is the very fastest way to do so. */
461  const_iterator const_end() const;
462 
463  //! Get constant (read-only) iterators to the beginning of the Image
464  /*! If you only need to inspect elements of a known-to-be-const Image, then this is the very fastest way to do so,
465  but see cref() for caveats. */
466  const_iterator end() const;
467 
468  //! Gets a read-write iterator to the beginning of the Image
469  /*! Use this method only if you really do need to modify elements of your Image because they may invoke a
470  deep-copy of the Image memory if it is shared by another Image. If only read access is necessary, use the
471  const_begin() method instead. */
472  iterator begin();
473 
474  //! Gets a read-write iterator to the end of the Image
475  /*! \see begin() */
476  iterator end();
477 
478  //! Gets a read-write pod iterator to the first channel of the first Pixel of the Image
479  /*! \see pod_iterator */
481 
482  //! Gets a read-write pod iterator to one place past the last channel of the lat Pixel of the Image
483  /*! \see pod_iterator */
485 
486  //! Gets a constant (read-only) pod iterator to the first channel of the first Pixel of the const Image
487  /*! \see pod_iterator */
489 
490  //! Gets a constant (read-only) pod iterator to one place past the last channel of the lat Pixel of the const
491  //! Image
492  /*! \see pod_iterator */
493  const_pod_iterator pod_end() const;
494 
495  //! Gets a constant (read-only) pod iterator to the first channel of the first Pixel of the Image
496  /*! \see pod_iterator */
498 
499  //! Gets a constant (read-only) pod iterator to one place past the last channel of the lat Pixel of the Image
500  /*! \see pod_iterator */
502 
503  //! Get a read-only iterator to the beginning of a row
504  const_row_iterator const_row_begin(int32 row) const;
505 
506  //! Get a read-only iterator to the end of a row
507  const_row_iterator const_row_end(int32 row) const;
508 
509  //! Gets a read-only iterator to the beginning of a row
510  const_row_iterator row_begin(int32 row) const;
511 
512  //! Gets a read-only iterator to the end of a row
513  const_row_iterator row_end(int32 row) const;
514 
515  //! Gets a read-write iterator to the beginning of a row
516  row_iterator row_begin(int32 row);
517 
518  //! Gets a read-write iterator to the end of a row
519  row_iterator row_end(int32 row);
520 
521  //! Get a read-only iterator to the beginning of a column
522  const_col_iterator const_col_begin(int32 col) const;
523 
524  //! Get a read-only iterator to the end of a column
525  const_col_iterator const_col_end(int32 col) const;
526 
527  //! Get a read-only iterator to the beginning of a column
528  const_col_iterator col_begin(int32 col) const;
529 
530  //! Get a read-only iterator to the end of a column
531  const_col_iterator col_end(int32 col) const;
532 
533  //! Get a read-write iterator to the beginning of a column
534  col_iterator col_begin(int32 col);
535 
536  //! Get a read-write iterator to the end of a column
537  col_iterator col_end(int32 col);
538 
539  //! Get a read-only iterator to the beginning of a rectangle
540  const_rect_iterator const_rect_begin(Rectangle<int32> const &rect) const;
541 
542  //! Get a read-only iterator to the end of a rectangle
543  const_rect_iterator const_rect_end(Rectangle<int32> const &rect) const;
544 
545  //! Get a read-only iterator to the beginning of a rectangle
546  const_rect_iterator rect_begin(Rectangle<int32> const &rect) const;
547 
548  //! Get a read-only iterator to the end of a rectangle
549  const_rect_iterator rect_end(Rectangle<int32> const &rect) const;
550 
551  //! Get a read-only iterator to the beginning of a rectangle
552  rect_iterator rect_begin(Rectangle<int32> const &rect);
553 
554  //! Get a read-only iterator to the end of a rectangle
555  rect_iterator rect_end(Rectangle<int32> const &rect);
556 
557  //! Get a read-write iterator to the beginning of a polygon
558  convex_poly_iterator convex_poly_begin(Polygon<int32> const &poly);
559 
560  //! Get a read-write iterator to the end of a polygon
561  convex_poly_iterator convex_poly_end(Polygon<int32> const &poly);
562 
563  //! Get a read-only iterator to the beginning of a polygon
564  const_convex_poly_iterator const_convex_poly_begin(Polygon<int32> const &poly) const;
565 
566  //! Get a read-only iterator to the end of a polygon
567  const_convex_poly_iterator const_convex_poly_end(Polygon<int32> const &poly) const;
568 
569  //! Get a read-only iterator to the beginning of a polygon
570  const_convex_poly_iterator convex_poly_begin(Polygon<int32> const &poly) const;
571 
572  //! Get a read-only iterator to the end of a polygon
573  const_convex_poly_iterator convex_poly_end(Polygon<int32> const &poly) const;
574  //! @}
575 
576  private:
577  template <class U, uint32 OtherFlags> friend class Image;
578 
579  friend class cereal::access;
580  template<class Archive> void serialize(Archive & ar)
581  {
582  ar( cereal::base_class<nrt::Array2D<T>>( this ) );
583  }
584 
585  static const boost::mpl::bool_<(Flags & SafeAccess)==true> itsSafeAccess;
586 
587  T& operator_paren_helper(int32 x, int32 y, /*safeaccess*/boost::mpl::bool_<true> );
588  T& operator_paren_helper(int32 x, int32 y, /*safeaccess*/boost::mpl::bool_<false>);
589 
590  T const& operator_paren_helper(int32 x, int32 y, /*safeaccess*/boost::mpl::bool_<true> ) const;
591  T const& operator_paren_helper(int32 x, int32 y, /*safeaccess*/boost::mpl::bool_<false>) const;
592 
593  T& operator_paren_helper(Point2D<int32> p, /*safeaccess*/boost::mpl::bool_<true> );
594  T& operator_paren_helper(Point2D<int32> p, /*safeaccess*/boost::mpl::bool_<false>);
595 
596  T const& operator_paren_helper(Point2D<int32> p, /*safeaccess*/boost::mpl::bool_<true> ) const;
597  T const& operator_paren_helper(Point2D<int32> p, /*safeaccess*/boost::mpl::bool_<false>) const;
598 
599  T& operator_paren_helper(uint32 idx, /*safeaccess*/boost::mpl::bool_<true> );
600  T& operator_paren_helper(uint32 idx, /*safeaccess*/boost::mpl::bool_<false>);
601 
602  T const& operator_paren_helper(uint32 idx, /*safeaccess*/boost::mpl::bool_<true> ) const;
603  T const& operator_paren_helper(uint32 idx, /*safeaccess*/boost::mpl::bool_<false>) const;
604 
605  T const & at_helper(int32 x, int32 y, /*safeaccess*/boost::mpl::bool_<true> ) const;
606  T const & at_helper(int32 x, int32 y, /*safeaccess*/boost::mpl::bool_<false>) const;
607 
608  T const & at_helper(Point2D<int32> p, /*safeaccess*/boost::mpl::bool_<true> ) const;
609  T const & at_helper(Point2D<int32> p, /*safeaccess*/boost::mpl::bool_<false>) const;
610 
611  T const & at_helper(uint32 idx, /*safeaccess*/boost::mpl::bool_<true> ) const;
612  T const & at_helper(uint32 idx, /*safeaccess*/boost::mpl::bool_<false>) const;
613 
614  static const boost::mpl::bool_<(Flags & UniqueAccess)==true> itsUniqueAccess;
615  typename nrt::Image<T, Flags>::iterator begin_helper(/*uniqueaccess*/boost::mpl::bool_<true>);
616  typename nrt::Image<T, Flags>::iterator begin_helper(/*uniqueaccess*/boost::mpl::bool_<false>);
617 
618  }; // class Image
619 
620  /*! @} */ // **********************************************************************
621 
622  /*! \defgroup imagerel Image-related classes and functions
623 
624  Classes and functions that relate to the Image class, including Layout, ImageSet, Pyramid, etc.
625 
626  \ingroup image */
627 
629 
630 } // namespace nrt
631 
634 
635 #endif // INCLUDE_NRT_CORE_IMAGE_IMAGE_H
636