ITK  5.2.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  * 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 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 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<TImage>::value;
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 = typename std::conditional<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) ITK_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 <std::size_t VIndex>
149  void Increment(std::true_type) ITK_NOEXCEPT
150  {
151  static_assert(VIndex < (ImageDimension - 1), "For a larger index value, the other overload should be picked");
152 
153  m_BufferIterator += m_OffsetTable[VIndex];
154 
155  if (static_cast<SizeValueType>(++m_IterationOffset[VIndex]) >= m_IterationRegionSize[VIndex])
156  {
157  m_IterationOffset[VIndex] = 0;
159  this->Increment<VIndex + 1>(std::integral_constant<bool, (VIndex + 1) < (ImageDimension - 1)>{});
160  }
161  }
162 
163  template <std::size_t VIndex>
164  void Increment(std::false_type) ITK_NOEXCEPT
165  {
166  static_assert(VIndex == (ImageDimension - 1), "For a smaller index value, the other overload should be picked");
167 
168  ++m_IterationOffset[VIndex];
169  m_BufferIterator += m_OffsetTable[VIndex];
170  }
171 
172 
173  template <std::size_t VIndex>
174  void Decrement(std::true_type) ITK_NOEXCEPT
175  {
176  static_assert(VIndex < (ImageDimension - 1), "For a larger index value, the other overload should be picked");
177 
178  m_BufferIterator -= m_OffsetTable[VIndex];
179 
180  if (--m_IterationOffset[VIndex] < 0)
181  {
182  m_IterationOffset[VIndex] = m_IterationRegionSize[VIndex] - 1;
184  this->Decrement<VIndex + 1>(std::integral_constant<bool, (VIndex + 1) < (ImageDimension - 1)>{});
185  }
186  }
187 
188  template <std::size_t VIndex>
189  void Decrement(std::false_type) ITK_NOEXCEPT
190  {
191  static_assert(VIndex == (ImageDimension - 1), "For a smaller index value, the other overload should be picked");
192 
193  --m_IterationOffset[VIndex];
194  m_BufferIterator -= m_OffsetTable[VIndex];
195  }
196 
197 
198  public:
199  // Types conforming the iterator requirements of the C++ standard library:
200  using difference_type = std::ptrdiff_t;
201  using value_type = typename std::iterator_traits<QualifiedBufferIteratorType>::value_type;
202  using reference = typename std::iterator_traits<QualifiedBufferIteratorType>::reference;
203  using pointer = typename std::iterator_traits<QualifiedBufferIteratorType>::pointer;
204  using iterator_category = std::bidirectional_iterator_tag;
205 
211  QualifiedIterator() = default;
212 
215  QualifiedIterator(const QualifiedIterator<false> & arg) ITK_NOEXCEPT
216  : m_BufferIterator(arg.m_BufferIterator)
217  ,
218  // Note: Use parentheses instead of curly braces to initialize data members,
219  // to avoid AppleClang 6.0.0.6000056 compilation error, "no viable conversion..."
220  m_OffsetTable(arg.m_OffsetTable)
221  , m_IterationOffset(arg.m_IterationOffset)
222  , m_IterationRegionSize(arg.m_IterationRegionSize)
223  {}
224 
225 
227  reference operator*() const ITK_NOEXCEPT { return *m_BufferIterator; }
228 
231  operator++() ITK_NOEXCEPT
232  {
233  this->Increment<0>(std::integral_constant<bool, (ImageDimension > 1)>{});
234  return *this;
235  }
237 
238 
242  operator++(int) ITK_NOEXCEPT
243  {
244  auto result = *this;
245  ++(*this);
246  return result;
247  }
249 
250 
253  operator--() ITK_NOEXCEPT
254  {
255  this->Decrement<0>(std::integral_constant<bool, (ImageDimension > 1)>{});
256  return *this;
257  }
259 
260 
264  operator--(int) ITK_NOEXCEPT
265  {
266  auto result = *this;
267  --(*this);
268  return result;
269  }
271 
272 
276  friend bool
277  operator==(const QualifiedIterator & lhs, const QualifiedIterator & rhs) ITK_NOEXCEPT
278  {
279  return lhs.m_BufferIterator == rhs.m_BufferIterator;
280  }
281 
282 
284  friend bool
285  operator!=(const QualifiedIterator & lhs, const QualifiedIterator & rhs) ITK_NOEXCEPT
286  {
287  // Implemented just like the corresponding std::rel_ops operator.
288  return !(lhs == rhs);
289  }
290 
291 
294  operator=(const QualifiedIterator &) ITK_NOEXCEPT = default;
295 
296 
298  ~QualifiedIterator() = default;
299  };
300 
301  // Inspired by, and originally copied from ImageBase::FastComputeOffset(ind)).
302  static OffsetValueType
303  ComputeOffset(const OffsetTableType & offsetTable, const IndexType & bufferedRegionIndex, const IndexType & index)
304  {
305  OffsetValueType offsetValue = 0;
307  bufferedRegionIndex, index, offsetTable.data(), offsetValue);
308  return offsetValue;
309  }
310 
311  // ImageRegionRange data members (strictly private):
312 
314 
316 
318 
320 
321  // A copy of the offset table of the image.
323 
324 public:
327  using reverse_iterator = std::reverse_iterator<iterator>;
328  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
329 
330 
333  ImageRegionRange() ITK_NOEXCEPT = default;
334 
335 
339  explicit ImageRegionRange(TImage & image, const RegionType & iterationRegion)
340  : m_BufferBegin{ std::begin(ImageBufferRange<TImage>{ image }) }
341  ,
342  // Note: Use parentheses instead of curly braces to initialize data members,
343  // to avoid AppleClang 6.0.0.6000056 compile errors, "no viable conversion..."
344  m_BufferedRegionIndex(image.TImage::GetBufferedRegion().GetIndex())
345  , m_IterationRegionIndex(iterationRegion.GetIndex())
346  , m_IterationRegionSize(iterationRegion.GetSize())
347  {
348  const OffsetValueType * const offsetTable = image.GetOffsetTable();
349  assert(offsetTable != nullptr);
351 
352  if (iterationRegion.GetNumberOfPixels() > 0) // If region is non-empty
353  {
354  // Check if the iteration region is within the buffered region, similar
355  // to checks in ImageConstIteratorWithIndex(const TImage*, const RegionType&)
356  // and ImageConstIterator::SetRegion(const RegionType&).
357 
358  const auto & bufferedRegion = image.GetBufferedRegion();
359 
360  itkAssertOrThrowMacro((bufferedRegion.IsInside(iterationRegion)),
361  "Iteration region " << iterationRegion << " is outside of buffered region "
362  << bufferedRegion);
363  }
364 
365  std::copy_n(offsetTable, ImageDimension + 1, m_OffsetTable.data());
366  }
367 
368 
371  explicit ImageRegionRange(TImage & image)
372  : ImageRegionRange(image, image.GetRequestedRegion())
373  {}
374 
375 
377  iterator
378  begin() const ITK_NOEXCEPT
379  {
382  OffsetType(),
384  }
386 
388  iterator
389  end() const ITK_NOEXCEPT
390  {
391  auto endRegionIndex = m_IterationRegionIndex;
392  endRegionIndex.back() += m_IterationRegionSize.back();
394 
395  OffsetType iterationOffset{ {} }; // Initialize offsets to 0, by aggregate initializer
396  *(iterationOffset.rbegin()) = m_IterationRegionSize.back();
397 
400  iterationOffset,
402  }
403 
407  cbegin() const ITK_NOEXCEPT
408  {
409  return this->begin();
410  }
411 
414  cend() const ITK_NOEXCEPT
415  {
416  return this->end();
417  }
418 
421  rbegin() const ITK_NOEXCEPT
422  {
423  return reverse_iterator{ this->end() };
424  }
426 
429  rend() const ITK_NOEXCEPT
430  {
431  return reverse_iterator{ this->begin() };
432  }
434 
437  crbegin() const ITK_NOEXCEPT
438  {
439  return this->rbegin();
440  }
441 
444  crend() const ITK_NOEXCEPT
445  {
446  return this->rend();
447  }
448 
449 
451  std::size_t
452  size() const ITK_NOEXCEPT
453  {
454  return std::accumulate(
455  m_IterationRegionSize.begin(), m_IterationRegionSize.end(), std::size_t{ 1 }, std::multiplies<std::size_t>{});
456  }
458 
459 
461  bool
462  empty() const ITK_NOEXCEPT
463  {
464  return std::any_of(m_IterationRegionSize.begin(), m_IterationRegionSize.end(), [](const SizeValueType sizeValue) {
465  return sizeValue == 0;
466  });
467  }
469 
470 
472  ~ImageRegionRange() = default;
473 };
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::QualifiedIterator::~QualifiedIterator
~QualifiedIterator()=default
itk::ImageRegionRange
Definition: itkImageRegionRange.h:72
itk::ImageRegionRange::ImageRegionRange
ImageRegionRange(TImage &image)
Definition: itkImageRegionRange.h:371
itk::ImageRegionRange::reverse_iterator
std::reverse_iterator< iterator > reverse_iterator
Definition: itkImageRegionRange.h:327
itk::ImageRegionRange::const_reverse_iterator
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: itkImageRegionRange.h:328
itk::ImageRegionRange::begin
iterator begin() const noexcept
Definition: itkImageRegionRange.h:378
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:414
itk::ImageRegionRange::QualifiedIterator::value_type
typename std::iterator_traits< QualifiedBufferIteratorType >::value_type value_type
Definition: itkImageRegionRange.h:201
itkImageHelper.h
itk::ImageRegionRange::QualifiedIterator::reference
typename std::iterator_traits< QualifiedBufferIteratorType >::reference reference
Definition: itkImageRegionRange.h:202
itk::ImageRegionRange::QualifiedIterator::difference_type
std::ptrdiff_t difference_type
Definition: itkImageRegionRange.h:200
itk::ImageRegionRange::~ImageRegionRange
~ImageRegionRange()=default
itk::ImageBufferRange::const_iterator
typename std::conditional< UsingPointerAsIterator, const InternalPixelType *, QualifiedIterator< true > >::type const_iterator
Definition: itkImageBufferRange.h:560
itk::ImageRegionRange::empty
bool empty() const noexcept
Definition: itkImageRegionRange.h:462
itk::GTest::TypedefsAndConstructors::Dimension2::SizeType
ImageBaseType::SizeType SizeType
Definition: itkGTestTypedefsAndConstructors.h:49
itk::ImageRegionRange::QualifiedIterator::operator++
QualifiedIterator operator++(int) noexcept
Definition: itkImageRegionRange.h:242
itk::ImageRegionRange::QualifiedIterator::operator--
QualifiedIterator & operator--() noexcept
Definition: itkImageRegionRange.h:253
itk::ImageRegionRange::QualifiedIterator::pointer
typename std::iterator_traits< QualifiedBufferIteratorType >::pointer pointer
Definition: itkImageRegionRange.h:203
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:277
itk::ImageRegionRange::QualifiedIterator::Increment
void Increment(std::false_type) noexcept
Definition: itkImageRegionRange.h:164
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::QualifiedIterator::Decrement
void Decrement(std::false_type) noexcept
Definition: itkImageRegionRange.h:189
itk::ImageRegionRange::ImageDimension
static constexpr ImageDimensionType ImageDimension
Definition: itkImageRegionRange.h:80
itk::ImageRegionRange::QualifiedIterator::QualifiedBufferIteratorType
typename std::conditional< VIsConst, typename ImageBufferRange< TImage >::const_iterator, typename ImageBufferRange< TImage >::iterator >::type QualifiedBufferIteratorType
Definition: itkImageRegionRange.h:117
itk::ImageRegionRange::QualifiedIterator::operator--
QualifiedIterator operator--(int) noexcept
Definition: itkImageRegionRange.h:264
itk::GTest::TypedefsAndConstructors::Dimension2::RegionType
ImageBaseType::RegionType RegionType
Definition: itkGTestTypedefsAndConstructors.h:54
itk::ImageRegionRange::QualifiedIterator::QualifiedIterator
QualifiedIterator(const QualifiedIterator< false > &arg) noexcept
Definition: itkImageRegionRange.h:215
itk::ImageBufferRange
Definition: itkImageBufferRange.h:73
itk::ImageRegionRange::m_OffsetTable
OffsetTableType m_OffsetTable
Definition: itkImageRegionRange.h:322
itk::ImageRegionRange::rbegin
reverse_iterator rbegin() const noexcept
Definition: itkImageRegionRange.h:421
itk::ImageBufferRange::iterator
typename std::conditional< UsingPointerAsIterator, QualifiedInternalPixelType *, QualifiedIterator< IsImageTypeConst > >::type iterator
Definition: itkImageBufferRange.h:562
itk::ImageRegionRange::rend
reverse_iterator rend() const noexcept
Definition: itkImageRegionRange.h:429
itk::ImageRegionRange::iterator
QualifiedIterator< IsImageTypeConst > iterator
Definition: itkImageRegionRange.h:326
itk::Offset< ImageDimension+1 >
itk::ImageRegionRange::end
iterator end() const noexcept
Definition: itkImageRegionRange.h:389
itk::ImageRegionRange::crend
const_reverse_iterator crend() const noexcept
Definition: itkImageRegionRange.h:444
itk::ImageRegionRange::m_BufferedRegionIndex
IndexType m_BufferedRegionIndex
Definition: itkImageRegionRange.h:315
itk
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....
Definition: itkAnnulusOperator.h:24
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:419
itk::OffsetValueType
signed long OffsetValueType
Definition: itkIntTypes.h:94
itk::ImageRegionRange::SizeType
typename TImage::SizeType SizeType
Definition: itkImageRegionRange.h:84
itk::ImageRegionRange::m_IterationRegionIndex
IndexType m_IterationRegionIndex
Definition: itkImageRegionRange.h:317
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::Increment
void Increment(std::true_type) noexcept
Definition: itkImageRegionRange.h:149
itk::ImageRegionRange::QualifiedIterator::operator*
reference operator*() const noexcept
Definition: itkImageRegionRange.h:227
itk::ImageRegionRange::cbegin
const_iterator cbegin() const noexcept
Definition: itkImageRegionRange.h:407
itk::ImageRegionRange::m_BufferBegin
BufferIteratorType m_BufferBegin
Definition: itkImageRegionRange.h:313
itk::ImageRegionRange::crbegin
const_reverse_iterator crbegin() const noexcept
Definition: itkImageRegionRange.h:437
itk::ImageRegionRange::PixelType
typename TImage::PixelType PixelType
Definition: itkImageRegionRange.h:77
itk::ImageRegionRange::QualifiedIterator::operator++
QualifiedIterator & operator++() noexcept
Definition: itkImageRegionRange.h:231
itk::ImageRegionRange::size
std::vcl_size_t size() const noexcept
Definition: itkImageRegionRange.h:452
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:325
itk::ImageRegionRange::ComputeOffset
static OffsetValueType ComputeOffset(const OffsetTableType &offsetTable, const IndexType &bufferedRegionIndex, const IndexType &index)
Definition: itkImageRegionRange.h:303
itk::ImageRegionRange::QualifiedIterator::Decrement
void Decrement(std::true_type) noexcept
Definition: itkImageRegionRange.h:174
itk::ImageRegionRange::QualifiedIterator::operator!=
friend bool operator!=(const QualifiedIterator &lhs, const QualifiedIterator &rhs) noexcept
Definition: itkImageRegionRange.h:285
itk::SizeValueType
unsigned long SizeValueType
Definition: itkIntTypes.h:83
itk::ImageRegionRange::QualifiedIterator::operator=
QualifiedIterator & operator=(const QualifiedIterator &) noexcept=default
itk::ImageHelper::ComputeOffset
static void ComputeOffset(const IndexType &bufferedRegionIndex, const IndexType &index, const OffsetValueType offsetTable[], OffsetValueType &offset)
Definition: itkImageHelper.h:103
itkImageBufferRange.h
itk::ImageRegionRange::ImageRegionRange
ImageRegionRange() noexcept=default
itk::ImageRegionRange::m_IterationRegionSize
SizeType m_IterationRegionSize
Definition: itkImageRegionRange.h:319
itk::ImageRegionRange::QualifiedIterator::iterator_category
std::bidirectional_iterator_tag iterator_category
Definition: itkImageRegionRange.h:204