1 /*=========================================================================
2 *
3 *  Copyright Insight Software Consortium
4 *
5 *  Licensed under the Apache License, Version 2.0 (the "License");
6 *  you may not use this file except in compliance with the License.
7 *  You may obtain a copy of the License at
8 *
9 *         http://www.apache.org/licenses/LICENSE-2.0.txt
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 *
17 *=========================================================================*/
18 
19 #ifndef itkImageBufferRange_h
20 #define itkImageBufferRange_h
21 
22 #include <cassert>
23 #include <cstddef> // For ptrdiff_t.
24 #include <iterator> // For random_access_iterator_tag.
25 #include <limits>
26 #include <type_traits> // For conditional, is_same, and is_const.
27 
28 #include "itkMacro.h" // For itkNotUsed.
29 #include "itkDefaultPixelAccessor.h"
30 #include "itkDefaultPixelAccessorFunctor.h"
31 #include "itkDefaultVectorPixelAccessor.h"
32 #include "itkDefaultVectorPixelAccessorFunctor.h"
33 #include "itkImageRegion.h"
34 
35 namespace itk
36 {
37 namespace Experimental
38 {
39 
40 /**
41  * \class ImageBufferRange
42  * Modern C++11 range to iterate over the pixels of an image.
43  * Designed to conform to Standard C++ Iterator requirements,
44  * so that it can be used in range-based for loop, and passed to
45  * Standard C++ algorithms.
46  *
47  * The following example adds 42 to each pixel, using a range-based for loop:
48    \code
49    ImageBufferRange<ImageType> range{ *image };
50 
51    for (auto&& pixel : range)
52    {
53      pixel = pixel + 42;
54    }
55    \endcode
56  *
57  * The following example prints the values of the pixels:
58    \code
59    for (const auto pixel : range)
60    {
61      std::cout << pixel << std::endl;
62    }
63    \endcode
64  *
65  * \author Niels Dekker, LKEB, Leiden University Medical Center
66  *
67  * \see ImageIterator
68  * \see ImageConstIterator
69  * \see IndexRange
70  * \see ShapedImageNeighborhoodRange
71  * \ingroup ImageIterators
72  * \ingroup ITKCommon
73  */
74 template<typename TImage>
75 class ImageBufferRange final
76 {
77 private:
78   using ImageType = TImage;
79   using PixelType = typename TImage::PixelType;
80   using InternalPixelType = typename TImage::InternalPixelType;
81   using AccessorFunctorType = typename TImage::AccessorFunctorType;
82 
83   // Tells whether or not this range supports direct pixel access. If it does,
84   // iterator::operator*() returns a reference to the internally stored pixel,
85   // otherwise iterator::operator*() returns a proxy, which internally uses the
86   // AccessorFunctor of the image to access the pixel indirectly.
87   constexpr static bool SupportsDirectPixelAccess =
88     std::is_same<PixelType, InternalPixelType>::value &&
89     std::is_same<typename TImage::AccessorType, DefaultPixelAccessor<PixelType>>::value &&
90     std::is_same<AccessorFunctorType, DefaultPixelAccessorFunctor<typename std::remove_const<TImage>::type>>::value;
91 
92   // Tells whether or not this range is using a pointer as iterator.
93   constexpr static bool UsingPointerAsIterator = SupportsDirectPixelAccess;
94 
95   struct EmptyAccessorFunctor {};
96 
97   using OptionalAccessorFunctorType = typename std::conditional<SupportsDirectPixelAccess,
98     EmptyAccessorFunctor, AccessorFunctorType>::type;
99 
100   // PixelProxy: internal class that aims to act like a reference to a pixel:
101   // It acts either like 'PixelType &' or like 'const PixelType &', depending
102   // on its boolean template argument, VIsConst.
103   // The proxy retrieves the pixel value using the AccessorFunctor from the image.
104   // Note: the extra TDummy argument aims to fix AppleClang 6.0.0.6000056 error
105   // "explicit specialization of 'PixelProxy'"and GCC 5.4.0 error "explicit
106   // specialization in non-namespace scope".
107   template <bool VIsConst, typename TDummy = void> class PixelProxy {};
108 
109   // PixelProxy specialization for const pixel types:
110   // acts like 'const PixelType &'
111   template <typename TDummy>
112   class PixelProxy<true, TDummy> final
113   {
114   private:
115     // Reference to the internal representation of the pixel, located in the image buffer.
116     const InternalPixelType& m_InternalPixel;
117 
118     // The accessor functor of the image.
119     const AccessorFunctorType m_AccessorFunctor;
120 
121   public:
122     // Deleted member functions:
123     PixelProxy() = delete;
124     PixelProxy& operator=(const PixelProxy&) = delete;
125 
126     // Explicitly-defaulted member functions:
127     PixelProxy(const PixelProxy&) ITK_NOEXCEPT = default;
128     ~PixelProxy() = default;
129 
130     // Constructor, called directly by operator*() of the iterator class.
PixelProxy(const InternalPixelType & internalPixel,const AccessorFunctorType & accessorFunctor)131     PixelProxy(
132       const InternalPixelType& internalPixel,
133       const AccessorFunctorType& accessorFunctor) ITK_NOEXCEPT
134       :
135     m_InternalPixel{ internalPixel },
136     m_AccessorFunctor(accessorFunctor)
137     {
138     }
139 
140     // Allows implicit conversion from non-const to const proxy.
PixelProxy(const PixelProxy<false> & pixelProxy)141     PixelProxy(const PixelProxy<false>& pixelProxy) ITK_NOEXCEPT
142       :
143     m_InternalPixel{ pixelProxy.m_InternalPixel },
144     m_AccessorFunctor{ pixelProxy.m_AccessorFunctor }
145     {
146     }
147 
148     // Conversion operator.
PixelType()149     operator PixelType() const ITK_NOEXCEPT
150     {
151       return m_AccessorFunctor.Get(m_InternalPixel);
152     }
153   };
154 
155 
156   // PixelProxy specialization for non-const pixel types:
157   // acts like 'PixelType &'.
158   template <typename TDummy>
159   class PixelProxy<false, TDummy> final
160   {
161   private:
162     // The const proxy is a friend, to ease implementing conversion from
163     // a non-const proxy to a const proxy.
164     friend class PixelProxy<true>;
165 
166     // Reference to the internal representation of the pixel, located in the image buffer.
167     InternalPixelType& m_InternalPixel;
168 
169     // The accessor functor of the image.
170     const AccessorFunctorType m_AccessorFunctor;
171 
172   public:
173     // Deleted member functions:
174     PixelProxy() = delete;
175 
176     // Explicitly-defaulted member functions:
177     ~PixelProxy() = default;
178     PixelProxy(const PixelProxy&) ITK_NOEXCEPT = default;
179 
180     // Constructor, called directly by operator*() of the iterator class.
PixelProxy(InternalPixelType & internalPixel,const AccessorFunctorType & accessorFunctor)181     explicit PixelProxy(
182       InternalPixelType& internalPixel,
183       const AccessorFunctorType& accessorFunctor) ITK_NOEXCEPT
184       :
185     m_InternalPixel{ internalPixel },
186     m_AccessorFunctor(accessorFunctor)
187     {
188     }
189 
190     // Conversion operator.
PixelType()191     operator PixelType() const ITK_NOEXCEPT
192     {
193       return m_AccessorFunctor.Get(m_InternalPixel);
194     }
195 
196     // Operator to assign a pixel value to the proxy.
197     PixelProxy& operator=(const PixelType& pixelValue) ITK_NOEXCEPT
198     {
199       m_AccessorFunctor.Set(m_InternalPixel, pixelValue);
200       return *this;
201     }
202 
203     // Copy-assignment operator.
204     PixelProxy& operator=(const PixelProxy& pixelProxy) ITK_NOEXCEPT
205     {
206       // Note that this assignment operator only copies the pixel value.
207       // That is the normal behavior when a reference is assigned to another.
208       const PixelType pixelValue = pixelProxy;
209       *this = pixelValue;
210       return *this;
211     }
212 
213 
swap(PixelProxy lhs,PixelProxy rhs)214     friend void swap(PixelProxy lhs, PixelProxy rhs) ITK_NOEXCEPT
215     {
216       const auto lhsPixelValue = lhs.m_AccessorFunctor.Get(lhs.m_InternalPixel);
217       const auto rhsPixelValue = rhs.m_AccessorFunctor.Get(rhs.m_InternalPixel);
218 
219       // Swap only the pixel values, not the image buffer pointers!
220       lhs.m_AccessorFunctor.Set(lhs.m_InternalPixel, rhsPixelValue);
221       rhs.m_AccessorFunctor.Set(rhs.m_InternalPixel, lhsPixelValue);
222     }
223   };
224 
225 
226   /**
227    * \class QualifiedIterator
228    * Iterator class that is either 'const' or non-const qualified.
229    * A non-const qualified instantiation of this template allows the pixel that
230    * it points to, to be modified. A const qualified instantiation does not.
231    *
232    * \note The definition of this class is private. Please use its type alias
233    * ImageBufferRange::iterator, or ImageBufferRange::const_iterator!
234    * \see ImageBufferRange
235    * \ingroup ImageIterators
236    * \ingroup ITKCommon
237    */
238   template <bool VIsConst>
239   class QualifiedIterator final
240   {
241   private:
242     // Const and non-const iterators are friends, in order to implement the
243     // constructor that allow conversion from non-const to const iterator.
244     friend class QualifiedIterator<!VIsConst>;
245 
246     // ImageBufferRange is a friend, as it should be the only one that can
247     // directly use the private constructor of the iterator.
248     friend class ImageBufferRange;
249 
250     // Image type class that is either 'const' or non-const qualified, depending on QualifiedIterator and TImage.
251     using QualifiedImageType = typename std::conditional<VIsConst, const ImageType, ImageType>::type;
252 
253     static constexpr bool IsImageTypeConst = std::is_const<QualifiedImageType>::value;
254 
255     using QualifiedInternalPixelType = typename std::conditional<IsImageTypeConst, const InternalPixelType, InternalPixelType>::type;
256 
257     // Pixel type class that is either 'const' or non-const qualified, depending on QualifiedImageType.
258     using QualifiedPixelType = typename std::conditional<IsImageTypeConst, const PixelType, PixelType>::type;
259 
260 
261     // Wraps a reference to a pixel.
262     class PixelReferenceWrapper final
263     {
264     public:
265       QualifiedPixelType& m_Pixel;
266 
267       // Wraps the pixel reference that is specified by the first argument.
268       // Note: the second parameter is unused, but it is there just to support
269       // the use case of iterator::operator*(), which uses either
270       // PixelReferenceWrapper or PixelProxy, interchangeable, in a generic way.
271       // (PixelProxy has an explicit constructor for which the second parameter
272       // is its essential AccessorFunctor parameter!)
PixelReferenceWrapper(QualifiedPixelType & pixel,EmptyAccessorFunctor itkNotUsed (accessorFunctor))273       explicit PixelReferenceWrapper(
274         QualifiedPixelType& pixel,
275         EmptyAccessorFunctor itkNotUsed(accessorFunctor)) ITK_NOEXCEPT
276         :
277       m_Pixel(pixel)
278       {
279       }
280 
281       // Converts implicitly to a reference to the pixel.
282       operator QualifiedPixelType&() const ITK_NOEXCEPT
283       {
284         return m_Pixel;
285       }
286     };
287 
288 
289     // QualifiedIterator data members (strictly private):
290 
291     // The accessor functor of the image.
292     OptionalAccessorFunctorType m_OptionalAccessorFunctor;
293 
294     // Pointer to the current pixel.
295     QualifiedInternalPixelType* m_InternalPixelPointer = nullptr;
296 
297     // Private constructor, used to create the begin and the end iterator of a range.
298     // Only used by its friend class ImageBufferRange.
QualifiedIterator(const OptionalAccessorFunctorType & accessorFunctor,QualifiedInternalPixelType * const internalPixelPointer)299     QualifiedIterator(
300       const OptionalAccessorFunctorType& accessorFunctor,
301       QualifiedInternalPixelType* const internalPixelPointer) ITK_NOEXCEPT
302       :
303     // Note: Use parentheses instead of curly braces to initialize data members,
304     // to avoid AppleClang 6.0.0.6000056 compilation error, "no viable conversion..."
305     m_OptionalAccessorFunctor(accessorFunctor),
306     m_InternalPixelPointer{ internalPixelPointer }
307     {
308     }
309 
310   public:
311     // Types conforming the iterator requirements of the C++ standard library:
312     using difference_type = std::ptrdiff_t;
313     using value_type = PixelType;
314     using reference = typename std::conditional< SupportsDirectPixelAccess,
315       QualifiedPixelType&, PixelProxy<IsImageTypeConst>>::type;
316     using pointer = QualifiedPixelType*;
317     using iterator_category = std::random_access_iterator_tag;
318 
319 
320     /** Default-constructor, as required for any C++11 Forward Iterator. Offers
321      * the guarantee added to the C++14 Standard: "value-initialized iterators
322      * may be compared and shall compare equal to other value-initialized
323      * iterators of the same type."
324      * \note `QualifiedIterator<VIsConst>` follows the C++ "Rule of Zero" when
325      * VIsConst is true: The other five "special member functions" of the class
326      * are then implicitly defaulted. When VIsConst is false, its
327      * copy-constructor is provided explicitly, but it still behaves the same as
328      * a default implementation.
329      */
330     QualifiedIterator() = default;
331 
332     /** Constructor that allows implicit conversion from non-const to const
333      * iterator. Also serves as copy-constructor of a non-const iterator.  */
QualifiedIterator(const QualifiedIterator<false> & arg)334     QualifiedIterator(const QualifiedIterator<false>& arg) ITK_NOEXCEPT
335       :
336       // Note: Use parentheses instead of curly braces to initialize data members,
337       // to avoid AppleClang 6.0.0.6000056 compilation error, "no viable conversion..."
338       m_OptionalAccessorFunctor(arg.m_OptionalAccessorFunctor),
339       m_InternalPixelPointer{ arg.m_InternalPixelPointer }
340     {
341     }
342 
343 
344     /**  Returns a reference to the current pixel. */
345     reference operator*() const ITK_NOEXCEPT
346     {
347       assert(m_InternalPixelPointer != nullptr);
348 
349       using PixelWrapper = typename std::conditional<SupportsDirectPixelAccess,
350         PixelReferenceWrapper, reference>::type;
351 
352       return PixelWrapper{ *m_InternalPixelPointer, m_OptionalAccessorFunctor };
353     }
354 
355 
356     /** Prefix increment ('++it'). */
357     QualifiedIterator& operator++() ITK_NOEXCEPT
358     {
359       assert(m_InternalPixelPointer != nullptr);
360       ++m_InternalPixelPointer;
361       return *this;
362     }
363 
364 
365     /** Postfix increment ('it++').
366      * \note Usually prefix increment ('++it') is preferable. */
367     QualifiedIterator operator++(int) ITK_NOEXCEPT
368     {
369       auto result = *this;
370       ++(*this);
371       return result;
372     }
373 
374 
375     /** Prefix decrement ('--it'). */
376     QualifiedIterator& operator--() ITK_NOEXCEPT
377     {
378       assert(m_InternalPixelPointer != nullptr);
379       --m_InternalPixelPointer;
380       return *this;
381     }
382 
383 
384     /** Postfix increment ('it--').
385      * \note  Usually prefix increment ('--it') is preferable. */
386     QualifiedIterator operator--(int) ITK_NOEXCEPT
387     {
388       auto result = *this;
389       --(*this);
390       return result;
391     }
392 
393 
394     /** Returns (it1 == it2) for iterators it1 and it2. Note that these iterators
395      * should be from the same range. This operator does not support comparing iterators
396      * from different ranges. */
397     friend bool operator==(const QualifiedIterator& lhs, const QualifiedIterator& rhs) ITK_NOEXCEPT
398     {
399       return lhs.m_InternalPixelPointer == rhs.m_InternalPixelPointer;
400     }
401 
402 
403     /** Returns (it1 != it2) for iterators it1 and it2. */
404     friend bool operator!=(const QualifiedIterator& lhs, const QualifiedIterator& rhs) ITK_NOEXCEPT
405     {
406       // Implemented just like the corresponding std::rel_ops operator.
407       return !(lhs == rhs);
408     }
409 
410 
411     /** Returns (it1 < it2) for iterators it1 and it2. */
412     friend bool operator<(const QualifiedIterator& lhs, const QualifiedIterator& rhs) ITK_NOEXCEPT
413     {
414       return lhs.m_InternalPixelPointer < rhs.m_InternalPixelPointer;
415     }
416 
417 
418     /** Returns (it1 > it2) for iterators it1 and it2. */
419     friend bool operator>(const QualifiedIterator& lhs, const QualifiedIterator& rhs) ITK_NOEXCEPT
420     {
421       // Implemented just like the corresponding std::rel_ops operator.
422       return rhs < lhs;
423     }
424 
425 
426     /** Returns (it1 <= it2) for iterators it1 and it2. */
427     friend bool operator<=(const QualifiedIterator& lhs, const QualifiedIterator& rhs) ITK_NOEXCEPT
428     {
429       // Implemented just like the corresponding std::rel_ops operator.
430       return !(rhs < lhs);
431     }
432 
433 
434     /** Returns (it1 >= it2) for iterators it1 and it2. */
435     friend bool operator>=(const QualifiedIterator& lhs, const QualifiedIterator& rhs) ITK_NOEXCEPT
436     {
437       // Implemented just like the corresponding std::rel_ops operator.
438       return !(lhs < rhs);
439     }
440 
441 
442     /** Does (it += d) for iterator 'it' and integer value 'n'. */
443     friend QualifiedIterator& operator+=(QualifiedIterator& it, const difference_type n) ITK_NOEXCEPT
444     {
445       it.m_InternalPixelPointer += n;
446       return it;
447     }
448 
449     /** Does (it -= d) for iterator 'it' and integer value 'n'. */
450     friend QualifiedIterator& operator-=(QualifiedIterator& it, const difference_type n) ITK_NOEXCEPT
451     {
452       it += (-n);
453       return it;
454     }
455 
456     /** Returns (it1 - it2) for iterators it1 and it2. */
457     friend difference_type operator-(const QualifiedIterator& lhs, const QualifiedIterator& rhs) ITK_NOEXCEPT
458     {
459       return lhs.m_InternalPixelPointer - rhs.m_InternalPixelPointer;
460     }
461 
462 
463     /** Returns (it + n) for iterator 'it' and integer value 'n'. */
464     friend QualifiedIterator operator+(QualifiedIterator it, const difference_type n) ITK_NOEXCEPT
465     {
466       return it += n;
467     }
468 
469 
470     /** Returns (n + it) for iterator 'it' and integer value 'n'. */
471     friend QualifiedIterator operator+(const difference_type n, QualifiedIterator it) ITK_NOEXCEPT
472     {
473       return it += n;
474     }
475 
476 
477     /** Returns (it - n) for iterator 'it' and integer value 'n'. */
478     friend QualifiedIterator operator-(QualifiedIterator it, const difference_type n) ITK_NOEXCEPT
479     {
480       return it += (-n);
481     }
482 
483 
484     /** Returns it[n] for iterator 'it' and integer value 'n'. */
485     reference operator[](const difference_type n) const ITK_NOEXCEPT
486     {
487       return *(*this + n);
488     }
489 
490 
491     /** Explicitly-defaulted assignment operator. */
492     QualifiedIterator& operator=(const QualifiedIterator&) ITK_NOEXCEPT = default;
493   };
494 
495   static constexpr bool IsImageTypeConst = std::is_const<TImage>::value;
496 
497   using QualifiedInternalPixelType = typename std::conditional<IsImageTypeConst, const InternalPixelType, InternalPixelType>::type;
498 
499   class AccessorFunctorInitializer final
500   {
501   private:
502     ImageType& m_Image;
503   public:
AccessorFunctorInitializer(ImageType & image)504     explicit AccessorFunctorInitializer(ImageType& image) ITK_NOEXCEPT
505       :
506       m_Image(image)
507     {
508     }
509 
EmptyAccessorFunctor()510     operator EmptyAccessorFunctor() const ITK_NOEXCEPT
511     {
512       return {};
513     }
514 
AccessorFunctorType()515     operator AccessorFunctorType() const ITK_NOEXCEPT
516     {
517       AccessorFunctorType result = {};
518       result.SetPixelAccessor(m_Image.GetPixelAccessor());
519       result.SetBegin(m_Image.ImageType::GetBufferPointer());
520       return result;
521     }
522   };
523 
524 
525   // Helper class for begin() and end(), to ease proper initialization of an
526   // ImageBufferRange iterator (either a 'QualifiedIterator' or a raw pixel pointer).
527   class IteratorInitializer final
528   {
529   private:
530     OptionalAccessorFunctorType m_OptionalAccessorFunctor;
531     QualifiedInternalPixelType* m_InternalPixelPointer;
532   public:
IteratorInitializer(OptionalAccessorFunctorType optionalAccessorFunctor,QualifiedInternalPixelType * internalPixelPointer)533     explicit IteratorInitializer(
534       OptionalAccessorFunctorType optionalAccessorFunctor,
535       QualifiedInternalPixelType* internalPixelPointer) ITK_NOEXCEPT
536       :
537       m_OptionalAccessorFunctor(optionalAccessorFunctor),
538       m_InternalPixelPointer(internalPixelPointer)
539     {
540     }
541 
542     // Converts to a 'QualifiedIterator' object.
543     template <bool VIsConst>
544     operator QualifiedIterator<VIsConst>() const ITK_NOEXCEPT
545     {
546       return QualifiedIterator<VIsConst>{m_OptionalAccessorFunctor, m_InternalPixelPointer};
547     }
548 
549     // Converts to a raw pixel pointer.
550     operator QualifiedInternalPixelType*() const ITK_NOEXCEPT
551     {
552       return m_InternalPixelPointer;
553     }
554   };
555 
556 
557   // ImageBufferRange data members (strictly private):
558 
559   // The accessor functor of the image.
560   OptionalAccessorFunctorType m_OptionalAccessorFunctor;
561 
562   // Pointer to the buffer of the image.
563   QualifiedInternalPixelType* m_ImageBufferPointer = nullptr;
564 
565   // Image size.
566   SizeValueType m_NumberOfPixels = 0;
567 
568 public:
569   using const_iterator = typename std::conditional<UsingPointerAsIterator,
570     const InternalPixelType*, QualifiedIterator<true>>::type;
571   using iterator = typename std::conditional<UsingPointerAsIterator,
572     QualifiedInternalPixelType*, QualifiedIterator<IsImageTypeConst>>::type;
573   using reverse_iterator = std::reverse_iterator<iterator>;
574   using const_reverse_iterator = std::reverse_iterator<const_iterator>;
575 
576 
577   /** Explicitly-defaulted default-constructor. Constructs an empty range.
578    * \note The other five "special member functions" (copy-constructor,
579    * copy-assignment operator, move-constructor, move-assignment operator,
580    * and destructor) are defaulted implicitly, following the C++ "Rule of Zero".
581    */
582   ImageBufferRange() = default;
583 
584 
585   /** Specifies a range of the pixels of an image.
586    */
ImageBufferRange(ImageType & image)587   explicit ImageBufferRange(ImageType& image)
588     :
589   // Note: Use parentheses instead of curly braces to initialize data members,
590   // to avoid AppleClang 6.0.0.6000056 compile errors, "no viable conversion..."
591   m_OptionalAccessorFunctor(AccessorFunctorInitializer{ image }),
592   m_ImageBufferPointer{ image.ImageType::GetBufferPointer() },
593   m_NumberOfPixels{ image.ImageType::GetBufferedRegion().GetNumberOfPixels() }
594   {
595   }
596 
597 
598   /** Returns an iterator to the first pixel. */
begin()599   iterator begin() const ITK_NOEXCEPT
600   {
601     return IteratorInitializer{ m_OptionalAccessorFunctor, m_ImageBufferPointer };
602   }
603 
604   /** Returns an 'end iterator' for this range. */
end()605   iterator end() const ITK_NOEXCEPT
606   {
607     return IteratorInitializer{ m_OptionalAccessorFunctor, m_ImageBufferPointer + m_NumberOfPixels, };
608   }
609 
610   /** Returns a const iterator to the first pixel.
611    * Provides only read-only access to the pixel data. */
cbegin()612   const_iterator cbegin() const ITK_NOEXCEPT
613   {
614     return this->begin();
615   }
616 
617   /** Returns a const 'end iterator' for this range. */
cend()618   const_iterator cend() const ITK_NOEXCEPT
619   {
620     return this->end();
621   }
622 
623   /** Returns a reverse 'begin iterator' for this range. */
rbegin()624   reverse_iterator rbegin() const ITK_NOEXCEPT
625   {
626     return reverse_iterator(this->end());
627   }
628 
629   /** Returns a reverse 'end iterator' for this range. */
rend()630   reverse_iterator rend() const ITK_NOEXCEPT
631   {
632     return reverse_iterator(this->begin());
633   }
634 
635   /** Returns a const reverse 'begin iterator' for this range. */
crbegin()636   const_reverse_iterator crbegin() const ITK_NOEXCEPT
637   {
638     return this->rbegin();
639   }
640 
641   /** Returns a const reverse 'end iterator' for this range. */
crend()642   const_reverse_iterator crend() const ITK_NOEXCEPT
643   {
644     return this->rend();
645   }
646 
647 
648   /** Returns the size of the range, that is the number of pixels. */
size()649   std::size_t size() const ITK_NOEXCEPT
650   {
651     return m_NumberOfPixels;
652   }
653 
654 
655   /** Tells whether the range is empty. */
empty()656   bool empty() const ITK_NOEXCEPT
657   {
658     return m_NumberOfPixels == 0;
659   }
660 
661 
662   /** Subscript operator. Allows random access, to the nth pixel.
663   * \note The return type QualifiedIterator<false>::reference is equivalent to
664   * iterator::reference.
665   */
666   typename QualifiedIterator<false>::reference operator[](const std::size_t n) const ITK_NOEXCEPT
667   {
668     assert(n < this->size());
669     assert(n <= static_cast<std::size_t>(std::numeric_limits<std::ptrdiff_t>::max()));
670 
671     return this->begin()[static_cast<std::ptrdiff_t>(n)];
672   }
673 };
674 
675 /** Creates a range to iterate over the pixels of the specified image.
676  * Returns an empty range when the specified argument is a nullptr (which
677  * is a valid use case).
678  */
679 template<typename TImage>
MakeImageBufferRange(TImage * const image)680 ImageBufferRange<TImage> MakeImageBufferRange(TImage* const image)
681 {
682   if (image == nullptr)
683   {
684     return {};
685   }
686   else
687   {
688     return ImageBufferRange<TImage>{*image};
689   }
690 }
691 
692 } // namespace Experimental
693 } // namespace itk
694 
695 #endif
696