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 itkImageRegionSplitterBase_h
19 #define itkImageRegionSplitterBase_h
20 
21 #include "itkImageRegion.h"
22 #include "itkObjectFactory.h"
23 #include "itkImageIORegion.h"
24 
25 namespace itk
26 {
27 
28 /** \class ImageRegionSplitterBase
29  * \brief Divide an image region into several pieces.
30  *
31  * ImageRegionSplitterBase is an abstract interface to divide an
32  * ImageRegion into smaller regions. ImageRegionSplitterBase is used
33  * by the ImageSource,  StreamingImageFilter, streaming ImageIO
34  * classes to divide a region into a series of smaller subregions.
35  *
36  * This object has two basic methods: \c GetNumberOfSplits() and
37  * \c GetSplit().
38  *
39  * \c GetNumberOfSplits() is used to determine how may subregions a given
40  * region can be divided.  You call GetNumberOfSplits with an argument
41  * that is the number of subregions you want.  If the image region can
42  * support that number of subregions, that number is returned.
43  * Otherwise, the maximum number of splits less then or equal to the
44  * argumen  be returned.  For example, if a region splitter class only divides
45  * a region into horizontal slabs, then the maximum number of splits
46  * will be the number of rows in the region.
47  *
48  * \c GetSplit() returns the ith of N subregions (as an ImageRegion object).
49  *
50  * \sa ImageRegionSplitterDirection
51  * \sa ImageRegionSplitterSlowDimension
52  *
53  * \ingroup ITKSystemObjects
54  * \ingroup DataProcessing
55  * \ingroup ITKCommon
56  */
57 
58 class ITKCommon_EXPORT ImageRegionSplitterBase
59   :public Object
60 {
61 public:
62   ITK_DISALLOW_COPY_AND_ASSIGN(ImageRegionSplitterBase);
63 
64   /** Standard class type aliases. */
65   using Self = ImageRegionSplitterBase;
66   using Superclass = Object;
67   using Pointer = SmartPointer< Self >;
68   using ConstPointer = SmartPointer< const Self >;
69 
70   /** Run-time type information (and related methods). */
71   itkTypeMacro(ImageRegionSplitterBase, Object);
72 
73   /** How many pieces can the specified region be split? A given region
74    * cannot always be divided into the requested number of pieces. For
75    * instance, if the \c numberOfPieces exceeds the number of pixels along
76    * a certain dimensions, then some splits will not be possible. This
77    * method returns a number less than or equal to the requested number
78    * of pieces. */
79   template <unsigned int VImageDimension>
GetNumberOfSplits(const ImageRegion<VImageDimension> & region,unsigned int requestedNumber)80     unsigned int GetNumberOfSplits(const ImageRegion<VImageDimension> & region,
81                                    unsigned int requestedNumber) const
82   {
83     return this->GetNumberOfSplitsInternal( VImageDimension,
84                                             region.GetIndex().m_InternalArray,
85                                             region.GetSize().m_InternalArray,
86                                             requestedNumber);
87   }
GetNumberOfSplits(const ImageIORegion & region,unsigned int requestedNumber)88   inline unsigned int GetNumberOfSplits(const ImageIORegion &region,
89                                         unsigned int requestedNumber) const
90   {
91     return this->GetNumberOfSplitsInternal( region.GetImageDimension(),
92                                             &region.GetIndex()[0],
93                                             &region.GetSize()[0],
94                                             requestedNumber);
95   }
96 
97 
98   /** \brief Get a region definition that represents the ith piece a
99    * specified region.
100    *
101    * The \c numberOfPieces must be equal to what \c GetNumberOfSplits()
102    * returns. The return value is the maximum number of splits
103    * available. If \c i is greater than or equal to the return value
104    * the value of the region is undefined.
105    */
106   template <unsigned int VImageDimension>
GetSplit(unsigned int i,unsigned int numberOfPieces,ImageRegion<VImageDimension> & region)107     unsigned int GetSplit( unsigned int i,
108                            unsigned int numberOfPieces,
109                            ImageRegion<VImageDimension> & region ) const
110   {
111     return this->GetSplitInternal( VImageDimension,
112                                    i,
113                                    numberOfPieces,
114                                    region.GetModifiableIndex().m_InternalArray,
115                                    region.GetModifiableSize().m_InternalArray );
116   }
GetSplit(unsigned int i,unsigned int numberOfPieces,ImageIORegion & region)117   unsigned int GetSplit( unsigned int i,
118                          unsigned int numberOfPieces,
119                          ImageIORegion & region ) const
120   {
121     return this->GetSplitInternal( region.GetImageDimension(),
122                                    i,
123                                    numberOfPieces,
124                                    &region.GetModifiableIndex()[0],
125                                    &region.GetModifiableSize()[0] );
126   }
127 
128 protected:
129   ImageRegionSplitterBase();
130 
131   /** Templetless method to compute the number of possible splits for
132    *  any number of dimensions. */
133   virtual unsigned int GetNumberOfSplitsInternal( unsigned int dim,
134                                                   const IndexValueType regionIndex[],
135                                                   const SizeValueType regionSize[],
136                                                   unsigned int requestedNumber ) const = 0;
137 
138   /** Templetless method to compute an actual split for any number of
139    * dimensions. \c dim is the size of the \c regionIndex and \c
140    * regionSize arrays.
141    */
142   virtual unsigned int GetSplitInternal( unsigned int dim,
143                                          unsigned int i,
144                                          unsigned int numberOfPieces,
145                                          IndexValueType regionIndex[],
146                                          SizeValueType regionSize[] ) const = 0;
147 
148   void PrintSelf(std::ostream & os, Indent indent) const override;
149 };
150 } // end namespace itk
151 
152 #endif
153