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