ITK 6.0.0
Insight Toolkit
 
Loading...
Searching...
No Matches
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 <type_traits> // For conditional, enable_if, and is_const.
28
29#include "itkImageHelper.h"
30#include "itkImageRegion.h"
31#include "itkImageBufferRange.h"
32
33namespace itk
34{
35
70template <typename TImage>
72{
73private:
75 using ImageDimensionType = typename TImage::ImageDimensionType;
76 using PixelType = typename TImage::PixelType;
77
78 static constexpr bool IsImageTypeConst = std::is_const_v<TImage>;
79 static constexpr ImageDimensionType ImageDimension = TImage::ImageDimension;
80
82 using RegionType = typename TImage::RegionType;
83 using SizeType = typename TImage::SizeType;
84 using OffsetType = typename TImage::OffsetType;
86 using IndexType = typename RegionType::IndexType;
87
88
101 template <bool VIsConst>
103 {
104 private:
105 // Const and non-const iterators are friends, in order to implement the
106 // constructor that allow conversion from non-const to const iterator.
107 friend class QualifiedIterator<!VIsConst>;
108
109 // ImageRegionRange is a friend, as it should be the only one that can
110 // directly use the private constructor of the iterator.
111 friend class ImageRegionRange;
112
113 // Use either a const or a non-const qualified image buffer iterator.
114 using QualifiedBufferIteratorType = std::conditional_t<VIsConst,
117
118 // QualifiedIterator data members (strictly private):
119
120 // Iterator to the current pixel.
122
123 // A copy of the offset table of the image.
125
126 // N-Dimensional offset relative to the index of the iteration region.
128
129 // Size of the iteration region.
131
132 // Private constructor, used to create the begin and the end iterator of a range.
133 // Only used by its friend class ImageRegionRange.
135 const OffsetTableType & offsetTable,
136 const OffsetType & iterationOffset,
137 const SizeType & regionSize) noexcept
138 : m_BufferIterator(bufferIterator)
139 ,
140 // Note: Use parentheses instead of curly braces to initialize data members,
141 // to avoid AppleClang 6.0.0.6000056 compilation error, "no viable conversion..."
142 m_OffsetTable(offsetTable)
143 , m_IterationOffset(iterationOffset)
144 , m_IterationRegionSize(regionSize)
145 {}
146
147 template <size_t VIndex>
148 void
149 Increment() noexcept
150 {
152
153 if constexpr (VIndex < (ImageDimension - 1))
154 {
155 if (static_cast<SizeValueType>(++m_IterationOffset[VIndex]) >= m_IterationRegionSize[VIndex])
156 {
157 m_IterationOffset[VIndex] = 0;
159 this->Increment<VIndex + 1>();
160 }
161 }
162 else
163 {
164 static_assert(VIndex == (ImageDimension - 1));
165
166 ++m_IterationOffset[VIndex];
167 }
168 }
169
170
171 template <size_t VIndex>
172 void
173 Decrement() noexcept
174 {
176
177 if constexpr (VIndex < (ImageDimension - 1))
178 {
179 if (--m_IterationOffset[VIndex] < 0)
180 {
181 m_IterationOffset[VIndex] = m_IterationRegionSize[VIndex] - 1;
183 this->Decrement<VIndex + 1>();
184 }
185 }
186 else
187 {
188 static_assert(VIndex == (ImageDimension - 1));
189
190 --m_IterationOffset[VIndex];
191 }
192 }
193
194
195 public:
196 // Types conforming the iterator requirements of the C++ standard library:
197 using difference_type = ptrdiff_t;
198 using value_type = typename std::iterator_traits<QualifiedBufferIteratorType>::value_type;
199 using reference = typename std::iterator_traits<QualifiedBufferIteratorType>::reference;
200 using pointer = typename std::iterator_traits<QualifiedBufferIteratorType>::pointer;
201 using iterator_category = std::bidirectional_iterator_tag;
202
211 QualifiedIterator() = default;
212
214 template <bool VIsArgumentConst, typename = std::enable_if_t<VIsConst && !VIsArgumentConst>>
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
228 operator*() const noexcept
229 {
230 return *m_BufferIterator;
231 }
232
235 operator++() noexcept
236 {
237 this->Increment<0>();
238 return *this;
239 }
240
241
245 operator++(int) noexcept
246 {
247 auto result = *this;
248 ++(*this);
249 return result;
250 }
251
252
255 operator--() noexcept
256 {
257 this->Decrement<0>();
258 return *this;
259 }
260
261
265 operator--(int) noexcept
266 {
267 auto result = *this;
268 --(*this);
269 return result;
270 }
271
272
276 friend bool
277 operator==(const QualifiedIterator & lhs, const QualifiedIterator & rhs) noexcept
278 {
279 return lhs.m_BufferIterator == rhs.m_BufferIterator;
280 }
281
282
284 friend bool
285 operator!=(const QualifiedIterator & lhs, const QualifiedIterator & rhs) noexcept
286 {
287 // Implemented just like the corresponding std::rel_ops operator.
288 return !(lhs == rhs);
289 }
290 };
291
292 // Inspired by, and originally copied from ImageBase::FastComputeOffset(ind)).
293 static OffsetValueType
294 ComputeOffset(const OffsetTableType & offsetTable, const IndexType & bufferedRegionIndex, const IndexType & index)
295 {
296 OffsetValueType offsetValue = 0;
298 bufferedRegionIndex, index, offsetTable.data(), offsetValue);
299 return offsetValue;
300 }
301
302 // ImageRegionRange data members (strictly private):
303
305
307
309
311
312 // A copy of the offset table of the image.
314
315public:
318 using reverse_iterator = std::reverse_iterator<iterator>;
319 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
320
321
324 ImageRegionRange() noexcept = default;
325
326
331 explicit ImageRegionRange(TImage & image, const RegionType & iterationRegion)
332 : m_BufferBegin{ std::begin(ImageBufferRange{ image }) }
333 ,
334 // Note: Use parentheses instead of curly braces to initialize data members,
335 // to avoid AppleClang 6.0.0.6000056 compile errors, "no viable conversion..."
336 m_BufferedRegionIndex(image.TImage::GetBufferedRegion().GetIndex())
337 , m_IterationRegionIndex(iterationRegion.GetIndex())
338 , m_IterationRegionSize(iterationRegion.GetSize())
339 {
340 const OffsetValueType * const offsetTable = image.GetOffsetTable();
341 assert(offsetTable != nullptr);
342
343 if (iterationRegion.GetNumberOfPixels() > 0) // If region is non-empty
344 {
345 // Check if the iteration region is within the buffered region, similar
346 // to checks in ImageConstIteratorWithIndex(const TImage*, const RegionType&)
347 // and ImageConstIterator::SetRegion(const RegionType&).
348
349 const auto & bufferedRegion = image.GetBufferedRegion();
350
351 itkAssertOrThrowMacro((bufferedRegion.IsInside(iterationRegion)),
352 "Iteration region " << iterationRegion << " is outside of buffered region "
353 << bufferedRegion);
354 }
355
356 std::copy_n(offsetTable, ImageDimension + 1, m_OffsetTable.data());
357 }
358
359
363 explicit ImageRegionRange(TImage & image)
364 : ImageRegionRange(image, image.GetRequestedRegion())
365 {}
366
367
369 [[nodiscard]] iterator
377
379 [[nodiscard]] iterator
380 end() const noexcept
381 {
382 auto endRegionIndex = m_IterationRegionIndex;
383 endRegionIndex.back() += m_IterationRegionSize.back();
384
385 OffsetType iterationOffset{ {} }; // Initialize offsets to 0, by aggregate initializer
386 *(iterationOffset.rbegin()) = m_IterationRegionSize.back();
387
390 iterationOffset,
392 }
393
396 [[nodiscard]] const_iterator
397 cbegin() const noexcept
398 {
399 return this->begin();
400 }
401
403 [[nodiscard]] const_iterator
404 cend() const noexcept
405 {
406 return this->end();
407 }
408
410 [[nodiscard]] reverse_iterator
411 rbegin() const noexcept
412 {
413 return reverse_iterator{ this->end() };
414 }
415
417 [[nodiscard]] reverse_iterator
418 rend() const noexcept
419 {
420 return reverse_iterator{ this->begin() };
421 }
422
424 [[nodiscard]] const_reverse_iterator
425 crbegin() const noexcept
426 {
427 return this->rbegin();
428 }
429
431 [[nodiscard]] const_reverse_iterator
432 crend() const noexcept
433 {
434 return this->rend();
435 }
436
437
439 [[nodiscard]] size_t
440 size() const noexcept
441 {
442 return m_IterationRegionSize.CalculateProductOfElements();
443 }
444
445
447 [[nodiscard]] bool
448 empty() const noexcept
449 {
450 return std::any_of(m_IterationRegionSize.begin(), m_IterationRegionSize.end(), [](const SizeValueType sizeValue) {
451 return sizeValue == 0;
452 });
453 }
454
455
457 ~ImageRegionRange() = default;
458};
459
460
461// Deduction guide to avoid compiler warnings (-wctad-maybe-unsupported) when using class template argument deduction.
462template <typename TImage>
464
465} // namespace itk
466
467#endif
std::conditional_t< UsingPointerAsIterator, QualifiedInternalPixelType *, QualifiedIterator< IsImageTypeConst > > iterator
std::conditional_t< UsingPointerAsIterator, const InternalPixelType *, QualifiedIterator< true > > const_iterator
static void ComputeOffset(const IndexType &bufferedRegionIndex, const IndexType &index, const OffsetValueType offsetTable[], OffsetValueType &offset)
friend bool operator!=(const QualifiedIterator &lhs, const QualifiedIterator &rhs) noexcept
typename std::iterator_traits< QualifiedBufferIteratorType >::reference reference
QualifiedIterator & operator--() noexcept
QualifiedIterator operator--(int) noexcept
QualifiedIterator(const QualifiedIterator< VIsArgumentConst > &arg) noexcept
QualifiedIterator & operator++() noexcept
friend bool operator==(const QualifiedIterator &lhs, const QualifiedIterator &rhs) noexcept
typename std::iterator_traits< QualifiedBufferIteratorType >::pointer pointer
typename std::iterator_traits< QualifiedBufferIteratorType >::value_type value_type
QualifiedIterator operator++(int) noexcept
QualifiedIterator(const QualifiedBufferIteratorType &bufferIterator, const OffsetTableType &offsetTable, const OffsetType &iterationOffset, const SizeType &regionSize) noexcept
std::conditional_t< VIsConst, typename ImageBufferRange< TImage >::const_iterator, typename ImageBufferRange< TImage >::iterator > QualifiedBufferIteratorType
std::bidirectional_iterator_tag iterator_category
typename RegionType::IndexType IndexType
typename TImage::ImageDimensionType ImageDimensionType
iterator begin() const noexcept
QualifiedIterator< true > const_iterator
const_reverse_iterator crbegin() const noexcept
reverse_iterator rbegin() const noexcept
typename TImage::RegionType RegionType
reverse_iterator rend() const noexcept
const_iterator cend() const noexcept
ImageRegionRange() noexcept=default
Offset< ImageDimension+1 > OffsetTableType
iterator end() const noexcept
typename ImageBufferRange< TImage >::iterator BufferIteratorType
const_iterator cbegin() const noexcept
typename TImage::SizeType SizeType
static OffsetValueType ComputeOffset(const OffsetTableType &offsetTable, const IndexType &bufferedRegionIndex, const IndexType &index)
std::reverse_iterator< const_iterator > const_reverse_iterator
vcl_size_t size() const noexcept
std::reverse_iterator< iterator > reverse_iterator
const_reverse_iterator crend() const noexcept
typename TImage::PixelType PixelType
typename TImage::OffsetType OffsetType
~ImageRegionRange()=default
QualifiedIterator< IsImageTypeConst > iterator
static constexpr ImageDimensionType ImageDimension
bool empty() const noexcept
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....
unsigned long SizeValueType
Definition itkIntTypes.h:86
ImageRegionRange(TImage &) -> ImageRegionRange< TImage >
long OffsetValueType
Definition itkIntTypes.h:97
Represent a n-dimensional offset between two n-dimensional indexes of n-dimensional image.
Definition itkOffset.h:67
OffsetValueType * data()
Definition itkOffset.h:430