template<typename T>
dip::ImageIterator class

An iterator to iterate over all pixels of an image, or all lines of an image.

If it is created with the processing dimension set, then the processing dimension indicates a dimension over which this iterator does not iterate. That is, it will iterate over all pixels that have a coordinate equal to 0 along this dimension. In this case, a dip::LineIterator can be obtained to iterate over the line that starts at the current pixel (using the GetLineIterator method).

If the processing dimension is not set, then the iterator visits all pixels in the image.

The iterator can be incremented until it reaches the end of the image. At this point, the iterator will become invalid. An invalid iterator will test false. The IsAtEnd method can be used instead to test for this condition. It is also possible to compare two iterators for equality (i.e. to compare against an end iterator).

Dereferencing the iterator yields the first sample of the current pixel (*it == it[ 0 ]). One can index using the [] operator to obtain each of the samples of the tensor (it[ 0 ] .. it[ image.TensorElements() - 1 ]).

Alternatively, a dip::SampleIterator can be obtained to iterate over the samples of the tensor (it.begin() .. it.end()).

It is possible to obtain neighboring pixel values by adding the neighbor’s offset to the current pointer:

*( it.Pointer() + offset )

Note that this offset can cause a read-out-of-bounds or simply access the wrong pixel if the neighbor is not within the image domain. One would have to test for it.Coordinates() to be far enough away from the edge of the image. The most optimal way to access neighbors is to iterate over a window within a larger image, such that one can be sure that neighbors always exist. See dip::ExtendImage.

By default, the iterator loops over pixels (or image lines) in linear index order. That is, coordinates change as: {0,0}, {1,0}, {2,0}, … {0,1}, {1,1}, … If the image does not have normal strides, this is not the most efficient way of looping over all pixels. The method Optimize changes the order in which pixels are accessed to be the order in which they are stored in memory. After calling Optimize, the output of Coordinates and Index no longer match the input image.

Satisfies all the requirements for a mutable ForwardIterator.

Note that when an image is stripped or reforged, all its iterators are invalidated.

Constructors, destructors, assignment and conversion operators

ImageIterator()
Default constructor yields an invalid iterator that cannot be dereferenced, and is equivalent to an end iterator
ImageIterator(dip::Image const& image, dip::uint procDim = std::numeric_limits::max()) explicit
To construct a useful iterator, provide an image and optionally a processing dimension
ImageIterator(dip::Image const& image, dip::UnsignedArray const& origin, dip::UnsignedArray sizes, dip::UnsignedArray const& spacing = {}, dip::uint procDim = std::numeric_limits::max())
To construct a useful iterator, provide an image, an ROI, and optionally a processing dimension.

Aliases

using iterator_category = std::forward_iterator_tag
Iterator category
using value_type = T
The data type of the sample, obtained when dereferencing the iterator
using reference = T&
The type of a reference to a sample
using pointer = T*
The type of a pointer to a pixel

Functions

void swap(ImageIterator<T>& other)
Swap
auto begin() const -> SampleIterator<dip::ImageIterator::value_type>
Get an iterator over the tensor for the current pixel
auto end() const -> SampleIterator<dip::ImageIterator::value_type>
Get an end iterator over the tensor for the current pixel
auto cbegin() const -> ConstSampleIterator<dip::ImageIterator::value_type>
Get a const iterator over the tensor for the current pixel
auto cend() const -> ConstSampleIterator<dip::ImageIterator::value_type>
Get an end const iterator over the tensor for the current pixel
auto GetLineIterator() const -> LineIterator<dip::ImageIterator::value_type>
Get an iterator over the current line
auto GetConstLineIterator() const -> ConstLineIterator<dip::ImageIterator::value_type>
Get a const iterator over the current line
auto IsAtEnd() const -> bool
Test to see if the iterator reached past the last pixel
auto Coordinates() const -> dip::UnsignedArray const&
Return the current coordinates
auto SetCoordinates(dip::UnsignedArray coords) -> ImageIterator<T>&
Set the iterator to point at a different location in the image
auto Sizes() const -> dip::UnsignedArray const&
Return the sizes of the image we’re iterating over.
auto ProcessingDimensionSize() const -> dip::uint
Return the size along the processing dimension
auto Strides() const -> dip::IntegerArray const&
Return the strides used to iterate over the image.
auto ProcessingDimensionStride() const -> dip::sint
Return the stride along the processing dimension
auto IsOnEdge() const -> bool
Return true if the iterator points at a pixel on the edge of the image.
auto Pointer() const -> dip::ImageIterator::pointer
Return the current pointer
auto Offset() const -> dip::sint
Return the current offset
auto Index() const -> dip::uint
Return the current index, which is computed: this function is not trivial
auto HasProcessingDimension() const -> bool
True if the processing dimension is set
auto ProcessingDimension() const -> dip::uint
Return the processing dimension, the direction of the lines over which the iterator iterates.
auto Reset() -> ImageIterator<T>&
Reset the iterator to the first pixel in the image (as it was when first created)
auto Optimize() -> ImageIterator<T>&
Optimizes the order in which the iterator visits the image pixels.
auto OptimizeAndFlatten() -> ImageIterator<T>&
Like Optimize, but additionally folds dimensions together where possible (flattens the image, so that the iterator has fewer dimensions to work with). The processing dimension is not affected.

Operators

auto operator*() const -> dip::ImageIterator::reference
Dereference
auto operator->() const -> dip::ImageIterator::pointer
Dereference
auto operator[](dip::uint index) const -> dip::ImageIterator::reference
Index into tensor, it[0] is equal to *it, but it[1] is not equal to *(++it).
auto operator++() -> ImageIterator<T>&
Pre-increment
auto operator++(int ) -> ImageIterator<T>
Post-increment
auto operator==(ImageIterator<T> const& other) const -> bool
Equality comparison
auto operator!=(ImageIterator<T> const& other) const -> bool
Inequality comparison
auto operator bool() const -> bool explicit
Test to see if the iterator is still pointing at a pixel

Alias documentation

template<typename T>
template<typename T>
using dip::ConstImageIterator = ImageIterator<const T>

A const iterator to iterate over all pixels of an image, or all lines of an image.

This iterator is identical to dip::ImageIterator, but with a const value type.

Satisfies all the requirements for a non-mutable ForwardIterator.

Function documentation

template<typename T>
ImageIterator(dip::Image const& image, dip::UnsignedArray const& origin, dip::UnsignedArray sizes, dip::UnsignedArray const& spacing = {}, dip::uint procDim = std::numeric_limits::max())

To construct a useful iterator, provide an image, an ROI, and optionally a processing dimension.

spacing can be an empty array or a scalar, but origin and sizes are expected to contain one value per image dimension. Iterator coordinates are within the ROI.

template<typename T>
bool IsOnEdge() const

Return true if the iterator points at a pixel on the edge of the image.

If there is a processing dimension, then the iterator always points at an edge pixel; in this case only returns true if all pixels on the line are edge pixels (i.e. the first and last pixel of the line are not counted).

template<typename T>
dip::uint ProcessingDimension() const

Return the processing dimension, the direction of the lines over which the iterator iterates.

If the return value is larger or equal to the dimensionality (i.e. not one of the image dimensions), then there is no processing dimension.

template<typename T>
ImageIterator<T>& Optimize()

Optimizes the order in which the iterator visits the image pixels.

The iterator internally reorders and flips image dimensions to change the linear index to match the storage order (see dip::Image::StandardizeStrides). If the image’s strides were not normal, this will significantly increase the speed of reading or writing to the image. Expanded singleton dimensions are eliminated, meaning that each pixel is always only accessed once. Additionally, singleton dimensions are ignored.

After calling this function, Coordinates and Index no longer match the input image. Do not use this method if the order of accessing pixels is relevant, or if Coordinates are needed.

Note that the processing dimension stride could change sign. Use ProcessingDimensionStride. If the processing dimension was a singleton dimension, or singleton-expanded, the iterator will no longer have a singleton dimension. In this case, HasProcessingDimension will return false.

The iterator is reset to the first pixel.