ITK  6.0.0
Insight Toolkit
itkImageRegionRange.h
Go to the documentation of this file.
1 /*=========================================================================
2  *
3  * Copyright NumFOCUS
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  * https://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 itkImageRegionRange_h
20 #define itkImageRegionRange_h
21 
22 #include <algorithm> // For any_of and copy_n.
23 #include <cassert>
24 #include <cstddef> // For ptrdiff_t.
25 #include <iterator> // For bidirectional_iterator_tag.
26 #include <functional> // For multiplies.
27 #include <numeric> // For accumulate.
28 #include <type_traits> // For conditional, enable_if, and is_const.
29 
30 #include "itkImageHelper.h"
31 #include "itkImageRegion.h"
32 #include "itkImageBufferRange.h"
33 
34 namespace itk
35 {
36 
71 template <typename TImage>
72 class ImageRegionRange final
73 {
74 private:
76  using ImageDimensionType = typename TImage::ImageDimensionType;
77  using PixelType = typename TImage::PixelType;
78 
79  static constexpr bool IsImageTypeConst = std::is_const_v<TImage>;
80  static constexpr ImageDimensionType ImageDimension = TImage::ImageDimension;
81 
83  using RegionType = typename TImage::RegionType;
84  using SizeType = typename TImage::SizeType;
85  using OffsetType = typename TImage::OffsetType;
87  using IndexType = typename RegionType::IndexType;
88 
89 
102  template <bool VIsConst>
103  class QualifiedIterator final
104  {
105  private:
106  // Const and non-const iterators are friends, in order to implement the
107  // constructor that allow conversion from non-const to const iterator.
108  friend class QualifiedIterator<!VIsConst>;
109 
110  // ImageRegionRange is a friend, as it should be the only one that can
111  // directly use the private constructor of the iterator.
112  friend class ImageRegionRange;
113 
114  // Use either a const or a non-const qualified image buffer iterator.
115  using QualifiedBufferIteratorType = std::conditional_t<VIsConst,
118 
119  // QualifiedIterator data members (strictly private):
120 
121  // Iterator to the current pixel.
123 
124  // A copy of the offset table of the image.
126 
127  // N-Dimensional offset relative to the index of the iteration region.
129 
130  // Size of the iteration region.
132 
133  // Private constructor, used to create the begin and the end iterator of a range.
134  // Only used by its friend class ImageRegionRange.
136  const OffsetTableType & offsetTable,
137  const OffsetType & iterationOffset,
138  const SizeType & regionSize) noexcept
139  : m_BufferIterator(bufferIterator)
140  ,
141  // Note: Use parentheses instead of curly braces to initialize data members,
142  // to avoid AppleClang 6.0.0.6000056 compilation error, "no viable conversion..."
143  m_OffsetTable(offsetTable)
144  , m_IterationOffset(iterationOffset)
145  , m_IterationRegionSize(regionSize)
146  {}
147 
148  template <size_t VIndex>
149  void
150  Increment() noexcept
151  {
152  m_BufferIterator += m_OffsetTable[VIndex];
153 
154  if constexpr (VIndex < (ImageDimension - 1))
155  {
156  if (static_cast<SizeValueType>(++m_IterationOffset[VIndex]) >= m_IterationRegionSize[VIndex])
157  {
158  m_IterationOffset[VIndex] = 0;
160  this->Increment<VIndex + 1>();
161  }
162  }
163  else
164  {
165  static_assert(VIndex == (ImageDimension - 1));
166 
167  ++m_IterationOffset[VIndex];
168  }
169  }
170 
171 
172  template <size_t VIndex>
173  void
174  Decrement() noexcept
175  {
176  m_BufferIterator -= m_OffsetTable[VIndex];
177 
178  if constexpr (VIndex < (ImageDimension - 1))
179  {
180  if (--m_IterationOffset[VIndex] < 0)
181  {
182  m_IterationOffset[VIndex] = m_IterationRegionSize[VIndex] - 1;
184  this->Decrement<VIndex + 1>();
185  }
186  }
187  else
188  {
189  static_assert(VIndex == (ImageDimension - 1));
190 
191  --m_IterationOffset[VIndex];
192  }
193  }
194 
195 
196  public:
197  // Types conforming the iterator requirements of the C++ standard library:
198  using difference_type = ptrdiff_t;
199  using value_type = typename std::iterator_traits<QualifiedBufferIteratorType>::value_type;
200  using reference = typename std::iterator_traits<QualifiedBufferIteratorType>::reference;
201  using pointer = typename std::iterator_traits<QualifiedBufferIteratorType>::pointer;
202  using iterator_category = std::bidirectional_iterator_tag;
203 
212  QualifiedIterator() = default;
213 
215  template <bool VIsArgumentConst, typename = std::enable_if_t<VIsConst && !VIsArgumentConst>>
217  : m_BufferIterator(arg.m_BufferIterator)
218  ,
219  // Note: Use parentheses instead of curly braces to initialize data members,
220  // to avoid AppleClang 6.0.0.6000056 compilation error, "no viable conversion..."
221  m_OffsetTable(arg.m_OffsetTable)
222  , m_IterationOffset(arg.m_IterationOffset)
223  , m_IterationRegionSize(arg.m_IterationRegionSize)
224  {}
225 
226 
228  reference
229  operator*() const noexcept
230  {
231  return *m_BufferIterator;
232  }
233 
236  operator++() noexcept
237  {
238  this->Increment<0>();
239  return *this;
240  }
247  operator++(int) noexcept
248  {
249  auto result = *this;
250  ++(*this);
251  return result;
252  }
258  operator--() noexcept
259  {
260  this->Decrement<0>();
261  return *this;
262  }
269  operator--(int) noexcept
270  {
271  auto result = *this;
272  --(*this);
273  return result;
274  }
281  friend bool
282  operator==(const QualifiedIterator & lhs, const QualifiedIterator & rhs) noexcept
283  {
284  return lhs.m_BufferIterator == rhs.m_BufferIterator;
285  }
286 
287 
289  friend bool
290  operator!=(const QualifiedIterator & lhs, const QualifiedIterator & rhs) noexcept
291  {
292  // Implemented just like the corresponding std::rel_ops operator.
293  return !(lhs == rhs);
294  }
295  };
298  // Inspired by, and originally copied from ImageBase::FastComputeOffset(ind)).
299  static OffsetValueType
300  ComputeOffset(const OffsetTableType & offsetTable, const IndexType & bufferedRegionIndex, const IndexType & index)
301  {
302  OffsetValueType offsetValue = 0;
304  bufferedRegionIndex, index, offsetTable.data(), offsetValue);
305  return offsetValue;
306  }
307 
308  // ImageRegionRange data members (strictly private):
309 
311 
313 
315 
317 
318  // A copy of the offset table of the image.
320 
321 public:
324  using reverse_iterator = std::reverse_iterator<iterator>;
325  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
326 
327 
330  ImageRegionRange() noexcept = default;
331 
332 
337  explicit ImageRegionRange(TImage & image, const RegionType & iterationRegion)
338  : m_BufferBegin{ std::begin(ImageBufferRange{ image }) }
339  ,
340  // Note: Use parentheses instead of curly braces to initialize data members,
341  // to avoid AppleClang 6.0.0.6000056 compile errors, "no viable conversion..."
342  m_BufferedRegionIndex(image.TImage::GetBufferedRegion().GetIndex())
343  , m_IterationRegionIndex(iterationRegion.GetIndex())
344  , m_IterationRegionSize(iterationRegion.GetSize())
345  {
346  const OffsetValueType * const offsetTable = image.GetOffsetTable();
347  assert(offsetTable != nullptr);
350  if (iterationRegion.GetNumberOfPixels() > 0) // If region is non-empty
351  {
352  // Check if the iteration region is within the buffered region, similar
353  // to checks in ImageConstIteratorWithIndex(const TImage*, const RegionType&)
354  // and ImageConstIterator::SetRegion(const RegionType&).
355 
356  const auto & bufferedRegion = image.GetBufferedRegion();
357 
358  itkAssertOrThrowMacro((bufferedRegion.IsInside(iterationRegion)),
359  "Iteration region " << iterationRegion << " is outside of buffered region "
360  << bufferedRegion);
361  }
362 
363  std::copy_n(offsetTable, ImageDimension + 1, m_OffsetTable.data());
364  }
365 
366 
370  explicit ImageRegionRange(TImage & image)
371  : ImageRegionRange(image, image.GetRequestedRegion())
372  {}
373 
374 
376  iterator
377  begin() const noexcept
378  {
381  OffsetType(),
383  }
387  iterator
388  end() const noexcept
389  {
390  auto endRegionIndex = m_IterationRegionIndex;
391  endRegionIndex.back() += m_IterationRegionSize.back();
394  OffsetType iterationOffset{ {} }; // Initialize offsets to 0, by aggregate initializer
395  *(iterationOffset.rbegin()) = m_IterationRegionSize.back();
396 
399  iterationOffset,
401  }
402 
406  cbegin() const noexcept
407  {
408  return this->begin();
409  }
410 
413  cend() const noexcept
414  {
415  return this->end();
416  }
417 
420  rbegin() const noexcept
421  {
422  return reverse_iterator{ this->end() };
423  }
428  rend() const noexcept
429  {
430  return reverse_iterator{ this->begin() };
431  }
436  crbegin() const noexcept
437  {
438  return this->rbegin();
439  }
440 
443  crend() const noexcept
444  {
445  return this->rend();
446  }
447 
448 
450  size_t
451  size() const noexcept
452  {
453  return std::accumulate(
454  m_IterationRegionSize.begin(), m_IterationRegionSize.end(), size_t{ 1 }, std::multiplies<size_t>{});
455  }
460  bool
461  empty() const noexcept
462  {
463  return std::any_of(m_IterationRegionSize.begin(), m_IterationRegionSize.end(), [](const SizeValueType sizeValue) {
464  return sizeValue == 0;
465  });
466  }
471  ~ImageRegionRange() = default;
472 };
473 
474 
475 // Deduction guide to avoid compiler warnings (-wctad-maybe-unsupported) when using class template argument deduction.
476 template <typename TImage>
477 ImageRegionRange(TImage &) -> ImageRegionRange<TImage>;
478 
479 } // namespace itk
480 
481 #endif
itk::ImageRegionRange::QualifiedIterator
Definition: itkImageRegionRange.h:103
itk::ImageRegionRange::OffsetType
typename TImage::OffsetType OffsetType
Definition: itkImageRegionRange.h:85
itk::ImageRegionRange
Definition: itkImageRegionRange.h:72
itk::ImageRegionRange::ImageRegionRange
ImageRegionRange(TImage &image)
Definition: itkImageRegionRange.h:370
itk::ImageRegionRange::reverse_iterator
std::reverse_iterator< iterator > reverse_iterator
Definition: itkImageRegionRange.h:324
itk::ImageRegionRange::const_reverse_iterator
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: itkImageRegionRange.h:325
itk::ImageRegionRange::size
vcl_size_t size() const noexcept
Definition: itkImageRegionRange.h:451
itk::ImageRegionRange::begin
iterator begin() const noexcept
Definition: itkImageRegionRange.h:377
itk::ImageRegionRange::QualifiedIterator::m_OffsetTable
OffsetTableType m_OffsetTable
Definition: itkImageRegionRange.h:125
itk::ImageRegionRange::BufferIteratorType
typename ImageBufferRange< TImage >::iterator BufferIteratorType
Definition: itkImageRegionRange.h:82
itk::ImageRegionRange::QualifiedIterator::m_IterationRegionSize
SizeType m_IterationRegionSize
Definition: itkImageRegionRange.h:131
itk::ImageRegionRange::cend
const_iterator cend() const noexcept
Definition: itkImageRegionRange.h:413
itk::ImageRegionRange::QualifiedIterator::value_type
typename std::iterator_traits< QualifiedBufferIteratorType >::value_type value_type
Definition: itkImageRegionRange.h:199
itk::ImageRegionRange::QualifiedIterator::Decrement
void Decrement() noexcept
Definition: itkImageRegionRange.h:174
itkImageHelper.h
itk::ImageRegionRange::QualifiedIterator::reference
typename std::iterator_traits< QualifiedBufferIteratorType >::reference reference
Definition: itkImageRegionRange.h:200
itk::ImageRegionRange::~ImageRegionRange
~ImageRegionRange()=default
itk::ImageRegionRange::empty
bool empty() const noexcept
Definition: itkImageRegionRange.h:461
itk::GTest::TypedefsAndConstructors::Dimension2::SizeType
ImageBaseType::SizeType SizeType
Definition: itkGTestTypedefsAndConstructors.h:49
itk::ImageRegionRange::QualifiedIterator::Increment
void Increment() noexcept
Definition: itkImageRegionRange.h:150
itk::ImageRegionRange::QualifiedIterator::operator++
QualifiedIterator operator++(int) noexcept
Definition: itkImageRegionRange.h:247
itk::ImageRegionRange::QualifiedIterator::operator--
QualifiedIterator & operator--() noexcept
Definition: itkImageRegionRange.h:258
itk::ImageRegionRange::QualifiedIterator::pointer
typename std::iterator_traits< QualifiedBufferIteratorType >::pointer pointer
Definition: itkImageRegionRange.h:201
itk::ImageBufferRange::const_iterator
std::conditional_t< UsingPointerAsIterator, const InternalPixelType *, QualifiedIterator< true > > const_iterator
Definition: itkImageBufferRange.h:556
itkImageRegion.h
itk::GTest::TypedefsAndConstructors::Dimension2::IndexType
ImageBaseType::IndexType IndexType
Definition: itkGTestTypedefsAndConstructors.h:50
itk::ImageRegionRange::QualifiedIterator::operator==
friend bool operator==(const QualifiedIterator &lhs, const QualifiedIterator &rhs) noexcept
Definition: itkImageRegionRange.h:282
itk::ImageRegionRange::QualifiedIterator::difference_type
ptrdiff_t difference_type
Definition: itkImageRegionRange.h:198
itk::ImageRegionRange::QualifiedIterator::QualifiedIterator
QualifiedIterator(const QualifiedBufferIteratorType &bufferIterator, const OffsetTableType &offsetTable, const OffsetType &iterationOffset, const SizeType &regionSize) noexcept
Definition: itkImageRegionRange.h:135
itk::ImageRegionRange::QualifiedIterator::QualifiedIterator
QualifiedIterator()=default
itk::ImageRegionRange::ImageDimension
static constexpr ImageDimensionType ImageDimension
Definition: itkImageRegionRange.h:80
itk::ImageRegionRange::QualifiedIterator::operator--
QualifiedIterator operator--(int) noexcept
Definition: itkImageRegionRange.h:269
itk::GTest::TypedefsAndConstructors::Dimension2::RegionType
ImageBaseType::RegionType RegionType
Definition: itkGTestTypedefsAndConstructors.h:54
itk::ImageBufferRange
Definition: itkImageBufferRange.h:73
itk::ImageRegionRange::m_OffsetTable
OffsetTableType m_OffsetTable
Definition: itkImageRegionRange.h:319
itk::ImageRegionRange::rbegin
reverse_iterator rbegin() const noexcept
Definition: itkImageRegionRange.h:420
itk::ImageHelper::ComputeOffset
static void ComputeOffset(const IndexType &bufferedRegionIndex, const IndexType &index, [[maybe_unused]] const OffsetValueType offsetTable[], OffsetValueType &offset)
Definition: itkImageHelper.h:92
itk::OffsetValueType
long OffsetValueType
Definition: itkIntTypes.h:97
itk::ImageRegionRange::rend
reverse_iterator rend() const noexcept
Definition: itkImageRegionRange.h:428
itk::ImageRegionRange::iterator
QualifiedIterator< IsImageTypeConst > iterator
Definition: itkImageRegionRange.h:323
itk::Offset< ImageDimension+1 >
itk::ImageRegionRange::end
iterator end() const noexcept
Definition: itkImageRegionRange.h:388
itk::ImageRegionRange::crend
const_reverse_iterator crend() const noexcept
Definition: itkImageRegionRange.h:443
itk::ImageRegionRange::m_BufferedRegionIndex
IndexType m_BufferedRegionIndex
Definition: itkImageRegionRange.h:312
itk
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....
Definition: itkAnatomicalOrientation.h:29
itk::ImageRegionRange
ImageRegionRange(TImage &) -> ImageRegionRange< TImage >
itk::ImageRegionRange::QualifiedIterator::m_IterationOffset
OffsetType m_IterationOffset
Definition: itkImageRegionRange.h:128
itk::ImageRegionRange::IsImageTypeConst
static constexpr bool IsImageTypeConst
Definition: itkImageRegionRange.h:79
itk::Offset::data
OffsetValueType * data()
Definition: itkOffset.h:438
itk::ImageRegionRange::SizeType
typename TImage::SizeType SizeType
Definition: itkImageRegionRange.h:84
itk::ImageRegionRange::m_IterationRegionIndex
IndexType m_IterationRegionIndex
Definition: itkImageRegionRange.h:314
itk::ImageRegionRange::IndexType
typename RegionType::IndexType IndexType
Definition: itkImageRegionRange.h:87
itk::ImageRegionRange::QualifiedIterator::m_BufferIterator
QualifiedBufferIteratorType m_BufferIterator
Definition: itkImageRegionRange.h:122
itk::ImageRegionRange::QualifiedIterator::operator*
reference operator*() const noexcept
Definition: itkImageRegionRange.h:229
itk::ImageRegionRange::cbegin
const_iterator cbegin() const noexcept
Definition: itkImageRegionRange.h:406
itk::ImageRegionRange::m_BufferBegin
BufferIteratorType m_BufferBegin
Definition: itkImageRegionRange.h:310
itk::ImageRegionRange::crbegin
const_reverse_iterator crbegin() const noexcept
Definition: itkImageRegionRange.h:436
itk::ImageRegionRange::PixelType
typename TImage::PixelType PixelType
Definition: itkImageRegionRange.h:77
itk::ImageRegionRange::QualifiedIterator::operator++
QualifiedIterator & operator++() noexcept
Definition: itkImageRegionRange.h:236
itk::ImageRegionRange::RegionType
typename TImage::RegionType RegionType
Definition: itkImageRegionRange.h:83
itk::ImageRegionRange::ImageDimensionType
typename TImage::ImageDimensionType ImageDimensionType
Definition: itkImageRegionRange.h:76
itk::ImageRegionRange::const_iterator
QualifiedIterator< true > const_iterator
Definition: itkImageRegionRange.h:322
itk::ImageRegionRange::ComputeOffset
static OffsetValueType ComputeOffset(const OffsetTableType &offsetTable, const IndexType &bufferedRegionIndex, const IndexType &index)
Definition: itkImageRegionRange.h:300
itk::ImageRegionRange::QualifiedIterator::operator!=
friend bool operator!=(const QualifiedIterator &lhs, const QualifiedIterator &rhs) noexcept
Definition: itkImageRegionRange.h:290
itk::ImageRegionRange::QualifiedIterator::QualifiedIterator
QualifiedIterator(const QualifiedIterator< VIsArgumentConst > &arg) noexcept
Definition: itkImageRegionRange.h:216
itk::ImageBufferRange::iterator
std::conditional_t< UsingPointerAsIterator, QualifiedInternalPixelType *, QualifiedIterator< IsImageTypeConst > > iterator
Definition: itkImageBufferRange.h:558
itk::SizeValueType
unsigned long SizeValueType
Definition: itkIntTypes.h:86
itk::ImageRegionRange::QualifiedIterator::QualifiedBufferIteratorType
std::conditional_t< VIsConst, typename ImageBufferRange< TImage >::const_iterator, typename ImageBufferRange< TImage >::iterator > QualifiedBufferIteratorType
Definition: itkImageRegionRange.h:117
itkImageBufferRange.h
itk::ImageRegionRange::ImageRegionRange
ImageRegionRange() noexcept=default
itk::ImageRegionRange::m_IterationRegionSize
SizeType m_IterationRegionSize
Definition: itkImageRegionRange.h:316
itk::ImageRegionRange::QualifiedIterator::iterator_category
std::bidirectional_iterator_tag iterator_category
Definition: itkImageRegionRange.h:202