Yes, you are right, i can reproduce the issue with Nifti IO. Here is test, no image is required to load, is created.
r@deb:~/tmp/test077/build$ ./test077
*** Origin [-100.04, -158.669, -101.794]
Direction
0.999998 0.00174533 0
-0.00174533 0.999998 0
0 0 1
*** Re-opened
Origin [-100.04, -158.669, -101.794]
Direction
0.999998 0.00182698 0
-0.00182698 0.999998 0
0 0 1
#include "itkImage.h"
#include "itkImageFileWriter.h"
#include "itkImageFileReader.h"
int main(int argc, char ** argv)
{
typedef itk::Image<float, 3> ImageType;
typedef itk::ImageFileWriter<ImageType> WriterType;
typedef itk::ImageFileReader<ImageType> ReaderType;
{
ImageType::Pointer image = ImageType::New();
ImageType::IndexType index;
ImageType::SizeType size;
ImageType::RegionType region;
ImageType::SpacingType spacing;
ImageType::PointType origin;
ImageType::DirectionType direction;
index.Fill(0);
size[0] = 192;
size[1] = 256;
size[2] = 192;
spacing[0] = 0.976562;
spacing[1] = 0.976562;
spacing[2] = 1;
origin[0] = -100.04;
origin[1] = -158.669;
origin[2] = -101.794;
direction(0,0) = 0.999998;
direction(0,1) = 0.00174533;
direction(0,2) = 0;
direction(1,0) = -0.00174533;
direction(1,1) = 0.999998;
direction(1,2) = 0;
direction(2,0) = 0;
direction(2,1) = 0;
direction(2,2) = 1;
region.SetIndex(index);
region.SetSize(size);
try
{
image->SetRegions(region);
image->Allocate();
image->SetOrigin(origin);
image->SetSpacing(spacing);
image->SetDirection(direction);
}
catch (itk::ExceptionObject & ex)
{
std::cout << ex.GetDescription() << std::endl;
return 1;
}
std::cout << "*** Origin " << image->GetOrigin() << std::endl;
std::cout << "Direction\n" << image->GetDirection() << std::endl;
WriterType::Pointer writer = WriterType::New();
writer->SetInput(image);
writer->SetFileName("output.nii.gz"); // MHA is OK
try
{
writer->Write();
}
catch (itk::ExceptionObject & ex)
{
std::cout << ex.GetDescription() << std::endl;
return 1;
}
}
{
ImageType::Pointer reopened;
ReaderType::Pointer reader = ReaderType::New();
reader->SetFileName("output.nii.gz"); // MHA is OK
try
{
reader->Update();
reopened = reader->GetOutput();
}
catch (itk::ExceptionObject & ex)
{
std::cout << ex.GetDescription() << std::endl;
return 1;
}
std::cout << "*** Re-opened\nOrigin " << reopened->GetOrigin() << std::endl;
std::cout << "Direction\n" << reopened->GetDirection() << std::endl;
}
return 0;
}
I didn’t looked closer, but could not reproduce with open/write Nifti images, may be, not sure, once written as Nifti image the image has matrix somehow compatible with computations, but not every matrix, the image above is valid, BTW, there should be no reason for mistake, IMHO. Don’t know, but there is something, there is also the issue about "round trip problems writing some DICOM files to Nifti and back, it is the same, may be.
P.S. As @blowekamp mentioned, orientation filter is absolutely OK, i have played with this testand geometry survived 500 random re-orientation. I think it is good news, IMHO.