1 /*========================================================================= 2 * 3 * Copyright Insight Software Consortium 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 * http://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 #ifndef itkImageRegionReverseConstIterator_h 19 #define itkImageRegionReverseConstIterator_h 20 21 #include "itkImageReverseConstIterator.h" 22 #include "itkImageRegionIterator.h" 23 24 namespace itk 25 { 26 /** 27 * \class ImageRegionReverseConstIterator 28 * \brief A multi-dimensional image iterator designed to walk a specified image 29 * region in reverse. 30 * 31 * ImageRegionReverseConstIterator is a templated class to represent a 32 * multi-dimensional iterator. ImageRegionReverseConstIterator is templated 33 * over the dimension of the image and the data type of the 34 * image. ImageRegionReverseConstIterator is constrained to walk only 35 * within the specified region. 36 * 37 * ImageRegionReverseConstIterator is a multi-dimensional iterator, 38 * requiring more information be specified before the iterator can be 39 * used than conventional iterators. Whereas the std::vector::iterator 40 * from the STL only needs to be passed a pointer to establish the 41 * iterator, the multi-dimensional image iterator needs a pointer, the 42 * size of the buffer, the size of the region, the start index of the 43 * buffer, and the start index of the region. To gain access to this 44 * information, ImageRegionReverseConstIterator holds a reference to the 45 * image over which it is traversing. 46 * 47 * ImageRegionReverseConstIterator assumes a particular layout of the image 48 * data. The is arranged in a 1D array as if it were 49 * [][][][slice][row][col] with Index[0] = col, Index[1] = row, 50 * Index[2] = slice, etc. 51 * 52 * operator++ provides a simple syntax for walking around a region of 53 * a multidimensional image. For a reverse iterator, operator++ moves 54 * backwards through the region. operator++ iterates across a row, 55 * constraining the movement to within a region of image. When the 56 * iterator reaches the boundary of the region along a row, the 57 * iterator automatically wraps to the previous row, starting at the last 58 * pixel in the row that is part of the region. This allows for simple 59 * processing loops of the form: 60 * 61 \code 62 63 it.GoToBegin(); 64 for (; !it.IsAtEnd(); ++it) 65 { 66 std::cout << it.Value() << std::endl; 67 } 68 69 \endcode 70 * 71 * \par MORE INFORMATION 72 * For a complete description of the ITK Image Iterators and their API, please 73 * see the Iterators chapter in the ITK Software Guide. The ITK Software Guide 74 * is available in print and as a free .pdf download from https://www.itk.org. 75 * 76 * \ingroup ImageIterators 77 * 78 * \sa ImageConstIterator \sa ConditionalConstIterator 79 * \sa ConstNeighborhoodIterator \sa ConstShapedNeighborhoodIterator 80 * \sa ConstSliceIterator \sa CorrespondenceDataStructureIterator 81 * \sa FloodFilledFunctionConditionalConstIterator 82 * \sa FloodFilledImageFunctionConditionalConstIterator 83 * \sa FloodFilledImageFunctionConditionalIterator 84 * \sa FloodFilledSpatialFunctionConditionalConstIterator 85 * \sa FloodFilledSpatialFunctionConditionalIterator 86 * \sa ImageConstIterator \sa ImageConstIteratorWithIndex 87 * \sa ImageIterator \sa ImageIteratorWithIndex 88 * \sa ImageLinearConstIteratorWithIndex \sa ImageLinearIteratorWithIndex 89 * \sa ImageRandomConstIteratorWithIndex \sa ImageRandomIteratorWithIndex 90 * \sa ImageRegionConstIterator \sa ImageRegionConstIteratorWithIndex 91 * \sa ImageRegionExclusionConstIteratorWithIndex 92 * \sa ImageRegionExclusionIteratorWithIndex 93 * \sa ImageRegionIterator \sa ImageRegionIteratorWithIndex 94 * \sa ImageRegionReverseConstIterator \sa ImageRegionReverseIterator 95 * \sa ImageReverseConstIterator \sa ImageReverseIterator 96 * \sa ImageSliceConstIteratorWithIndex \sa ImageSliceIteratorWithIndex 97 * \sa NeighborhoodIterator \sa PathConstIterator \sa PathIterator 98 * \sa ShapedNeighborhoodIterator \sa SliceIterator 99 * \sa ImageConstIteratorWithIndex 100 * \ingroup ITKCommon 101 */ 102 template< typename TImage > 103 class ITK_TEMPLATE_EXPORT ImageRegionReverseConstIterator:public ImageReverseConstIterator< TImage > 104 { 105 public: 106 /** Standard class type aliases. */ 107 using Self = ImageRegionReverseConstIterator; 108 using Superclass = ImageReverseConstIterator< TImage >; 109 110 /** Index type alias support While this was already typdef'ed in the superclass 111 * it needs to be redone here for this subclass to compile properly with gcc. */ 112 using IndexType = typename Superclass::IndexType; 113 114 /** Size type alias support While this was already typdef'ed in the superclass 115 * it needs to be redone here for this subclass to compile properly with gcc. */ 116 using SizeType = typename Superclass::SizeType; 117 118 /** Offset type alias support While this was already typdef'ed in the superclass 119 * it needs to be redone here for this subclass to compile properly with gcc. */ 120 using OffsetType = typename Superclass::OffsetType; 121 122 /** Region type alias support */ 123 using RegionType = typename Superclass::RegionType; 124 125 /** Image type alias support While this was already typdef'ed in the superclass 126 * it needs to be redone here for this subclass to compile properly with gcc. */ 127 using ImageType = typename Superclass::ImageType; 128 129 /** PixelContainer type alias support Used to refer to the container for 130 * the pixel data. While this was already typdef'ed in the superclass 131 * it needs to be redone here for this subclass to compile properly with gcc. */ 132 using PixelContainer = typename Superclass::PixelContainer; 133 using PixelContainerPointer = typename PixelContainer::Pointer; 134 135 /** Internal Pixel Type */ 136 using InternalPixelType = typename Superclass::InternalPixelType; 137 138 /** External Pixel Type */ 139 using PixelType = typename Superclass::PixelType; 140 141 /** Accessor type that convert data between internal and external 142 * representations. */ 143 using AccessorType = typename Superclass::AccessorType; 144 145 /** Run-time type information (and related methods). */ 146 itkTypeMacro(ImageRegionReverseConstIterator, ImageReverseConstIterator); 147 148 /** Default constructor. Needed since we provide a cast constructor. */ ImageRegionReverseConstIterator()149 ImageRegionReverseConstIterator():Superclass() 150 { 151 m_SpanBeginOffset = 0; 152 m_SpanEndOffset = 0; 153 } 154 155 /** Constructor establishes an iterator to walk a particular image and a 156 * particular region of that image. */ ImageRegionReverseConstIterator(const ImageType * ptr,const RegionType & region)157 ImageRegionReverseConstIterator(const ImageType *ptr, const RegionType & region): 158 Superclass(ptr, region) 159 { 160 m_SpanBeginOffset = this->m_BeginOffset; 161 m_SpanEndOffset = this->m_BeginOffset - static_cast< OffsetValueType >( this->m_Region.GetSize()[0] ); 162 } 163 164 /** Constructor that can be used to cast from an ImageIterator to an 165 * ImageRegionReverseConstIterator. Many routines return an ImageIterator 166 * but for a particular task, you may want an 167 * ImageRegionReverseConstIterator. Rather than provide overloaded APIs 168 * that return different types of Iterators, itk returns 169 * ImageIterators and uses constructors to cast from an 170 * ImageIterator to a ImageRegionReverseConstIterator. */ ImageRegionReverseConstIterator(const ImageConstIterator<TImage> & it)171 ImageRegionReverseConstIterator(const ImageConstIterator< TImage > & it):Superclass(it) 172 { 173 IndexType ind = this->GetIndex(); 174 175 m_SpanBeginOffset = this->m_Offset + static_cast< OffsetValueType >( this->m_Region.GetSize()[0] ) 176 - ( ind[0] - this->m_Region.GetIndex()[0] ); 177 m_SpanEndOffset = m_SpanBeginOffset - static_cast< OffsetValueType >( this->m_Region.GetSize()[0] ); 178 } 179 180 /** Constructor that takes in a reverse image iterator. This can be used 181 * to cast between the various types of reverse image iterators. */ ImageRegionReverseConstIterator(const ImageReverseConstIterator<TImage> & it)182 ImageRegionReverseConstIterator(const ImageReverseConstIterator< TImage > & it):Superclass(it) 183 { 184 IndexType ind = this->GetIndex(); 185 186 m_SpanBeginOffset = this->m_Offset + static_cast< OffsetValueType >( this->m_Region.GetSize()[0] ) 187 - ( ind[0] - this->m_Region.GetIndex()[0] ); 188 m_SpanEndOffset = m_SpanBeginOffset - static_cast< OffsetValueType >( this->m_Region.GetSize()[0] ); 189 } 190 191 /** Constructor that takes in an image region iterator. This can be used 192 * to cast between the various types of reverse image iterators. */ ImageRegionReverseConstIterator(const ImageRegionIterator<TImage> & it)193 ImageRegionReverseConstIterator(const ImageRegionIterator< TImage > & it):Superclass(it) 194 { 195 IndexType ind = this->GetIndex(); 196 197 m_SpanBeginOffset = this->m_Offset + static_cast< OffsetValueType >( this->m_Region.GetSize()[0] ) 198 - ( ind[0] - this->m_Region.GetIndex()[0] ); 199 m_SpanEndOffset = m_SpanBeginOffset - static_cast< OffsetValueType >( this->m_Region.GetSize()[0] ); 200 } 201 202 /** Move an iterator to the beginning of the region. "Begin" for a reverse 203 * iterator is the last pixel in the region. */ GoToBegin()204 void GoToBegin() 205 { 206 Superclass::GoToBegin(); 207 208 // reset the span offsets 209 m_SpanBeginOffset = this->m_BeginOffset; 210 m_SpanEndOffset = this->m_BeginOffset - static_cast< OffsetValueType >( this->m_Region.GetSize()[0] ); 211 } 212 213 /** Move an iterator to the end of the region. "End" for a reverse iterator 214 * is defined as one pixel before the first pixel in the region. */ GoToEnd()215 void GoToEnd() 216 { 217 Superclass::GoToEnd(); 218 219 // reset the span offsets 220 m_SpanEndOffset = this->m_EndOffset; 221 m_SpanBeginOffset = m_SpanEndOffset + static_cast< OffsetValueType >( this->m_Region.GetSize()[0] ); 222 } 223 224 /** Set the index. No bounds checking is performed. This is overridden 225 * from the parent because we have an extra ivar. 226 * \sa GetIndex */ SetIndex(const IndexType & ind)227 void SetIndex(const IndexType & ind) override 228 { 229 Superclass::SetIndex(ind); 230 m_SpanBeginOffset = this->m_Offset + static_cast< OffsetValueType >( this->m_Region.GetSize()[0] ) 231 - ( ind[0] - this->m_Region.GetIndex()[0] ); 232 m_SpanEndOffset = m_SpanBeginOffset - static_cast< OffsetValueType >( this->m_Region.GetSize()[0] ); 233 } 234 235 /** iterator's index. For a reverse iterator, this moves backwards 236 * through the region. This operator will constrain the iterator 237 * within the region (i.e. the iterator will automatically wrap from 238 * the start of the row of the region to the end of the previous row 239 * of the region) up until the iterator tries to moves before the 240 * first pixel of the region. Here, the iterator will be set to be 241 * one pixel before the start of the region. 242 * \sa operator++(int). */ 243 Self & 244 operator++() 245 { 246 if ( --this->m_Offset <= m_SpanEndOffset ) 247 { 248 // We have past the beginning of the span (row), need to wrap around. 249 250 // First move forward one pixel, because we are going to use a different 251 // algorithm to compute the next pixel 252 this->m_Offset++; 253 254 // Get the index of the first pixel on the span (row) 255 typename ImageConstIterator< TImage >::IndexType 256 ind = this->m_Image->ComputeIndex( static_cast< OffsetValueType >( this->m_Offset ) ); 257 258 const typename ImageConstIterator< TImage >::IndexType & 259 startIndex = this->m_Region.GetIndex(); 260 const typename ImageConstIterator< TImage >::SizeType & 261 size = this->m_Region.GetSize(); 262 263 // Deccrement along a row, then wrap at the beginning of the region row. 264 bool done; 265 unsigned int dim; 266 267 // Check to see if we are past the first pixel in the region 268 // Note that --ind[0] moves to the previous pixel along the row. 269 done = ( --ind[0] == startIndex[0] - 1 ); 270 for ( unsigned int i = 1; done && i < this->ImageIteratorDimension; i++ ) 271 { 272 done = ( ind[i] == startIndex[i] ); 273 } 274 275 // if the iterator is outside the region (but not past region begin) then 276 // we need to wrap around the region 277 dim = 0; 278 if ( !done ) 279 { 280 while ( ( dim < this->ImageIteratorDimension - 1 ) 281 && ( ind[dim] < startIndex[dim] ) ) 282 { 283 ind[dim] = startIndex[dim] + static_cast< OffsetValueType >( size[dim] ) - 1; 284 ind[++dim]--; 285 } 286 } 287 this->m_Offset = this->m_Image->ComputeOffset(ind); 288 m_SpanBeginOffset = this->m_Offset; 289 m_SpanEndOffset = m_SpanBeginOffset - static_cast< OffsetValueType >( size[0] ); 290 } 291 return *this; 292 } 293 294 /** Decrement (prefix) the fastest moving dimension of the iterator's index. 295 * For a reverse iterator, this moves forward through the region. 296 * This operator will constrain the iterator within the region (i.e. the 297 * iterator will automatically wrap from the end of the row of the region 298 * to the start of the next row of the region) up until the iterator 299 * tries to moves past the last pixel of the region. Here, the iterator 300 * will be set to be one pixel past the end of the region. 301 * \sa operator--(int) */ 302 Self & operator--() 303 { 304 if ( ++this->m_Offset >= m_SpanBeginOffset ) 305 { 306 // We have reached the end of the span (row), need to wrap around. 307 308 // First back up one pixel, because we are going to use a different 309 // algorithm to compute the next pixel 310 --this->m_Offset; 311 312 // Get the index of the last pixel on the span (row) 313 typename ImageConstIterator< TImage >::IndexType 314 ind = this->m_Image->ComputeIndex( static_cast< OffsetValueType >( this->m_Offset ) ); 315 316 const typename ImageIterator< TImage >::IndexType & 317 startIndex = this->m_Region.GetIndex(); 318 const typename ImageIterator< TImage >::SizeType & 319 size = this->m_Region.GetSize(); 320 321 // Increment along a row, then wrap at the end of the region row. 322 bool done; 323 unsigned int dim; 324 325 // Check to see if we are past the last pixel in the region 326 // Note that ++ind[0] moves to the next pixel along the row. 327 done = ( ++ind[0] == startIndex[0] + static_cast< OffsetValueType >( size[0] ) ); 328 for ( unsigned int i = 1; done && i < this->ImageIteratorDimension; i++ ) 329 { 330 done = ( ind[i] == startIndex[i] + static_cast< OffsetValueType >( size[i] ) - 1 ); 331 } 332 333 // if the iterator is outside the region (but not past region end) then 334 // we need to wrap around the region 335 dim = 0; 336 if ( !done ) 337 { 338 while ( ( dim < this->ImageIteratorDimension - 1 ) 339 && ( ind[dim] > startIndex[dim] + static_cast< OffsetValueType >( size[dim] ) - 1 ) ) 340 { 341 ind[dim] = startIndex[dim]; 342 ind[++dim]++; 343 } 344 } 345 this->m_Offset = this->m_Image->ComputeOffset(ind); 346 m_SpanBeginOffset = this->m_Offset; 347 m_SpanEndOffset = this->m_Offset - static_cast< OffsetValueType >( size[0] ); 348 } 349 return *this; 350 } 351 352 protected: 353 SizeValueType m_SpanBeginOffset; // offset to last pixel in the row 354 SizeValueType m_SpanEndOffset; // offset to one pixel before the row 355 }; 356 } // end namespace itk 357 358 #endif 359