]> Creatis software - clitk.git/blob - segmentation/clitkExtractImageFilter.txx
020cbb1bd6abc10385ab49f602defe1f952e7f02
[clitk.git] / segmentation / clitkExtractImageFilter.txx
1
2 #ifndef _clitkExtractImageFilter_txx
3 #define _clitkExtractImageFilter_txx
4
5 #include "clitkExtractImageFilter.h"
6 #include "itkImageRegionIterator.h"
7 #include "itkImageRegionConstIterator.h"
8 #include "itkObjectFactory.h"
9 #include "itkExtractImageFilterRegionCopier.h"
10 #include "itkProgressReporter.h"
11
12
13 namespace clitk
14 {
15
16 /**
17  *
18  */
19 template <class TInputImage, class TOutputImage>
20 ExtractImageFilter<TInputImage,TOutputImage>
21 ::ExtractImageFilter() 
22 {
23 }
24
25
26 /**
27  *
28  */
29 template <class TInputImage, class TOutputImage>
30 void 
31 ExtractImageFilter<TInputImage,TOutputImage>
32 ::PrintSelf(std::ostream& os, itk::Indent indent) const
33 {
34   Superclass::PrintSelf(os,indent);
35
36   os << indent << "ExtractionRegion: " << m_ExtractionRegion << std::endl;
37   os << indent << "OutputImageRegion: " << m_OutputImageRegion << std::endl;
38 }
39
40
41 template<class TInputImage, class TOutputImage>
42 void 
43 ExtractImageFilter<TInputImage,TOutputImage>
44 ::CallCopyOutputRegionToInputRegion(InputImageRegionType &destRegion,
45                                     const OutputImageRegionType &srcRegion)
46 {
47   ExtractImageFilterRegionCopierType extractImageRegionCopier;
48   extractImageRegionCopier(destRegion, srcRegion, m_ExtractionRegion);
49 }
50
51
52 template <class TInputImage, class TOutputImage>
53 void 
54 ExtractImageFilter<TInputImage,TOutputImage>
55 ::SetExtractionRegion(InputImageRegionType extractRegion)
56 {
57   m_ExtractionRegion = extractRegion;
58
59   unsigned int nonzeroSizeCount = 0;
60   InputImageSizeType inputSize = extractRegion.GetSize();
61   OutputImageSizeType outputSize;
62   OutputImageIndexType outputIndex;
63
64   /**
65    * check to see if the number of non-zero entries in the extraction region
66    * matches the number of dimensions in the output image.  
67    **/
68   for (unsigned int i = 0; i < InputImageDimension; ++i)
69     {
70     if (inputSize[i])
71       { 
72       outputSize[nonzeroSizeCount] = inputSize[i];    
73       outputIndex[nonzeroSizeCount] = extractRegion.GetIndex()[i];
74       nonzeroSizeCount++;
75       }
76     }
77     
78   if (nonzeroSizeCount != OutputImageDimension)
79     {
80     itkExceptionMacro("Extraction Region not consistent with output image");
81     }
82
83   m_OutputImageRegion.SetSize(outputSize);
84   m_OutputImageRegion.SetIndex(outputIndex);
85   this->Modified();
86 }
87
88
89
90 /** 
91  * ExtractImageFilter can produce an image which is a different resolution
92  * than its input image.  As such, ExtractImageFilter needs to provide an
93  * implementation for GenerateOutputInformation() in order to inform
94  * the pipeline execution model.  The original documentation of this
95  * method is below.
96  *
97  * \sa ProcessObject::GenerateOutputInformaton() 
98  */
99 template <class TInputImage, class TOutputImage>
100 void 
101 ExtractImageFilter<TInputImage,TOutputImage>
102 ::GenerateOutputInformation()
103 {
104   // do not call the superclass' implementation of this method since
105   // this filter allows the input and the output to be of different dimensions
106  
107   // get pointers to the input and output
108   typename Superclass::OutputImagePointer      outputPtr = this->GetOutput();
109   typename Superclass::InputImageConstPointer  inputPtr  = this->GetInput();
110
111   if ( !outputPtr || !inputPtr)
112     {
113     return;
114     }
115
116   // Set the output image size to the same value as the extraction region.
117   outputPtr->SetLargestPossibleRegion( m_OutputImageRegion );
118
119   // Set the output spacing and origin
120   const itk::ImageBase<InputImageDimension> *phyData;
121
122   phyData
123     = dynamic_cast<const itk::ImageBase<InputImageDimension>*>(this->GetInput());
124
125   if (phyData)
126     {
127     // Copy what we can from the image from spacing and origin of the input
128     // This logic needs to be augmented with logic that select which
129     // dimensions to copy
130
131     unsigned int i;
132     const typename InputImageType::SpacingType& 
133       inputSpacing = inputPtr->GetSpacing();
134     const typename InputImageType::DirectionType&
135       inputDirection = inputPtr->GetDirection();
136     const typename InputImageType::PointType&
137       inputOrigin = inputPtr->GetOrigin();
138
139     typename OutputImageType::SpacingType outputSpacing;
140     typename OutputImageType::DirectionType outputDirection;
141     typename OutputImageType::PointType outputOrigin;
142
143     if ( static_cast<unsigned int>(OutputImageDimension) > 
144          static_cast<unsigned int>(InputImageDimension )    )
145       {
146       // copy the input to the output and fill the rest of the
147       // output with zeros.
148       for (i=0; i < InputImageDimension; ++i)
149         {
150         outputSpacing[i] = inputSpacing[i];
151         outputOrigin[i] = inputOrigin[i];
152         for (unsigned int dim = 0; dim < InputImageDimension; ++dim)
153           {
154           outputDirection[i][dim] = inputDirection[i][dim];
155           }
156         }
157       for (; i < OutputImageDimension; ++i)
158         {
159         outputSpacing[i] = 1.0;
160         outputOrigin[i] = 0.0;
161         for (unsigned int dim = 0; dim < InputImageDimension; ++dim)
162           {
163           outputDirection[i][dim] = 0.0;
164           }
165         outputDirection[i][i] = 1.0;
166         }
167       }
168     else
169       {
170       // copy the non-collapsed part of the input spacing and origing to the output
171       int nonZeroCount = 0;
172       for (i=0; i < InputImageDimension; ++i)
173         {
174         if (m_ExtractionRegion.GetSize()[i])
175           {
176           outputSpacing[nonZeroCount] = inputSpacing[i];
177           outputOrigin[nonZeroCount] = inputOrigin[i];
178           int nonZeroCount2 = 0;
179           for (unsigned int dim = 0; dim < InputImageDimension; ++dim)
180             {
181             if (m_ExtractionRegion.GetSize()[dim])
182               {
183               outputDirection[nonZeroCount][nonZeroCount2] =
184                 inputDirection[i][dim];
185               ++nonZeroCount2;
186               }
187             }
188           nonZeroCount++;
189           }
190         }
191       }
192
193     // set the spacing and origin
194     outputPtr->SetSpacing( outputSpacing );
195     outputPtr->SetDirection( outputDirection );
196     outputPtr->SetOrigin( outputOrigin );
197     outputPtr->SetNumberOfComponentsPerPixel(inputPtr->GetNumberOfComponentsPerPixel() );
198     }
199   else
200     {
201     // pointer could not be cast back down
202     itkExceptionMacro(<< "itk::ExtractImageFilter::GenerateOutputInformation "
203                       << "cannot cast input to "
204                       << typeid(itk::ImageBase<InputImageDimension>*).name() );
205     }
206 }
207
208 /** 
209    * ExtractImageFilter can be implemented as a multithreaded filter.
210    * Therefore, this implementation provides a ThreadedGenerateData()
211    * routine which is called for each processing thread. The output
212    * image data is allocated automatically by the superclass prior to
213    * calling ThreadedGenerateData().  ThreadedGenerateData can only
214    * write to the portion of the output image specified by the
215    * parameter "outputRegionForThread"
216    *
217    * \sa ImageToImageFilter::ThreadedGenerateData(),
218    *     ImageToImageFilter::GenerateData() 
219    */
220 template <class TInputImage, class TOutputImage>
221 void 
222 ExtractImageFilter<TInputImage,TOutputImage>
223 ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
224                        int threadId)
225 {
226   itkDebugMacro(<<"Actually executing");
227
228   // Get the input and output pointers
229   typename Superclass::InputImageConstPointer  inputPtr = this->GetInput();
230   typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
231
232   // support progress methods/callbacks
233  itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
234   
235   // Define the portion of the input to walk for this thread
236   InputImageRegionType inputRegionForThread;
237   this->CallCopyOutputRegionToInputRegion(inputRegionForThread, outputRegionForThread);
238   
239   // Define the iterators.
240   typedef itk::ImageRegionIterator<TOutputImage> OutputIterator;
241   typedef itk::ImageRegionConstIterator<TInputImage> InputIterator;
242
243   OutputIterator outIt(outputPtr, outputRegionForThread);
244   InputIterator inIt(inputPtr, inputRegionForThread);
245
246   // walk the output region, and sample the input image
247   while( !outIt.IsAtEnd() )
248     {
249     // copy the input pixel to the output
250     outIt.Set( static_cast<OutputImagePixelType>(inIt.Get()));
251     ++outIt; 
252     ++inIt; 
253     progress.CompletedPixel();
254     }
255 }
256
257 } // end namespace clitk
258
259 #endif