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