diff --git a/Modules/Core/src/IO/mitkItkImageIO.cpp b/Modules/Core/src/IO/mitkItkImageIO.cpp index 90b4e85d5a..f8f73dfeff 100644 --- a/Modules/Core/src/IO/mitkItkImageIO.cpp +++ b/Modules/Core/src/IO/mitkItkImageIO.cpp @@ -1,481 +1,492 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkItkImageIO.h" #include #include #include #include #include #include #include #include #include #include namespace mitk { ItkImageIO::ItkImageIO(const ItkImageIO& other) : AbstractFileIO(other) , m_ImageIO(dynamic_cast(other.m_ImageIO->Clone().GetPointer())) { } std::vector ItkImageIO::FixUpImageIOExtensions(const std::string& imageIOName) { std::vector extensions; // Try to fix-up some known ITK image IO classes if (imageIOName == "GiplImageIO") { extensions.push_back("gipl"); extensions.push_back("gipl.gz"); } else if (imageIOName == "GDCMImageIO") { extensions.push_back("gdcm"); extensions.push_back("dcm"); extensions.push_back("DCM"); extensions.push_back("dc3"); extensions.push_back("DC3"); extensions.push_back("ima"); extensions.push_back("img"); } else if (imageIOName == "PNGImageIO") { extensions.push_back("png"); extensions.push_back("PNG"); } else if (imageIOName == "StimulateImageIO") { extensions.push_back("spr"); } else if (imageIOName == "HDF5ImageIO") { extensions.push_back("hdf"); extensions.push_back("h4"); extensions.push_back("hdf4"); extensions.push_back("h5"); extensions.push_back("hdf5"); extensions.push_back("he4"); extensions.push_back("he5"); extensions.push_back("hd5"); } else if (imageIOName == "GE4ImageIO" || imageIOName == "GE5ImageIO") { extensions.push_back(""); } if (!extensions.empty()) { MITK_DEBUG << "Fixing up known extensions for " << imageIOName; } return extensions; } ItkImageIO::ItkImageIO(itk::ImageIOBase::Pointer imageIO) : AbstractFileIO(Image::GetStaticNameOfClass()) , m_ImageIO(imageIO) { if (m_ImageIO.IsNull() ) { mitkThrow() << "ITK ImageIOBase argument must not be NULL"; } this->AbstractFileReader::SetMimeTypePrefix(IOMimeTypes::DEFAULT_BASE_NAME() + ".image."); std::vector readExtensions = m_ImageIO->GetSupportedReadExtensions(); if (readExtensions.empty()) { std::string imageIOName = m_ImageIO->GetNameOfClass(); MITK_DEBUG << "ITK ImageIOBase " << imageIOName << " does not provide read extensions"; readExtensions = FixUpImageIOExtensions(imageIOName); } CustomMimeType customReaderMimeType; customReaderMimeType.SetCategory("Images"); for(std::vector::const_iterator iter = readExtensions.begin(), endIter = readExtensions.end(); iter != endIter; ++iter) { std::string extension = *iter; if (!extension.empty() && extension[0] == '.') { extension.assign(iter->begin()+1, iter->end()); } customReaderMimeType.AddExtension(extension); } this->AbstractFileReader::SetMimeType(customReaderMimeType); std::vector writeExtensions = imageIO->GetSupportedWriteExtensions(); if (writeExtensions.empty()) { std::string imageIOName = imageIO->GetNameOfClass(); MITK_DEBUG << "ITK ImageIOBase " << imageIOName << " does not provide write extensions"; writeExtensions = FixUpImageIOExtensions(imageIOName); } if (writeExtensions != readExtensions) { CustomMimeType customWriterMimeType; customWriterMimeType.SetCategory("Images"); for(std::vector::const_iterator iter = writeExtensions.begin(), endIter = writeExtensions.end(); iter != endIter; ++iter) { std::string extension = *iter; if (!extension.empty() && extension[0] == '.') { extension.assign(iter->begin()+1, iter->end()); } customWriterMimeType.AddExtension(extension); } this->AbstractFileWriter::SetMimeType(customWriterMimeType); } std::string description = std::string("ITK ") + imageIO->GetNameOfClass(); this->SetReaderDescription(description); this->SetWriterDescription(description); this->RegisterService(); } ItkImageIO::ItkImageIO(const CustomMimeType& mimeType, itk::ImageIOBase::Pointer imageIO, int rank) : AbstractFileIO(Image::GetStaticNameOfClass(), mimeType, std::string("ITK ") + imageIO->GetNameOfClass()) , m_ImageIO(imageIO) { if (m_ImageIO.IsNull() ) { mitkThrow() << "ITK ImageIOBase argument must not be NULL"; } this->AbstractFileReader::SetMimeTypePrefix(IOMimeTypes::DEFAULT_BASE_NAME() + ".image."); if (rank) { this->AbstractFileReader::SetRanking(rank); this->AbstractFileWriter::SetRanking(rank); } this->RegisterService(); } std::vector ItkImageIO::Read() { std::vector result; const std::string& locale = "C"; const std::string& currLocale = setlocale( LC_ALL, NULL ); if ( locale.compare(currLocale)!=0 ) { try { setlocale(LC_ALL, locale.c_str()); } catch(...) { MITK_INFO << "Could not set locale " << locale; } } Image::Pointer image = Image::New(); const unsigned int MINDIM = 2; const unsigned int MAXDIM = 4; const std::string path = this->GetLocalFileName(); MITK_INFO << "loading " << path << " via itk::ImageIOFactory... " << std::endl; // Check to see if we can read the file given the name or prefix if (path.empty()) { mitkThrow() << "Empty filename in mitk::ItkImageIO "; } // Got to allocate space for the image. Determine the characteristics of // the image. m_ImageIO->SetFileName( path ); m_ImageIO->ReadImageInformation(); unsigned int ndim = m_ImageIO->GetNumberOfDimensions(); if ( ndim < MINDIM || ndim > MAXDIM ) { MITK_WARN << "Sorry, only dimensions 2, 3 and 4 are supported. The given file has " << ndim << " dimensions! Reading as 4D."; ndim = MAXDIM; } itk::ImageIORegion ioRegion( ndim ); itk::ImageIORegion::SizeType ioSize = ioRegion.GetSize(); itk::ImageIORegion::IndexType ioStart = ioRegion.GetIndex(); unsigned int dimensions[ MAXDIM ]; dimensions[ 0 ] = 0; dimensions[ 1 ] = 0; dimensions[ 2 ] = 0; dimensions[ 3 ] = 0; ScalarType spacing[ MAXDIM ]; spacing[ 0 ] = 1.0f; spacing[ 1 ] = 1.0f; spacing[ 2 ] = 1.0f; spacing[ 3 ] = 1.0f; Point3D origin; origin.Fill(0); unsigned int i; for ( i = 0; i < ndim ; ++i ) { ioStart[ i ] = 0; ioSize[ i ] = m_ImageIO->GetDimensions( i ); if(iGetDimensions( i ); spacing[ i ] = m_ImageIO->GetSpacing( i ); if(spacing[ i ] <= 0) spacing[ i ] = 1.0f; } if(i<3) { origin[ i ] = m_ImageIO->GetOrigin( i ); } } ioRegion.SetSize( ioSize ); ioRegion.SetIndex( ioStart ); MITK_INFO << "ioRegion: " << ioRegion << std::endl; m_ImageIO->SetIORegion( ioRegion ); void* buffer = new unsigned char[m_ImageIO->GetImageSizeInBytes()]; m_ImageIO->Read( buffer ); image->Initialize( MakePixelType(m_ImageIO), ndim, dimensions ); image->SetImportChannel( buffer, 0, Image::ManageMemory ); // access direction of itk::Image and include spacing mitk::Matrix3D matrix; matrix.SetIdentity(); unsigned int j, itkDimMax3 = (ndim >= 3? 3 : ndim); for ( i=0; i < itkDimMax3; ++i) for( j=0; j < itkDimMax3; ++j ) matrix[i][j] = m_ImageIO->GetDirection(j)[i]; // re-initialize PlaneGeometry with origin and direction PlaneGeometry* planeGeometry = image->GetSlicedGeometry(0)->GetPlaneGeometry(0); planeGeometry->SetOrigin(origin); planeGeometry->GetIndexToWorldTransform()->SetMatrix(matrix); // re-initialize SlicedGeometry3D SlicedGeometry3D* slicedGeometry = image->GetSlicedGeometry(0); slicedGeometry->InitializeEvenlySpaced(planeGeometry, image->GetDimension(2)); slicedGeometry->SetSpacing(spacing); MITK_INFO << slicedGeometry->GetCornerPoint(false,false,false); MITK_INFO << slicedGeometry->GetCornerPoint(true,true,true); // re-initialize TimeGeometry ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New(); timeGeometry->Initialize(slicedGeometry, image->GetDimension(3)); image->SetTimeGeometry(timeGeometry); buffer = NULL; MITK_INFO << "number of image components: "<< image->GetPixelType().GetNumberOfComponents() << std::endl; const itk::MetaDataDictionary& dictionary = m_ImageIO->GetMetaDataDictionary(); for (itk::MetaDataDictionary::ConstIterator iter = dictionary.Begin(), iterEnd = dictionary.End(); iter != iterEnd; ++iter) { std::string key = std::string("meta.") + iter->first; if (iter->second->GetMetaDataObjectTypeInfo() == typeid(std::string)) { std::string value = dynamic_cast*>(iter->second.GetPointer())->GetMetaDataObjectValue(); image->SetProperty(key.c_str(), mitk::StringProperty::New(value)); } } MITK_INFO << "...finished!" << std::endl; try { setlocale(LC_ALL, currLocale.c_str()); } catch(...) { MITK_INFO << "Could not reset locale " << currLocale; } result.push_back(image.GetPointer()); return result; } AbstractFileIO::ConfidenceLevel ItkImageIO::GetReaderConfidenceLevel() const { return m_ImageIO->CanReadFile(GetLocalFileName().c_str()) ? IFileReader::Supported : IFileReader::Unsupported; } void ItkImageIO::Write() { const mitk::Image* image = dynamic_cast(this->GetInput()); if (image == NULL) { mitkThrow() << "Cannot write non-image data"; } // Switch the current locale to "C" LocaleSwitch localeSwitch("C"); // Clone the image geometry, because we might have to change it // for writing purposes BaseGeometry::Pointer geometry = image->GetGeometry()->Clone(); // Check if geometry information will be lost if (image->GetDimension() == 2 && !geometry->Is2DConvertable()) { MITK_WARN << "Saving a 2D image with 3D geometry information. Geometry information will be lost! You might consider using Convert2Dto3DImageFilter before saving."; // set matrix to identity mitk::AffineTransform3D::Pointer affTrans = mitk::AffineTransform3D::New(); affTrans->SetIdentity(); mitk::Vector3D spacing = geometry->GetSpacing(); mitk::Point3D origin = geometry->GetOrigin(); geometry->SetIndexToWorldTransform(affTrans); geometry->SetSpacing(spacing); geometry->SetOrigin(origin); } LocalFile localFile(this); const std::string path = localFile.GetFileName(); MITK_INFO << "Writing image: " << path << std::endl; try { // Implementation of writer using itkImageIO directly. This skips the use // of templated itkImageFileWriter, which saves the multiplexing on MITK side. const unsigned int dimension = image->GetDimension(); const unsigned int* const dimensions = image->GetDimensions(); const mitk::PixelType pixelType = image->GetPixelType(); const mitk::Vector3D mitkSpacing = geometry->GetSpacing(); const mitk::Point3D mitkOrigin = geometry->GetOrigin(); // Due to templating in itk, we are forced to save a 4D spacing and 4D Origin, // though they are not supported in MITK itk::Vector spacing4D; spacing4D[0] = mitkSpacing[0]; spacing4D[1] = mitkSpacing[1]; spacing4D[2] = mitkSpacing[2]; spacing4D[3] = 1; // There is no support for a 4D spacing. However, we should have a valid value here itk::Vector origin4D; origin4D[0] = mitkOrigin[0]; origin4D[1] = mitkOrigin[1]; origin4D[2] = mitkOrigin[2]; origin4D[3] = 0; // There is no support for a 4D origin. However, we should have a valid value here // Set the necessary information for imageIO m_ImageIO->SetNumberOfDimensions(dimension); m_ImageIO->SetPixelType(pixelType.GetPixelType()); m_ImageIO->SetComponentType(pixelType.GetComponentType() < PixelComponentUserType ? static_cast(pixelType.GetComponentType()) : itk::ImageIOBase::UNKNOWNCOMPONENTTYPE); m_ImageIO->SetNumberOfComponents( pixelType.GetNumberOfComponents() ); itk::ImageIORegion ioRegion( dimension ); for(unsigned int i = 0; i < dimension; i++) { m_ImageIO->SetDimensions(i, dimensions[i]); m_ImageIO->SetSpacing(i, spacing4D[i]); m_ImageIO->SetOrigin(i, origin4D[i]); mitk::Vector3D mitkDirection; mitkDirection.SetVnlVector(geometry->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(i)); itk::Vector direction4D; direction4D[0] = mitkDirection[0]; direction4D[1] = mitkDirection[1]; direction4D[2] = mitkDirection[2]; // MITK only supports a 3x3 direction matrix. Due to templating in itk, however, we must // save a 4x4 matrix for 4D images. in this case, add an homogneous component to the matrix. if (i == 3) { direction4D[3] = 1; // homogenous component } else { direction4D[3] = 0; } vnl_vector axisDirection(dimension); for(unsigned int j = 0; j < dimension; j++) { axisDirection[j] = direction4D[j] / spacing4D[i]; } m_ImageIO->SetDirection(i, axisDirection); ioRegion.SetSize(i, image->GetLargestPossibleRegion().GetSize(i)); ioRegion.SetIndex(i, image->GetLargestPossibleRegion().GetIndex(i)); } //use compression if available m_ImageIO->UseCompressionOn(); m_ImageIO->SetIORegion(ioRegion); m_ImageIO->SetFileName(path); // ***** Remove const_cast after bug 17952 is fixed **** ImageReadAccessor imageAccess(const_cast(image)); m_ImageIO->Write(imageAccess.GetData()); } catch (const std::exception& e) { mitkThrow() << e.what(); } } AbstractFileIO::ConfidenceLevel ItkImageIO::GetWriterConfidenceLevel() const { // Check if the image dimension is supported const Image* image = dynamic_cast(this->GetInput()); - if (image == NULL || !m_ImageIO->SupportsDimension(image->GetDimension())) + if (image == NULL) { + // We cannot write a null object, DUH! return IFileWriter::Unsupported; } + if ( ! m_ImageIO->SupportsDimension(image->GetDimension())) + { + // okay, dimension is not supported. We have to look at a special case: + // 3D-Image with one slice. We can treat that as a 2D image. + if ((image->GetDimension() == 3) && (image->GetSlicedGeometry()->GetSlices() == 1)) + return IFileWriter::Supported; + else + return IFileWriter::Unsupported; + } + // Check if geometry information will be lost if (image->GetDimension() == 2 && !image->GetGeometry()->Is2DConvertable()) { return IFileWriter::PartiallySupported; } return IFileWriter::Supported; } ItkImageIO* ItkImageIO::IOClone() const { return new ItkImageIO(*this); } } diff --git a/Modules/Core/test/CMakeLists.txt b/Modules/Core/test/CMakeLists.txt index c4274d0061..dd1c9e5c5b 100644 --- a/Modules/Core/test/CMakeLists.txt +++ b/Modules/Core/test/CMakeLists.txt @@ -1,230 +1,222 @@ # The core tests need relaxed compiler flags... # TODO fix core tests to compile without these additional no-error flags if(MSVC_VERSION) # disable deprecated warnings (they would lead to errors) mitkFunctionCheckCAndCXXCompilerFlags("/wd4996" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) else() mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=deprecated" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=deprecated-declarations" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() MITK_CREATE_MODULE_TESTS(US_MODULE) if(TARGET ${TESTDRIVER}) mitk_use_modules(TARGET ${TESTDRIVER} PACKAGES ITK|ITKThresholding+ITKTestKernel VTK|vtkTestingRendering tinyxml) mitkAddCustomModuleTest(mitkVolumeCalculatorTest_Png2D-bw mitkVolumeCalculatorTest ${MITK_DATA_DIR}/Png2D-bw.png ${MITK_DATA_DIR}/Pic2DplusT.nrrd ) mitkAddCustomModuleTest(mitkEventMapperTest_Test1And2 mitkEventMapperTest ${MITK_DATA_DIR}/TestStateMachine1.xml ${MITK_DATA_DIR}/TestStateMachine2.xml ) mitkAddCustomModuleTest(mitkEventConfigTest_CreateObjectInDifferentWays mitkEventConfigTest ${MITK_SOURCE_DIR}/Modules/Core/test/resource/Interactions/StatemachineConfigTest.xml ) mitkAddCustomModuleTest(mitkNodeDependentPointSetInteractorTest mitkNodeDependentPointSetInteractorTest ${MITK_DATA_DIR}/Pic3D.nrrd ${MITK_DATA_DIR}/BallBinary30x30x30.nrrd ) mitkAddCustomModuleTest(mitkDataStorageTest_US4DCyl mitkDataStorageTest ${MITK_DATA_DIR}/US4DCyl.nrrd ) mitkAddCustomModuleTest(mitkStateMachineFactoryTest_TestStateMachine1_2 mitkStateMachineFactoryTest ${MITK_DATA_DIR}/TestStateMachine1.xml ${MITK_DATA_DIR}/TestStateMachine2.xml ) mitkAddCustomModuleTest(mitkDicomSeriesReaderTest_CTImage mitkDicomSeriesReaderTest ${MITK_DATA_DIR}/TinyCTAbdomen ${MITK_DATA_DIR}/DICOMReader/Broken-Series ) mitkAddCustomModuleTest(mitkPointSetReaderTest mitkPointSetReaderTest ${MITK_DATA_DIR}/PointSetReaderTestData.mps ) mitkAddCustomModuleTest(mitkImageTest_4DImageData mitkImageTest ${MITK_DATA_DIR}/US4DCyl.nrrd ) mitkAddCustomModuleTest(mitkImageTest_2D+tImageData mitkImageTest ${MITK_DATA_DIR}/Pic2DplusT.nrrd ) mitkAddCustomModuleTest(mitkImageTest_3DImageData mitkImageTest ${MITK_DATA_DIR}/Pic3D.nrrd ) mitkAddCustomModuleTest(mitkImageEqualTest mitkImageEqualTest) mitkAddCustomModuleTest(mitkImageTest_brainImage mitkImageTest ${MITK_DATA_DIR}/brain.mhd ) mitkAddCustomModuleTest(mitkImageTest_3DImageData mitkImageGeneratorTest ${MITK_DATA_DIR}/Pic3D.nrrd ) mitkAddCustomModuleTest(mitkLevelWindowManagerTest mitkLevelWindowManagerTest ${MITK_DATA_DIR}/Pic3D.nrrd ) mitkAddCustomModuleTest(mitkMultiComponentImageDataComparisonFilterTest mitkMultiComponentImageDataComparisonFilterTest ${MITK_DATA_DIR}/NrrdWritingTestImage.jpg ) mitkAddCustomModuleTest(mitkImageToItkTest mitkImageToItkTest ${MITK_DATA_DIR}/Pic3D.nrrd ) mitkAddCustomModuleTest(mitkImageSliceSelectorTest mitkImageSliceSelectorTest ${MITK_DATA_DIR}/Pic2DplusT.nrrd ) if(MITK_ENABLE_RENDERING_TESTING) ### since the rendering test's do not run in ubuntu, yet, we build them only for other systems or if the user explicitly sets the variable MITK_ENABLE_RENDERING_TESTING mitkAddCustomModuleTest(mitkImageVtkMapper2D_rgbaImage640x480 mitkImageVtkMapper2DTest ${MITK_DATA_DIR}/RenderingTestData/rgbaImage.png #input image to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/rgbaImage640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleTest(mitkImageVtkMapper2D_pic3d640x480 mitkImageVtkMapper2DTest #test for standard Pic3D axial slice ${MITK_DATA_DIR}/Pic3D.nrrd #input image to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3d640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleTest(mitkImageVtkMapper2D_pic3dColorBlue640x480 mitkImageVtkMapper2DColorTest #test for color property (=blue) Pic3D sagittal slice ${MITK_DATA_DIR}/Pic3D.nrrd #input image to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3dColorBlue640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleTest(mitkImageVtkMapper2D_pic3dLevelWindow640x480 mitkImageVtkMapper2DLevelWindowTest #test for levelwindow property (=blood) #Pic3D sagittal slice ${MITK_DATA_DIR}/Pic3D.nrrd #input image to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3dLevelWindowBlood640x480REF.png #corresponding reference #screenshot ) #mitkAddCustomModuleTest(mitkImageVtkMapper2D_pic3dOpacity640x480 mitkImageVtkMapper2DOpacityTest #test for opacity (=0.5) Pic3D coronal slice # ${MITK_DATA_DIR}/Pic3D.nrrd #input image to load in data storage # -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3dOpacity640x480REF.png corresponding reference screenshot #) mitkAddCustomModuleTest(mitkImageVtkMapper2D_pic3dSwivel640x480 mitkImageVtkMapper2DSwivelTest #test for a randomly chosen Pic3D swivelled slice ${MITK_DATA_DIR}/Pic3D.nrrd #input image to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3dSwivel640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleTest(mitkPointSetVtkMapper2D_openMeAlone640x480 mitkPointSetVtkMapper2DTest ${MITK_DATA_DIR}/RenderingTestData/openMeAlone.mps #input point set to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/openMeAlone640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleTest(mitkPointSetVtkMapper2D_Pic3DPointSetForPic3D640x480 mitkPointSetVtkMapper2DImageTest ${MITK_DATA_DIR}/Pic3D.nrrd ${MITK_DATA_DIR}/RenderingTestData/PointSetForPic3D.mps #input point set and image to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/Pic3DPointSetForPic3D640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleTest(mitkPointSetVtkMapper2D_openMeAloneGlyphType640x480 mitkPointSetVtkMapper2DGlyphTypeTest ${MITK_DATA_DIR}/RenderingTestData/openMeAlone.mps #input point set to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/openMeAloneGlyphType640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleTest(mitkPointSetVtkMapper2D_openMeAloneTransformed640x480 mitkPointSetVtkMapper2DTransformedPointsTest ${MITK_DATA_DIR}/RenderingTestData/openMeAlone.mps #input point set to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/openMeAloneTransformedPoints640x480REF.png #corresponding reference screenshot ) # Currently not working on windows because of a rendering timing issue # see bug 18083 for details if(NOT WIN32) mitkAddCustomModuleTest(mitkSurfaceDepthSortingTransparency_StanfordBunnySTL640x480 mitkSurfaceDepthSortingTest ${MITK_DATA_DIR}/RenderingTestData/Stanford_bunny.stl -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/Stanford_bunnySTLDepthSorting640x480REF.png ) endif() if(NOT APPLE) mitkAddCustomModuleTest(mitkSurfaceDepthPeelingTransparency_StanfordBunnySTL640x480 mitkSurfaceDepthPeelingTest ${MITK_DATA_DIR}/RenderingTestData/Stanford_bunny.stl -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/Stanford_bunnySTLDepthPeeling640x480REF.png #corresponding reference screenshot ) endif() #Test reslice interpolation #note: nearest mode is already tested by swivel test mitkAddCustomModuleTest(ResliceInterpolationIsLinear mitkImageVtkMapper2DResliceInterpolationPropertyTest 1 #linear ${MITK_DATA_DIR}/Pic3D.nrrd -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3dRefLinear.png #corresponding reference screenshot LINEAR ) mitkAddCustomModuleTest(ResliceInterpolationIsCubic mitkImageVtkMapper2DResliceInterpolationPropertyTest 3 #cubic ${MITK_DATA_DIR}/Pic3D.nrrd -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3dRefCubic.png #corresponding reference screenshot CUBIC ) #End test reslice interpolation # Testing of the rendering of binary images #mitkAddCustomModuleTest(mitkImageVtkMapper2D_binaryTestImage640x480 mitkImageVtkMapper2DTest #test for standard Pic3D axial slice # ${MITK_DATA_DIR}/RenderingTestData/binaryImage.nrrd #input image to load in data storage # -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/binaryImage640x480REF.png #corresponding reference screenshot #) #mitkAddCustomModuleTest(mitkImageVtkMapper2D_binaryTestImageWithRef640x480 mitkImageVtkMapper2DTest #test for standard Pic3D axial slice # ${MITK_DATA_DIR}/Pic3D.nrrd ${MITK_DATA_DIR}/RenderingTestData/binaryImage.nrrd #input image to load in data storage # -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/binaryImageWithRef640x480REF.png #corresponding reference screenshot #) # End of binary image tests mitkAddCustomModuleTest(mitkSurfaceVtkMapper3DTest_TextureProperty mitkSurfaceVtkMapper3DTest ${MITK_DATA_DIR}/ToF-Data/Kinect_LiverPhantom.vtp ${MITK_DATA_DIR}/ToF-Data/Kinect_LiverPhantom_RGBImage.nrrd -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/texturedLiver640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleTest(mitkImageVtkMapper2DTransferFunctionTest_Png2D-bw mitkImageVtkMapper2DTransferFunctionTest ${MITK_DATA_DIR}/Png2D-bw.png -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/Png2D-bw-TransferFunctionRGBImage640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleTest(mitkImageVtkMapper2DOpacityTransferFunctionTest_Png2D-bw mitkImageVtkMapper2DOpacityTransferFunctionTest ${MITK_DATA_DIR}/Png2D-bw.png -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/Png2D-bw-OpacityTransferFunctionRGBImage640x480REF.png #corresponding reference screenshot ) ############################## DISABLED TESTS #Removed due to high rendering error. #mitkAddCustomModuleTest(mitkSurfaceVtkMapper3DTexturedSphereTest_Football mitkSurfaceVtkMapper3DTexturedSphereTest # ${MITK_DATA_DIR}/RenderingTestData/texture.jpg #input texture # -V # ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/texturedSphere640x480REF.png corresponding reference screenshot #) mitkAddCustomModuleTest(mitkImageVtkMapper2DLookupTableTest_Png2D-bw mitkImageVtkMapper2DLookupTableTest ${MITK_DATA_DIR}/Png2D-bw.png -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/Png2D-bw-LookupTableRGBImage640x480REF.png #corresponding reference screenshot ) #mitkAddCustomModuleTest(mitkImageTest_color2DImage mitkImageTest # ${MITK_DATA_DIR}/NrrdWritingTestImage.jpg #) #mitkAddCustomModuleTest(mitkNodeDependentPointSetInteractorTest mitkNodeDependentPointSetInteractorTest # ${MITK_DATA_DIR}/Pic3D.pic.gz ${MITK_DATA_DIR}/BallBinary30x30x30.pic.gz #) SET_PROPERTY(TEST mitkImageVtkMapper2D_rgbaImage640x480 mitkImageVtkMapper2D_pic3d640x480 mitkImageVtkMapper2D_pic3dColorBlue640x480 mitkImageVtkMapper2D_pic3dLevelWindow640x480 mitkImageVtkMapper2D_pic3dSwivel640x480 mitkImageVtkMapper2DTransferFunctionTest_Png2D-bw # mitkImageVtkMapper2D_pic3dOpacity640x480 mitkSurfaceVtkMapper2DTest mitkSurfaceVtkMapper3DTest_TextureProperty mitkPointSetVtkMapper2D_Pic3DPointSetForPic3D640x480 mitkPointSetVtkMapper2D_openMeAlone640x480 mitkPointSetVtkMapper2D_openMeAloneGlyphType640x480 mitkPointSetVtkMapper2D_openMeAloneTransformed640x480 #mitkSurfaceVtkMapper3DTexturedSphereTest_Football PROPERTY RUN_SERIAL TRUE) endif() add_test(mitkPointSetLocaleTest ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTDRIVER} mitkPointSetLocaleTest ${MITK_DATA_DIR}/pointSet.mps) set_property(TEST mitkPointSetLocaleTest PROPERTY LABELS MITK-Core) - add_test(mitkImageWriterTest_nrrdImage ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTDRIVER} mitkImageWriterTest ${MITK_DATA_DIR}/NrrdWritingTestImage.jpg) - add_test(mitkImageWriterTest_2DPNGImage ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTDRIVER} mitkImageWriterTest ${MITK_DATA_DIR}/Png2D-bw.png) - add_test(mitkImageWriterTest_rgbPNGImage ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTDRIVER} mitkImageWriterTest ${MITK_DATA_DIR}/RenderingTestData/rgbImage.png) - add_test(mitkImageWriterTest_rgbaPNGImage ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTDRIVER} mitkImageWriterTest ${MITK_DATA_DIR}/RenderingTestData/rgbaImage.png) - set_property(TEST mitkImageWriterTest_nrrdImage PROPERTY LABELS MITK-Core) - set_property(TEST mitkImageWriterTest_2DPNGImage PROPERTY LABELS MITK-Core) - set_property(TEST mitkImageWriterTest_rgbPNGImage PROPERTY LABELS MITK-Core) - set_property(TEST mitkImageWriterTest_rgbaPNGImage PROPERTY LABELS MITK-Core) endif() # TARGET ${TESTDRIVER} diff --git a/Modules/Core/test/files.cmake b/Modules/Core/test/files.cmake index 1d3a17cffb..a48057fffb 100644 --- a/Modules/Core/test/files.cmake +++ b/Modules/Core/test/files.cmake @@ -1,194 +1,194 @@ # tests with no extra command line parameter set(MODULE_TESTS # IMPORTANT: If you plan to deactivate / comment out a test please write a bug number to the commented out line of code. # # Example: #mitkMyTest #this test is commented out because of bug 12345 # # It is important that the bug is open and that the test will be activated again before the bug is closed. This assures that # no test is forgotten after it was commented out. If there is no bug for your current problem, please add a new one and # mark it as critical. ################## DISABLED TESTS ################################################# #mitkAbstractTransformGeometryTest.cpp #seems as tested class mitkExternAbstractTransformGeometry doesnt exist any more #mitkStateMachineContainerTest.cpp #rewrite test, indirect since no longer exported Bug 14529 #mitkRegistrationBaseTest.cpp #tested class mitkRegistrationBase doesn't exist any more #mitkSegmentationInterpolationTest.cpp #file doesn't exist! #mitkPipelineSmartPointerCorrectnessTest.cpp #file doesn't exist! #mitkITKThreadingTest.cpp #test outdated because itk::Semaphore was removed from ITK #mitkAbstractTransformPlaneGeometryTest.cpp #mitkVtkAbstractTransformPlaneGeometry doesn't exist any more #mitkTestUtilSharedLibrary.cpp #Linker problem with this test... #mitkTextOverlay2DSymbolsRenderingTest.cpp #Implementation of the tested feature is not finished yet. Ask Christoph or see bug 15104 for details. ################# RUNNING TESTS ################################################### mitkAccessByItkTest.cpp mitkCoreObjectFactoryTest.cpp mitkDataNodeTest.cpp mitkMaterialTest.cpp mitkActionTest.cpp mitkDispatcherTest.cpp mitkEnumerationPropertyTest.cpp mitkEventTest.cpp mitkFileReaderRegistryTest.cpp #mitkFileWriterRegistryTest.cpp mitkFocusManagerTest.cpp mitkGenericPropertyTest.cpp mitkGeometry3DTest.cpp mitkGeometry3DEqualTest.cpp mitkGeometryDataToSurfaceFilterTest.cpp mitkGlobalInteractionTest.cpp mitkImageCastTest.cpp mitkImageEqualTest.cpp mitkImageDataItemTest.cpp mitkImageGeneratorTest.cpp mitkIOUtilTest.cpp mitkBaseDataTest.cpp mitkImportItkImageTest.cpp mitkGrabItkImageMemoryTest.cpp mitkInstantiateAccessFunctionTest.cpp mitkInteractorTest.cpp mitkLevelWindowTest.cpp mitkMessageTest.cpp mitkPixelTypeTest.cpp mitkPlaneGeometryTest.cpp mitkPointSetTest.cpp mitkPointSetEqualTest.cpp mitkPointSetFileIOTest.cpp mitkPointSetOnEmptyTest.cpp mitkPointSetWriterTest.cpp mitkPointSetReaderTest.cpp mitkPointSetInteractorTest.cpp mitkPointSetPointOperationsTest.cpp mitkProgressBarTest.cpp mitkPropertyTest.cpp mitkPropertyListTest.cpp mitkSlicedGeometry3DTest.cpp mitkSliceNavigationControllerTest.cpp mitkStateMachineTest.cpp mitkStateTest.cpp mitkSurfaceTest.cpp mitkSurfaceEqualTest.cpp mitkSurfaceToSurfaceFilterTest.cpp mitkTimeGeometryTest.cpp mitkProportionalTimeGeometryTest.cpp mitkTransitionTest.cpp mitkUndoControllerTest.cpp mitkVtkWidgetRenderingTest.cpp mitkVerboseLimitedLinearUndoTest.cpp mitkWeakPointerTest.cpp mitkTransferFunctionTest.cpp mitkStepperTest.cpp mitkRenderingManagerTest.cpp vtkMitkThickSlicesFilterTest.cpp mitkNodePredicateSourceTest.cpp mitkVectorTest.cpp mitkClippedSurfaceBoundsCalculatorTest.cpp mitkExceptionTest.cpp mitkExtractSliceFilterTest.cpp mitkLogTest.cpp mitkImageDimensionConverterTest.cpp mitkLoggingAdapterTest.cpp mitkUIDGeneratorTest.cpp mitkShaderRepositoryTest.cpp mitkPlanePositionManagerTest.cpp mitkAffineTransformBaseTest.cpp mitkPropertyAliasesTest.cpp mitkPropertyDescriptionsTest.cpp mitkPropertyExtensionsTest.cpp mitkPropertyFiltersTest.cpp mitkTinyXMLTest.cpp mitkRawImageFileReaderTest.cpp mitkInteractionEventTest.cpp mitkLookupTableTest.cpp mitkSTLFileReaderTest.cpp mitkPointTypeConversionTest.cpp mitkVectorTypeConversionTest.cpp mitkMatrixTypeConversionTest.cpp mitkArrayTypeConversionTest.cpp mitkSurfaceToImageFilterTest.cpp mitkBaseGeometryTest.cpp mitkImageToSurfaceFilterTest.cpp mitkEqualTest.cpp mitkLineTest.cpp + mitkItkImageIOTest.cpp ) if(MITK_ENABLE_RENDERING_TESTING) set(MODULE_TESTS ${MODULE_TESTS} mitkPointSetDataInteractorTest.cpp #since mitkInteractionTestHelper is currently creating a vtkRenderWindow mitkSurfaceVtkMapper2DTest.cpp #new rendering test in CppUnit style ) endif() # test with image filename as an extra command line parameter set(MODULE_IMAGE_TESTS mitkImageTimeSelectorTest.cpp #only runs on images mitkImageAccessorTest.cpp #only runs on images ) set(MODULE_SURFACE_TESTS mitkSurfaceVtkWriterTest.cpp #only runs on surfaces ) # list of images for which the tests are run set(MODULE_TESTIMAGES US4DCyl.nrrd Pic3D.nrrd Pic2DplusT.nrrd BallBinary30x30x30.nrrd Png2D-bw.png ) set(MODULE_TESTSURFACES binary.stl ball.stl ) set(MODULE_CUSTOM_TESTS mitkDataStorageTest.cpp mitkDicomSeriesReaderTest.cpp mitkDICOMLocaleTest.cpp mitkDataNodeTest.cpp mitkEventMapperTest.cpp mitkEventConfigTest.cpp mitkNodeDependentPointSetInteractorTest.cpp mitkStateMachineFactoryTest.cpp mitkPointSetLocaleTest.cpp mitkImageTest.cpp - mitkImageWriterTest.cpp mitkImageVtkMapper2DTest.cpp mitkImageVtkMapper2DLevelWindowTest.cpp mitkImageVtkMapper2DOpacityTest.cpp mitkImageVtkMapper2DResliceInterpolationPropertyTest.cpp mitkImageVtkMapper2DColorTest.cpp mitkImageVtkMapper2DSwivelTest.cpp mitkImageVtkMapper2DTransferFunctionTest.cpp mitkImageVtkMapper2DOpacityTransferFunctionTest.cpp mitkImageVtkMapper2DLookupTableTest.cpp mitkSurfaceVtkMapper3DTest mitkSurfaceVtkMapper3DTexturedSphereTest.cpp mitkVolumeCalculatorTest.cpp mitkLevelWindowManagerTest.cpp mitkPointSetVtkMapper2DTest.cpp mitkPointSetVtkMapper2DImageTest.cpp mitkPointSetVtkMapper2DGlyphTypeTest.cpp mitkPointSetVtkMapper2DTransformedPointsTest.cpp mitkVTKRenderWindowSizeTest.cpp mitkMultiComponentImageDataComparisonFilterTest.cpp mitkImageToItkTest.cpp mitkImageSliceSelectorTest.cpp mitkSurfaceDepthPeelingTest.cpp ) # Currently not working on windows because of a rendering timing issue # see bug 18083 for details if(NOT WIN32) set(MODULE_CUSTOM_TESTS ${MODULE_CUSTOM_TESTS} mitkSurfaceDepthSortingTest.cpp) endif() set(RESOURCE_FILES Interactions/AddAndRemovePoints.xml Interactions/globalConfig.xml Interactions/StatemachineTest.xml Interactions/StatemachineConfigTest.xml ) diff --git a/Modules/Core/test/mitkImageWriterTest.cpp b/Modules/Core/test/mitkImageWriterTest.cpp deleted file mode 100644 index 5df68f0b2b..0000000000 --- a/Modules/Core/test/mitkImageWriterTest.cpp +++ /dev/null @@ -1,259 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - -#include "mitkTestingMacros.h" -#include "mitkException.h" - -#include -#include "mitkIOUtil.h" - -#include "itksys/SystemTools.hxx" - -#include -#include - -#ifdef WIN32 -#include "process.h" -#else -#include -#endif - -std::string AppendExtension(const std::string &filename, const char *extension) -{ - std::string new_filename = filename; - - new_filename += extension; - return new_filename; -} - -bool CompareImageMetaData( mitk::Image::Pointer image, mitk::Image::Pointer reference, bool checkPixelType = true ) -{ - // switch to AreIdentical() methods as soon as Bug 11925 (Basic comparison operators) is fixed - - if( image->GetDimension() != reference->GetDimension() ) - { - MITK_ERROR << "The image dimension differs: IN (" << image->GetDimension() << ") REF(" << reference->GetDimension() << ")"; - return false; - } - - // pixel type - if( checkPixelType && - ( image->GetPixelType() != reference->GetPixelType() - && image->GetPixelType().GetBitsPerComponent() != reference->GetPixelType().GetBitsPerComponent() ) ) - { - MITK_ERROR << "Pixeltype differs ( image=" << image->GetPixelType().GetPixelTypeAsString() << "[" << image->GetPixelType().GetBitsPerComponent() << "]" << " reference=" << reference->GetPixelType().GetPixelTypeAsString() << "[" << reference->GetPixelType().GetBitsPerComponent() << "]" << " )"; - return false; - } - - return true; -} - - -/* -Test writing picture formats like *.bmp, *.png, *.tiff or *.jpg -NOTE: Saving as picture format must ignore PixelType comparison - not all bits per components are supported (see specification of the format) -*/ -void TestPictureWriting(mitk::Image* image, const std::string& filename, const std::string& extension) -{ - const std::string fullFileName = AppendExtension(filename, extension.c_str()); - - mitk::Image::Pointer singleSliceImage = NULL; - if( image->GetDimension() == 3 ) - { - mitk::ExtractSliceFilter::Pointer extractFilter = mitk::ExtractSliceFilter::New(); - extractFilter->SetInput( image ); - extractFilter->SetWorldGeometry( image->GetSlicedGeometry()->GetPlaneGeometry(0) ); - - extractFilter->Update(); - singleSliceImage = extractFilter->GetOutput(); - - // test 3D writing in format supporting only 2D - mitk::IOUtil::Save(image, fullFileName); - - // test images - unsigned int foundImagesCount = 0; - - //if the image only contains one sinlge slice the itkImageSeriesWriter won't add a number like filename.XX.extension - if(image->GetDimension(2) == 1) - { - std::stringstream series_filenames; - series_filenames << filename << extension; - mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage( series_filenames.str() ); - if( compareImage.IsNotNull() ) - { - foundImagesCount++; - MITK_TEST_CONDITION(CompareImageMetaData( singleSliceImage, compareImage, false ), "Image meta data unchanged after writing and loading again. "); //ignore bits per component - } - remove( series_filenames.str().c_str() ); - } - else //test the whole slice stack - { - for( unsigned int i=0; i< image->GetDimension(2); i++) - { - std::stringstream series_filenames; - series_filenames << filename << "." << i+1 << extension; - mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage( series_filenames.str() ); - if( compareImage.IsNotNull() ) - { - foundImagesCount++; - MITK_TEST_CONDITION(CompareImageMetaData( singleSliceImage, compareImage, false ), "Image meta data unchanged after writing and loading again. "); //ignore bits per component - } - remove( series_filenames.str().c_str() ); - } - } - MITK_TEST_CONDITION( foundImagesCount == image->GetDimension(2), "All 2D-Slices of a 3D image were stored correctly."); - } - else if( image->GetDimension() == 2 ) - { - singleSliceImage = image; - } - - // test 2D writing - if( singleSliceImage.IsNotNull() ) - { - try - { - mitk::IOUtil::Save(singleSliceImage, fullFileName); - - mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage(fullFileName.c_str()); - MITK_TEST_CONDITION_REQUIRED( compareImage.IsNotNull(), "Image stored was succesfully loaded again"); - - MITK_TEST_CONDITION_REQUIRED( CompareImageMetaData(singleSliceImage, compareImage, false ), "Image meta data unchanged after writing and loading again. ");//ignore bits per component - remove(fullFileName.c_str()); - } - catch(itk::ExceptionObject &e) - { - MITK_TEST_FAILED_MSG(<< "Exception during file writing for ." << extension << ": " << e.what() ); - } - - } - -} - -/** -* test for "ImageWriter". -* -* argc and argv are the command line parameters which were passed to -* the ADD_TEST command in the CMakeLists.txt file. For the automatic -* tests, argv is either empty for the simple tests or contains the filename -* of a test image for the image tests (see CMakeLists.txt). -*/ -int mitkImageWriterTest(int argc , char* argv[]) -{ - // always start with this! - MITK_TEST_BEGIN("ImageWriter") - - // write your own tests here and use the macros from mitkTestingMacros.h !!! - // do not write to std::cout and do not return from this function yourself! - - // load image - MITK_TEST_CONDITION_REQUIRED(argc > 1, "File to load has been specified"); - - - mitk::Image::Pointer image = NULL; - - try - { - MITK_TEST_OUTPUT(<< "Loading file: " << argv[1]); - image = mitk::IOUtil::LoadImage( argv[1] ); - } - catch (itk::ExceptionObject & ex) - { - MITK_TEST_FAILED_MSG(<< "Exception during file loading: " << ex.GetDescription()); - } - - - MITK_TEST_CONDITION_REQUIRED(image.IsNotNull(),"loaded image not NULL") - - // write ITK .mhd image (2D and 3D only) - if( image->GetDimension() <= 3 ) - { - std::ofstream tmpStream; - std::string tmpFilePath = mitk::IOUtil::CreateTemporaryFile(tmpStream, "XXXXXX.mhd"); - tmpStream.close(); - - std::string tmpFilePathWithoutExt = tmpFilePath.substr(0, tmpFilePath.size() - 4); - - try - { - mitk::IOUtil::Save(image, tmpFilePath); - - mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage(tmpFilePath); - MITK_TEST_CONDITION_REQUIRED( compareImage.IsNotNull(), "Image stored in MHD format was succesfully loaded again! "); - - MITK_TEST_CONDITION(itksys::SystemTools::FileExists((tmpFilePathWithoutExt + ".mhd").c_str()), ".mhd file exists") - MITK_TEST_CONDITION(itksys::SystemTools::FileExists((tmpFilePathWithoutExt + ".raw").c_str()) || - itksys::SystemTools::FileExists((tmpFilePathWithoutExt + ".zraw").c_str()), ".raw or .zraw exists") - - // delete - remove(tmpFilePath.c_str()); - remove((tmpFilePathWithoutExt + ".raw").c_str()); - remove((tmpFilePathWithoutExt + ".zraw").c_str()); - } - catch (const std::exception& e) - { - MITK_TEST_FAILED_MSG(<< "Exception during .mhd file writing: " << e.what()); - } - } - - //testing more component image writing as nrrd files - - { - std::ofstream tmpStream; - std::string tmpFilePath = mitk::IOUtil::CreateTemporaryFile(tmpStream, "XXXXXX.nrrd"); - tmpStream.close(); - - try - { - mitk::IOUtil::Save(image, tmpFilePath); - - mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage(tmpFilePath); - MITK_TEST_CONDITION_REQUIRED(compareImage.IsNotNull(), "Image stored in NRRD format was succesfully loaded again"); - - remove(tmpFilePath.c_str()); - } - catch(...) - { - std::remove(tmpFilePath.c_str()); - MITK_TEST_FAILED_MSG(<< "Exception during .nrrd file writing"); - } - } - - std::ofstream tmpStream; - std::string tmpFilePath = mitk::IOUtil::CreateTemporaryFile(tmpStream, "XXXXXX"); - tmpStream.close(); - - TestPictureWriting(image, tmpFilePath, ".png"); - TestPictureWriting(image, tmpFilePath, ".jpg"); - TestPictureWriting(image, tmpFilePath, ".tiff"); - TestPictureWriting(image, tmpFilePath, ".bmp"); - - // test for exception handling - try - { - mitk::IOUtil::Save(image, "/usr/bin"); - MITK_TEST_FAILED_MSG( << "mitk::Exception expected") - } - catch (const mitk::Exception&) { /* this is expected */ } - catch (...) - { - //this means that a wrong exception (i.e. no itk:Exception) has been thrown - MITK_TEST_FAILED_MSG(<< "Wrong exception (i.e. no itk:Exception) caught during write"); - } - - // always end with this! - MITK_TEST_END(); -} diff --git a/Modules/Core/test/mitkItkImageIOTest.cpp b/Modules/Core/test/mitkItkImageIOTest.cpp new file mode 100644 index 0000000000..13f2f53ce3 --- /dev/null +++ b/Modules/Core/test/mitkItkImageIOTest.cpp @@ -0,0 +1,394 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include "mitkException.h" +#include +#include + +#include +#include "mitkIOUtil.h" +#include "mitkITKImageImport.h" + +#include "itksys/SystemTools.hxx" +#include + +#include +#include + +#ifdef WIN32 +#include "process.h" +#else +#include +#endif + +class mitkItkImageIOTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkItkImageIOTestSuite); + MITK_TEST(TestImageWriterJpg); + MITK_TEST(TestImageWriterPng1); + MITK_TEST(TestImageWriterPng2); + MITK_TEST(TestImageWriterPng3); + MITK_TEST(TestImageWriterSimple); + MITK_TEST(TestWrite3DImageWithOnePlane); + MITK_TEST(TestWrite3DImageWithTwoPlanes); + CPPUNIT_TEST_SUITE_END(); + +public: + + void setUp() + { + + } + + void tearDown() + { + } + + + void TestImageWriterJpg() + { + TestImageWriter("NrrdWritingTestImage.jpg"); + } + + void TestImageWriterPng1() + { + TestImageWriter("Png2D-bw.png"); + } + + void TestImageWriterPng2() + { + TestImageWriter("RenderingTestData/rgbImage.png"); + } + + void TestImageWriterPng3() + { + TestImageWriter("RenderingTestData/rgbaImage.png"); + } + + void TestImageWriterSimple() + { + // TODO + } + + std::string AppendExtension(const std::string &filename, const char *extension) + { + std::string new_filename = filename; + + new_filename += extension; + return new_filename; + } + + bool CompareImageMetaData( mitk::Image::Pointer image, mitk::Image::Pointer reference, bool checkPixelType = true ) + { + // switch to AreIdentical() methods as soon as Bug 11925 (Basic comparison operators) is fixed + + if( image->GetDimension() != reference->GetDimension() ) + { + MITK_ERROR << "The image dimension differs: IN (" << image->GetDimension() << ") REF(" << reference->GetDimension() << ")"; + return false; + } + + // pixel type + if( checkPixelType && + ( image->GetPixelType() != reference->GetPixelType() + && image->GetPixelType().GetBitsPerComponent() != reference->GetPixelType().GetBitsPerComponent() ) ) + { + MITK_ERROR << "Pixeltype differs ( image=" << image->GetPixelType().GetPixelTypeAsString() << "[" << image->GetPixelType().GetBitsPerComponent() << "]" << " reference=" << reference->GetPixelType().GetPixelTypeAsString() << "[" << reference->GetPixelType().GetBitsPerComponent() << "]" << " )"; + return false; + } + + return true; + } + + + /* + Test writing picture formats like *.bmp, *.png, *.tiff or *.jpg + NOTE: Saving as picture format must ignore PixelType comparison - not all bits per components are supported (see specification of the format) + */ + void TestPictureWriting(mitk::Image* image, const std::string& filename, const std::string& extension) + { + const std::string fullFileName = AppendExtension(filename, extension.c_str()); + + mitk::Image::Pointer singleSliceImage = NULL; + if( image->GetDimension() == 3 ) + { + mitk::ExtractSliceFilter::Pointer extractFilter = mitk::ExtractSliceFilter::New(); + extractFilter->SetInput( image ); + extractFilter->SetWorldGeometry( image->GetSlicedGeometry()->GetPlaneGeometry(0) ); + + extractFilter->Update(); + singleSliceImage = extractFilter->GetOutput(); + + // test 3D writing in format supporting only 2D + mitk::IOUtil::Save(image, fullFileName); + + // test images + unsigned int foundImagesCount = 0; + + //if the image only contains one sinlge slice the itkImageSeriesWriter won't add a number like filename.XX.extension + if(image->GetDimension(2) == 1) + { + std::stringstream series_filenames; + series_filenames << filename << extension; + mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage( series_filenames.str() ); + if( compareImage.IsNotNull() ) + { + foundImagesCount++; + MITK_TEST_CONDITION(CompareImageMetaData( singleSliceImage, compareImage, false ), "Image meta data unchanged after writing and loading again. "); //ignore bits per component + } + remove( series_filenames.str().c_str() ); + } + else //test the whole slice stack + { + for( unsigned int i=0; i< image->GetDimension(2); i++) + { + std::stringstream series_filenames; + series_filenames << filename << "." << i+1 << extension; + mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage( series_filenames.str() ); + if( compareImage.IsNotNull() ) + { + foundImagesCount++; + MITK_TEST_CONDITION(CompareImageMetaData( singleSliceImage, compareImage, false ), "Image meta data unchanged after writing and loading again. "); //ignore bits per component + } + remove( series_filenames.str().c_str() ); + } + } + MITK_TEST_CONDITION( foundImagesCount == image->GetDimension(2), "All 2D-Slices of a 3D image were stored correctly."); + } + else if( image->GetDimension() == 2 ) + { + singleSliceImage = image; + } + + // test 2D writing + if( singleSliceImage.IsNotNull() ) + { + try + { + mitk::IOUtil::Save(singleSliceImage, fullFileName); + + mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage(fullFileName.c_str()); + MITK_TEST_CONDITION_REQUIRED( compareImage.IsNotNull(), "Image stored was succesfully loaded again"); + + MITK_TEST_CONDITION_REQUIRED( CompareImageMetaData(singleSliceImage, compareImage, false ), "Image meta data unchanged after writing and loading again. ");//ignore bits per component + remove(fullFileName.c_str()); + } + catch(itk::ExceptionObject &e) + { + MITK_TEST_FAILED_MSG(<< "Exception during file writing for ." << extension << ": " << e.what() ); + } + + } + + } + + /** + * test for "ImageWriter". + * + * argc and argv are the command line parameters which were passed to + * the ADD_TEST command in the CMakeLists.txt file. For the automatic + * tests, argv is either empty for the simple tests or contains the filename + * of a test image for the image tests (see CMakeLists.txt). + */ + void TestImageWriter(std::string sourcefile) + { + + sourcefile = GetTestDataFilePath(sourcefile); + + // load image + CPPUNIT_ASSERT_MESSAGE("Checking whether source image exists", itksys::SystemTools::FileExists(sourcefile.c_str())); + + mitk::Image::Pointer image = NULL; + + try + { + image = mitk::IOUtil::LoadImage( sourcefile ); + } + catch (...) + { + CPPUNIT_FAIL("Exception during file loading:"); + } + + CPPUNIT_ASSERT_MESSAGE("loaded image not NULL", image.IsNotNull()); + + // write ITK .mhd image (2D and 3D only) + if( image->GetDimension() <= 3 ) + { + std::ofstream tmpStream; + std::string tmpFilePath = mitk::IOUtil::CreateTemporaryFile(tmpStream, "XXXXXX.mhd"); + tmpStream.close(); + + std::string tmpFilePathWithoutExt = tmpFilePath.substr(0, tmpFilePath.size() - 4); + + try + { + mitk::IOUtil::Save(image, tmpFilePath); + + mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage(tmpFilePath); + CPPUNIT_ASSERT_MESSAGE("Image stored in MHD format was succesfully loaded again! ", compareImage.IsNotNull()); + + + CPPUNIT_ASSERT_MESSAGE(".mhd file exists", itksys::SystemTools::FileExists((tmpFilePathWithoutExt + ".mhd").c_str())); + CPPUNIT_ASSERT_MESSAGE(".raw or .zraw exists", itksys::SystemTools::FileExists((tmpFilePathWithoutExt + ".raw").c_str()) || + itksys::SystemTools::FileExists((tmpFilePathWithoutExt + ".zraw").c_str())); + + // delete + remove(tmpFilePath.c_str()); + remove((tmpFilePathWithoutExt + ".raw").c_str()); + remove((tmpFilePathWithoutExt + ".zraw").c_str()); + } + catch (...) + { + CPPUNIT_FAIL("Exception during.mhd file writing"); + } + } + + //testing more component image writing as nrrd files + + { + std::ofstream tmpStream; + std::string tmpFilePath = mitk::IOUtil::CreateTemporaryFile(tmpStream, "XXXXXX.nrrd"); + tmpStream.close(); + + try + { + mitk::IOUtil::Save(image, tmpFilePath); + + mitk::Image::Pointer compareImage = mitk::IOUtil::LoadImage(tmpFilePath); + CPPUNIT_ASSERT_MESSAGE("Image stored in NRRD format was succesfully loaded again", compareImage.IsNotNull()); + + remove(tmpFilePath.c_str()); + } + catch(...) + { + std::remove(tmpFilePath.c_str()); + CPPUNIT_FAIL("Exception during.mhd file writing"); + } + } + + std::ofstream tmpStream; + std::string tmpFilePath = mitk::IOUtil::CreateTemporaryFile(tmpStream, "XXXXXX"); + tmpStream.close(); + + TestPictureWriting(image, tmpFilePath, ".png"); + TestPictureWriting(image, tmpFilePath, ".jpg"); + TestPictureWriting(image, tmpFilePath, ".tiff"); + TestPictureWriting(image, tmpFilePath, ".bmp"); + // always end with this! + + } + + /** + * Try to write a 3D image with only one plane (a 2D images in disguise for all intents and purposes) + */ + void TestWrite3DImageWithOnePlane(){ + typedef itk::Image ImageType; + + ImageType::Pointer itkImage = ImageType::New(); + + ImageType::IndexType start; + start.Fill(0); + + ImageType::SizeType size; + size[0] = 100; + size[1] = 100; + size[2] = 1; + + ImageType::RegionType region; + region.SetSize(size); + region.SetIndex(start); + itkImage->SetRegions(region); + itkImage->Allocate(); + itkImage->FillBuffer(0); + + itk::ImageRegionIterator imageIterator(itkImage, itkImage->GetLargestPossibleRegion()); + + // Make two squares + while (!imageIterator.IsAtEnd()) + { + if ((imageIterator.GetIndex()[0] > 5 && imageIterator.GetIndex()[0] < 20) && + (imageIterator.GetIndex()[1] > 5 && imageIterator.GetIndex()[1] < 20)) + { + imageIterator.Set(255); + } + + if ((imageIterator.GetIndex()[0] > 50 && imageIterator.GetIndex()[0] < 70) && + (imageIterator.GetIndex()[1] > 50 && imageIterator.GetIndex()[1] < 70)) + { + imageIterator.Set(60); + } + ++imageIterator; + } + + mitk::Image::Pointer image = mitk::ImportItkImage(itkImage); + + mitk::IOUtil::SaveImage(image, mitk::IOUtil::CreateTemporaryFile("3Dto2DTestImageXXXXXX.nrrd")); + mitk::IOUtil::SaveImage(image, mitk::IOUtil::CreateTemporaryFile("3Dto2DTestImageXXXXXX.png")); + + } + + /** + * Try to write a 3D image with only one plane (a 2D images in disguise for all intents and purposes) + */ + void TestWrite3DImageWithTwoPlanes(){ + typedef itk::Image ImageType; + + ImageType::Pointer itkImage = ImageType::New(); + + ImageType::IndexType start; + start.Fill(0); + + ImageType::SizeType size; + size[0] = 100; + size[1] = 100; + size[2] = 2; + + ImageType::RegionType region; + region.SetSize(size); + region.SetIndex(start); + itkImage->SetRegions(region); + itkImage->Allocate(); + itkImage->FillBuffer(0); + + itk::ImageRegionIterator imageIterator(itkImage, itkImage->GetLargestPossibleRegion()); + + // Make two squares + while (!imageIterator.IsAtEnd()) + { + if ((imageIterator.GetIndex()[0] > 5 && imageIterator.GetIndex()[0] < 20) && + (imageIterator.GetIndex()[1] > 5 && imageIterator.GetIndex()[1] < 20)) + { + imageIterator.Set(255); + } + if ((imageIterator.GetIndex()[0] > 50 && imageIterator.GetIndex()[0] < 70) && + (imageIterator.GetIndex()[1] > 50 && imageIterator.GetIndex()[1] < 70)) + { + imageIterator.Set(60); + } + ++imageIterator; + } + mitk::Image::Pointer image = mitk::ImportItkImage(itkImage); + + mitk::IOUtil::SaveImage(image, mitk::IOUtil::CreateTemporaryFile("3Dto2DTestImageXXXXXX.nrrd")); + + CPPUNIT_ASSERT_THROW(mitk::IOUtil::SaveImage(image, mitk::IOUtil::CreateTemporaryFile("3Dto2DTestImageXXXXXX.png")), mitk::Exception); + + } + +}; + +MITK_TEST_SUITE_REGISTRATION(mitkItkImageIO)