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