diff --git a/Core/Code/IO/mitkIOUtil.cpp b/Core/Code/IO/mitkIOUtil.cpp index d671110b0a..68aa63fec0 100644 --- a/Core/Code/IO/mitkIOUtil.cpp +++ b/Core/Code/IO/mitkIOUtil.cpp @@ -1,317 +1,373 @@ /*=================================================================== 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 "mitkIOUtil.h" #include "mitkDataNodeFactory.h" #include "mitkImageWriter.h" #include "mitkPointSetWriter.h" #include "mitkSurfaceVtkWriter.h" #include #include #include #include #include +#include + //ITK #include //VTK #include #include #include namespace mitk { const std::string IOUtil::DEFAULTIMAGEEXTENSION = ".nrrd"; const std::string IOUtil::DEFAULTSURFACEEXTENSION = ".stl"; const std::string IOUtil::DEFAULTPOINTSETEXTENSION = ".mps"; int IOUtil::LoadFiles(const std::vector &fileNames, DataStorage &ds) { // Get the set of registered mitk::IDataNodeReader services ModuleContext* context = mitk::GetModuleContext(); const std::list refs = context->GetServiceReferences(); std::vector services; services.reserve(refs.size()); for (std::list::const_iterator i = refs.begin(); i != refs.end(); ++i) { IDataNodeReader* s = context->GetService(*i); if (s != 0) { services.push_back(s); } } mitk::ProgressBar::GetInstance()->AddStepsToDo(2*fileNames.size()); // Iterate over all file names and use the IDataNodeReader services // to load them. int nodesRead = 0; for (std::vector::const_iterator i = fileNames.begin(); i != fileNames.end(); ++i) { for (std::vector::const_iterator readerIt = services.begin(); readerIt != services.end(); ++readerIt) { try { int n = (*readerIt)->Read(*i, ds); nodesRead += n; if (n > 0) break; } catch (const std::exception& e) { MITK_WARN << e.what(); } } mitk::ProgressBar::GetInstance()->Progress(2); } for (std::list::const_iterator i = refs.begin(); i != refs.end(); ++i) { context->UngetService(*i); } return nodesRead; } DataStorage::Pointer IOUtil::LoadFiles(const std::vector& fileNames) { mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New(); LoadFiles(fileNames, *ds); return ds.GetPointer(); } DataNode::Pointer IOUtil::LoadDataNode(const std::string path) { mitk::DataNodeFactory::Pointer reader = mitk::DataNodeFactory::New(); try { reader->SetFileName( path ); reader->Update(); if((reader->GetNumberOfOutputs()<1)) { MITK_ERROR << "Could not find data '" << path << "'"; mitkThrow() << "An exception occured during loading the file " << path << ". Exception says could not find data."; } mitk::DataNode::Pointer node = reader->GetOutput(); if(node.IsNull()) { MITK_ERROR << "Could not find path: '" << path << "'" << " datanode is NULL" ; mitkThrow() << "An exception occured during loading the file " << path << ". Exception says datanode is NULL."; } return reader->GetOutput( 0 ); } catch ( itk::ExceptionObject & e ) { MITK_ERROR << "Exception occured during load data of '" << path << "': Exception: " << e.what(); mitkThrow() << "An exception occured during loading the file " << path << ". Exception says: " << e.what(); } } Image::Pointer IOUtil::LoadImage(const std::string path) { mitk::DataNode::Pointer node = LoadDataNode(path); mitk::Image::Pointer image = dynamic_cast(node->GetData()); if(image.IsNull()) { MITK_ERROR << "Image is NULL '" << path << "'"; mitkThrow() << "An exception occured during loading the image " << path << ". Exception says: Image is NULL."; } return image; } Surface::Pointer IOUtil::LoadSurface(const std::string path) { mitk::DataNode::Pointer node = LoadDataNode(path); mitk::Surface::Pointer surface = dynamic_cast(node->GetData()); if(surface.IsNull()) { MITK_ERROR << "Surface is NULL '" << path << "'"; mitkThrow() << "An exception occured during loading the file " << path << ". Exception says: Surface is NULL."; } return surface; } PointSet::Pointer IOUtil::LoadPointSet(const std::string path) { mitk::DataNode::Pointer node = LoadDataNode(path); mitk::PointSet::Pointer pointset = dynamic_cast(node->GetData()); if(pointset.IsNull()) { MITK_ERROR << "PointSet is NULL '" << path << "'"; mitkThrow() << "An exception occured during loading the file " << path << ". Exception says: Pointset is NULL."; } return pointset; } bool IOUtil::SaveImage(mitk::Image::Pointer image, const std::string path) { std::string dir = itksys::SystemTools::GetFilenamePath( path ); std::string baseFilename = itksys::SystemTools::GetFilenameWithoutLastExtension( path ); std::string extension = itksys::SystemTools::GetFilenameLastExtension( path ); std::string finalFileName = dir + "/" + baseFilename; mitk::ImageWriter::Pointer imageWriter = mitk::ImageWriter::New(); //check if an extension is given, else use the defaul extension if( extension == "" ) { MITK_WARN << extension << " extension is not set. Extension set to default: " << finalFileName << DEFAULTIMAGEEXTENSION; extension = DEFAULTIMAGEEXTENSION; } // check if extension is suitable for writing image data if (!imageWriter->IsExtensionValid(extension)) { MITK_WARN << extension << " extension is unknown. Extension set to default: " << finalFileName << DEFAULTIMAGEEXTENSION; extension = DEFAULTIMAGEEXTENSION; } try { //write the data imageWriter->SetInput(image); imageWriter->SetFileName(finalFileName.c_str()); imageWriter->SetExtension(extension.c_str()); imageWriter->Write(); } catch ( std::exception& e ) { MITK_ERROR << " during attempt to write '" << finalFileName + extension << "' Exception says:"; MITK_ERROR << e.what(); mitkThrow() << "An exception occured during writing the file " << finalFileName << ". Exception says " << e.what(); } return true; } bool IOUtil::SaveSurface(Surface::Pointer surface, const std::string path) { std::string dir = itksys::SystemTools::GetFilenamePath( path ); std::string baseFilename = itksys::SystemTools::GetFilenameWithoutLastExtension( path ); std::string extension = itksys::SystemTools::GetFilenameLastExtension( path ); std::string finalFileName = dir + "/" + baseFilename; if (extension == "") // if no extension has been set we use the default extension { MITK_WARN << extension << " extension is not set. Extension set to default: " << finalFileName << DEFAULTSURFACEEXTENSION; extension = DEFAULTSURFACEEXTENSION; } try { finalFileName += extension; if(extension == ".stl" ) { mitk::SurfaceVtkWriter::Pointer surfaceWriter = mitk::SurfaceVtkWriter::New(); // check if surface actually consists of triangles; if not, the writer will not do anything; so, convert to triangles... vtkPolyData* polys = surface->GetVtkPolyData(); if( polys->GetNumberOfStrips() > 0 ) { vtkSmartPointer triangleFilter = vtkSmartPointer::New(); triangleFilter->SetInput(polys); triangleFilter->Update(); polys = triangleFilter->GetOutput(); polys->Register(NULL); surface->SetVtkPolyData(polys); } surfaceWriter->SetInput( surface ); surfaceWriter->SetFileName( finalFileName.c_str() ); surfaceWriter->GetVtkWriter()->SetFileTypeToBinary(); surfaceWriter->Write(); } else if(extension == ".vtp") { mitk::SurfaceVtkWriter::Pointer surfaceWriter = mitk::SurfaceVtkWriter::New(); surfaceWriter->SetInput( surface ); surfaceWriter->SetFileName( finalFileName.c_str() ); surfaceWriter->GetVtkWriter()->SetDataModeToBinary(); surfaceWriter->Write(); } else if(extension == ".vtk") { mitk::SurfaceVtkWriter::Pointer surfaceWriter = mitk::SurfaceVtkWriter::New(); surfaceWriter->SetInput( surface ); surfaceWriter->SetFileName( finalFileName.c_str() ); surfaceWriter->Write(); } else { // file extension not suitable for writing specified data type MITK_ERROR << "File extension is not suitable for writing'" << finalFileName; mitkThrow() << "An exception occured during writing the file " << finalFileName << ". File extension " << extension << " is not suitable for writing."; } } catch(std::exception& e) { MITK_ERROR << " during attempt to write '" << finalFileName << "' Exception says:"; MITK_ERROR << e.what(); mitkThrow() << "An exception occured during writing the file " << finalFileName << ". Exception says " << e.what(); } return true; } bool IOUtil::SavePointSet(PointSet::Pointer pointset, const std::string path) { mitk::PointSetWriter::Pointer pointSetWriter = mitk::PointSetWriter::New(); std::string dir = itksys::SystemTools::GetFilenamePath( path ); std::string baseFilename = itksys::SystemTools::GetFilenameWithoutLastExtension( path ); std::string extension = itksys::SystemTools::GetFilenameLastExtension( path ); std::string finalFileName = dir + "/" + baseFilename; if (extension == "") // if no extension has been entered manually into the filename { MITK_WARN << extension << " extension is not set. Extension set to default: " << finalFileName << DEFAULTPOINTSETEXTENSION; extension = DEFAULTPOINTSETEXTENSION; } // check if extension is valid if (!pointSetWriter->IsExtensionValid(extension)) { MITK_WARN << extension << " extension is unknown. Extension set to default: " << finalFileName << DEFAULTPOINTSETEXTENSION; extension = DEFAULTPOINTSETEXTENSION; } try { pointSetWriter->SetInput( pointset ); finalFileName += extension; pointSetWriter->SetFileName( finalFileName.c_str() ); pointSetWriter->Update(); } catch( std::exception& e ) { MITK_ERROR << " during attempt to write '" << finalFileName << "' Exception says:"; MITK_ERROR << e.what(); mitkThrow() << "An exception occured during writing the file " << finalFileName << ". Exception says " << e.what(); } return true; } + +bool IOUtil::SaveBaseData( mitk::BaseData* data, const std::string& path ) +{ + if (data == NULL || path.empty()) return false; + + std::string dir = itksys::SystemTools::GetFilenamePath( path ); + std::string baseFilename = itksys::SystemTools::GetFilenameWithoutLastExtension( path ); + std::string extension = itksys::SystemTools::GetFilenameLastExtension( path ); + std::string finalFileName = dir + "/" + baseFilename; + + mitk::CoreObjectFactory::FileWriterList fileWriters = mitk::CoreObjectFactory::GetInstance()->GetFileWriters(); + + for (mitk::CoreObjectFactory::FileWriterList::iterator it = fileWriters.begin() ; it != fileWriters.end() ; ++it) + { + if ( (*it)->CanWriteBaseDataType(data) ) + { + // Ensure a valid filename + if(baseFilename=="") + { + baseFilename = (*it)->GetDefaultFilename(); + } + // Check if an extension exists already and if not, append the default extension + if (extension=="" ) + { + extension=(*it)->GetDefaultExtension(); + } + else + { + if (!(*it)->IsExtensionValid(extension)) + { + MITK_WARN << extension << " extension is unknown"; + continue; + } + } + + finalFileName = dir + "/" + baseFilename + extension; + try + { + (*it)->SetFileName( finalFileName.c_str() ); + (*it)->DoWrite( data ); + return true; + } + catch( const std::exception& e ) + { + MITK_ERROR << " during attempt to write '" << finalFileName << "' Exception says:"; + MITK_ERROR << e.what(); + mitkThrow() << "An exception occured during writing the file " << finalFileName << ". Exception says " << e.what(); + } + } + } + + return false; +} + } diff --git a/Core/Code/IO/mitkIOUtil.h b/Core/Code/IO/mitkIOUtil.h index af9d8c8593..d59a58176d 100644 --- a/Core/Code/IO/mitkIOUtil.h +++ b/Core/Code/IO/mitkIOUtil.h @@ -1,144 +1,154 @@ /*=================================================================== 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. ===================================================================*/ #ifndef MITKIOUTIL_H #define MITKIOUTIL_H #include #include #include #include #include namespace mitk { /** * \ingroup IO * * \brief A utility class to load and save data from/to the local file system. * * This method LoadFiles queries the MITK Micro Services registry for registered mitk::IDataNodeReader service * instances. The service instance with the highest ranking will be asked first to load the * given file. On error (exception thrown) or if no mitk::DataNode was constructed, the next * service instance is used. * * The methods LoadImage, LoadSurface, and LoadPointSet are convenience methods for general loading of * the three main data types in MITK. They all use the more generic method LoadDataNode. * * The methods SaveImage, SaveSurface, and SurfacePointSet are also meant for convenience (e.g. during testing). * Currently, there is no generic way to save a generic DataNode with an appropriate format. Thus, every method * initializes the corresponding instance of the special writer for the data type. * * \see mitk::IDataNodeReader */ class MITK_CORE_EXPORT IOUtil { public: /** * Load a files in fileNames and add the constructed mitk::DataNode instances * to the mitk::DataStorage storage * * \param fileNames A list (vector) of absolute file name paths. * \param storage The data storage to which the constructed data nodes are added. * \return The number of added mitk::DataNode instances. */ static int LoadFiles(const std::vector&fileNames, DataStorage& storage); /** * This method will create a new mitk::DataStorage instance and pass it to * LoadFiles(std::vector,DataStorage). * * \param fileNames A list (vector) of absolute file name paths. * \return The new mitk::DataStorage containing the constructed data nodes. * * \see LoadFiles(std::vector,DataStorage) */ static DataStorage::Pointer LoadFiles(const std::vector& fileNames); /** * @brief LoadDataNode Method to load an arbitrary DataNode. * @param path The path to the file including file name and file extension. * @throws mitk::Exception This exception is thrown when the DataNodeFactory is not able to read/find the file * or the DataNode is NULL. * @return Returns the DataNode. */ static mitk::DataNode::Pointer LoadDataNode(const std::string path); /** * @brief LoadImage Convenience method to load an arbitrary mitkImage. * @param path The path to the image including file name and file extension. * @throws mitk::Exception This exception is thrown when the Image is NULL. * @return Returns the mitkImage. */ static mitk::Image::Pointer LoadImage(const std::string path); /** * @brief LoadSurface Convenience method to load an arbitrary mitkSurface. * @param path The path to the surface including file name and file extension. * @throws mitk::Exception This exception is thrown when the Surface is NULL. * @return Returns the mitkSurface. */ static mitk::Surface::Pointer LoadSurface(const std::string path); /** * @brief LoadPointSet Convenience method to load an arbitrary mitkPointSet. * @param path The path to the pointset including file name and file extension (currently, only .mps is supported). * @throws mitk::Exception This exception is thrown when the PointSet is NULL. * @return Returns the mitkPointSet. */ static mitk::PointSet::Pointer LoadPointSet(const std::string path); /** * @brief SaveImage Convenience method to save an arbitrary mitkImage. * @param path The path to the image including file name and file extension. * If not extention is set, the default value (defined in DEFAULTIMAGEEXTENSION) is used. * @param image The image to save. * @throws mitk::Exception This exception is thrown when the writer is not able to write the image. * @return Returns true for success else false. */ static bool SaveImage(mitk::Image::Pointer image, const std::string path); + /** + * @brief SaveBaseData Convenience method to save arbitrary baseData. + * @param path The path to the image including file name and file extension. + * If not extention is set, the default value (defined in DEFAULTIMAGEEXTENSION) is used. + * @param data The data to save. + * @throws mitk::Exception This exception is thrown when the writer is not able to write the image. + * @return Returns true for success else false. + */ + static bool SaveBaseData(mitk::BaseData* data, const std::string& path); + /** * @brief SaveSurface Convenience method to save an arbitrary mitkSurface. * @param path The path to the surface including file name and file extension. * If not extention is set, the default value (defined in DEFAULTSURFACEEXTENSION) is used. * @throws mitk::Exception This exception is thrown when the writer is not able to write the surface. * or if the fileextension is not suitable for writing. * @return Returns true for success else false. */ static bool SaveSurface(mitk::Surface::Pointer surface, const std::string path); /** * @brief SavePointSet Convenience method to save an mitkPointSet. * @param path The path to the pointset including file name and file extension (currently, only .mps is supported). * If not extention is set, the default value (defined in DEFAULTPOINTSETEXTENSION) is used. * @throws mitk::Exception This exception is thrown when the writer is not able to write the pointset. * @return Returns true for success else false. */ static bool SavePointSet(mitk::PointSet::Pointer pointset, const std::string path); static const std::string DEFAULTIMAGEEXTENSION; static const std::string DEFAULTSURFACEEXTENSION; static const std::string DEFAULTPOINTSETEXTENSION; }; } #endif // MITKIOUTIL_H