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_h 19 #define itkResampleImageFilter_h 20 21 #include "itkFixedArray.h" 22 #include "itkTransform.h" 23 #include "itkImageRegionIterator.h" 24 #include "itkImageToImageFilter.h" 25 #include "itkExtrapolateImageFunction.h" 26 #include "itkLinearInterpolateImageFunction.h" 27 #include "itkSize.h" 28 #include "itkDefaultConvertPixelTraits.h" 29 #include "itkDataObjectDecorator.h" 30 31 32 namespace itk 33 { 34 /** \class ResampleImageFilter 35 * \brief Resample an image via a coordinate transform 36 * 37 * ResampleImageFilter resamples an existing image through some coordinate 38 * transform, interpolating via some image function. The class is templated 39 * over the types of the input and output images. 40 * 41 * Note that the choice of interpolator function can be important. 42 * This function is set via SetInterpolator(). The default is 43 * LinearInterpolateImageFunction<InputImageType, 44 * TInterpolatorPrecisionType>, which 45 * is reasonable for ordinary medical images. However, some synthetic 46 * images have pixels drawn from a finite prescribed set. An example 47 * would be a mask indicating the segmentation of a brain into a small 48 * number of tissue types. For such an image, one does not want to 49 * interpolate between different pixel values, and so 50 * NearestNeighborInterpolateImageFunction< InputImageType, 51 * TCoordRep > would be a better choice. 52 * 53 * If an sample is taken from outside the image domain, the default behavior is 54 * to use a default pixel value. If different behavior is desired, an 55 * extrapolator function can be set with SetExtrapolator(). 56 * 57 * Output information (spacing, size and direction) for the output 58 * image should be set. This information has the normal defaults of 59 * unit spacing, zero origin and identity direction. Optionally, the 60 * output information can be obtained from a reference image. If the 61 * reference image is provided and UseReferenceImage is On, then the 62 * spacing, origin and direction of the reference image will be used. 63 * 64 * Since this filter produces an image which is a different size than 65 * its input, it needs to override several of the methods defined 66 * in ProcessObject in order to properly manage the pipeline execution model. 67 * In particular, this filter overrides 68 * ProcessObject::GenerateInputRequestedRegion() and 69 * ProcessObject::GenerateOutputInformation(). 70 * 71 * This filter is implemented as a multithreaded filter. It provides a 72 * DynamicThreadedGenerateData() method for its implementation. 73 * \warning For multithreading, the TransformPoint method of the 74 * user-designated coordinate transform must be threadsafe. 75 * 76 * \ingroup GeometricTransform 77 * \ingroup ITKImageGrid 78 * 79 * \wiki 80 * \wikiexample{SimpleOperations/TranslationTransform,Translate an image} 81 * \wikiexample{ImageProcessing/Upsampling,Upsampling an image} 82 * \wikiexample{ImageProcessing/ResampleImageFilter,Resample (stretch or compress) an image} 83 * \endwiki 84 */ 85 template< typename TInputImage, 86 typename TOutputImage, 87 typename TInterpolatorPrecisionType = double, 88 typename TTransformPrecisionType = TInterpolatorPrecisionType> 89 class ITK_TEMPLATE_EXPORT ResampleImageFilter : 90 public ImageToImageFilter< TInputImage, TOutputImage > 91 { 92 public: 93 ITK_DISALLOW_COPY_AND_ASSIGN(ResampleImageFilter); 94 95 /** Standard class type aliases. */ 96 using Self = ResampleImageFilter; 97 using Superclass = ImageToImageFilter< TInputImage, TOutputImage >; 98 using Pointer = SmartPointer< Self >; 99 using ConstPointer = SmartPointer< const Self >; 100 101 using InputImageType = TInputImage; 102 using OutputImageType = TOutputImage; 103 using InputImagePointer = typename InputImageType::Pointer; 104 using InputImageConstPointer = typename InputImageType::ConstPointer; 105 using OutputImagePointer = typename OutputImageType::Pointer; 106 using InputImageRegionType = typename InputImageType::RegionType; 107 108 /** Method for creation through the object factory. */ 109 itkNewMacro(Self); 110 111 /** Run-time type information (and related methods). */ 112 itkTypeMacro(ResampleImageFilter, ImageToImageFilter); 113 114 /** Number of dimensions. */ 115 static constexpr unsigned int ImageDimension = TOutputImage::ImageDimension; 116 static constexpr unsigned int InputImageDimension = TInputImage::ImageDimension; 117 118 /** base type for images of the current ImageDimension */ 119 using ImageBaseType = ImageBase< Self::ImageDimension >; 120 121 /** 122 * Transform type alias. 123 */ 124 using TransformType = Transform< TTransformPrecisionType, 125 Self::ImageDimension, 126 Self::ImageDimension >; 127 using TransformPointerType = typename TransformType::ConstPointer; 128 using DecoratedTransformType = DataObjectDecorator<TransformType>; 129 using DecoratedTransformPointer = typename DecoratedTransformType::Pointer; 130 131 132 /** Interpolator type alias. */ 133 using InterpolatorType = InterpolateImageFunction< InputImageType, 134 TInterpolatorPrecisionType >; 135 using InterpolatorPointerType = typename InterpolatorType::Pointer; 136 137 using InterpolatorOutputType = typename InterpolatorType::OutputType; 138 139 using InterpolatorConvertType = DefaultConvertPixelTraits< InterpolatorOutputType >; 140 141 using ComponentType = typename InterpolatorConvertType::ComponentType; 142 143 using LinearInterpolatorType = LinearInterpolateImageFunction< InputImageType, 144 TInterpolatorPrecisionType >; 145 using LinearInterpolatorPointerType = typename LinearInterpolatorType::Pointer; 146 147 /** Extrapolator type alias. */ 148 using ExtrapolatorType = ExtrapolateImageFunction< InputImageType, 149 TInterpolatorPrecisionType >; 150 using ExtrapolatorPointerType = typename ExtrapolatorType::Pointer; 151 152 /** Image size type alias. */ 153 using SizeType = Size< Self::ImageDimension >; 154 155 /** Image index type alias. */ 156 using IndexType = typename TOutputImage::IndexType; 157 158 /** Image point type alias. */ 159 using PointType = typename InterpolatorType::PointType; 160 //using PointType = typename TOutputImage::PointType; 161 162 /** Image pixel value type alias. */ 163 using PixelType = typename TOutputImage::PixelType; 164 using InputPixelType = typename TInputImage::PixelType; 165 166 using PixelConvertType = DefaultConvertPixelTraits<PixelType>; 167 168 using PixelComponentType = typename PixelConvertType::ComponentType; 169 170 /** Input pixel continuous index typdef */ 171 using ContinuousInputIndexType = 172 ContinuousIndex< TInterpolatorPrecisionType, ImageDimension >; 173 174 /** Typedef to describe the output image region type. */ 175 using OutputImageRegionType = typename TOutputImage::RegionType; 176 177 /** Image spacing,origin and direction type alias */ 178 using SpacingType = typename TOutputImage::SpacingType; 179 using OriginPointType = typename TOutputImage::PointType; 180 using DirectionType = typename TOutputImage::DirectionType; 181 182 /** Typedef the reference image type to be the ImageBase of the OutputImageType */ 183 using ReferenceImageBaseType = ImageBase<ImageDimension>; 184 185 /** Get/Set the coordinate transformation. 186 * Set the coordinate transform to use for resampling. Note that this must 187 * be in physical coordinates and it is the output-to-input transform, NOT 188 * the input-to-output transform that you might naively expect. By default 189 * the filter uses an Identity transform. You must provide a different 190 * transform here, before attempting to run the filter, if you do not want to 191 * use the default Identity transform. */ 192 itkSetGetDecoratedObjectInputMacro(Transform, TransformType); 193 194 /** Get/Set the interpolator function. The default is 195 * LinearInterpolateImageFunction<InputImageType, 196 * TInterpolatorPrecisionType>. Some 197 * other options are NearestNeighborInterpolateImageFunction 198 * (useful for binary masks and other images with a small number of 199 * possible pixel values), and BSplineInterpolateImageFunction 200 * (which provides a higher order of interpolation). */ 201 itkSetObjectMacro(Interpolator, InterpolatorType); 202 itkGetModifiableObjectMacro(Interpolator, InterpolatorType); 203 204 /** Get/Set the extrapolator function. The default behavior when sampling outside 205 * of the input image is to use the DefaultPixelValue. Some other options 206 * include NearestNeighborExtrapolateImageFunction. */ 207 itkSetObjectMacro(Extrapolator, ExtrapolatorType); 208 itkGetModifiableObjectMacro(Extrapolator, ExtrapolatorType); 209 210 /** Get/Set the size of the output image. */ 211 itkSetMacro(Size, SizeType); 212 itkGetConstReferenceMacro(Size, SizeType); 213 214 /** Get/Set the pixel value when a transformed pixel is outside of the 215 * image. The default default pixel value is 0. */ 216 itkSetMacro(DefaultPixelValue, PixelType); 217 itkGetConstReferenceMacro(DefaultPixelValue, PixelType); 218 219 /** Set the output image spacing. */ 220 itkSetMacro(OutputSpacing, SpacingType); 221 virtual void SetOutputSpacing(const double *values); 222 223 /** Get the output image spacing. */ 224 itkGetConstReferenceMacro(OutputSpacing, SpacingType); 225 226 /** Set the output image origin. */ 227 itkSetMacro(OutputOrigin, OriginPointType); 228 virtual void SetOutputOrigin(const double *values); 229 230 /** Get the output image origin. */ 231 itkGetConstReferenceMacro(OutputOrigin, OriginPointType); 232 233 /** Set the output direciton cosine matrix. */ 234 itkSetMacro(OutputDirection, DirectionType); 235 itkGetConstReferenceMacro(OutputDirection, DirectionType); 236 237 /** Helper method to set the output parameters based on this image. */ 238 void SetOutputParametersFromImage(const ImageBaseType *image); 239 240 /** Set the start index of the output largest possible region. 241 * The default is an index of all zeros. */ 242 itkSetMacro(OutputStartIndex, IndexType); 243 244 /** Get the start index of the output largest possible region. */ 245 itkGetConstReferenceMacro(OutputStartIndex, IndexType); 246 247 /** Set a reference image to use to define the output information. 248 * By default, output information is specificed through the 249 * SetOutputSpacing, Origin, and Direction methods. Alternatively, 250 * this method can be used to specify an image from which to 251 * copy the information. UseReferenceImageOn must be set to utilize the 252 * reference image. */ 253 itkSetInputMacro(ReferenceImage, ReferenceImageBaseType); 254 255 /** Get the reference image that is defining the output information. */ 256 itkGetInputMacro(ReferenceImage, ReferenceImageBaseType); 257 258 /** Turn on/off whether a specified reference image should be used to define 259 * the output information. */ 260 itkSetMacro(UseReferenceImage, bool); 261 itkBooleanMacro(UseReferenceImage); 262 itkGetConstMacro(UseReferenceImage, bool); 263 264 #ifdef ITK_USE_CONCEPT_CHECKING 265 // Begin concept checking 266 itkConceptMacro( OutputHasNumericTraitsCheck, 267 ( Concept::HasNumericTraits< PixelComponentType > ) ); 268 // End concept checking 269 #endif 270 271 protected: 272 ResampleImageFilter(); 273 ~ResampleImageFilter() override = default; 274 void PrintSelf(std::ostream & os, Indent indent) const override; 275 276 /** Override VeriyInputInformation() since this filter's inputs do 277 * not need to occoupy the same physical space. 278 * 279 * \sa ProcessObject::VerifyInputInformation 280 */ VerifyInputInformation()281 void VerifyInputInformation() ITKv5_CONST override { } 282 283 /** ResampleImageFilter produces an image which is a different size 284 * than its input. As such, it needs to provide an implementation 285 * for GenerateOutputInformation() in order to inform the pipeline 286 * execution model. The original documentation of this method is 287 * below. \sa ProcessObject::GenerateOutputInformaton() */ 288 void GenerateOutputInformation() override; 289 290 /** ResampleImageFilter needs a different input requested region than 291 * the output requested region. As such, ResampleImageFilter needs 292 * to provide an implementation for GenerateInputRequestedRegion() 293 * in order to inform the pipeline execution model. 294 * \sa ProcessObject::GenerateInputRequestedRegion() */ 295 void GenerateInputRequestedRegion() override; 296 297 /** Set up state of filter before multi-threading. 298 * InterpolatorType::SetInputImage is not thread-safe and hence 299 * has to be set up before DynamicThreadedGenerateData */ 300 void BeforeThreadedGenerateData() override; 301 302 /** Set the state of the filter after multi-threading. */ 303 void AfterThreadedGenerateData() override; 304 305 /** Compute the Modified Time based on the changed components. */ 306 ModifiedTimeType GetMTime() const override; 307 308 /** ResampleImageFilter can be implemented as a multithreaded filter. 309 * Therefore, this implementation provides a DynamicThreadedGenerateData() 310 * routine which is called for each processing thread. The output 311 * image data is allocated automatically by the superclass prior 312 * to calling DynamicThreadedGenerateData(). 313 * DynamicThreadedGenerateData can only write to the portion of the output image 314 * specified by the parameter "outputRegionForThread" 315 * \sa ImageToImageFilter::ThreadedGenerateData(), 316 * ImageToImageFilter::GenerateData() */ 317 void DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override; 318 319 320 /** Default implementation for resampling that works for any 321 * transformation type. */ 322 virtual void NonlinearThreadedGenerateData(const OutputImageRegionType & outputRegionForThread); 323 324 /** Implementation for resampling that works for with linear 325 * transformation types. */ 326 virtual void LinearThreadedGenerateData(const OutputImageRegionType & outputRegionForThread); 327 328 /** Cast pixel from interpolator output to PixelType. */ 329 itkLegacyMacro( 330 virtual PixelType CastPixelWithBoundsChecking( const InterpolatorOutputType value, 331 const ComponentType minComponent, 332 const ComponentType maxComponent) const); 333 334 private: 335 static PixelComponentType CastComponentWithBoundsChecking(const PixelComponentType value); 336 337 template <typename TComponent> 338 static PixelComponentType CastComponentWithBoundsChecking(const TComponent value); 339 340 static PixelType CastPixelWithBoundsChecking(const ComponentType value); 341 342 template <typename TPixel> 343 static PixelType CastPixelWithBoundsChecking(const TPixel value); 344 345 SizeType m_Size; // Size of the output image 346 InterpolatorPointerType m_Interpolator; // Image function for 347 // interpolation 348 ExtrapolatorPointerType m_Extrapolator; // Image function for 349 // extrapolation 350 PixelType m_DefaultPixelValue; // default pixel value 351 // if the point is 352 // outside the image 353 SpacingType m_OutputSpacing; // output image spacing 354 OriginPointType m_OutputOrigin; // output image origin 355 DirectionType m_OutputDirection; // output image direction cosines 356 IndexType m_OutputStartIndex; // output image start index 357 bool m_UseReferenceImage{ false }; 358 359 }; 360 } // end namespace itk 361 362 #ifndef ITK_MANUAL_INSTANTIATION 363 #include "itkResampleImageFilter.hxx" 364 #endif 365 366 #endif 367