ITK  5.4.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 operator*() const noexcept { return *m_BufferIterator; }
229 
232  operator++() noexcept
233  {
234  this->Increment<0>();
235  return *this;
236  }
243  operator++(int) noexcept
244  {
245  auto result = *this;
246  ++(*this);
247  return result;
248  }
254  operator--() noexcept
255  {
256  this->Decrement<0>();
257  return *this;
258  }
265  operator--(int) noexcept
266  {
267  auto result = *this;
268  --(*this);
269  return result;
270  }
277  friend bool
278  operator==(const QualifiedIterator & lhs, const QualifiedIterator & rhs) noexcept
279  {
280  return lhs.m_BufferIterator == rhs.m_BufferIterator;
281  }
282 
283 
285  friend bool
286  operator!=(const QualifiedIterator & lhs, const QualifiedIterator & rhs) noexcept
287  {
288  // Implemented just like the corresponding std::rel_ops operator.
289  return !(lhs == rhs);
290  }
291  };
294  // Inspired by, and originally copied from ImageBase::FastComputeOffset(ind)).
295  static OffsetValueType
296  ComputeOffset(const OffsetTableType & offsetTable, const IndexType & bufferedRegionIndex, const IndexType & index)
297  {
298  OffsetValueType offsetValue = 0;
300  bufferedRegionIndex, index, offsetTable.data(), offsetValue);
301  return offsetValue;
302  }
303 
304  // ImageRegionRange data members (strictly private):
305 
307 
309 
311 
313 
314  // A copy of the offset table of the image.
316 
317 public:
320  using reverse_iterator = std::reverse_iterator<iterator>;
321  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
322 
323 
326  ImageRegionRange() noexcept = default;
327 
328 
333  explicit ImageRegionRange(TImage & image, const RegionType & iterationRegion)
334  : m_BufferBegin{ std::begin(ImageBufferRange{ image }) }
335  ,
336  // Note: Use parentheses instead of curly braces to initialize data members,
337  // to avoid AppleClang 6.0.0.6000056 compile errors, "no viable conversion..."
338  m_BufferedRegionIndex(image.TImage::GetBufferedRegion().GetIndex())
339  , m_IterationRegionIndex(iterationRegion.GetIndex())
340  , m_IterationRegionSize(iterationRegion.GetSize())
341  {
342  const OffsetValueType * const offsetTable = image.GetOffsetTable();
343  assert(offsetTable != nullptr);
346  if (iterationRegion.GetNumberOfPixels() > 0) // If region is non-empty
347  {
348  // Check if the iteration region is within the buffered region, similar
349  // to checks in ImageConstIteratorWithIndex(const TImage*, const RegionType&)
350  // and ImageConstIterator::SetRegion(const RegionType&).
351 
352  const auto & bufferedRegion = image.GetBufferedRegion();
353 
354  itkAssertOrThrowMacro((bufferedRegion.IsInside(iterationRegion)),
355  "Iteration region " << iterationRegion << " is outside of buffered region "
356  << bufferedRegion);
357  }
358 
359  std::copy_n(offsetTable, ImageDimension + 1, m_OffsetTable.data());
360  }
361 
362 
366  explicit ImageRegionRange(TImage & image)
367  : ImageRegionRange(image, image.GetRequestedRegion())
368  {}
369 
370 
372  iterator
373  begin() const noexcept
374  {
377  OffsetType(),
379  }
383  iterator
384  end() const noexcept
385  {
386  auto endRegionIndex = m_IterationRegionIndex;
387  endRegionIndex.back() += m_IterationRegionSize.back();
390  OffsetType iterationOffset{ {} }; // Initialize offsets to 0, by aggregate initializer
391  *(iterationOffset.rbegin()) = m_IterationRegionSize.back();
392 
395  iterationOffset,
397  }
398 
402  cbegin() const noexcept
403  {
404  return this->begin();
405  }
406 
409  cend() const noexcept
410  {
411  return this->end();
412  }
413 
416  rbegin() const noexcept
417  {
418  return reverse_iterator{ this->end() };
419  }
424  rend() const noexcept
425  {
426  return reverse_iterator{ this->begin() };
427  }
432  crbegin() const noexcept
433  {
434  return this->rbegin();
435  }
436 
439  crend() const noexcept
440  {
441  return this->rend();
442  }
443 
444 
446  size_t
447  size() const noexcept
448  {
449  return std::accumulate(
450  m_IterationRegionSize.begin(), m_IterationRegionSize.end(), size_t{ 1 }, std::multiplies<size_t>{});
451  }
456  bool
457  empty() const noexcept
458  {
459  return std::any_of(m_IterationRegionSize.begin(), m_IterationRegionSize.end(), [](const SizeValueType sizeValue) {
460  return sizeValue == 0;
461  });
462  }
467  ~ImageRegionRange() = default;
468 };
469 
470 
471 // Deduction guide to avoid compiler warnings (-wctad-maybe-unsupported) when using class template argument deduction.
472 template <typename TImage>
473 ImageRegionRange(TImage &)->ImageRegionRange<TImage>;
474 
475 } // namespace itk
476 
477 #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:366
itk::ImageRegionRange::reverse_iterator
std::reverse_iterator< iterator > reverse_iterator
Definition: itkImageRegionRange.h:320
itk::ImageRegionRange::const_reverse_iterator
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: itkImageRegionRange.h:321
itk::ImageRegionRange::size
vcl_size_t size() const noexcept
Definition: itkImageRegionRange.h:447
itk::ImageRegionRange::begin
iterator begin() const noexcept
Definition: itkImageRegionRange.h:373
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:409
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:457
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:243
itk::ImageRegionRange::QualifiedIterator::operator--
QualifiedIterator & operator--() noexcept
Definition: itkImageRegionRange.h:254
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:550
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:278
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:265
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:315
itk::ImageRegionRange::rbegin
reverse_iterator rbegin() const noexcept
Definition: itkImageRegionRange.h:416
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:94
itk::ImageRegionRange::rend
reverse_iterator rend() const noexcept
Definition: itkImageRegionRange.h:424
itk::ImageRegionRange::iterator
QualifiedIterator< IsImageTypeConst > iterator
Definition: itkImageRegionRange.h:319
itk::Offset< ImageDimension+1 >
itk::ImageRegionRange::end
iterator end() const noexcept
Definition: itkImageRegionRange.h:384
itk::ImageRegionRange::crend
const_reverse_iterator crend() const noexcept
Definition: itkImageRegionRange.h:439
itk::ImageRegionRange::m_BufferedRegionIndex
IndexType m_BufferedRegionIndex
Definition: itkImageRegionRange.h:308
itk
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....
Definition: itkAnnulusOperator.h:24
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:433
itk::ImageRegionRange::SizeType
typename TImage::SizeType SizeType
Definition: itkImageRegionRange.h:84
itk::ImageRegionRange::m_IterationRegionIndex
IndexType m_IterationRegionIndex
Definition: itkImageRegionRange.h:310
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:228
itk::ImageRegionRange::cbegin
const_iterator cbegin() const noexcept
Definition: itkImageRegionRange.h:402
itk::ImageRegionRange::m_BufferBegin
BufferIteratorType m_BufferBegin
Definition: itkImageRegionRange.h:306
itk::ImageRegionRange::crbegin
const_reverse_iterator crbegin() const noexcept
Definition: itkImageRegionRange.h:432
itk::ImageRegionRange::PixelType
typename TImage::PixelType PixelType
Definition: itkImageRegionRange.h:77
itk::ImageRegionRange::QualifiedIterator::operator++
QualifiedIterator & operator++() noexcept
Definition: itkImageRegionRange.h:232
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:318
itk::ImageRegionRange::ComputeOffset
static OffsetValueType ComputeOffset(const OffsetTableType &offsetTable, const IndexType &bufferedRegionIndex, const IndexType &index)
Definition: itkImageRegionRange.h:296
itk::ImageRegionRange::QualifiedIterator::operator!=
friend bool operator!=(const QualifiedIterator &lhs, const QualifiedIterator &rhs) noexcept
Definition: itkImageRegionRange.h:286
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:552
itk::SizeValueType
unsigned long SizeValueType
Definition: itkIntTypes.h:83
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:312
itk::ImageRegionRange::QualifiedIterator::iterator_category
std::bidirectional_iterator_tag iterator_category
Definition: itkImageRegionRange.h:202