ITK  5.1.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 namespace Experimental
37 {
38 
73 template <typename TImage>
74 class ImageRegionRange final
75 {
76 private:
78  using ImageDimensionType = typename TImage::ImageDimensionType;
79  using PixelType = typename TImage::PixelType;
80 
81  static constexpr bool IsImageTypeConst = std::is_const<TImage>::value;
82  static constexpr ImageDimensionType ImageDimension = TImage::ImageDimension;
83 
85  using RegionType = typename TImage::RegionType;
86  using SizeType = typename TImage::SizeType;
87  using OffsetType = typename TImage::OffsetType;
89  using IndexType = typename RegionType::IndexType;
90 
91 
104  template <bool VIsConst>
105  class QualifiedIterator final
106  {
107  private:
108  // Const and non-const iterators are friends, in order to implement the
109  // constructor that allow conversion from non-const to const iterator.
110  friend class QualifiedIterator<!VIsConst>;
111 
112  // ImageRegionRange is a friend, as it should be the only one that can
113  // directly use the private constructor of the iterator.
114  friend class ImageRegionRange;
115 
116  // Use either a const or a non-const qualified image buffer iterator.
117  using QualifiedBufferIteratorType = typename std::conditional<VIsConst,
120 
121  // QualifiedIterator data members (strictly private):
122 
123  // Iterator to the current pixel.
125 
126  // A copy of the offset table of the image.
128 
129  // N-Dimensional offset relative to the index of the iteration region.
131 
132  // Size of the iteration region.
134 
135  // Private constructor, used to create the begin and the end iterator of a range.
136  // Only used by its friend class ImageRegionRange.
138  const OffsetTableType & offsetTable,
139  const OffsetType & iterationOffset,
140  const SizeType & regionSize) ITK_NOEXCEPT
141  : m_BufferIterator(bufferIterator)
142  ,
143  // Note: Use parentheses instead of curly braces to initialize data members,
144  // to avoid AppleClang 6.0.0.6000056 compilation error, "no viable conversion..."
145  m_OffsetTable(offsetTable)
146  , m_IterationOffset(iterationOffset)
147  , m_IterationRegionSize(regionSize)
148  {}
149 
150  template <std::size_t VIndex>
151  void Increment(std::true_type) ITK_NOEXCEPT
152  {
153  static_assert(VIndex < (ImageDimension - 1), "For a larger index value, the other overload should be picked");
154 
155  m_BufferIterator += m_OffsetTable[VIndex];
156 
157  if (static_cast<SizeValueType>(++m_IterationOffset[VIndex]) >= m_IterationRegionSize[VIndex])
158  {
159  m_IterationOffset[VIndex] = 0;
161  this->Increment<VIndex + 1>(std::integral_constant<bool, (VIndex + 1) < (ImageDimension - 1)>{});
162  }
163  }
164 
165  template <std::size_t VIndex>
166  void Increment(std::false_type) ITK_NOEXCEPT
167  {
168  static_assert(VIndex == (ImageDimension - 1), "For a smaller index value, the other overload should be picked");
169 
170  ++m_IterationOffset[VIndex];
171  m_BufferIterator += m_OffsetTable[VIndex];
172  }
173 
174 
175  template <std::size_t VIndex>
176  void Decrement(std::true_type) ITK_NOEXCEPT
177  {
178  static_assert(VIndex < (ImageDimension - 1), "For a larger index value, the other overload should be picked");
179 
180  m_BufferIterator -= m_OffsetTable[VIndex];
181 
182  if (--m_IterationOffset[VIndex] < 0)
183  {
184  m_IterationOffset[VIndex] = m_IterationRegionSize[VIndex] - 1;
186  this->Decrement<VIndex + 1>(std::integral_constant<bool, (VIndex + 1) < (ImageDimension - 1)>{});
187  }
188  }
189 
190  template <std::size_t VIndex>
191  void Decrement(std::false_type) ITK_NOEXCEPT
192  {
193  static_assert(VIndex == (ImageDimension - 1), "For a smaller index value, the other overload should be picked");
194 
195  --m_IterationOffset[VIndex];
196  m_BufferIterator -= m_OffsetTable[VIndex];
197  }
198 
199 
200  public:
201  // Types conforming the iterator requirements of the C++ standard library:
202  using difference_type = std::ptrdiff_t;
203  using value_type = typename std::iterator_traits<QualifiedBufferIteratorType>::value_type;
204  using reference = typename std::iterator_traits<QualifiedBufferIteratorType>::reference;
205  using pointer = typename std::iterator_traits<QualifiedBufferIteratorType>::pointer;
206  using iterator_category = std::bidirectional_iterator_tag;
207 
213  QualifiedIterator() = default;
214 
217  QualifiedIterator(const QualifiedIterator<false> & arg) ITK_NOEXCEPT
218  : m_BufferIterator(arg.m_BufferIterator)
219  ,
220  // Note: Use parentheses instead of curly braces to initialize data members,
221  // to avoid AppleClang 6.0.0.6000056 compilation error, "no viable conversion..."
222  m_OffsetTable(arg.m_OffsetTable)
223  , m_IterationOffset(arg.m_IterationOffset)
224  , m_IterationRegionSize(arg.m_IterationRegionSize)
225  {}
226 
227 
229  reference operator*() const ITK_NOEXCEPT { return *m_BufferIterator; }
230 
233  operator++() ITK_NOEXCEPT
234  {
235  this->Increment<0>(std::integral_constant<bool, (ImageDimension > 1)>{});
236  return *this;
237  }
239 
240 
244  operator++(int) ITK_NOEXCEPT
245  {
246  auto result = *this;
247  ++(*this);
248  return result;
249  }
251 
252 
255  operator--() ITK_NOEXCEPT
256  {
257  this->Decrement<0>(std::integral_constant<bool, (ImageDimension > 1)>{});
258  return *this;
259  }
261 
262 
266  operator--(int) ITK_NOEXCEPT
267  {
268  auto result = *this;
269  --(*this);
270  return result;
271  }
273 
274 
278  friend bool
279  operator==(const QualifiedIterator & lhs, const QualifiedIterator & rhs) ITK_NOEXCEPT
280  {
281  return lhs.m_BufferIterator == rhs.m_BufferIterator;
282  }
283 
284 
286  friend bool
287  operator!=(const QualifiedIterator & lhs, const QualifiedIterator & rhs) ITK_NOEXCEPT
288  {
289  // Implemented just like the corresponding std::rel_ops operator.
290  return !(lhs == rhs);
291  }
292 
293 
296  operator=(const QualifiedIterator &) ITK_NOEXCEPT = default;
297 
298 
300  ~QualifiedIterator() = default;
301  };
302 
303  // Inspired by, and originally copied from ImageBase::FastComputeOffset(ind)).
304  static OffsetValueType
305  ComputeOffset(const OffsetTableType & offsetTable, const IndexType & bufferedRegionIndex, const IndexType & index)
306  {
307  OffsetValueType offsetValue = 0;
309  bufferedRegionIndex, index, offsetTable.data(), offsetValue);
310  return offsetValue;
311  }
312 
313  // ImageRegionRange data members (strictly private):
314 
316 
318 
320 
322 
323  // A copy of the offset table of the image.
325 
326 public:
329  using reverse_iterator = std::reverse_iterator<iterator>;
330  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
331 
332 
335  ImageRegionRange() ITK_NOEXCEPT = default;
336 
337 
341  explicit ImageRegionRange(TImage & image, const RegionType & iterationRegion)
342  : m_BufferBegin{ std::begin(ImageBufferRange<TImage>{ image }) }
343  ,
344  // Note: Use parentheses instead of curly braces to initialize data members,
345  // to avoid AppleClang 6.0.0.6000056 compile errors, "no viable conversion..."
346  m_BufferedRegionIndex(image.TImage::GetBufferedRegion().GetIndex())
347  , m_IterationRegionIndex(iterationRegion.GetIndex())
348  , m_IterationRegionSize(iterationRegion.GetSize())
349  {
350  const OffsetValueType * const offsetTable = image.GetOffsetTable();
351  assert(offsetTable != nullptr);
353 
354  if (iterationRegion.GetNumberOfPixels() > 0) // If region is non-empty
355  {
356  // Check if the iteration region is within the buffered region, similar
357  // to checks in ImageConstIteratorWithIndex(const TImage*, const RegionType&)
358  // and ImageConstIterator::SetRegion(const RegionType&).
359 
360  const auto & bufferedRegion = image.GetBufferedRegion();
361 
362  itkAssertOrThrowMacro((bufferedRegion.IsInside(iterationRegion)),
363  "Iteration region " << iterationRegion << " is outside of buffered region "
364  << bufferedRegion);
365  }
366 
367  std::copy_n(offsetTable, ImageDimension + 1, m_OffsetTable.data());
368  }
369 
370 
373  explicit ImageRegionRange(TImage & image)
374  : ImageRegionRange(image, image.GetRequestedRegion())
375  {}
376 
377 
379  iterator
380  begin() const ITK_NOEXCEPT
381  {
384  OffsetType(),
386  }
388 
390  iterator
391  end() const ITK_NOEXCEPT
392  {
393  auto endRegionIndex = m_IterationRegionIndex;
394  endRegionIndex.back() += m_IterationRegionSize.back();
396 
397  OffsetType iterationOffset{ {} }; // Initialize offsets to 0, by aggregate initializer
398  *(iterationOffset.rbegin()) = m_IterationRegionSize.back();
399 
402  iterationOffset,
404  }
405 
409  cbegin() const ITK_NOEXCEPT
410  {
411  return this->begin();
412  }
413 
416  cend() const ITK_NOEXCEPT
417  {
418  return this->end();
419  }
420 
423  rbegin() const ITK_NOEXCEPT
424  {
425  return reverse_iterator{ this->end() };
426  }
428 
431  rend() const ITK_NOEXCEPT
432  {
433  return reverse_iterator{ this->begin() };
434  }
436 
439  crbegin() const ITK_NOEXCEPT
440  {
441  return this->rbegin();
442  }
443 
446  crend() const ITK_NOEXCEPT
447  {
448  return this->rend();
449  }
450 
451 
453  std::size_t
454  size() const ITK_NOEXCEPT
455  {
456  return std::accumulate(
457  m_IterationRegionSize.begin(), m_IterationRegionSize.end(), std::size_t{ 1 }, std::multiplies<std::size_t>{});
458  }
460 
461 
463  bool
464  empty() const ITK_NOEXCEPT
465  {
466  return std::any_of(m_IterationRegionSize.begin(), m_IterationRegionSize.end(), [](const SizeValueType sizeValue) {
467  return sizeValue == 0;
468  });
469  }
471 
472 
474  ~ImageRegionRange() = default;
475 };
476 
477 } // namespace Experimental
478 } // namespace itk
479 
480 #endif
itk::Experimental::ImageRegionRange::QualifiedIterator::Decrement
void Decrement(std::true_type) noexcept
Definition: itkImageRegionRange.h:176
itk::Experimental::ImageRegionRange::QualifiedIterator::operator++
QualifiedIterator & operator++() noexcept
Definition: itkImageRegionRange.h:233
itk::Experimental::ImageRegionRange::QualifiedIterator::operator=
QualifiedIterator & operator=(const QualifiedIterator &) noexcept=default
itk::Experimental::ImageRegionRange::QualifiedIterator::QualifiedBufferIteratorType
typename std::conditional< VIsConst, typename ImageBufferRange< TImage >::const_iterator, typename ImageBufferRange< TImage >::iterator >::type QualifiedBufferIteratorType
Definition: itkImageRegionRange.h:119
itk::Experimental::ImageRegionRange::QualifiedIterator::m_IterationRegionSize
SizeType m_IterationRegionSize
Definition: itkImageRegionRange.h:133
itk::Experimental::ImageRegionRange::end
iterator end() const noexcept
Definition: itkImageRegionRange.h:391
itk::Experimental::ImageRegionRange::m_BufferBegin
BufferIteratorType m_BufferBegin
Definition: itkImageRegionRange.h:315
itk::Experimental::ImageRegionRange::QualifiedIterator::m_OffsetTable
OffsetTableType m_OffsetTable
Definition: itkImageRegionRange.h:127
itk::Experimental::ImageRegionRange::PixelType
typename TImage::PixelType PixelType
Definition: itkImageRegionRange.h:79
itk::Experimental::ImageRegionRange::rbegin
reverse_iterator rbegin() const noexcept
Definition: itkImageRegionRange.h:423
itk::Experimental::ImageRegionRange::m_IterationRegionIndex
IndexType m_IterationRegionIndex
Definition: itkImageRegionRange.h:319
itkImageHelper.h
itk::Experimental::ImageRegionRange::const_iterator
QualifiedIterator< true > const_iterator
Definition: itkImageRegionRange.h:327
itk::Experimental::ImageRegionRange::RegionType
typename TImage::RegionType RegionType
Definition: itkImageRegionRange.h:85
itk::Experimental::ImageRegionRange::QualifiedIterator::~QualifiedIterator
~QualifiedIterator()=default
itk::Experimental::ImageRegionRange::QualifiedIterator::m_IterationOffset
OffsetType m_IterationOffset
Definition: itkImageRegionRange.h:130
itk::Experimental::ImageRegionRange::cend
const_iterator cend() const noexcept
Definition: itkImageRegionRange.h:416
itk::Experimental::ImageRegionRange::reverse_iterator
std::reverse_iterator< iterator > reverse_iterator
Definition: itkImageRegionRange.h:329
itk::GTest::TypedefsAndConstructors::Dimension2::SizeType
ImageBaseType::SizeType SizeType
Definition: itkGTestTypedefsAndConstructors.h:49
itk::Experimental::ImageRegionRange::QualifiedIterator::operator--
QualifiedIterator operator--(int) noexcept
Definition: itkImageRegionRange.h:266
itk::Experimental::ImageRegionRange::OffsetType
typename TImage::OffsetType OffsetType
Definition: itkImageRegionRange.h:87
itk::Experimental::ImageRegionRange::QualifiedIterator::value_type
typename std::iterator_traits< QualifiedBufferIteratorType >::value_type value_type
Definition: itkImageRegionRange.h:203
itk::Experimental::ImageRegionRange::ImageRegionRange
ImageRegionRange() noexcept=default
itk::Experimental::ImageRegionRange::QualifiedIterator::pointer
typename std::iterator_traits< QualifiedBufferIteratorType >::pointer pointer
Definition: itkImageRegionRange.h:205
itk::Experimental::ImageRegionRange::m_OffsetTable
OffsetTableType m_OffsetTable
Definition: itkImageRegionRange.h:324
itk::Experimental::ImageRegionRange::crend
const_reverse_iterator crend() const noexcept
Definition: itkImageRegionRange.h:446
itkImageRegion.h
itk::Experimental::ImageRegionRange::QualifiedIterator::QualifiedIterator
QualifiedIterator(const QualifiedIterator< false > &arg) noexcept
Definition: itkImageRegionRange.h:217
itk::Experimental::ImageRegionRange::IndexType
typename RegionType::IndexType IndexType
Definition: itkImageRegionRange.h:89
itk::Experimental::ImageRegionRange::BufferIteratorType
typename ImageBufferRange< TImage >::iterator BufferIteratorType
Definition: itkImageRegionRange.h:84
itk::Experimental::ImageRegionRange::const_reverse_iterator
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: itkImageRegionRange.h:330
itk::GTest::TypedefsAndConstructors::Dimension2::IndexType
ImageBaseType::IndexType IndexType
Definition: itkGTestTypedefsAndConstructors.h:50
itk::Experimental::ImageRegionRange::QualifiedIterator
Definition: itkImageRegionRange.h:105
itk::Experimental::ImageBufferRange::iterator
typename std::conditional< UsingPointerAsIterator, QualifiedInternalPixelType *, QualifiedIterator< IsImageTypeConst > >::type iterator
Definition: itkImageBufferRange.h:564
itk::Experimental::ImageRegionRange::QualifiedIterator::QualifiedIterator
QualifiedIterator()=default
itk::Experimental::ImageRegionRange::rend
reverse_iterator rend() const noexcept
Definition: itkImageRegionRange.h:431
itk::GTest::TypedefsAndConstructors::Dimension2::RegionType
ImageBaseType::RegionType RegionType
Definition: itkGTestTypedefsAndConstructors.h:54
itk::Experimental::ImageRegionRange::ImageDimension
static constexpr ImageDimensionType ImageDimension
Definition: itkImageRegionRange.h:82
itk::Experimental::ImageRegionRange::QualifiedIterator::operator++
QualifiedIterator operator++(int) noexcept
Definition: itkImageRegionRange.h:244
itk::Experimental::ImageRegionRange
Definition: itkImageRegionRange.h:74
itk::Experimental::ImageRegionRange::SizeType
typename TImage::SizeType SizeType
Definition: itkImageRegionRange.h:86
itk::Experimental::ImageRegionRange::QualifiedIterator::operator*
reference operator*() const noexcept
Definition: itkImageRegionRange.h:229
itk::Experimental::ImageRegionRange::QualifiedIterator::Increment
void Increment(std::true_type) noexcept
Definition: itkImageRegionRange.h:151
itk::Experimental::ImageRegionRange::QualifiedIterator::operator!=
friend bool operator!=(const QualifiedIterator &lhs, const QualifiedIterator &rhs) noexcept
Definition: itkImageRegionRange.h:287
itk::Experimental::ImageRegionRange::QualifiedIterator::m_BufferIterator
QualifiedBufferIteratorType m_BufferIterator
Definition: itkImageRegionRange.h:124
itk::Experimental::ImageRegionRange::QualifiedIterator::Decrement
void Decrement(std::false_type) noexcept
Definition: itkImageRegionRange.h:191
itk::Experimental::ImageRegionRange::iterator
QualifiedIterator< IsImageTypeConst > iterator
Definition: itkImageRegionRange.h:328
itk::Experimental::ImageRegionRange::begin
iterator begin() const noexcept
Definition: itkImageRegionRange.h:380
itk::Experimental::ImageRegionRange::QualifiedIterator::reference
typename std::iterator_traits< QualifiedBufferIteratorType >::reference reference
Definition: itkImageRegionRange.h:204
itk::Experimental::ImageRegionRange::empty
bool empty() const noexcept
Definition: itkImageRegionRange.h:464
itk::Experimental::ImageRegionRange::crbegin
const_reverse_iterator crbegin() const noexcept
Definition: itkImageRegionRange.h:439
itk::Offset< ImageDimension+1 >
itk::Experimental::ImageRegionRange::QualifiedIterator::Increment
void Increment(std::false_type) noexcept
Definition: itkImageRegionRange.h:166
itk::Experimental::ImageRegionRange::m_IterationRegionSize
SizeType m_IterationRegionSize
Definition: itkImageRegionRange.h:321
itk::Experimental::ImageRegionRange::ImageRegionRange
ImageRegionRange(TImage &image)
Definition: itkImageRegionRange.h:373
itk::Experimental::ImageRegionRange::QualifiedIterator::difference_type
std::ptrdiff_t difference_type
Definition: itkImageRegionRange.h:202
itk
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....
Definition: itkArray.h:26
itk::Experimental::ImageRegionRange::cbegin
const_iterator cbegin() const noexcept
Definition: itkImageRegionRange.h:409
itk::Experimental::ImageRegionRange::IsImageTypeConst
static constexpr bool IsImageTypeConst
Definition: itkImageRegionRange.h:81
itk::Experimental::ImageBufferRange
Definition: itkImageBufferRange.h:75
itk::Offset::data
OffsetValueType * data()
Definition: itkOffset.h:419
itk::OffsetValueType
signed long OffsetValueType
Definition: itkIntTypes.h:94
itk::Experimental::ImageRegionRange::~ImageRegionRange
~ImageRegionRange()=default
itk::Experimental::ImageBufferRange::const_iterator
typename std::conditional< UsingPointerAsIterator, const InternalPixelType *, QualifiedIterator< true > >::type const_iterator
Definition: itkImageBufferRange.h:562
itk::Experimental::ImageRegionRange::QualifiedIterator::operator==
friend bool operator==(const QualifiedIterator &lhs, const QualifiedIterator &rhs) noexcept
Definition: itkImageRegionRange.h:279
itk::Experimental::ImageRegionRange::ComputeOffset
static OffsetValueType ComputeOffset(const OffsetTableType &offsetTable, const IndexType &bufferedRegionIndex, const IndexType &index)
Definition: itkImageRegionRange.h:305
itk::Experimental::ImageRegionRange::ImageDimensionType
typename TImage::ImageDimensionType ImageDimensionType
Definition: itkImageRegionRange.h:78
itk::Experimental::ImageRegionRange::QualifiedIterator::iterator_category
std::bidirectional_iterator_tag iterator_category
Definition: itkImageRegionRange.h:206
itk::Experimental::ImageRegionRange::size
std::vcl_size_t size() const noexcept
Definition: itkImageRegionRange.h:454
itk::SizeValueType
unsigned long SizeValueType
Definition: itkIntTypes.h:83
itk::Experimental::ImageRegionRange::QualifiedIterator::QualifiedIterator
QualifiedIterator(const QualifiedBufferIteratorType &bufferIterator, const OffsetTableType &offsetTable, const OffsetType &iterationOffset, const SizeType &regionSize) noexcept
Definition: itkImageRegionRange.h:137
itk::Experimental::ImageRegionRange::m_BufferedRegionIndex
IndexType m_BufferedRegionIndex
Definition: itkImageRegionRange.h:317
itk::Experimental::ImageRegionRange::QualifiedIterator::operator--
QualifiedIterator & operator--() noexcept
Definition: itkImageRegionRange.h:255
itk::ImageHelper::ComputeOffset
static void ComputeOffset(const IndexType &bufferedRegionIndex, const IndexType &index, const OffsetValueType offsetTable[], OffsetValueType &offset)
Definition: itkImageHelper.h:103
itkImageBufferRange.h