Change Image Origin Spacing Or Direction

Synopsis

Change an Image’s Origin, Spacing, or Direction.

The ChangeInformationImageFilter is commonly used to modify image metadata such as Origin, Spacing, and Orientation. This filter leaves intact the pixel data of the image. This filter should be used with extreme caution, since it can easily change information that is critical for the safety of many medical image analysis tasks, such as measurement the volume of a tumor, or providing guidance for surgery.

Results

Original image: Image (0x3131ce0)
  RTTI typeinfo:   itk::Image<unsigned char, 3u>
  Reference Count: 3
  Modified Time: 195
  Debug: Off
  Object Name:
  Observers:
    none
  Source: (0x312d620)
  Source output name: Primary
  Release Data: Off
  Data Released: False
  Global Release Data: Off
  PipelineMTime: 47
  UpdateMTime: 0
  RealTimeStamp: 0 seconds
  LargestPossibleRegion:
    Dimension: 3
    Index: [0, 0, 0]
    Size: [48, 62, 42]
  BufferedRegion:
    Dimension: 3
    Index: [0, 0, 0]
    Size: [0, 0, 0]
  RequestedRegion:
    Dimension: 3
    Index: [0, 0, 0]
    Size: [0, 0, 0]
  Spacing: [4, 4, 4]
  Origin: [0, 0, 0]
  Direction:
1 0 0
0 1 0
0 0 1

  IndexToPointMatrix:
4 0 0
0 4 0
0 0 4

  PointToIndexMatrix:
0.25 0 0
0 0.25 0
0 0 0.25

  Inverse Direction:
1 0 0
0 1 0
0 0 1

  PixelContainer:
    ImportImageContainer (0x3131fa0)
      RTTI typeinfo:   itk::ImportImageContainer<unsigned long, unsigned char>
      Reference Count: 1
      Modified Time: 34
      Debug: Off
      Object Name:
      Observers:
        none
      Pointer: 0
      Container manages memory: true
      Size: 0
      Capacity: 0

**************************************
Changed image: Image (0x3137100)
  RTTI typeinfo:   itk::Image<unsigned char, 3u>
  Reference Count: 3
  Modified Time: 222
  Debug: Off
  Object Name:
  Observers:
    none
  Source: (0x3132240)
  Source output name: Primary
  Release Data: Off
  Data Released: False
  Global Release Data: Off
  PipelineMTime: 215
  UpdateMTime: 0
  RealTimeStamp: 0 seconds
  LargestPossibleRegion:
    Dimension: 3
    Index: [0, 0, 0]
    Size: [48, 62, 42]
  BufferedRegion:
    Dimension: 3
    Index: [0, 0, 0]
    Size: [0, 0, 0]
  RequestedRegion:
    Dimension: 3
    Index: [0, 0, 0]
    Size: [0, 0, 0]
  Spacing: [8.4, 8.4, 8.4]
  Origin: [8.4, 2.9, 4.4]
  Direction:
0.866025 -0.5 0
0.5 0.866025 0
0 0 1

  IndexToPointMatrix:
7.27461 -4.2 0
4.2 7.27461 0
0 0 8.4

  PointToIndexMatrix:
0.103098 0.0595238 0
-0.0595238 0.103098 0
0 0 0.119048

  Inverse Direction:
0.866025 0.5 0
-0.5 0.866025 0
0 0 1

  PixelContainer:
    ImportImageContainer (0x3137520)
      RTTI typeinfo:   itk::ImportImageContainer<unsigned long, unsigned char>
      Reference Count: 1
      Modified Time: 200
      Debug: Off
      Object Name:
      Observers:
        none
      Pointer: 0
      Container manages memory: true
      Size: 0
      Capacity: 0

Code

C++

#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkVersor.h"
#include "itkChangeInformationImageFilter.h"

int
main(int argc, char * argv[])
{
  if (argc < 2)
  {
    std::cerr << "Usage: " << argv[0] << " <inputFileName>"
              << " [scalingFactor]"
              << " [translationX translationY translationZ]"
              << " [rotationZinDegrees]" << std::endl;
    return EXIT_FAILURE;
  }

  const char * inputFileName = argv[1];
  double       scalingFactor = 1.0;
  if (argc > 3)
  {
    scalingFactor = std::stod(argv[3]);
  }
  double translationX = 0.0;
  if (argc > 3)
  {
    translationX = std::stod(argv[3]);
  }
  double translationY = 0.0;
  if (argc > 4)
  {
    translationY = std::stod(argv[4]);
  }
  double translationZ = 0.0;
  if (argc > 5)
  {
    translationZ = std::stod(argv[5]);
  }
  double rotationZ = 0.0;
  if (argc > 6)
  {
    rotationZ = std::stod(argv[6]);
  }

  constexpr unsigned int Dimension = 3;

  using PixelType = unsigned char;
  using ImageType = itk::Image<PixelType, Dimension>;

  using ReaderType = itk::ImageFileReader<ImageType>;
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(inputFileName);
  try
  {
    reader->UpdateOutputInformation();
  }
  catch (itk::ExceptionObject & error)
  {
    std::cerr << "Error: " << error << std::endl;
    return EXIT_FAILURE;
  }
  ImageType::ConstPointer inputImage = reader->GetOutput();
  std::cout << "Original image: " << inputImage << std::endl;

  using FilterType = itk::ChangeInformationImageFilter<ImageType>;
  FilterType::Pointer filter = FilterType::New();
  filter->SetInput(reader->GetOutput());

  const ImageType::SpacingType spacing(scalingFactor);
  filter->SetOutputSpacing(spacing);
  filter->ChangeSpacingOn();

  ImageType::PointType::VectorType translation;
  translation[0] = translationX;
  translation[1] = translationY;
  translation[2] = translationZ;
  ImageType::PointType origin = inputImage->GetOrigin();
  origin += translation;
  filter->SetOutputOrigin(origin);
  filter->ChangeOriginOn();

  itk::Versor<double> rotation;
  const double        angleInRadians = rotationZ * itk::Math::pi / 180.0;
  rotation.SetRotationAroundZ(angleInRadians);
  const ImageType::DirectionType direction = inputImage->GetDirection();
  const ImageType::DirectionType newDirection = direction * rotation.GetMatrix();
  filter->SetOutputDirection(newDirection);
  filter->ChangeDirectionOn();

  try
  {
    filter->UpdateOutputInformation();
  }
  catch (itk::ExceptionObject & error)
  {
    std::cerr << "Error: " << error << std::endl;
    return EXIT_FAILURE;
  }
  std::cout << "**************************************" << std::endl;
  ImageType::ConstPointer output = filter->GetOutput();
  std::cout << "Changed image: " << output << std::endl;

  return EXIT_SUCCESS;
}

Classes demonstrated