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 itkResampleImageFilter_hxx
19 #define itkResampleImageFilter_hxx
20
21 #include "itkResampleImageFilter.h"
22 #include "itkObjectFactory.h"
23 #include "itkIdentityTransform.h"
24 #include "itkProgressReporter.h"
25 #include "itkImageRegionIteratorWithIndex.h"
26 #include "itkImageScanlineIterator.h"
27 #include "itkSpecialCoordinatesImage.h"
28 #include "itkDefaultConvertPixelTraits.h"
29 #include "itkImageAlgorithm.h"
30
31 #include <type_traits> // For is_same.
32
33 namespace itk
34 {
35
36 template< typename TInputImage,
37 typename TOutputImage,
38 typename TInterpolatorPrecisionType,
39 typename TTransformPrecisionType >
40 ResampleImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType >
ResampleImageFilter()41 ::ResampleImageFilter() :
42 m_Extrapolator( nullptr ),
43 m_OutputSpacing( 1.0 ),
44 m_OutputOrigin( 0.0 )
45
46 {
47
48 m_Size.Fill( 0 );
49 m_OutputStartIndex.Fill( 0 );
50
51 m_OutputDirection.SetIdentity();
52
53 // Pipeline input configuration
54
55 // implicit:
56 // #0 "Primary" required
57
58 // #1 "ReferenceImage" optional
59 Self::AddRequiredInputName("ReferenceImage",1);
60 Self::RemoveRequiredInputName("ReferenceImage");
61
62 // "Transform" required ( not numbered )
63 Self::AddRequiredInputName("Transform");
64 Self::SetTransform(IdentityTransform< TTransformPrecisionType, ImageDimension >::New());
65
66 m_Interpolator = dynamic_cast< InterpolatorType * >
67 ( LinearInterpolatorType::New().GetPointer() );
68
69 m_DefaultPixelValue = NumericTraits<PixelType>::ZeroValue( m_DefaultPixelValue );
70 this->DynamicMultiThreadingOn();
71 }
72
73 template< typename TInputImage,
74 typename TOutputImage,
75 typename TInterpolatorPrecisionType,
76 typename TTransformPrecisionType >
77 void
78 ResampleImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType >
SetOutputSpacing(const double * spacing)79 ::SetOutputSpacing(const double *spacing)
80 {
81 SpacingType s;
82 for(unsigned int i = 0; i < TOutputImage::ImageDimension; ++i)
83 {
84 s[i] = static_cast< typename SpacingType::ValueType >(spacing[i]);
85 }
86 this->SetOutputSpacing(s);
87 }
88
89 template< typename TInputImage,
90 typename TOutputImage,
91 typename TInterpolatorPrecisionType,
92 typename TTransformPrecisionType >
93 void
94 ResampleImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType >
SetOutputOrigin(const double * origin)95 ::SetOutputOrigin(const double *origin)
96 {
97 OriginPointType p(origin);
98
99 this->SetOutputOrigin(p);
100 }
101
102 template< typename TInputImage,
103 typename TOutputImage,
104 typename TInterpolatorPrecisionType,
105 typename TTransformPrecisionType >
106 void
107 ResampleImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType >
SetOutputParametersFromImage(const ImageBaseType * image)108 ::SetOutputParametersFromImage(const ImageBaseType *image)
109 {
110 this->SetOutputOrigin ( image->GetOrigin() );
111 this->SetOutputSpacing ( image->GetSpacing() );
112 this->SetOutputDirection ( image->GetDirection() );
113 this->SetOutputStartIndex ( image->GetLargestPossibleRegion().GetIndex() );
114 this->SetSize ( image->GetLargestPossibleRegion().GetSize() );
115 }
116
117 template< typename TInputImage,
118 typename TOutputImage,
119 typename TInterpolatorPrecisionType,
120 typename TTransformPrecisionType >
121 void
122 ResampleImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType >
BeforeThreadedGenerateData()123 ::BeforeThreadedGenerateData()
124 {
125 m_Interpolator->SetInputImage( this->GetInput() );
126
127 // Connect input image to extrapolator
128 if( !m_Extrapolator.IsNull() )
129 {
130 m_Extrapolator->SetInputImage( this->GetInput() );
131 }
132
133 unsigned int nComponents
134 = DefaultConvertPixelTraits<PixelType>::GetNumberOfComponents(
135 m_DefaultPixelValue );
136
137 if (nComponents == 0)
138 {
139 PixelComponentType zeroComponent
140 = NumericTraits<PixelComponentType>::ZeroValue( zeroComponent );
141 nComponents = this->GetInput()->GetNumberOfComponentsPerPixel();
142 NumericTraits<PixelType>::SetLength(m_DefaultPixelValue, nComponents );
143 for (unsigned int n=0; n<nComponents; n++)
144 {
145 PixelConvertType::SetNthComponent( n, m_DefaultPixelValue,
146 zeroComponent );
147 }
148 }
149 }
150
151 template< typename TInputImage,
152 typename TOutputImage,
153 typename TInterpolatorPrecisionType,
154 typename TTransformPrecisionType >
155 void
156 ResampleImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType >
AfterThreadedGenerateData()157 ::AfterThreadedGenerateData()
158 {
159 // Disconnect input image from the interpolator
160 m_Interpolator->SetInputImage(nullptr);
161 if( !m_Extrapolator.IsNull() )
162 {
163 // Disconnect input image from the extrapolator
164 m_Extrapolator->SetInputImage(nullptr);
165 }
166 }
167
168 template< typename TInputImage,
169 typename TOutputImage,
170 typename TInterpolatorPrecisionType,
171 typename TTransformPrecisionType >
172 void
173 ResampleImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType >
DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread)174 ::DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread)
175 {
176 // Check whether the input or the output is a
177 // SpecialCoordinatesImage. If either are, then we cannot use the
178 // fast path since index mapping will definitely not be linear.
179 using OutputSpecialCoordinatesImageType = SpecialCoordinatesImage< PixelType, ImageDimension >;
180 using InputSpecialCoordinatesImageType = SpecialCoordinatesImage< InputPixelType, InputImageDimension >;
181
182 if( outputRegionForThread.GetNumberOfPixels() == 0 )
183 {
184 return;
185 }
186
187 const bool isSpecialCoordinatesImage = ( dynamic_cast< const InputSpecialCoordinatesImageType * >( this->GetInput() )
188 || dynamic_cast< const OutputSpecialCoordinatesImageType * >( this->GetOutput() ) );
189
190
191 // Check whether we can use a fast path for resampling. Fast path
192 // can be used if the transformation is linear. Transform respond
193 // to the IsLinear() call.
194 if ( !isSpecialCoordinatesImage && this->GetTransform()->GetTransformCategory() == TransformType::Linear )
195 {
196 this->LinearThreadedGenerateData(outputRegionForThread);
197 return;
198 }
199
200 // Otherwise, we use the normal method where the transform is called
201 // for computing the transformation of every point.
202 this->NonlinearThreadedGenerateData(outputRegionForThread);
203 }
204
205
206 #ifndef ITK_LEGACY_REMOVE
207 template< typename TInputImage,
208 typename TOutputImage,
209 typename TInterpolatorPrecisionType,
210 typename TTransformPrecisionType >
211 typename ResampleImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType >
212 ::PixelType
213 ResampleImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType >
CastPixelWithBoundsChecking(const InterpolatorOutputType value,const ComponentType minComponent,const ComponentType maxComponent) const214 ::CastPixelWithBoundsChecking(const InterpolatorOutputType value,
215 const ComponentType minComponent,
216 const ComponentType maxComponent ) const
217 {
218 const unsigned int nComponents = InterpolatorConvertType::GetNumberOfComponents(value);
219 PixelType outputValue;
220
221 NumericTraits<PixelType>::SetLength( outputValue, nComponents );
222
223 for (unsigned int n = 0; n < nComponents; n++)
224 {
225 ComponentType component = InterpolatorConvertType::GetNthComponent( n, value );
226
227 if ( component < minComponent )
228 {
229 PixelConvertType::SetNthComponent( n, outputValue, static_cast<PixelComponentType>( minComponent ) );
230 }
231 else if ( component > maxComponent )
232 {
233 PixelConvertType::SetNthComponent( n, outputValue, static_cast<PixelComponentType>( maxComponent ) );
234 }
235 else
236 {
237 PixelConvertType::SetNthComponent(n, outputValue,
238 static_cast<PixelComponentType>( component ) );
239 }
240 }
241
242 return outputValue;
243 }
244 #endif // ITK_LEGACY_REMOVE
245
246
247 template< typename TInputImage,
248 typename TOutputImage,
249 typename TInterpolatorPrecisionType,
250 typename TTransformPrecisionType >
251 auto ResampleImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType >
CastComponentWithBoundsChecking(const PixelComponentType value)252 ::CastComponentWithBoundsChecking(const PixelComponentType value) -> PixelComponentType
253 {
254 // Just return the argument. In this case, there is no need to cast or clamp its value.
255 return value;
256 }
257
258
259 template< typename TInputImage,
260 typename TOutputImage,
261 typename TInterpolatorPrecisionType,
262 typename TTransformPrecisionType >
263 template <typename TComponent>
264 auto ResampleImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType >
CastComponentWithBoundsChecking(const TComponent value)265 ::CastComponentWithBoundsChecking(const TComponent value) -> PixelComponentType
266 {
267 static_assert(std::is_same<TComponent, ComponentType>::value,
268 "TComponent should just be the same as the ComponentType!");
269 static_assert(!std::is_same<TComponent, PixelComponentType>::value,
270 "For PixelComponentType there is a more appropriate overload, that should be called instead!");
271
272 // Retrieve minimum and maximum values at compile-time:
273 constexpr auto minPixelComponent = NumericTraits< PixelComponentType >::NonpositiveMin();
274 constexpr auto maxPixelComponent = NumericTraits< PixelComponentType >::max();
275 constexpr auto minComponent = static_cast<ComponentType>(minPixelComponent);
276 constexpr auto maxComponent = static_cast<ComponentType>(maxPixelComponent);
277
278 // Clamp the value between minPixelComponent and maxPixelComponent:
279 return (value <= minComponent) ? minPixelComponent :
280 (value >= maxComponent) ? maxPixelComponent : static_cast<PixelComponentType>(value);
281 }
282
283
284 template< typename TInputImage,
285 typename TOutputImage,
286 typename TInterpolatorPrecisionType,
287 typename TTransformPrecisionType >
288 auto ResampleImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType >
CastPixelWithBoundsChecking(const ComponentType value)289 ::CastPixelWithBoundsChecking(const ComponentType value) -> PixelType
290 {
291 return CastComponentWithBoundsChecking(value);
292 }
293
294
295 template< typename TInputImage,
296 typename TOutputImage,
297 typename TInterpolatorPrecisionType,
298 typename TTransformPrecisionType >
299 template <typename TPixel>
300 auto ResampleImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType >
CastPixelWithBoundsChecking(const TPixel value)301 ::CastPixelWithBoundsChecking(const TPixel value) -> PixelType
302 {
303 static_assert(std::is_same<TPixel, InterpolatorOutputType>::value,
304 "TPixel should just be the same as the InterpolatorOutputType!");
305 static_assert(!std::is_same<TPixel, ComponentType>::value,
306 "For ComponentType there is a more efficient overload, that should be called instead!");
307
308 const unsigned int nComponents = InterpolatorConvertType::GetNumberOfComponents(value);
309 PixelType outputValue;
310
311 NumericTraits<PixelType>::SetLength(outputValue, nComponents);
312
313 for (unsigned int n = 0; n < nComponents; ++n)
314 {
315 const ComponentType component = InterpolatorConvertType::GetNthComponent(n, value);
316 PixelConvertType::SetNthComponent(n, outputValue,
317 Self::CastComponentWithBoundsChecking(component));
318 }
319
320 return outputValue;
321 }
322
323
324 template< typename TInputImage,
325 typename TOutputImage,
326 typename TInterpolatorPrecisionType,
327 typename TTransformPrecisionType >
328 void
329 ResampleImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType >
NonlinearThreadedGenerateData(const OutputImageRegionType & outputRegionForThread)330 ::NonlinearThreadedGenerateData(const OutputImageRegionType & outputRegionForThread)
331 {
332 OutputImageType *outputPtr = this->GetOutput();
333 const InputImageType *inputPtr = this->GetInput();
334 const TransformType *transformPtr = this->GetTransform();
335
336 // Honor the SpecialCoordinatesImage isInside value returned
337 // by TransformPhysicalPointToContinuousIndex
338 using InputSpecialCoordinatesImageType = SpecialCoordinatesImage< InputPixelType, InputImageDimension >;
339 const bool isSpecialCoordinatesImage = dynamic_cast< const InputSpecialCoordinatesImageType * >( inputPtr );
340
341
342 // Create an iterator that will walk the output region for this thread.
343 using OutputIterator = ImageRegionIteratorWithIndex< TOutputImage >;
344 OutputIterator outIt(outputPtr, outputRegionForThread);
345
346 // Define a few indices that will be used to translate from an input pixel
347 // to an output pixel
348 PointType outputPoint; // Coordinates of current output pixel
349 PointType inputPoint; // Coordinates of current input pixel
350
351 ContinuousInputIndexType inputIndex;
352
353 using OutputType = typename InterpolatorType::OutputType;
354
355 // Walk the output region
356 outIt.GoToBegin();
357
358 while ( !outIt.IsAtEnd() )
359 {
360 // Determine the index of the current output pixel
361 outputPtr->TransformIndexToPhysicalPoint(outIt.GetIndex(), outputPoint);
362
363 // Compute corresponding input pixel position
364 inputPoint = transformPtr->TransformPoint(outputPoint);
365 const bool isInsideInput = inputPtr->TransformPhysicalPointToContinuousIndex(inputPoint, inputIndex);
366
367 OutputType value;
368 // Evaluate input at right position and copy to the output
369 if( m_Interpolator->IsInsideBuffer(inputIndex) && ( !isSpecialCoordinatesImage || isInsideInput ) )
370 {
371 value = m_Interpolator->EvaluateAtContinuousIndex(inputIndex);
372 outIt.Set( Self::CastPixelWithBoundsChecking(value) );
373 }
374 else
375 {
376 if( m_Extrapolator.IsNull() )
377 {
378 outIt.Set( m_DefaultPixelValue ); // default background value
379 }
380 else
381 {
382 value = m_Extrapolator->EvaluateAtContinuousIndex( inputIndex );
383 outIt.Set( Self::CastPixelWithBoundsChecking(value) );
384 }
385 }
386
387 ++outIt;
388 }
389 }
390
391 template< typename TInputImage,
392 typename TOutputImage,
393 typename TInterpolatorPrecisionType,
394 typename TTransformPrecisionType >
395 void
396 ResampleImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType >
LinearThreadedGenerateData(const OutputImageRegionType & outputRegionForThread)397 ::LinearThreadedGenerateData(const OutputImageRegionType & outputRegionForThread)
398 {
399 OutputImageType *outputPtr = this->GetOutput();
400 const InputImageType *inputPtr = this->GetInput();
401 const TransformType *transformPtr = this->GetTransform();
402
403 // Create an iterator that will walk the output region for this thread.
404 using OutputIterator = ImageScanlineIterator< TOutputImage >;
405 OutputIterator outIt(outputPtr, outputRegionForThread);
406
407 // Define a few indices that will be used to translate from an input pixel
408 // to an output pixel
409 PointType outputPoint; // Coordinates of current output pixel
410 PointType inputPoint; // Coordinates of current input pixel
411
412 const InputImageRegionType &largestPossibleRegion = outputPtr->GetLargestPossibleRegion();
413
414 using OutputType = typename InterpolatorType::OutputType;
415
416 // Cache information from the superclass
417 PixelType defaultValue = this->GetDefaultPixelValue();
418
419 using OutputType = typename InterpolatorType::OutputType;
420
421 // As we walk across a scan line in the output image, we trace
422 // an oriented/scaled/translated line in the input image. Each scan
423 // line has a starting and ending point. Since all transforms
424 // are linear, the path between the points is linear and can be
425 // defined by interpolating between the two points. By using
426 // interpolation we avoid accumulation errors, and by using the
427 // whole scan line from the largest possible region we make the
428 // computation independent for each point and independent of the
429 // region we are processing which makes the method independent of
430 // how the whole image is split for processing ( threading,
431 // streaming, etc ).
432 //
433
434 while ( !outIt.IsAtEnd() )
435 {
436 // Determine the continuous index of the first and end pixel of output
437 // scan line when mapped to the input coordinate frame.
438
439 IndexType index = outIt.GetIndex();
440 index[0] = largestPossibleRegion.GetIndex(0);
441
442 ContinuousInputIndexType startIndex;
443 outputPtr->TransformIndexToPhysicalPoint(index, outputPoint);
444 inputPoint = transformPtr->TransformPoint(outputPoint);
445 inputPtr->TransformPhysicalPointToContinuousIndex(inputPoint, startIndex);
446
447 ContinuousInputIndexType endIndex;
448 index[0] += largestPossibleRegion.GetSize(0);
449 outputPtr->TransformIndexToPhysicalPoint(index, outputPoint);
450 inputPoint = transformPtr->TransformPoint(outputPoint);
451 inputPtr->TransformPhysicalPointToContinuousIndex(inputPoint, endIndex);
452
453 IndexValueType scanlineIndex = outIt.GetIndex()[0];
454
455
456 while ( !outIt.IsAtEndOfLine() )
457 {
458
459 // Perform linear interpolation between startIndex and endIndex
460 const double alpha = (scanlineIndex - largestPossibleRegion.GetIndex(0)) / (double)(largestPossibleRegion.GetSize(0));
461
462 ContinuousInputIndexType inputIndex( startIndex );
463 for (unsigned int i = 0; i < ImageDimension; ++i)
464 {
465 inputIndex[i] += alpha * ( endIndex[i] - startIndex[i] );
466 }
467
468 OutputType value;
469 // Evaluate input at right position and copy to the output
470 if ( m_Interpolator->IsInsideBuffer(inputIndex) )
471 {
472 value = m_Interpolator->EvaluateAtContinuousIndex(inputIndex);
473 outIt.Set( Self::CastPixelWithBoundsChecking(value) );
474 }
475 else
476 {
477 if( m_Extrapolator.IsNull() )
478 {
479 outIt.Set(defaultValue); // default background value
480 }
481 else
482 {
483 value = m_Extrapolator->EvaluateAtContinuousIndex( inputIndex );
484 outIt.Set( Self::CastPixelWithBoundsChecking(value) );
485 }
486 }
487
488 ++outIt;
489 ++scanlineIndex;
490 }
491 outIt.NextLine();
492 }
493 }
494
495 template< typename TInputImage,
496 typename TOutputImage,
497 typename TInterpolatorPrecisionType,
498 typename TTransformPrecisionType >
499 void
500 ResampleImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType >
GenerateInputRequestedRegion()501 ::GenerateInputRequestedRegion()
502 {
503 if ( !m_Interpolator )
504 {
505 itkExceptionMacro(<< "Interpolator not set");
506 }
507
508 // Get pointers to the input and output
509 InputImageType * input = const_cast< InputImageType * >( this->GetInput() );
510
511 // Some interpolators need to look at their images in GetRadius()
512 m_Interpolator->SetInputImage( input );
513
514 #if !defined(ITKV4_COMPATIBILITY)
515 // Check whether the input or the output is a
516 // SpecialCoordinatesImage. If either are, then we cannot use the
517 // fast path since index mapping will definitely not be linear.
518 typedef SpecialCoordinatesImage< PixelType, ImageDimension > OutputSpecialCoordinatesImageType;
519 typedef SpecialCoordinatesImage< InputPixelType, InputImageDimension > InputSpecialCoordinatesImageType;
520
521 const bool isSpecialCoordinatesImage = ( dynamic_cast< const InputSpecialCoordinatesImageType * >( this->GetInput() )
522 || dynamic_cast< const OutputSpecialCoordinatesImageType * >( this->GetOutput() ) );
523
524 const OutputImageType *output = this->GetOutput();
525 // Get the input transform
526 const TransformType *transform = this->GetTransform();
527
528 // Check whether we can use upstream streaming for resampling. Upstream streaming
529 // can be used if the transformation is linear. Transform respond
530 // to the IsLinear() call.
531 if ( !isSpecialCoordinatesImage && transform->GetTransformCategory() == TransformType::Linear )
532 {
533 typename TInputImage::RegionType inputRequestedRegion;
534 inputRequestedRegion = ImageAlgorithm::EnlargeRegionOverBox(output->GetRequestedRegion(),
535 output,
536 input,
537 transform);
538
539 const typename TInputImage::RegionType inputLargestRegion( input->GetLargestPossibleRegion() );
540 if( inputLargestRegion.IsInside( inputRequestedRegion.GetIndex() ) || inputLargestRegion.IsInside( inputRequestedRegion.GetUpperIndex() ) )
541 {
542 // Input requested region is partially outside the largest possible region.
543 // or
544 // Input requested region is completely inside the largest possible region.
545 inputRequestedRegion.PadByRadius( m_Interpolator->GetRadius() );
546 inputRequestedRegion.Crop( inputLargestRegion );
547 input->SetRequestedRegion( inputRequestedRegion );
548 }
549 else if( inputRequestedRegion.IsInside( inputLargestRegion ) )
550 {
551 // Input requested region completely surrounds the largest possible region.
552 input->SetRequestedRegion( inputLargestRegion );
553 }
554 else
555 {
556 // Input requested region is completely outside the largest possible region. Do not set the requested region in this case.
557 }
558 return;
559 }
560 #endif
561
562 // Otherwise, determining the actual input region is non-trivial, especially
563 // when we cannot assume anything about the transform being used.
564 // So we do the easy thing and request the entire input image.
565 //
566 input->SetRequestedRegionToLargestPossibleRegion();
567 }
568
569 template< typename TInputImage,
570 typename TOutputImage,
571 typename TInterpolatorPrecisionType,
572 typename TTransformPrecisionType >
573 void
574 ResampleImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType >
GenerateOutputInformation()575 ::GenerateOutputInformation()
576 {
577 // Call the superclass' implementation of this method
578 Superclass::GenerateOutputInformation();
579
580 // Get pointers to the input and output
581 OutputImageType *outputPtr = this->GetOutput();
582
583 const ReferenceImageBaseType *referenceImage = this->GetReferenceImage();
584
585 // Set the size of the output region
586 if ( m_UseReferenceImage && referenceImage )
587 {
588 outputPtr->SetLargestPossibleRegion(
589 referenceImage->GetLargestPossibleRegion() );
590 }
591 else
592 {
593 typename TOutputImage::RegionType outputLargestPossibleRegion;
594 outputLargestPossibleRegion.SetSize(m_Size);
595 outputLargestPossibleRegion.SetIndex(m_OutputStartIndex);
596 outputPtr->SetLargestPossibleRegion(outputLargestPossibleRegion);
597 }
598
599 // Set spacing and origin
600 if ( m_UseReferenceImage && referenceImage )
601 {
602 outputPtr->SetSpacing( referenceImage->GetSpacing() );
603 outputPtr->SetOrigin( referenceImage->GetOrigin() );
604 outputPtr->SetDirection( referenceImage->GetDirection() );
605 }
606 else
607 {
608 outputPtr->SetSpacing(m_OutputSpacing);
609 outputPtr->SetOrigin(m_OutputOrigin);
610 outputPtr->SetDirection(m_OutputDirection);
611 }
612 }
613
614 template< typename TInputImage,
615 typename TOutputImage,
616 typename TInterpolatorPrecisionType,
617 typename TTransformPrecisionType >
618 ModifiedTimeType
619 ResampleImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType >
GetMTime() const620 ::GetMTime() const
621 {
622 ModifiedTimeType latestTime = Object::GetMTime();
623
624 if ( m_Interpolator )
625 {
626 if ( latestTime < m_Interpolator->GetMTime() )
627 {
628 latestTime = m_Interpolator->GetMTime();
629 }
630 }
631
632 return latestTime;
633 }
634
635 template< typename TInputImage,
636 typename TOutputImage,
637 typename TInterpolatorPrecisionType,
638 typename TTransformPrecisionType >
639 void
640 ResampleImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTransformPrecisionType >
PrintSelf(std::ostream & os,Indent indent) const641 ::PrintSelf(std::ostream & os, Indent indent) const
642 {
643 Superclass::PrintSelf(os, indent);
644
645 os << indent << "DefaultPixelValue: "
646 << static_cast< typename NumericTraits< PixelType >::PrintType >
647 ( m_DefaultPixelValue )
648 << std::endl;
649 os << indent << "Size: " << m_Size << std::endl;
650 os << indent << "OutputStartIndex: " << m_OutputStartIndex << std::endl;
651 os << indent << "OutputSpacing: " << m_OutputSpacing << std::endl;
652 os << indent << "OutputOrigin: " << m_OutputOrigin << std::endl;
653 os << indent << "OutputDirection: " << m_OutputDirection << std::endl;
654 os << indent << "Transform: " << this->GetTransform() << std::endl;
655 os << indent << "Interpolator: " << m_Interpolator.GetPointer() << std::endl;
656 os << indent << "Extrapolator: " << m_Extrapolator.GetPointer() << std::endl;
657 os << indent << "UseReferenceImage: " << ( m_UseReferenceImage ? "On" : "Off" )
658 << std::endl;
659 }
660 } // end namespace itk
661
662 #endif
663