/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef itkImageLinearConstIteratorWithIndex_h #define itkImageLinearConstIteratorWithIndex_h #include "itkImageConstIteratorWithIndex.h" namespace itk { /** \class ImageLinearConstIteratorWithIndex * \brief A multi-dimensional image iterator that visits image pixels within a * region in a "scan-line" order. * * ImageLinearConstIteratorWithIndex is templated over image type and is * constrained to walk within a specified image region. It is designed for * line-by-line processing of images. This iterator walks a linear path along * a selected image direction that is parallel to one of the coordinate axes * of the image. The iterator conceptually breaks the image into a set of * parallel lines that span the selected image dimension. * * ImageLinearConstIteratorWithIndex assumes a particular layout of the image * data. The is arranged in a 1D array as if it were [][][][slice][row][col] * with Index[0] = col, Index[1] = row, Index[2] = slice, etc. * * operator++ provides a simple syntax for walking around a region of a * multidimensional image. operator++ iterates across a preselected direction * constraining the movement to within a region of image. The user can verify * when the iterator reaches the boundary of the region along this direction, * by calling the IsAtEndOfLine() method. Then it is possible to pass to the * next line starting at the first pixel in the row that is part of the region * by calling the NextLine() method. * * This is the typical use of this iterator in a loop: * \code ImageLinearConstIteratorWithIndex it( image, image->GetRequestedRegion() ); it.SetDirection(2); it.GoToBegin(); while( !it.IsAtEnd() ) { while( !it.IsAtEndOfLine() ) { value = it.Get(); // it.Set() doesn't exist in the Const Iterator ++it; } it.NextLine(); } \endcode * * \par MORE INFORMATION * For a complete description of the ITK Image Iterators and their API, please * see the Iterators chapter in the ITK Software Guide. The ITK Software Guide * is available in print and as a free .pdf download from https://www.itk.org. * * \ingroup ImageIterators * * \sa ImageConstIterator \sa ConditionalConstIterator * \sa ConstNeighborhoodIterator \sa ConstShapedNeighborhoodIterator * \sa ConstSliceIterator \sa CorrespondenceDataStructureIterator * \sa FloodFilledFunctionConditionalConstIterator * \sa FloodFilledImageFunctionConditionalConstIterator * \sa FloodFilledImageFunctionConditionalIterator * \sa FloodFilledSpatialFunctionConditionalConstIterator * \sa FloodFilledSpatialFunctionConditionalIterator * \sa ImageConstIterator \sa ImageConstIteratorWithIndex * \sa ImageIterator \sa ImageIteratorWithIndex * \sa ImageLinearConstIteratorWithIndex \sa ImageLinearIteratorWithIndex * \sa ImageRandomConstIteratorWithIndex \sa ImageRandomIteratorWithIndex * \sa ImageRegionConstIterator \sa ImageRegionConstIteratorWithIndex * \sa ImageRegionExclusionConstIteratorWithIndex * \sa ImageRegionExclusionIteratorWithIndex * \sa ImageRegionIterator \sa ImageRegionIteratorWithIndex * \sa ImageRegionReverseConstIterator \sa ImageRegionReverseIterator * \sa ImageReverseConstIterator \sa ImageReverseIterator * \sa ImageSliceConstIteratorWithIndex \sa ImageSliceIteratorWithIndex * \sa NeighborhoodIterator \sa PathConstIterator \sa PathIterator * \sa ShapedNeighborhoodIterator \sa SliceIterator * \sa ImageConstIteratorWithIndex * * \ingroup ITKCommon */ template class ITK_TEMPLATE_EXPORT ImageLinearConstIteratorWithIndex : public ImageConstIteratorWithIndex { public: /** Standard class type aliases. */ using Self = ImageLinearConstIteratorWithIndex; using Superclass = ImageConstIteratorWithIndex; /** Index type alias support While this was already typedef'ed in the superclass, * it needs to be redone here for this subclass to compile properly with gcc. * Note that we have to rescope Index back to itk::Index so that it is not * confused with ImageIterator::Index. */ using IndexType = typename TImage::IndexType; /** Region type alias support While this was already typedef'ed in the superclass, * it needs to be redone here for this subclass to compile properly with gcc. * Note that we have to rescope Region back to itk::ImageRegion so that it * is not confused with ImageIterator::Index. */ using RegionType = typename TImage::RegionType; /** Image type alias support While this was already typedef'ed in the superclass, * it needs to be redone here for this subclass to compile properly with gcc. * Note that we have to rescope Index back to itk::Index so that it is not * confused with ImageIterator::Index. */ using ImageType = TImage; /** PixelContainer type alias support Used to refer to the container for * the pixel data. While this was already typedef'ed in the superclass, * it needs to be redone here for this subclass to compile properly with gcc. */ using PixelContainer = typename TImage::PixelContainer; using PixelContainerPointer = typename PixelContainer::Pointer; /** Default constructor. Needed since we provide a cast constructor. */ ImageLinearConstIteratorWithIndex() : ImageConstIteratorWithIndex() {} /** Constructor establishes an iterator to walk a particular image and a * particular region of that image. */ ImageLinearConstIteratorWithIndex(const ImageType * ptr, const RegionType & region); /** Constructor that can be used to cast from an ImageIterator to an * ImageLinearConstIteratorWithIndex. Many routines return an ImageIterator but for a * particular task, you may want an ImageLinearConstIteratorWithIndex. Rather than * provide overloaded APIs that return different types of Iterators, itk * returns ImageIterators and uses constructors to cast from an * ImageIterator to a ImageLinearConstIteratorWithIndex. */ ImageLinearConstIteratorWithIndex(const ImageConstIteratorWithIndex & it) { this->ImageConstIteratorWithIndex::operator=(it); } /** Go to the next line. * \sa operator++ \sa operator-- \sa IsAtEndOfLine \sa PreviousLine \sa End */ inline void NextLine(); /** Go to the previous line. * \sa operator++ \sa operator-- \sa IsAtEndOfLine \sa NextLine \sa End */ inline void PreviousLine(); /** Go to the beginning pixel of the current line. * \sa GoToReverseBeginOfLine \sa operator++ \sa operator-- \sa NextLine \sa IsAtEndOfLine */ void GoToBeginOfLine(); /** Go to the beginning pixel of the current line. * \sa GoToBeginOfLine \sa operator++ \sa operator-- \sa NextLine \sa IsAtEndOfLine */ void GoToReverseBeginOfLine(); /** Go to the past end pixel of the current line. * \sa GoToBeginOfLine \sa operator++ \sa operator-- \sa NextLine \sa IsAtEndOfLine */ void GoToEndOfLine(); /** Test if the index is at the end of line */ inline bool IsAtEndOfLine() const { return this->m_PositionIndex[m_Direction] >= this->m_EndIndex[m_Direction]; } /** Test if the index is at the begin of line */ inline bool IsAtReverseEndOfLine() const { return this->m_PositionIndex[m_Direction] < this->m_BeginIndex[m_Direction]; } /** Set the direction of movement */ inline void SetDirection(unsigned int direction) { if (direction >= TImage::ImageDimension) { itkGenericExceptionMacro("In image of dimension " << TImage::ImageDimension << " Direction " << direction << " was selected"); } m_Direction = direction; m_Jump = this->m_OffsetTable[m_Direction]; } /** get the direction of movement */ unsigned int GetDirection() { return m_Direction; } /** Increment (prefix) the selected dimension. * No bounds checking is performed. \sa GetIndex \sa operator-- */ inline Self & operator++() { this->m_PositionIndex[m_Direction]++; this->m_Position += m_Jump; return *this; } /** Decrement (prefix) the selected dimension. * No bounds checking is performed. \sa GetIndex \sa operator++ */ inline Self & operator--() { this->m_PositionIndex[m_Direction]--; this->m_Position -= m_Jump; return *this; } private: OffsetValueType m_Jump{ 0 }; unsigned int m_Direction{ 0 }; }; //---------------------------------------------------------------------- // Go to next line //---------------------------------------------------------------------- template inline void ImageLinearConstIteratorWithIndex::NextLine() { this->m_Position -= this->m_OffsetTable[m_Direction] * (this->m_PositionIndex[m_Direction] - this->m_BeginIndex[m_Direction]); this->m_PositionIndex[m_Direction] = this->m_BeginIndex[m_Direction]; for (unsigned int n = 0; n < TImage::ImageDimension; ++n) { this->m_Remaining = false; if (n == m_Direction) { continue; } this->m_PositionIndex[n]++; if (this->m_PositionIndex[n] < this->m_EndIndex[n]) { this->m_Position += this->m_OffsetTable[n]; this->m_Remaining = true; break; } else { this->m_Position -= this->m_OffsetTable[n] * (this->m_Region.GetSize()[n] - 1); this->m_PositionIndex[n] = this->m_BeginIndex[n]; } } } //---------------------------------------------------------------------- // Pass to the last pixel on the previous line //---------------------------------------------------------------------- template inline void ImageLinearConstIteratorWithIndex::PreviousLine() { this->m_Position += this->m_OffsetTable[m_Direction] * (this->m_EndIndex[m_Direction] - 1 - this->m_PositionIndex[m_Direction]); this->m_PositionIndex[m_Direction] = this->m_EndIndex[m_Direction] - 1; for (unsigned int n = 0; n < TImage::ImageDimension; ++n) { this->m_Remaining = false; if (n == m_Direction) { continue; } this->m_PositionIndex[n]--; if (this->m_PositionIndex[n] >= this->m_BeginIndex[n]) { this->m_Position -= this->m_OffsetTable[n]; this->m_Remaining = true; break; } else { this->m_Position += this->m_OffsetTable[n] * (this->m_Region.GetSize()[n] - 1); this->m_PositionIndex[n] = this->m_EndIndex[n] - 1; } } } } // end namespace itk #ifndef ITK_MANUAL_INSTANTIATION # include "itkImageLinearConstIteratorWithIndex.hxx" #endif #endif