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 /*=========================================================================
19  *
20  *  Portions of this file are subject to the VTK Toolkit Version 3 copyright.
21  *
22  *  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
23  *
24  *  For complete copyright, license and disclaimer of warranty information
25  *  please refer to the NOTICE file at the top of the ITK source tree.
26  *
27  *=========================================================================*/
28 #ifndef itkImageRegion_hxx
29 #define itkImageRegion_hxx
30 
31 #include "itkImageRegion.h"
32 
33 namespace itk
34 {
35 template< unsigned int VImageDimension >
36 typename ImageRegion< VImageDimension >::IndexType
37 ImageRegion< VImageDimension >
GetUpperIndex() const38 ::GetUpperIndex() const
39 {
40   IndexType idx;
41   for ( unsigned int i = 0; i < VImageDimension; i++ )
42     {
43     idx[i] = m_Index[i] + m_Size[i] - 1;
44     }
45 
46   return idx;
47 }
48 
49 template< unsigned int VImageDimension >
50 void
51 ImageRegion< VImageDimension >
SetUpperIndex(const IndexType & idx)52 ::SetUpperIndex( const IndexType & idx )
53 {
54   for ( unsigned int i = 0; i < VImageDimension; i++ )
55     {
56     m_Size[i] = idx[i] - m_Index[i] + 1;
57     }
58 }
59 
60 template< unsigned int VImageDimension >
61 void
62 ImageRegion< VImageDimension >
ComputeOffsetTable(OffsetTableType offsetTable) const63 ::ComputeOffsetTable(OffsetTableType offsetTable) const
64 {
65   OffsetValueType num=1;
66 
67   offsetTable[0] = num;
68   for (unsigned int i=0; i < ImageDimension; i++)
69     {
70     num *= m_Size[i];
71     offsetTable[i+1] = num;
72     }
73 }
74 
75 template< unsigned int VImageDimension >
76 typename ImageRegion< VImageDimension >::SizeValueType
77 ImageRegion< VImageDimension >
GetNumberOfPixels() const78 ::GetNumberOfPixels() const
79 {
80   SizeValueType numPixels = 1;
81 
82   for ( unsigned int i = 0; i < VImageDimension; i++ )
83     {
84     numPixels *= m_Size[i];
85     }
86 
87   return numPixels;
88 }
89 
90 template< unsigned int VImageDimension >
91 void
92 ImageRegion< VImageDimension >
PrintSelf(std::ostream & os,Indent indent) const93 ::PrintSelf(std::ostream & os, Indent indent) const
94 {
95   Superclass::PrintSelf(os, indent);
96 
97   os << indent << "Dimension: " << this->GetImageDimension() << std::endl;
98   os << indent << "Index: " << this->GetIndex() << std::endl;
99   os << indent << "Size: " << this->GetSize() << std::endl;
100 }
101 
102 template< unsigned int VImageDimension >
103 void
104 ImageRegion< VImageDimension >
PadByRadius(OffsetValueType radius)105 ::PadByRadius(OffsetValueType radius)
106 {
107   SizeType radiusVector;
108 
109   for ( unsigned int i = 0; i < VImageDimension; ++i )
110     {
111     radiusVector[i] = radius;
112     }
113 
114   this->PadByRadius(radiusVector);
115 }
116 
117 template< unsigned int VImageDimension >
118 void
119 ImageRegion< VImageDimension >
PadByRadius(const SizeType & radius)120 ::PadByRadius(const SizeType & radius)
121 {
122   for ( unsigned int i = 0; i < VImageDimension; i++ )
123     {
124     m_Size[i] += 2 * radius[i];
125     m_Index[i] -= static_cast< OffsetValueType >( radius[i] );
126     }
127 }
128 
129 template< unsigned int VImageDimension >
130 void
131 ImageRegion< VImageDimension >
PadByRadius(const IndexValueArrayType radius)132 ::PadByRadius(const IndexValueArrayType radius)
133 {
134   for ( unsigned int i = 0; i < VImageDimension; i++ )
135     {
136     m_Size[i] += 2 * radius[i];
137     m_Index[i] -= static_cast< OffsetValueType >( radius[i] );
138     }
139 }
140 
141 template< unsigned int VImageDimension >
142 bool
143 ImageRegion< VImageDimension >
ShrinkByRadius(OffsetValueType radius)144 ::ShrinkByRadius(OffsetValueType radius)
145 {
146   SizeType radiusVector;
147 
148   for ( unsigned int i = 0; i < VImageDimension; ++i )
149     {
150     radiusVector[i] = radius;
151     }
152 
153   return this->ShrinkByRadius(radiusVector);
154 }
155 
156 template< unsigned int VImageDimension >
157 bool
158 ImageRegion< VImageDimension >
ShrinkByRadius(const SizeType & radius)159 ::ShrinkByRadius(const SizeType & radius)
160 {
161   bool shrunkSuccessfully = true;
162   for ( unsigned int i = 0; i < VImageDimension; i++ )
163     {
164     if( m_Size[i] <= 2 * radius[i] )
165       {
166       shrunkSuccessfully = false;
167       }
168     else
169       {
170       m_Size[i] -= 2 * radius[i];
171       m_Index[i] += static_cast< OffsetValueType >( radius[i] );
172       }
173     }
174   return shrunkSuccessfully;
175 }
176 
177 template< unsigned int VImageDimension >
178 bool
179 ImageRegion< VImageDimension >
ShrinkByRadius(const IndexValueArrayType radius)180 ::ShrinkByRadius(const IndexValueArrayType radius)
181 {
182   bool shrunkSuccessfully = true;
183   for ( unsigned int i = 0; i < VImageDimension; i++ )
184     {
185     if( static_cast< IndexValueType >( m_Size[i] ) <= 2 * radius[i] )
186       {
187       shrunkSuccessfully = false;
188       }
189     else
190       {
191       m_Size[i] -= 2 * radius[i];
192       m_Index[i] += static_cast< OffsetValueType >( radius[i] );
193       }
194     }
195   return shrunkSuccessfully;
196 }
197 
198 template< unsigned int VImageDimension >
199 bool
200 ImageRegion< VImageDimension >
Crop(const Self & region)201 ::Crop(const Self & region)
202 {
203   OffsetValueType crop;
204   unsigned int    i;
205   bool            cropPossible = true;
206 
207   // Can we crop?
208   for ( i = 0; i < VImageDimension && cropPossible; i++ )
209     {
210     // Is left edge of current region to the right of the right edge
211     // of the region to crop with? (if so, we cannot crop)
212     if ( m_Index[i] >= region.GetIndex()[i]
213          + static_cast< OffsetValueType >( region.GetSize()[i] ) )
214       {
215       cropPossible = false;
216       }
217     // If right edge of the current region to the left of the left
218     // edge of the region to crop with? (if so, we cannot crop)
219     if ( m_Index[i] + static_cast< OffsetValueType >( m_Size[i] ) <= region.GetIndex()[i] )
220       {
221       cropPossible = false;
222       }
223     }
224 
225   // if we cannot crop, return without changing anythin
226   if ( !cropPossible )
227     {
228     return cropPossible;
229     }
230 
231   // we can crop, so crop
232   for ( i = 0; i < VImageDimension; i++ )
233     {
234     // first check the start index
235     if ( m_Index[i] < region.GetIndex()[i] )
236       {
237       // how much do we need to adjust
238       crop = region.GetIndex()[i] - m_Index[i];
239 
240       // adjust the start index and the size of the current region
241       m_Index[i] += crop;
242       m_Size[i] -= static_cast< SizeValueType >( crop );
243       }
244     // now check the final size
245     if ( m_Index[i] + static_cast< OffsetValueType >( m_Size[i] )
246          > region.GetIndex()[i] + static_cast< OffsetValueType >( region.GetSize()[i] ) )
247       {
248       // how much do we need to adjust
249       crop = m_Index[i] + static_cast< OffsetValueType >( m_Size[i] )
250              - region.GetIndex()[i] - static_cast< OffsetValueType >( region.GetSize()[i] );
251 
252       // adjust the size
253       m_Size[i] -= static_cast< SizeValueType >( crop );
254       }
255     }
256 
257   return cropPossible;
258 }
259 
260 template< unsigned int VImageDimension >
261 typename ImageRegion< VImageDimension >::SliceRegion
262 ImageRegion< VImageDimension >
Slice(const unsigned int dim) const263 ::Slice(const unsigned int dim) const
264 {
265   if ( dim >= VImageDimension )
266     {
267     itkGenericExceptionMacro(
268       << "The dimension to remove: " << dim
269       << " is greater than the dimension of the image: " << VImageDimension);
270     }
271 
272   Index< SliceDimension > sliceIndex;
273   Size< SliceDimension >  sliceSize;
274 
275   sliceIndex.Fill(0);
276   sliceSize.Fill(0);
277   unsigned int ii = 0;
278   for ( unsigned int i = 0; i < VImageDimension; i++ )
279     {
280     if ( i != dim )
281       {
282       sliceIndex[ii] = m_Index[i];
283       sliceSize[ii] = m_Size[i];
284       ++ii;
285       }
286     }
287 
288   return ImageRegion< SliceDimension >(sliceIndex, sliceSize);
289 }
290 
291 template< unsigned int VImageDimension >
operator <<(std::ostream & os,const ImageRegion<VImageDimension> & region)292 std::ostream & operator<<(std::ostream & os, const ImageRegion< VImageDimension > & region)
293 {
294   region.Print(os);
295   return os;
296 }
297 } // end namespace itk
298 
299 #endif
300