2 #ifndef _clitkExtractImageFilter_txx
3 #define _clitkExtractImageFilter_txx
5 #include "clitkExtractImageFilter.h"
6 #include "itkImageRegionIterator.h"
7 #include "itkImageRegionConstIterator.h"
8 #include "itkObjectFactory.h"
9 #include "itkExtractImageFilterRegionCopier.h"
10 #include "itkProgressReporter.h"
19 template <class TInputImage, class TOutputImage>
20 ExtractImageFilter<TInputImage,TOutputImage>
21 ::ExtractImageFilter()
29 template <class TInputImage, class TOutputImage>
31 ExtractImageFilter<TInputImage,TOutputImage>
32 ::PrintSelf(std::ostream& os, itk::Indent indent) const
34 Superclass::PrintSelf(os,indent);
36 os << indent << "ExtractionRegion: " << m_ExtractionRegion << std::endl;
37 os << indent << "OutputImageRegion: " << m_OutputImageRegion << std::endl;
41 template<class TInputImage, class TOutputImage>
43 ExtractImageFilter<TInputImage,TOutputImage>
44 ::CallCopyOutputRegionToInputRegion(InputImageRegionType &destRegion,
45 const OutputImageRegionType &srcRegion)
47 ExtractImageFilterRegionCopierType extractImageRegionCopier;
48 extractImageRegionCopier(destRegion, srcRegion, m_ExtractionRegion);
52 template <class TInputImage, class TOutputImage>
54 ExtractImageFilter<TInputImage,TOutputImage>
55 ::SetExtractionRegion(InputImageRegionType extractRegion)
57 m_ExtractionRegion = extractRegion;
59 unsigned int nonzeroSizeCount = 0;
60 InputImageSizeType inputSize = extractRegion.GetSize();
61 OutputImageSizeType outputSize;
62 OutputImageIndexType outputIndex;
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.
68 for (unsigned int i = 0; i < InputImageDimension; ++i)
72 outputSize[nonzeroSizeCount] = inputSize[i];
73 outputIndex[nonzeroSizeCount] = extractRegion.GetIndex()[i];
78 if (nonzeroSizeCount != OutputImageDimension)
80 itkExceptionMacro("Extraction Region not consistent with output image");
83 m_OutputImageRegion.SetSize(outputSize);
84 m_OutputImageRegion.SetIndex(outputIndex);
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
97 * \sa ProcessObject::GenerateOutputInformaton()
99 template <class TInputImage, class TOutputImage>
101 ExtractImageFilter<TInputImage,TOutputImage>
102 ::GenerateOutputInformation()
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
107 // get pointers to the input and output
108 typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
109 typename Superclass::InputImageConstPointer inputPtr = this->GetInput();
111 if ( !outputPtr || !inputPtr)
116 // Set the output image size to the same value as the extraction region.
117 outputPtr->SetLargestPossibleRegion( m_OutputImageRegion );
119 // Set the output spacing and origin
120 const itk::ImageBase<InputImageDimension> *phyData;
123 = dynamic_cast<const itk::ImageBase<InputImageDimension>*>(this->GetInput());
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
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();
139 typename OutputImageType::SpacingType outputSpacing;
140 typename OutputImageType::DirectionType outputDirection;
141 typename OutputImageType::PointType outputOrigin;
143 if ( static_cast<unsigned int>(OutputImageDimension) >
144 static_cast<unsigned int>(InputImageDimension ) )
146 // copy the input to the output and fill the rest of the
147 // output with zeros.
148 for (i=0; i < InputImageDimension; ++i)
150 outputSpacing[i] = inputSpacing[i];
151 outputOrigin[i] = inputOrigin[i];
152 for (unsigned int dim = 0; dim < InputImageDimension; ++dim)
154 outputDirection[i][dim] = inputDirection[i][dim];
157 for (; i < OutputImageDimension; ++i)
159 outputSpacing[i] = 1.0;
160 outputOrigin[i] = 0.0;
161 for (unsigned int dim = 0; dim < InputImageDimension; ++dim)
163 outputDirection[i][dim] = 0.0;
165 outputDirection[i][i] = 1.0;
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)
174 if (m_ExtractionRegion.GetSize()[i])
176 outputSpacing[nonZeroCount] = inputSpacing[i];
177 outputOrigin[nonZeroCount] = inputOrigin[i];
178 int nonZeroCount2 = 0;
179 for (unsigned int dim = 0; dim < InputImageDimension; ++dim)
181 if (m_ExtractionRegion.GetSize()[dim])
183 outputDirection[nonZeroCount][nonZeroCount2] =
184 inputDirection[i][dim];
193 // set the spacing and origin
194 outputPtr->SetSpacing( outputSpacing );
195 outputPtr->SetDirection( outputDirection );
196 outputPtr->SetOrigin( outputOrigin );
197 outputPtr->SetNumberOfComponentsPerPixel(inputPtr->GetNumberOfComponentsPerPixel() );
201 // pointer could not be cast back down
202 itkExceptionMacro(<< "itk::ExtractImageFilter::GenerateOutputInformation "
203 << "cannot cast input to "
204 << typeid(itk::ImageBase<InputImageDimension>*).name() );
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"
217 * \sa ImageToImageFilter::ThreadedGenerateData(),
218 * ImageToImageFilter::GenerateData()
220 template <class TInputImage, class TOutputImage>
222 ExtractImageFilter<TInputImage,TOutputImage>
223 ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
226 itkDebugMacro(<<"Actually executing");
228 // Get the input and output pointers
229 typename Superclass::InputImageConstPointer inputPtr = this->GetInput();
230 typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
232 // support progress methods/callbacks
233 itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
235 // Define the portion of the input to walk for this thread
236 InputImageRegionType inputRegionForThread;
237 this->CallCopyOutputRegionToInputRegion(inputRegionForThread, outputRegionForThread);
239 // Define the iterators.
240 typedef itk::ImageRegionIterator<TOutputImage> OutputIterator;
241 typedef itk::ImageRegionConstIterator<TInputImage> InputIterator;
243 OutputIterator outIt(outputPtr, outputRegionForThread);
244 InputIterator inIt(inputPtr, inputRegionForThread);
246 // walk the output region, and sample the input image
247 while( !outIt.IsAtEnd() )
249 // copy the input pixel to the output
250 outIt.Set( static_cast<OutputImagePixelType>(inIt.Get()));
253 progress.CompletedPixel();
257 } // end namespace clitk