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 {
151 if constexpr (VIndex == 0)
152 {
154 }
155 else
156 {
158 }
159
160 if constexpr (VIndex < (ImageDimension - 1))
161 {
162 if (static_cast<SizeValueType>(++m_IterationOffset[VIndex]) >= m_IterationRegionSize[VIndex])
163 {
164 m_IterationOffset[VIndex] = 0;
166 this->Increment<VIndex + 1>();
167 }
168 }
169 else
170 {
171 static_assert(VIndex == (ImageDimension - 1));
172
173 ++m_IterationOffset[VIndex];
174 }
175 }
176
177
178 template <size_t VIndex>
179 void
180 Decrement() noexcept
181 {
182 if constexpr (VIndex == 0)
183 {
185 }
186 else
187 {
189 }
190
191 if constexpr (VIndex < (ImageDimension - 1))
192 {
193 if (--m_IterationOffset[VIndex] < 0)
194 {
195 m_IterationOffset[VIndex] = m_IterationRegionSize[VIndex] - 1;
197 this->Decrement<VIndex + 1>();
198 }
199 }
200 else
201 {
202 static_assert(VIndex == (ImageDimension - 1));
203
204 --m_IterationOffset[VIndex];
205 }
206 }
207
208
209 public:
210 // Types conforming the iterator requirements of the C++ standard library:
211 using difference_type = ptrdiff_t;
212 using value_type = typename std::iterator_traits<QualifiedBufferIteratorType>::value_type;
213 using reference = typename std::iterator_traits<QualifiedBufferIteratorType>::reference;
214 using pointer = typename std::iterator_traits<QualifiedBufferIteratorType>::pointer;
215 using iterator_category = std::bidirectional_iterator_tag;
216
225 QualifiedIterator() = default;
226
228 template <bool VIsArgumentConst, typename = std::enable_if_t<VIsConst && !VIsArgumentConst>>
230 : m_BufferIterator(arg.m_BufferIterator)
231 ,
232 // Note: Use parentheses instead of curly braces to initialize data members,
233 // to avoid AppleClang 6.0.0.6000056 compilation error, "no viable conversion..."
234 m_OffsetTable(arg.m_OffsetTable)
235 , m_IterationOffset(arg.m_IterationOffset)
236 , m_IterationRegionSize(arg.m_IterationRegionSize)
237 {}
238
239
242 operator*() const noexcept
243 {
244 return *m_BufferIterator;
245 }
246
249 operator++() noexcept
250 {
251 this->Increment<0>();
252 return *this;
253 }
254
255
259 operator++(int) noexcept
260 {
261 auto result = *this;
262 ++(*this);
263 return result;
264 }
265
266
269 operator--() noexcept
270 {
271 this->Decrement<0>();
272 return *this;
273 }
274
275
279 operator--(int) noexcept
280 {
281 auto result = *this;
282 --(*this);
283 return result;
284 }
285
286
290 friend bool
291 operator==(const QualifiedIterator & lhs, const QualifiedIterator & rhs) noexcept
292 {
293 return lhs.m_BufferIterator == rhs.m_BufferIterator;
294 }
295
296
298 friend bool
299 operator!=(const QualifiedIterator & lhs, const QualifiedIterator & rhs) noexcept
300 {
301 // Implemented just like the corresponding std::rel_ops operator.
302 return !(lhs == rhs);
303 }
304 };
305
306 // Inspired by, and originally copied from ImageBase::FastComputeOffset(ind)).
307 static OffsetValueType
308 ComputeOffset(const OffsetTableType & offsetTable, const IndexType & bufferedRegionIndex, const IndexType & index)
309 {
310 OffsetValueType offsetValue = 0;
312 bufferedRegionIndex, index, offsetTable.data(), offsetValue);
313 return offsetValue;
314 }
315
316 // ImageRegionRange data members (strictly private):
317
319
321
323
325
326 // A copy of the offset table of the image.
328
329public:
332 using reverse_iterator = std::reverse_iterator<iterator>;
333 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
334
335
338 ImageRegionRange() noexcept = default;
339
340
345 explicit ImageRegionRange(TImage & image, const RegionType & iterationRegion)
346 : m_BufferBegin{ std::begin(ImageBufferRange{ image }) }
347 ,
348 // Note: Use parentheses instead of curly braces to initialize data members,
349 // to avoid AppleClang 6.0.0.6000056 compile errors, "no viable conversion..."
350 m_BufferedRegionIndex(image.TImage::GetBufferedRegion().GetIndex())
351 , m_IterationRegionIndex(iterationRegion.GetIndex())
352 , m_IterationRegionSize(iterationRegion.GetSize())
353 {
354 const OffsetValueType * const offsetTable = image.GetOffsetTable();
355 assert(offsetTable != nullptr);
356
357 if (iterationRegion.GetNumberOfPixels() > 0) // If region is non-empty
358 {
359 // Check if the iteration region is within the buffered region, similar
360 // to checks in ImageConstIteratorWithIndex(const TImage*, const RegionType&)
361 // and ImageConstIterator::SetRegion(const RegionType&).
362
363 const auto & bufferedRegion = image.GetBufferedRegion();
364
365 itkAssertOrThrowMacro((bufferedRegion.IsInside(iterationRegion)),
366 "Iteration region " << iterationRegion << " is outside of buffered region "
367 << bufferedRegion);
368 }
369
370 std::copy_n(offsetTable, ImageDimension + 1, m_OffsetTable.data());
371 }
372
373
377 explicit ImageRegionRange(TImage & image)
378 : ImageRegionRange(image, image.GetRequestedRegion())
379 {}
380
381
383 [[nodiscard]] iterator
391
393 [[nodiscard]] iterator
394 end() const noexcept
395 {
396 auto endRegionIndex = m_IterationRegionIndex;
397 endRegionIndex.back() += m_IterationRegionSize.back();
398
399 OffsetType iterationOffset{ {} }; // Initialize offsets to 0, by aggregate initializer
400 iterationOffset.back() = m_IterationRegionSize.back();
401
404 iterationOffset,
406 }
407
410 [[nodiscard]] const_iterator
411 cbegin() const noexcept
412 {
413 return this->begin();
414 }
415
417 [[nodiscard]] const_iterator
418 cend() const noexcept
419 {
420 return this->end();
421 }
422
424 [[nodiscard]] reverse_iterator
425 rbegin() const noexcept
426 {
427 return reverse_iterator{ this->end() };
428 }
429
431 [[nodiscard]] reverse_iterator
432 rend() const noexcept
433 {
434 return reverse_iterator{ this->begin() };
435 }
436
438 [[nodiscard]] const_reverse_iterator
439 crbegin() const noexcept
440 {
441 return this->rbegin();
442 }
443
445 [[nodiscard]] const_reverse_iterator
446 crend() const noexcept
447 {
448 return this->rend();
449 }
450
451
453 [[nodiscard]] size_t
454 size() const noexcept
455 {
456 return m_IterationRegionSize.CalculateProductOfElements();
457 }
458
459
461 [[nodiscard]] bool
462 empty() const noexcept
463 {
464 return std::any_of(m_IterationRegionSize.begin(), m_IterationRegionSize.end(), [](const SizeValueType sizeValue) {
465 return sizeValue == 0;
466 });
467 }
468
469
471 ~ImageRegionRange() = default;
472};
473
474
475// Deduction guide to avoid compiler warnings (-wctad-maybe-unsupported) when using class template argument deduction.
476template <typename TImage>
478
479} // namespace itk
480
481#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