template<dip::uint N, typename T = dip::dfloat>
dip::GenericJointImageIterator class

A data-type–agnostic version of dip::JointImageIterator. Use this iterator only to write code that does not know at compile-time what the data type of the image is.

This iterator works similarly to dip::JointImageIterator. The Pointer<N> method returns a void pointer to the first sample in the pixel for image N. This is the more efficient way of using the iterator.

The Sample<N> method returns a dip::Image::Sample object. This object references the sample, so that assigning to it changes the samples’s value in the image. It is convenient in use, but not very efficient. The optional template argument to GenericJointImageIterator sets the template argument to the dip::Image::CastSample object that is actually returned by the method. Choose a type in which you wish to work, but know that this choice will not affect the results of reading from and assigning to the samples. The only difference is the type to which the output can implicitly be cast to.

Example usage slightly modified from dip::Image::Copy:

dip::uint processingDim = Framework::OptimalProcessingDim( src );
auto it = dip::GenericJointImageIterator< 2 >( { src, dest }, processingDim );
do {
   detail::CopyBuffer(
         it.InPointer(),
         src.DataType(),
         src.Stride( processingDim ),
         src.TensorStride(),
         it.OutPointer(),
         dest.DataType(),
         dest.Stride( processingDim ),
         dest.TensorStride(),
         dest.Size( processingDim ),
         dest.TensorElements()
   );
} while( ++it );

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

Constructors, destructors, assignment and conversion operators

GenericJointImageIterator()
Default constructor yields an invalid iterator that cannot be dereferenced, and is equivalent to an end iterator
GenericJointImageIterator(dip::ImageConstRefArray const& images, dip::uint procDim = std::numeric_limits::max()) explicit
To construct a useful iterator, provide two images, and optionally a processing dimension

Aliases

using iterator_category = std::forward_iterator_tag
Iterator category
using value_type = dip::Image::CastPixel
The type of the pixel, obtained when dereferencing the iterator
using reference = dip::GenericJointImageIterator::value_type
The type of a reference to a pixel (note dip::Image::CastPixel references a value in the image)
using pointer = dip::GenericJointImageIterator::value_type*
The type of a pointer to a pixel

Functions

template<typename S>
void swap(dip::GenericJointImageIterator& other)
Swap
template<dip::uint I>
auto Sample(dip::uint index) const -> dip::Image::CastSample
Index into image tensor for image I
auto InSample(dip::uint index) const -> dip::Image::CastSample
Index into image tensor for image 0.
auto OutSample(dip::uint index) const -> dip::Image::CastSample
Index into image tensor for image 1.
template<dip::uint I>
auto Sample() const -> dip::Image::CastSample
Get first tensor element for image I.
auto In() const -> dip::GenericJointImageIterator::value_type
Get pixel for image 0.
auto Out() const -> dip::GenericJointImageIterator::value_type
Get pixel for image 1.
template<dip::uint I>
auto Pixel() const -> dip::GenericJointImageIterator::value_type
Get pixel for image I.
template<dip::uint I>
auto begin() const -> typename value_type::Iterator
Get an iterator over the tensor for the current pixel of image I
template<dip::uint I>
auto end() const -> typename value_type::Iterator
Get an end iterator over the tensor for the current pixel of image I
template<dip::uint I, typename S = T>
auto GetLineIterator() const -> dip::LineIterator
Get an iterator over the current line of image I
template<dip::uint I, typename S = T>
auto GetConstLineIterator() const -> dip::ConstLineIterator
Get a const iterator over the current line of image I
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) -> dip::GenericJointImageIterator&
Set the iterator to point at a different location in the image
auto Sizes() const -> dip::UnsignedArray const&
Return the sizes of the images we’re iterating over.
auto ProcessingDimensionSize() const -> dip::uint
Return the size along the processing dimension.
template<dip::uint I>
auto Strides() const -> dip::IntegerArray const&
Return the strides used to iterate over the image I.
template<dip::uint I>
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.
template<dip::uint I>
auto Pointer(dip::uint index) const -> void*
Index into image tensor for image I
auto InPointer(dip::uint index) const -> void*
Index into image tensor for image 0.
auto OutPointer(dip::uint index) const -> void*
Index into image tensor for image 1.
template<dip::uint I>
auto Pointer() const -> void*
Return the current pointer for image I
auto InPointer() const -> void*
Return the current pointer for image 0.
auto OutPointer() const -> void*
Return the current pointer for image 1.
template<dip::uint I>
auto Offset() const -> dip::sint
Return the current offset for image I
auto InOffset() const -> dip::sint
Index into image tensor for image 0.
auto OutOffset() const -> dip::sint
Index into image tensor for image 1.
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() -> dip::GenericJointImageIterator&
Reset the iterator to the first pixel in the image (as it was when first created)
auto Optimize(dip::uint n = 0) -> dip::GenericJointImageIterator&
Optimizes the order in which the iterator visits the image pixels.
auto OptimizeAndFlatten(dip::uint n = 0) -> dip::GenericJointImageIterator&
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++() -> dip::GenericJointImageIterator&
Pre-increment
auto operator++(int ) -> dip::GenericJointImageIterator
Post-increment
template<typename S>
auto operator==(dip::GenericJointImageIterator const& other) const -> bool
Equality comparison, is equal if the two iterators have the same coordinates.
template<typename S>
auto operator!=(dip::GenericJointImageIterator const& other) const -> bool
Inequality comparison
auto operator bool() const -> bool explicit
Test to see if the iterator is still pointing at a pixel

Function documentation

template<dip::uint N, 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<dip::uint N, 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<dip::uint N, typename T>
dip::GenericJointImageIterator& Optimize(dip::uint n = 0)

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 of the first image (see dip::Image::StandardizeStrides), or image n if a parameter is given. 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 only if the dimension is expanded in all images. Additionally, singleton dimensions are ignored.

After calling this function, Coordinates and Index no longer match the input images. 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.