diff --git a/Modules/IO/NIFTI/include/itkNiftiImageIO.h b/Modules/IO/NIFTI/include/itkNiftiImageIO.h index 16f02aba3b0..d77a743c6b4 100644 --- a/Modules/IO/NIFTI/include/itkNiftiImageIO.h +++ b/Modules/IO/NIFTI/include/itkNiftiImageIO.h @@ -120,6 +120,10 @@ class ITKIONIFTI_EXPORT NiftiImageIO:public ImageIOBase ImageIORegion GenerateStreamableReadRegionFromRequestedRegion(const ImageIORegion & requestedRegion) const override; + /** Set the slope and intercept for voxel value rescaling. */ + itkSetMacro(RescaleSlope, double); + itkSetMacro(RescaleIntercept, double); + /** A mode to allow the Nifti filter to read and write to the LegacyAnalyze75 format as interpreted by * the nifti library maintainers. This format does not properly respect the file orientation fields. * By default this is set to true. diff --git a/Modules/IO/NIFTI/src/itkNiftiImageIO.cxx b/Modules/IO/NIFTI/src/itkNiftiImageIO.cxx index d41cb78c953..ecc3293c4e9 100644 --- a/Modules/IO/NIFTI/src/itkNiftiImageIO.cxx +++ b/Modules/IO/NIFTI/src/itkNiftiImageIO.cxx @@ -1707,8 +1707,8 @@ ::WriteImageInformation(void) // ----------------------------------------------------- // magic must be "ni1\0" or "n+1\0" // ----------------------------------------------------- - this->m_NiftiImage->scl_slope = 1.0f; - this->m_NiftiImage->scl_inter = 0.0f; + this->m_NiftiImage->scl_slope = static_cast< float >( m_RescaleSlope ); + this->m_NiftiImage->scl_inter = static_cast< float >( m_RescaleIntercept ); //TODO: Note both arguments are the same, no need to distinguish between them. this->SetNIfTIOrientationFromImageIO( this->GetNumberOfDimensions(), this->GetNumberOfDimensions() ); } diff --git a/Modules/IO/NIFTI/test/itkNiftiImageIOTest5.cxx b/Modules/IO/NIFTI/test/itkNiftiImageIOTest5.cxx index 179914eff9b..d31d113950e 100644 --- a/Modules/IO/NIFTI/test/itkNiftiImageIOTest5.cxx +++ b/Modules/IO/NIFTI/test/itkNiftiImageIOTest5.cxx @@ -132,6 +132,96 @@ SlopeInterceptTest() return maxerror > 0.00001 ? EXIT_FAILURE : EXIT_SUCCESS; } +template +int +SlopeInterceptWriteTest() +{ + // + // fill out an image and write it as nifti. + const char *filename = "SlopeIntercept.nii"; + typedef itk::Image OutputImageType; + typename OutputImageType::RegionType region; + typename OutputImageType::IndexType start; + start[0] = 0; + start[1] = 0; + start[2] = 0; + typename OutputImageType::SizeType size; + size[0] = 8; + size[1] = 8; + size[2] = 4; + region.SetSize(size); + region.SetIndex(start); + typename OutputImageType::Pointer outputimage = OutputImageType::New(); + outputimage->SetRegions(region); + outputimage->Allocate(); + typedef itk::ImageRegionIterator OutputIteratorType; + OutputIteratorType itout(outputimage,outputimage->GetLargestPossibleRegion()); + itout.GoToBegin(); + for(unsigned i = 0; i < 256; i++,++itout) + { + if(itout.IsAtEnd()) + { + return EXIT_FAILURE; + } + itout.Set(static_cast(i)); + } + typedef itk::ImageFileWriter< OutputImageType > WriterType; + typename WriterType::Pointer writer = WriterType::New(); + itk::NiftiImageIO::Pointer niftiImageIO(itk::NiftiImageIO::New()); + niftiImageIO->SetRescaleSlope(1.0/256.0); + niftiImageIO->SetRescaleIntercept(-10.0); + writer->SetImageIO(niftiImageIO); + writer->SetFileName(filename); + writer->SetInput(outputimage); + try + { + writer->Update(); + } + catch (itk::ExceptionObject &err) + { + std::cerr << "Exception Object caught: " << std::endl + << err << std::endl; + throw; + } + // + // read the image back in + typedef itk::Image ImageType; + typename ImageType::Pointer image; + try + { + image = itk::IOTestHelper::ReadImage(std::string(filename)); + } + catch(...) + { + itk::IOTestHelper::Remove(filename); + return EXIT_FAILURE; + } + typedef itk::ImageRegionIterator IteratorType; + IteratorType it(image,image->GetLargestPossibleRegion()); + it.GoToBegin(); + double maxerror = 0.0; + for(unsigned i = 0; i < 256; i++,++it) + { + if(it.IsAtEnd()) + { + return EXIT_FAILURE; + } + if(!Equal(it.Value(),static_cast(i)/256.0-10.0)) + { + // return EXIT_FAILURE; + double error = std::abs(it.Value() - + (static_cast(i)/256.0-10.0)); + if(error > maxerror) + { + maxerror = error; + } + } + } + std::cerr << "Max error " << maxerror << std::endl; + itk::IOTestHelper::Remove(filename); + return maxerror > 0.00001 ? EXIT_FAILURE : EXIT_SUCCESS; +} + // // test vector images int itkNiftiImageIOTest5(int ac, char* av[]) @@ -155,5 +245,12 @@ int itkNiftiImageIOTest5(int ac, char* av[]) success |= SlopeInterceptTest(); success |= SlopeInterceptTest(); success |= SlopeInterceptTest(); + success |= SlopeInterceptWriteTest(); + success |= SlopeInterceptWriteTest(); + success |= SlopeInterceptWriteTest(); + success |= SlopeInterceptWriteTest(); + success |= SlopeInterceptWriteTest(); + success |= SlopeInterceptWriteTest(); + success |= SlopeInterceptWriteTest(); return success; }