diff --git a/Core/Code/IO/mitkAbstractFileIO.cpp b/Core/Code/IO/mitkAbstractFileIO.cpp index 0789b88c60..4fd52a6613 100644 --- a/Core/Code/IO/mitkAbstractFileIO.cpp +++ b/Core/Code/IO/mitkAbstractFileIO.cpp @@ -1,193 +1,194 @@ /*=================================================================== 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 "mitkAbstractFileIO.h" #include "mitkCustomMimeType.h" namespace mitk { AbstractFileIO::Options AbstractFileIO::GetReaderOptions() const { return AbstractFileReader::GetOptions(); } us::Any AbstractFileIO::GetReaderOption(const std::string& name) const { return AbstractFileReader::GetOption(name); } void AbstractFileIO::SetReaderOptions(const AbstractFileIO::Options& options) { AbstractFileReader::SetOptions(options); } void AbstractFileIO::SetReaderOption(const std::string& name, const us::Any& value) { AbstractFileReader::SetOption(name, value); } AbstractFileIO::Options AbstractFileIO::GetWriterOptions() const { return AbstractFileWriter::GetOptions(); } us::Any AbstractFileIO::GetWriterOption(const std::string& name) const { return AbstractFileWriter::GetOption(name); } void AbstractFileIO::SetWriterOptions(const AbstractFileIO::Options& options) { AbstractFileWriter::SetOptions(options); } void AbstractFileIO::SetWriterOption(const std::string& name, const us::Any& value) { AbstractFileWriter::SetOption(name, value); } IFileIO::ConfidenceLevel AbstractFileIO::GetReaderConfidenceLevel() const { return AbstractFileIOReader::GetReaderConfidenceLevel(); } IFileIO::ConfidenceLevel AbstractFileIO::GetWriterConfidenceLevel() const { return AbstractFileIOWriter::GetWriterConfidenceLevel(); } std::pair, us::ServiceRegistration > AbstractFileIO::RegisterService(us::ModuleContext* context) { std::pair, us::ServiceRegistration > result; result.first = this->AbstractFileReader::RegisterService(context); - CustomMimeType writerMimeType = this->AbstractFileWriter::GetMimeType(); - if (writerMimeType.GetName().empty() && writerMimeType.GetExtensions().empty()) + const CustomMimeType* writerMimeType = this->AbstractFileWriter::GetMimeType(); + if (writerMimeType == NULL || + (writerMimeType->GetName().empty() && writerMimeType->GetExtensions().empty())) { this->AbstractFileWriter::SetMimeType(CustomMimeType(this->AbstractFileReader::GetRegisteredMimeType().GetName())); } result.second = this->AbstractFileWriter::RegisterService(context); return result; } AbstractFileIO::AbstractFileIO(const AbstractFileIO& other) : AbstractFileIOReader(other) , AbstractFileIOWriter(other) { } AbstractFileIO::AbstractFileIO(const std::string& baseDataType) : AbstractFileIOReader() , AbstractFileIOWriter(baseDataType) { } AbstractFileIO::AbstractFileIO(const std::string& baseDataType, const CustomMimeType& mimeType, const std::string& description) : AbstractFileIOReader(mimeType, description) , AbstractFileIOWriter(baseDataType, CustomMimeType(mimeType.GetName()), description) { } void AbstractFileIO::SetMimeType(const CustomMimeType& mimeType) { this->AbstractFileReader::SetMimeType(mimeType); this->AbstractFileWriter::SetMimeType(CustomMimeType(mimeType.GetName())); } -CustomMimeType AbstractFileIO::GetMimeType() const +const CustomMimeType* AbstractFileIO::GetMimeType() const { - CustomMimeType mimeType = this->AbstractFileReader::GetMimeType(); - if (mimeType.GetName() != this->AbstractFileWriter::GetMimeType().GetName()) + const CustomMimeType* mimeType = this->AbstractFileReader::GetMimeType(); + if (mimeType->GetName() != this->AbstractFileWriter::GetMimeType()->GetName()) { MITK_WARN << "Reader and writer mime-tpyes are different, using the mime-type from IFileReader"; } return mimeType; } void AbstractFileIO::SetReaderDescription(const std::string& description) { this->AbstractFileReader::SetDescription(description); } std::string AbstractFileIO::GetReaderDescription() const { return this->AbstractFileReader::GetDescription(); } void AbstractFileIO::SetWriterDescription(const std::string& description) { this->AbstractFileWriter::SetDescription(description); } std::string AbstractFileIO::GetWriterDescription() const { return this->AbstractFileWriter::GetDescription(); } void AbstractFileIO::SetDefaultReaderOptions(const AbstractFileIO::Options& defaultOptions) { this->AbstractFileReader::SetDefaultOptions(defaultOptions); } AbstractFileIO::Options AbstractFileIO::GetDefaultReaderOptions() const { return this->AbstractFileReader::GetDefaultOptions(); } void AbstractFileIO::SetDefaultWriterOptions(const AbstractFileIO::Options& defaultOptions) { this->AbstractFileWriter::SetDefaultOptions(defaultOptions); } AbstractFileIO::Options AbstractFileIO::GetDefaultWriterOptions() const { return this->AbstractFileWriter::GetDefaultOptions(); } void AbstractFileIO::SetReaderRanking(int ranking) { this->AbstractFileReader::SetRanking(ranking); } int AbstractFileIO::GetReaderRanking() const { return this->AbstractFileReader::GetRanking(); } void AbstractFileIO::SetWriterRanking(int ranking) { this->AbstractFileWriter::SetRanking(ranking); } int AbstractFileIO::GetWriterRanking() const { return this->AbstractFileWriter::GetRanking(); } IFileReader* AbstractFileIO::ReaderClone() const { return this->IOClone(); } IFileWriter* AbstractFileIO::WriterClone() const { return this->IOClone(); } } diff --git a/Core/Code/IO/mitkAbstractFileIO.h b/Core/Code/IO/mitkAbstractFileIO.h index b66a73dce3..3791432ac0 100644 --- a/Core/Code/IO/mitkAbstractFileIO.h +++ b/Core/Code/IO/mitkAbstractFileIO.h @@ -1,192 +1,192 @@ /*=================================================================== 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 MITKABSTRACTFILEIO_H #define MITKABSTRACTFILEIO_H #include "mitkAbstractFileReader.h" #include "mitkAbstractFileWriter.h" namespace mitk { #ifndef DOXYGEN_SKIP // Skip this code during Doxygen processing, because it only // exists to resolve name clashes when inheriting from both // AbstractFileReader and AbstractFileWriter. class AbstractFileIOReader : public AbstractFileReader { public: virtual ConfidenceLevel GetReaderConfidenceLevel() const { return AbstractFileReader::GetConfidenceLevel(); } virtual ConfidenceLevel GetConfidenceLevel() const { return this->GetReaderConfidenceLevel(); } protected: AbstractFileIOReader() {} AbstractFileIOReader(const CustomMimeType& mimeType, const std::string& description) : AbstractFileReader(mimeType, description) {} private: virtual IFileReader* ReaderClone() const = 0; IFileReader* Clone() const { return ReaderClone(); } }; struct AbstractFileIOWriter : public AbstractFileWriter { virtual ConfidenceLevel GetWriterConfidenceLevel() const { return AbstractFileWriter::GetConfidenceLevel(); } virtual ConfidenceLevel GetConfidenceLevel() const { return this->GetWriterConfidenceLevel(); } protected: AbstractFileIOWriter(const std::string& baseDataType) : AbstractFileWriter(baseDataType) {} AbstractFileIOWriter(const std::string& baseDataType, const CustomMimeType& mimeType, const std::string& description) : AbstractFileWriter(baseDataType, mimeType, description) {} private: virtual IFileWriter* WriterClone() const = 0; IFileWriter* Clone() const { return WriterClone(); } }; #endif // DOXYGEN_SKIP class MITK_CORE_EXPORT AbstractFileIO : public AbstractFileIOReader, public AbstractFileIOWriter { public: Options GetReaderOptions() const; us::Any GetReaderOption(const std::string &name) const; void SetReaderOptions(const Options& options); void SetReaderOption(const std::string& name, const us::Any& value); Options GetWriterOptions() const; us::Any GetWriterOption(const std::string &name) const; void SetWriterOptions(const Options& options); void SetWriterOption(const std::string& name, const us::Any& value); virtual ConfidenceLevel GetReaderConfidenceLevel() const; virtual ConfidenceLevel GetWriterConfidenceLevel() const; std::pair, us::ServiceRegistration > RegisterService(us::ModuleContext* context = us::GetModuleContext()); protected: AbstractFileIO(const AbstractFileIO& other); AbstractFileIO(const std::string& baseDataType); /** * Associate this reader instance with the given MIME type. * * @param mimeType The mime type this reader can read. * @param description A human readable description of this reader. * * @throws std::invalid_argument if \c mimeType is empty. * * @see RegisterService */ explicit AbstractFileIO(const std::string& baseDataType, const CustomMimeType& mimeType, const std::string& description); /** * Associate this reader with the given file extension. * * Additonal file extensions can be added by sub-classes by calling AddExtension * or SetExtensions on the CustomMimeType object returned by GetMimeType() and * setting the modified object again via SetMimeType(). * * @param extension The file extension (without a leading period) for which a registered * mime-type object is looked up and associated with this instance. * @param description A human readable description of this reader. * * @see RegisterService */ explicit AbstractFileIO(const std::string& baseDataType, const std::string& extension, const std::string& description); void SetMimeType(const CustomMimeType& mimeType); /** * @return The mime-type this reader can handle. */ - CustomMimeType GetMimeType() const; + const CustomMimeType* GetMimeType() const; void SetReaderDescription(const std::string& description); std::string GetReaderDescription() const; void SetWriterDescription(const std::string& description); std::string GetWriterDescription() const; void SetDefaultReaderOptions(const Options& defaultOptions); Options GetDefaultReaderOptions() const; void SetDefaultWriterOptions(const Options& defaultOptions); Options GetDefaultWriterOptions() const; /** * \brief Set the service ranking for this file reader. * * Default is zero and should only be chosen differently for a reason. * The ranking is used to determine which reader to use if several * equivalent readers have been found. * It may be used to replace a default reader from MITK in your own project. * E.g. if you want to use your own reader for nrrd files instead of the default, * implement it and give it a higher ranking than zero. */ void SetReaderRanking(int ranking); int GetReaderRanking() const; void SetWriterRanking(int ranking); int GetWriterRanking() const; private: AbstractFileIO& operator=(const AbstractFileIO& other); virtual AbstractFileIO* IOClone() const = 0; virtual IFileReader* ReaderClone() const; virtual IFileWriter* WriterClone() const; }; } #endif // MITKABSTRACTFILEIO_H diff --git a/Core/Code/IO/mitkAbstractFileReader.cpp b/Core/Code/IO/mitkAbstractFileReader.cpp index c03e03d3fd..77f309986a 100644 --- a/Core/Code/IO/mitkAbstractFileReader.cpp +++ b/Core/Code/IO/mitkAbstractFileReader.cpp @@ -1,399 +1,399 @@ /*=================================================================== 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 #include #include #include #include #include #include #include namespace mitk { AbstractFileReader::InputStream::InputStream(IFileReader* reader, std::ios_base::openmode mode) : std::istream(NULL) , m_Stream(NULL) { std::istream* stream = reader->GetInputStream(); if (stream) { this->init(stream->rdbuf()); } else { m_Stream = new std::ifstream(reader->GetInputLocation().c_str(), mode); this->init(m_Stream->rdbuf()); } } AbstractFileReader::InputStream::~InputStream() { delete m_Stream; } class AbstractFileReader::Impl : public FileReaderWriterBase { public: Impl() : FileReaderWriterBase() , m_Stream(NULL) , m_PrototypeFactory(NULL) {} Impl(const Impl& other) : FileReaderWriterBase(other) , m_Stream(NULL) , m_PrototypeFactory(NULL) {} std::string m_Location; std::string m_TmpFile; std::istream* m_Stream; us::PrototypeServiceFactory* m_PrototypeFactory; us::ServiceRegistration m_Reg; }; AbstractFileReader::AbstractFileReader() : d(new Impl) { } AbstractFileReader::~AbstractFileReader() { UnregisterService(); delete d->m_PrototypeFactory; if (!d->m_TmpFile.empty()) { std::remove(d->m_TmpFile.c_str()); } } AbstractFileReader::AbstractFileReader(const AbstractFileReader& other) : IFileReader(), d(new Impl(*other.d.get())) { } AbstractFileReader::AbstractFileReader(const CustomMimeType& mimeType, const std::string& description) : d(new Impl) { d->SetMimeType(mimeType); d->SetDescription(description); } ////////////////////// Reading ///////////////////////// DataStorage::SetOfObjects::Pointer AbstractFileReader::Read(DataStorage& ds) { DataStorage::SetOfObjects::Pointer result = DataStorage::SetOfObjects::New(); std::vector data = this->Read(); for (std::vector::iterator iter = data.begin(); iter != data.end(); ++iter) { mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(*iter); this->SetDefaultDataNodeProperties(node, this->GetInputLocation()); ds.Add(node); result->InsertElement(result->Size(), node); } return result; } IFileReader::ConfidenceLevel AbstractFileReader::GetConfidenceLevel() const { if (d->m_Stream) { if (*d->m_Stream) return Supported; } else { if (itksys::SystemTools::FileExists(this->GetInputLocation().c_str(), true)) { return Supported; } } return Unsupported; } //////////// µS Registration & Properties ////////////// us::ServiceRegistration AbstractFileReader::RegisterService(us::ModuleContext* context) { if (d->m_PrototypeFactory) return us::ServiceRegistration(); if(context == NULL) { context = us::GetModuleContext(); } d->RegisterMimeType(context); - if (this->GetMimeType().GetName().empty()) + if (this->GetMimeType()->GetName().empty()) { MITK_WARN << "Not registering reader due to empty MIME type."; return us::ServiceRegistration(); } struct PrototypeFactory : public us::PrototypeServiceFactory { AbstractFileReader* const m_Prototype; PrototypeFactory(AbstractFileReader* prototype) : m_Prototype(prototype) {} us::InterfaceMap GetService(us::Module* /*module*/, const us::ServiceRegistrationBase& /*registration*/) { return us::MakeInterfaceMap(m_Prototype->Clone()); } void UngetService(us::Module* /*module*/, const us::ServiceRegistrationBase& /*registration*/, const us::InterfaceMap& service) { delete us::ExtractInterface(service); } }; d->m_PrototypeFactory = new PrototypeFactory(this); us::ServiceProperties props = this->GetServiceProperties(); d->m_Reg = context->RegisterService(d->m_PrototypeFactory, props); return d->m_Reg; } void AbstractFileReader::UnregisterService() { try { d->m_Reg.Unregister(); } catch (const std::exception&) {} } us::ServiceProperties AbstractFileReader::GetServiceProperties() const { us::ServiceProperties result; result[IFileReader::PROP_DESCRIPTION()] = this->GetDescription(); - result[IFileReader::PROP_MIMETYPE()] = this->GetMimeType().GetName(); + result[IFileReader::PROP_MIMETYPE()] = this->GetMimeType()->GetName(); result[us::ServiceConstants::SERVICE_RANKING()] = this->GetRanking(); return result; } us::ServiceRegistration AbstractFileReader::RegisterMimeType(us::ModuleContext* context) { return d->RegisterMimeType(context); } void AbstractFileReader::SetMimeType(const CustomMimeType& mimeType) { d->SetMimeType(mimeType); } void AbstractFileReader::SetDescription(const std::string& description) { d->SetDescription(description); } void AbstractFileReader::SetRanking(int ranking) { d->SetRanking(ranking); } int AbstractFileReader::GetRanking() const { return d->GetRanking(); } std::string AbstractFileReader::GetLocalFileName() const { std::string localFileName; if (d->m_Stream) { if (d->m_TmpFile.empty()) { // write the stream contents to temporary file std::string ext = itksys::SystemTools::GetFilenameExtension(this->GetInputLocation()); std::ofstream tmpStream; localFileName = mitk::IOUtil::CreateTemporaryFile(tmpStream, std::ios_base::out | std::ios_base::trunc | std::ios_base::binary, "XXXXXX" + ext); tmpStream << d->m_Stream->rdbuf(); d->m_TmpFile = localFileName; } else { localFileName = d->m_TmpFile; } } else { localFileName = d->m_Location; } return localFileName; } //////////////////////// Options /////////////////////// void AbstractFileReader::SetDefaultOptions(const IFileReader::Options& defaultOptions) { d->SetDefaultOptions(defaultOptions); } IFileReader::Options AbstractFileReader::GetDefaultOptions() const { return d->GetDefaultOptions(); } void AbstractFileReader::SetInput(const std::string& location) { d->m_Location = location; d->m_Stream = NULL; } void AbstractFileReader::SetInput(const std::string& location, std::istream* is) { if (d->m_Stream != is && !d->m_TmpFile.empty()) { std::remove(d->m_TmpFile.c_str()); d->m_TmpFile.clear(); } d->m_Location = location; d->m_Stream = is; } std::string AbstractFileReader::GetInputLocation() const { return d->m_Location; } std::istream*AbstractFileReader::GetInputStream() const { return d->m_Stream; } MimeType AbstractFileReader::GetRegisteredMimeType() const { return d->GetRegisteredMimeType(); } IFileReader::Options AbstractFileReader::GetOptions() const { return d->GetOptions(); } us::Any AbstractFileReader::GetOption(const std::string& name) const { return d->GetOption(name); } void AbstractFileReader::SetOptions(const Options& options) { d->SetOptions(options); } void AbstractFileReader::SetOption(const std::string& name, const us::Any& value) { d->SetOption(name, value); } ////////////////// MISC ////////////////// void AbstractFileReader::AddProgressCallback(const ProgressCallback& callback) { d->AddProgressCallback(callback); } void AbstractFileReader::RemoveProgressCallback(const ProgressCallback& callback) { d->RemoveProgressCallback(callback); } ////////////////// µS related Getters ////////////////// -CustomMimeType AbstractFileReader::GetMimeType() const +const CustomMimeType* AbstractFileReader::GetMimeType() const { return d->GetMimeType(); } void AbstractFileReader::SetMimeTypePrefix(const std::string& prefix) { d->SetMimeTypePrefix(prefix); } std::string AbstractFileReader::GetMimeTypePrefix() const { return d->GetMimeTypePrefix(); } std::string AbstractFileReader::GetDescription() const { return d->GetDescription(); } void AbstractFileReader::SetDefaultDataNodeProperties(DataNode* node, const std::string& filePath) { // path if (!filePath.empty()) { mitk::StringProperty::Pointer pathProp = mitk::StringProperty::New( itksys::SystemTools::GetFilenamePath(filePath) ); node->SetProperty(StringProperty::PATH, pathProp); } // name already defined? mitk::StringProperty::Pointer nameProp = dynamic_cast(node->GetProperty("name")); if(nameProp.IsNull() || (strcmp(nameProp->GetValue(),"No Name!")==0)) { // name already defined in BaseData mitk::StringProperty::Pointer baseDataNameProp = dynamic_cast(node->GetData()->GetProperty("name").GetPointer() ); if(baseDataNameProp.IsNull() || (strcmp(baseDataNameProp->GetValue(),"No Name!")==0)) { // name neither defined in node, nor in BaseData -> name = filebasename; nameProp = mitk::StringProperty::New(itksys::SystemTools::GetFilenameWithoutExtension(itksys::SystemTools::GetFilenameName(filePath))); node->SetProperty("name", nameProp); } else { // name defined in BaseData! nameProp = mitk::StringProperty::New(baseDataNameProp->GetValue()); node->SetProperty("name", nameProp); } } // visibility if(!node->GetProperty("visible")) { node->SetVisibility(true); } } } diff --git a/Core/Code/IO/mitkAbstractFileReader.h b/Core/Code/IO/mitkAbstractFileReader.h index de905aa836..dbcccfa3d3 100644 --- a/Core/Code/IO/mitkAbstractFileReader.h +++ b/Core/Code/IO/mitkAbstractFileReader.h @@ -1,231 +1,231 @@ /*=================================================================== 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 AbstractFileReader_H_HEADER_INCLUDED_C1E7E521 #define AbstractFileReader_H_HEADER_INCLUDED_C1E7E521 // Macro #include // MITK #include #include #include // Microservices #include #include #include namespace us { struct PrototypeServiceFactory; } namespace mitk { class CustomMimeType; /** * @brief Base class for creating mitk::BaseData objects from files or streams. * @ingroup IO */ class MITK_CORE_EXPORT AbstractFileReader : public mitk::IFileReader { public: virtual void SetInput(const std::string& location); virtual void SetInput(const std::string &location, std::istream* is); virtual std::string GetInputLocation() const; virtual std::istream* GetInputStream() const; MimeType GetRegisteredMimeType() const; /** * @brief Reads a path or stream and creates a list of BaseData objects. * * This method must be implemented for each specific reader. Call * GetInputStream() first and check for a non-null stream to read from. * If the input stream is \c NULL, use GetInputLocation() to read from a local * file-system path. * * If the reader cannot use streams directly, use GetLocalFileName() instead. * * @return The created BaseData objects. * @throws mitk::Exception * * @see GetLocalFileName() * @see IFileReader::Read() */ virtual std::vector > Read() = 0; virtual DataStorage::SetOfObjects::Pointer Read(mitk::DataStorage& ds); virtual ConfidenceLevel GetConfidenceLevel() const; virtual Options GetOptions() const; virtual us::Any GetOption(const std::string &name) const; virtual void SetOptions(const Options& options); virtual void SetOption(const std::string& name, const us::Any& value); virtual void AddProgressCallback(const ProgressCallback& callback); virtual void RemoveProgressCallback(const ProgressCallback& callback); /** * Associate this reader with the MIME type returned by the current IMimeTypeProvider * service for the provided extension if the MIME type exists, otherwise registers * a new MIME type when RegisterService() is called. * * If no MIME type for \c extension is already registered, a call to RegisterService() * will register a new MIME type and associate this reader instance with it. The MIME * type id can be set via SetMimeType() or it will be auto-generated using \c extension, * having the form "application/vnd.mitk.". * * @param extension The file extension (without a leading period) for which a registered * mime-type object is looked up and associated with this reader instance. * @param description A human readable description of this reader. */ us::ServiceRegistration RegisterService(us::ModuleContext* context = us::GetModuleContext()); void UnregisterService(); protected: /** * @brief An input stream wrapper. * * If a reader can only work with input streams, use an instance * of this class to either wrap the specified input stream or * create a new input stream based on the input location in the * file system. */ class InputStream : public std::istream { public: InputStream(IFileReader* writer, std::ios_base::openmode mode = std::ios_base::in); ~InputStream(); private: std::istream* m_Stream; }; AbstractFileReader(); ~AbstractFileReader(); AbstractFileReader(const AbstractFileReader& other); /** * Associate this reader instance with the given MIME type. * * If \c mimeType does not provide an extension list, an already * registered mime-type object is used. Otherwise, the first entry in * the extensions list is used to construct a mime-type name and * register it as a new CustomMimeType service object in the default * implementation of RegisterMimeType(). * * @param mimeType The mime type this reader can read. * @param description A human readable description of this reader. * * @throws std::invalid_argument if \c mimeType is empty. * * @see RegisterService */ explicit AbstractFileReader(const CustomMimeType& mimeType, const std::string& description); virtual us::ServiceProperties GetServiceProperties() const; /** * Registers a new CustomMimeType service object. * * This method is called from RegisterService and the default implementation * registers a new mime-type service object if all of the following conditions * are true: * * - TODO * * @param context * @return * @throws std::invalid_argument if \c context is NULL. */ virtual us::ServiceRegistration RegisterMimeType(us::ModuleContext* context); void SetMimeType(const CustomMimeType& mimeType); /** * @return The mime-type this reader can handle. */ - CustomMimeType GetMimeType() const; + const CustomMimeType* GetMimeType() const; void SetMimeTypePrefix(const std::string& prefix); std::string GetMimeTypePrefix() const; void SetDescription(const std::string& description); std::string GetDescription() const; void SetDefaultOptions(const Options& defaultOptions); Options GetDefaultOptions() const; /** * \brief Set the service ranking for this file reader. * * Default is zero and should only be chosen differently for a reason. * The ranking is used to determine which reader to use if several * equivalent readers have been found. * It may be used to replace a default reader from MITK in your own project. * E.g. if you want to use your own reader for nrrd files instead of the default, * implement it and give it a higher ranking than zero. */ void SetRanking(int ranking); int GetRanking() const; /** * @brief Get a local file name for reading. * * This is a convenience method for readers which cannot work natively * with input streams. If no input stream has been been set, * this method just returns the result of GetLocation(). However, if * SetLocation(std::string, std::istream*) has been called with a non-null * input stream, this method writes the contents of the stream to a temporary * file and returns the name of the temporary file. * * The temporary file is deleted when either SetLocation(std::string, std::istream*) * is called again with a different input stream or the destructor of this * class is called. * * This method does not validate file names set via SetInput(std::string). * * @return A file path in the local file-system for reading. */ std::string GetLocalFileName() const; virtual void SetDefaultDataNodeProperties(DataNode* node, const std::string& filePath); private: AbstractFileReader& operator=(const AbstractFileReader& other); virtual mitk::IFileReader* Clone() const = 0; class Impl; std::auto_ptr d; }; } // namespace mitk #endif /* AbstractFileReader_H_HEADER_INCLUDED_C1E7E521 */ diff --git a/Core/Code/IO/mitkAbstractFileWriter.cpp b/Core/Code/IO/mitkAbstractFileWriter.cpp index 0fa5c0a066..41b7c5e4df 100644 --- a/Core/Code/IO/mitkAbstractFileWriter.cpp +++ b/Core/Code/IO/mitkAbstractFileWriter.cpp @@ -1,395 +1,395 @@ /*=================================================================== 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 #include #include #include #include #include #include #include #include #include namespace mitk { struct AbstractFileWriter::LocalFile::Impl { Impl(const std::string& location, std::ostream* os) : m_Location(location) , m_Stream(os) {} std::string m_Location; std::string m_TmpFileName; std::ostream* m_Stream; }; AbstractFileWriter::LocalFile::LocalFile(IFileWriter *writer) : d(new Impl(writer->GetOutputLocation(), writer->GetOutputStream())) { } AbstractFileWriter::LocalFile::~LocalFile() { if (d->m_Stream && !d->m_TmpFileName.empty()) { std::ifstream ifs(d->m_TmpFileName.c_str(), std::ios_base::binary); *d->m_Stream << ifs.rdbuf(); d->m_Stream->flush(); ifs.close(); std::remove(d->m_TmpFileName.c_str()); } } std::string AbstractFileWriter::LocalFile::GetFileName() { if (d->m_Stream == NULL) { return d->m_Location; } else if (d->m_TmpFileName.empty()) { std::string ext = itksys::SystemTools::GetFilenameExtension(d->m_Location); d->m_TmpFileName = IOUtil::CreateTemporaryFile("XXXXXX" + ext); } return d->m_TmpFileName; } AbstractFileWriter::OutputStream::OutputStream(IFileWriter* writer, std::ios_base::openmode mode) : std::ostream(NULL) , m_Stream(NULL) { std::ostream* stream = writer->GetOutputStream(); if (stream) { this->init(stream->rdbuf()); } else { m_Stream = new std::ofstream(writer->GetOutputLocation().c_str(), mode); this->init(m_Stream->rdbuf()); } } AbstractFileWriter::OutputStream::~OutputStream() { delete m_Stream; } class AbstractFileWriter::Impl : public FileReaderWriterBase { public: Impl() : FileReaderWriterBase() , m_BaseData(NULL) , m_Stream(NULL) , m_PrototypeFactory(NULL) {} Impl(const Impl& other) : FileReaderWriterBase(other) , m_BaseDataType(other.m_BaseDataType) , m_BaseData(NULL) , m_Stream(NULL) , m_PrototypeFactory(NULL) {} std::string m_BaseDataType; const BaseData* m_BaseData; std::string m_Location; std::ostream* m_Stream; us::PrototypeServiceFactory* m_PrototypeFactory; us::ServiceRegistration m_Reg; }; void AbstractFileWriter::SetInput(const BaseData* data) { d->m_BaseData = data; } const BaseData* AbstractFileWriter::GetInput() const { return d->m_BaseData; } void AbstractFileWriter::SetOutputLocation(const std::string& location) { d->m_Location = location; d->m_Stream = NULL; } std::string AbstractFileWriter::GetOutputLocation() const { return d->m_Location; } void AbstractFileWriter::SetOutputStream(const std::string& location, std::ostream* os) { d->m_Location = location; d->m_Stream = os; } std::ostream* AbstractFileWriter::GetOutputStream() const { return d->m_Stream; } AbstractFileWriter::~AbstractFileWriter() { UnregisterService(); delete d->m_PrototypeFactory; } AbstractFileWriter::AbstractFileWriter(const AbstractFileWriter& other) : IFileWriter(), d(new Impl(*other.d.get())) { } AbstractFileWriter::AbstractFileWriter(const std::string& baseDataType) : d(new Impl) { d->m_BaseDataType = baseDataType; } AbstractFileWriter::AbstractFileWriter(const std::string& baseDataType, const CustomMimeType& mimeType, const std::string& description) : d(new Impl) { d->m_BaseDataType = baseDataType; d->SetMimeType(mimeType); d->SetDescription(description); } ////////////////////// Writing ///////////////////////// IFileWriter::ConfidenceLevel AbstractFileWriter::GetConfidenceLevel() const { if (d->m_BaseData == NULL) return Unsupported; std::vector classHierarchy = d->m_BaseData->GetClassHierarchy(); if (std::find(classHierarchy.begin(), classHierarchy.end(), d->m_BaseDataType) == classHierarchy.end()) { return Unsupported; } return Supported; } MimeType AbstractFileWriter::GetRegisteredMimeType() const { return d->GetRegisteredMimeType(); } //////////// µS Registration & Properties ////////////// us::ServiceRegistration AbstractFileWriter::RegisterService(us::ModuleContext* context) { if (d->m_PrototypeFactory) return us::ServiceRegistration(); if(context == NULL) { context = us::GetModuleContext(); } d->RegisterMimeType(context); - if (this->GetMimeType().GetName().empty()) + if (this->GetMimeType()->GetName().empty()) { MITK_WARN << "Not registering writer due to empty MIME type."; return us::ServiceRegistration(); } struct PrototypeFactory : public us::PrototypeServiceFactory { AbstractFileWriter* const m_Prototype; PrototypeFactory(AbstractFileWriter* prototype) : m_Prototype(prototype) {} us::InterfaceMap GetService(us::Module* /*module*/, const us::ServiceRegistrationBase& /*registration*/) { return us::MakeInterfaceMap(m_Prototype->Clone()); } void UngetService(us::Module* /*module*/, const us::ServiceRegistrationBase& /*registration*/, const us::InterfaceMap& service) { delete us::ExtractInterface(service); } }; d->m_PrototypeFactory = new PrototypeFactory(this); us::ServiceProperties props = this->GetServiceProperties(); d->m_Reg = context->RegisterService(d->m_PrototypeFactory, props); return d->m_Reg; } void AbstractFileWriter::UnregisterService() { try { d->m_Reg.Unregister(); } catch (const std::exception&) {} } us::ServiceProperties AbstractFileWriter::GetServiceProperties() const { us::ServiceProperties result; result[IFileWriter::PROP_DESCRIPTION()] = this->GetDescription(); - result[IFileWriter::PROP_MIMETYPE()] = this->GetMimeType().GetName(); + result[IFileWriter::PROP_MIMETYPE()] = this->GetMimeType()->GetName(); result[IFileWriter::PROP_BASEDATA_TYPE()] = d->m_BaseDataType; result[us::ServiceConstants::SERVICE_RANKING()] = this->GetRanking(); // for (IFileWriter::OptionList::const_iterator it = d->m_Options.begin(); it != d->m_Options.end(); ++it) // { // result[it->first] = std::string("true"); // } return result; } -CustomMimeType AbstractFileWriter::GetMimeType() const +const CustomMimeType* AbstractFileWriter::GetMimeType() const { return d->GetMimeType(); } void AbstractFileWriter::SetMimeTypePrefix(const std::string& prefix) { d->SetMimeTypePrefix(prefix); } std::string AbstractFileWriter::GetMimeTypePrefix() const { return d->GetMimeTypePrefix(); } us::ServiceRegistration AbstractFileWriter::RegisterMimeType(us::ModuleContext* context) { return d->RegisterMimeType(context); } void AbstractFileWriter::SetMimeType(const CustomMimeType& mimeType) { d->SetMimeType(mimeType); } void AbstractFileWriter::SetRanking(int ranking) { d->SetRanking(ranking); } //////////////////////// Options /////////////////////// void AbstractFileWriter::SetDefaultOptions(const IFileWriter::Options& defaultOptions) { d->SetDefaultOptions(defaultOptions); } IFileWriter::Options AbstractFileWriter::GetDefaultOptions() const { return d->GetDefaultOptions(); } IFileWriter::Options AbstractFileWriter::GetOptions() const { return d->GetOptions(); } us::Any AbstractFileWriter::GetOption(const std::string& name) const { return d->GetOption(name); } void AbstractFileWriter::SetOption(const std::string& name, const us::Any& value) { d->SetOption(name, value); } void AbstractFileWriter::SetOptions(const Options& options) { d->SetOptions(options); } ////////////////// MISC ////////////////// void AbstractFileWriter::AddProgressCallback(const ProgressCallback& callback) { d->AddProgressCallback(callback); } void AbstractFileWriter::RemoveProgressCallback(const ProgressCallback& callback) { d->RemoveProgressCallback(callback); } ////////////////// µS related Getters ////////////////// int AbstractFileWriter::GetRanking() const { return d->GetRanking(); } void AbstractFileWriter::SetBaseDataType(const std::string& baseDataType) { d->m_BaseDataType = baseDataType; } std::string AbstractFileWriter::GetDescription() const { return d->GetDescription(); } std::string AbstractFileWriter::GetBaseDataType() const { return d->m_BaseDataType; } void AbstractFileWriter::ValidateOutputLocation() const { if (this->GetOutputStream() == NULL) { // check if a file name is set and if we can write to it const std::string fileName = this->GetOutputLocation(); if (fileName.empty()) { mitkThrow() << "No output location or stream specified"; } } } void AbstractFileWriter::SetDescription(const std::string& description) { d->SetDescription(description); } } diff --git a/Core/Code/IO/mitkAbstractFileWriter.h b/Core/Code/IO/mitkAbstractFileWriter.h index a9620eff97..9cbcb55568 100644 --- a/Core/Code/IO/mitkAbstractFileWriter.h +++ b/Core/Code/IO/mitkAbstractFileWriter.h @@ -1,232 +1,232 @@ /*=================================================================== 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 AbstractFileWriter_H_HEADER_INCLUDED_C1E7E521 #define AbstractFileWriter_H_HEADER_INCLUDED_C1E7E521 // Macro #include // MITK #include #include // Microservices #include #include #include #include namespace us { struct PrototypeServiceFactory; } namespace mitk { class CustomMimeType; /** * @brief Base class for writing mitk::BaseData objects to files or streams. * * In general, all file writers should derive from this class, this way it is * made sure that the new implementation is * exposed to the Microservice-Framework and that is automatically available troughout MITK. * The default implementation only requires one Write() * method and the Clone() method to be implemented. * * @ingroup IO */ class MITK_CORE_EXPORT AbstractFileWriter : public mitk::IFileWriter { public: virtual void SetInput(const BaseData* data); virtual const BaseData* GetInput() const; virtual void SetOutputLocation(const std::string& location); virtual std::string GetOutputLocation() const; virtual void SetOutputStream(const std::string& location, std::ostream* os); virtual std::ostream* GetOutputStream() const; /** * \brief Write the base data to the specified location or output stream. * * This method must be implemented for each specific writer. Call * GetOutputStream() first and check for a non-null stream to write to. * If the output stream is \c NULL, use GetOutputLocation() to write * to a local file-system path. * * If the reader cannot use streams directly, use GetLocalFile() to retrieve * a temporary local file name instead. * * \throws mitk::Exception * * \see GetLocalFile() * \see IFileWriter::Write() */ virtual void Write() = 0; virtual ConfidenceLevel GetConfidenceLevel() const; MimeType GetRegisteredMimeType() const; virtual Options GetOptions() const; virtual us::Any GetOption(const std::string &name) const; virtual void SetOptions(const Options& options); virtual void SetOption(const std::string& name, const us::Any& value); virtual void AddProgressCallback(const ProgressCallback& callback); virtual void RemoveProgressCallback(const ProgressCallback& callback); us::ServiceRegistration RegisterService(us::ModuleContext* context = us::GetModuleContext()); void UnregisterService(); protected: /** * @brief A local file representation for streams. * * If a writer can only work with local files, use an instance * of this class to get either a temporary file name for writing * to the specified output stream or the original output location * if no output stream was set. */ class LocalFile { public: LocalFile(IFileWriter* writer); // Writes to the ostream and removes the temporary file ~LocalFile(); // Creates a temporary file for output operations. std::string GetFileName(); private: // disabled LocalFile(); LocalFile(const LocalFile&); LocalFile& operator=(const LocalFile& other); struct Impl; std::auto_ptr d; }; /** * @brief An output stream wrapper. * * If a writer can only work with output streams, use an instance * of this class to either wrap the specified output stream or * create a new output stream based on the output location in the * file system. */ class OutputStream : public std::ostream { public: OutputStream(IFileWriter* writer, std::ios_base::openmode mode = std::ios_base::trunc | std::ios_base::out); ~OutputStream(); private: std::ostream* m_Stream; }; ~AbstractFileWriter(); AbstractFileWriter(const AbstractFileWriter& other); AbstractFileWriter(const std::string& baseDataType); AbstractFileWriter(const std::string& baseDataType, const CustomMimeType& mimeType, const std::string& description); virtual us::ServiceProperties GetServiceProperties() const; /** * Registers a new CustomMimeType service object. * * This method is called from RegisterService and the default implementation * registers a new mime-type service object if all of the following conditions * are true: * * - TODO * * @param context * @return * @throws std::invalid_argument if \c context is NULL. */ virtual us::ServiceRegistration RegisterMimeType(us::ModuleContext* context); void SetMimeType(const CustomMimeType& mimeType); /** * @return Get the mime-type this writer can handle. */ - CustomMimeType GetMimeType() const; + const CustomMimeType* GetMimeType() const; void SetMimeTypePrefix(const std::string& prefix); std::string GetMimeTypePrefix() const; /** * \brief Sets a human readable description of this writer. * * This will be used in file dialogs for example. */ void SetDescription(const std::string& description); std::string GetDescription() const; void SetDefaultOptions(const Options& defaultOptions); Options GetDefaultOptions() const; /** * \brief Set the service ranking for this file writer. * * Default is zero and should only be chosen differently for a reason. * The ranking is used to determine which writer to use if several * equivalent writers have been found. * It may be used to replace a default writer from MITK in your own project. * E.g. if you want to use your own writer for nrrd files instead of the default, * implement it and give it a higher ranking than zero. */ void SetRanking(int ranking); int GetRanking() const; /** * \brief Sets the name of the mitk::Basedata that this writer is able to handle. * * The correct value is the one given as the first parameter in the mitkNewMacro of that BaseData derivate. * You can also retrieve it by calling GetNameOfClass() on an instance of said data. */ void SetBaseDataType(const std::string& baseDataType); virtual std::string GetBaseDataType() const; void ValidateOutputLocation() const; private: AbstractFileWriter& operator=(const AbstractFileWriter& other); virtual mitk::IFileWriter* Clone() const = 0; class Impl; std::auto_ptr d; }; } // namespace mitk #endif /* AbstractFileWriter_H_HEADER_INCLUDED_C1E7E521 */ diff --git a/Core/Code/IO/mitkCustomMimeType.cpp b/Core/Code/IO/mitkCustomMimeType.cpp index b25349b78c..240570efdb 100644 --- a/Core/Code/IO/mitkCustomMimeType.cpp +++ b/Core/Code/IO/mitkCustomMimeType.cpp @@ -1,144 +1,165 @@ /*=================================================================== 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 "mitkCustomMimeType.h" #include "mitkMimeType.h" #include namespace mitk { struct CustomMimeType::Impl { std::string m_Name; std::string m_Category; std::vector m_Extensions; std::string m_Comment; }; CustomMimeType::~CustomMimeType() { delete d; } CustomMimeType::CustomMimeType() : d(new Impl) { } CustomMimeType::CustomMimeType(const std::string& name) : d(new Impl) { d->m_Name = name; } CustomMimeType::CustomMimeType(const CustomMimeType& other) : d(new Impl(*other.d)) { } CustomMimeType::CustomMimeType(const MimeType& other) : d(new Impl) { d->m_Name = other.GetName(); d->m_Category = other.GetCategory(); d->m_Extensions = other.GetExtensions(); d->m_Comment = other.GetComment(); } CustomMimeType& CustomMimeType::operator=(const CustomMimeType& other) { CustomMimeType tmp(other); Swap(tmp); return *this; } CustomMimeType&CustomMimeType::operator=(const MimeType& other) { CustomMimeType tmp(other); Swap(tmp); return *this; } std::string CustomMimeType::GetName() const { return d->m_Name; } std::string CustomMimeType::GetCategory() const { return d->m_Category; } std::vector CustomMimeType::GetExtensions() const { return d->m_Extensions; } std::string CustomMimeType::GetComment() const { if (!d->m_Comment.empty()) return d->m_Comment; if (!d->m_Extensions.empty()) { return d->m_Extensions.front() + " File"; } return "Unknown"; } +bool CustomMimeType::AppliesTo(const std::string& path) const +{ + for (std::vector::const_iterator iter = d->m_Extensions.begin(), + iterEnd = d->m_Extensions.end(); iter != iterEnd; ++iter) + { + if (!iter->empty() && path.size() >= iter->size()) + { + if (path.substr(path.size() - iter->size()) == *iter) + { + return true; + } + } + } + return false; +} + void CustomMimeType::SetName(const std::string& name) { d->m_Name = name; } void CustomMimeType::SetCategory(const std::string& category) { d->m_Category = category; } void CustomMimeType::SetExtension(const std::string& extension) { d->m_Extensions.clear(); d->m_Extensions.push_back(extension); } void CustomMimeType::AddExtension(const std::string& extension) { if (std::find(d->m_Extensions.begin(), d->m_Extensions.end(), extension) == d->m_Extensions.end()) { d->m_Extensions.push_back(extension); } } void CustomMimeType::SetComment(const std::string& comment) { d->m_Comment = comment; } void CustomMimeType::Swap(CustomMimeType& r) { Impl* d1 = d; d = r.d; r.d = d1; } +CustomMimeType* CustomMimeType::Clone() const +{ + return new CustomMimeType(*this); +} + void swap(CustomMimeType& l, CustomMimeType& r) { l.Swap(r); } } diff --git a/Core/Code/IO/mitkCustomMimeType.h b/Core/Code/IO/mitkCustomMimeType.h index b232c58696..2925936920 100644 --- a/Core/Code/IO/mitkCustomMimeType.h +++ b/Core/Code/IO/mitkCustomMimeType.h @@ -1,70 +1,74 @@ /*=================================================================== 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 MITKCUSTOMMIMETYPE_H #define MITKCUSTOMMIMETYPE_H #include #include #include #include namespace mitk { class MimeType; class MITK_CORE_EXPORT CustomMimeType { public: CustomMimeType(); CustomMimeType(const std::string& name); CustomMimeType(const CustomMimeType& other); explicit CustomMimeType(const MimeType& other); - ~CustomMimeType(); + virtual ~CustomMimeType(); CustomMimeType& operator=(const CustomMimeType& other); CustomMimeType& operator=(const MimeType& other); std::string GetName() const; std::string GetCategory() const; std::vector GetExtensions() const; std::string GetComment() const; + virtual bool AppliesTo(const std::string& path) const; + void SetName(const std::string& name); void SetCategory(const std::string& category); void SetExtension(const std::string& extension); void AddExtension(const std::string& extension); void SetComment(const std::string& comment); void Swap(CustomMimeType& r); + virtual CustomMimeType* Clone() const; + private: struct Impl; Impl* d; }; void swap(CustomMimeType& l, CustomMimeType& r); } US_DECLARE_SERVICE_INTERFACE(mitk::CustomMimeType, "org.mitk.CustomMimeType") #endif // MITKCUSTOMMIMETYPE_H diff --git a/Core/Code/IO/mitkFileReaderRegistry.cpp b/Core/Code/IO/mitkFileReaderRegistry.cpp index 682e6237f2..11805052d7 100644 --- a/Core/Code/IO/mitkFileReaderRegistry.cpp +++ b/Core/Code/IO/mitkFileReaderRegistry.cpp @@ -1,114 +1,114 @@ /*=================================================================== 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 "mitkFileReaderRegistry.h" #include "mitkIMimeTypeProvider.h" #include "mitkCoreServices.h" // Microservices #include #include #include #include #include "itksys/SystemTools.hxx" mitk::FileReaderRegistry::FileReaderRegistry() { } mitk::FileReaderRegistry::~FileReaderRegistry() { for (std::map >::iterator iter = m_ServiceObjects.begin(), end = m_ServiceObjects.end(); iter != end; ++iter) { iter->second.UngetService(iter->first); } } -mitk::MimeType mitk::FileReaderRegistry::GetMimeTypeForExtension(const std::string& extension, us::ModuleContext* context) +mitk::MimeType mitk::FileReaderRegistry::GetMimeTypeForFile(const std::string& path, us::ModuleContext* context) { mitk::CoreServicePointer mimeTypeProvider(mitk::CoreServices::GetMimeTypeProvider(context)); - std::vector mimeTypes = mimeTypeProvider->GetMimeTypesForExtension(extension); + std::vector mimeTypes = mimeTypeProvider->GetMimeTypesForFile(path); if (mimeTypes.empty()) { return MimeType(); } else { return mimeTypes.front(); } } std::vector mitk::FileReaderRegistry::GetReferences(const MimeType& mimeType, us::ModuleContext* context) { std::string filter = us::LDAPProp(us::ServiceConstants::OBJECTCLASS()) == us_service_interface_iid() && us::LDAPProp(IFileReader::PROP_MIMETYPE()) == mimeType.GetName(); return context->GetServiceReferences(filter); } mitk::IFileReader* mitk::FileReaderRegistry::GetReader(const mitk::FileReaderRegistry::ReaderReference& ref, us::ModuleContext* context) { us::ServiceObjects serviceObjects = context->GetServiceObjects(ref); mitk::IFileReader* reader = serviceObjects.GetService(); m_ServiceObjects.insert(std::make_pair(reader, serviceObjects)); return reader; } std::vector mitk::FileReaderRegistry::GetReaders(const MimeType& mimeType, us::ModuleContext* context ) { std::vector result; if (!mimeType.IsValid()) return result; std::vector > refs = GetReferences(mimeType, context); std::sort(refs.begin(), refs.end()); result.reserve(refs.size()); // Translate List of ServiceRefs to List of Pointers for (std::vector >::const_reverse_iterator iter = refs.rbegin(), end = refs.rend(); iter != end; ++iter) { us::ServiceObjects serviceObjects = context->GetServiceObjects(*iter); mitk::IFileReader* reader = serviceObjects.GetService(); m_ServiceObjects.insert(std::make_pair(reader, serviceObjects)); result.push_back(reader); } return result; } void mitk::FileReaderRegistry::UngetReader(mitk::IFileReader* reader) { std::map >::iterator readerIter = m_ServiceObjects.find(reader); if (readerIter != m_ServiceObjects.end()) { readerIter->second.UngetService(reader); m_ServiceObjects.erase(readerIter); } } void mitk::FileReaderRegistry::UngetReaders(const std::vector& readers) { for (std::vector::const_iterator iter = readers.begin(), end = readers.end(); iter != end; ++iter) { this->UngetReader(*iter); } } diff --git a/Core/Code/IO/mitkFileReaderRegistry.h b/Core/Code/IO/mitkFileReaderRegistry.h index b0abe285cb..6cb13d2f85 100644 --- a/Core/Code/IO/mitkFileReaderRegistry.h +++ b/Core/Code/IO/mitkFileReaderRegistry.h @@ -1,85 +1,85 @@ /*=================================================================== 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 FileReaderRegistry_H_HEADER_INCLUDED_C1E7E521 #define FileReaderRegistry_H_HEADER_INCLUDED_C1E7E521 #include #include #include // Microservices #include #include #include namespace mitk { class MimeType; /** * @ingroup IO * * Provides convenient access to mitk::IFileReader instances and reading * files into mitk::BaseData types. * * \note The life-time of all mitk::IFileReader objects returned by an * instance of this class ends with the destruction of that instance. */ class MITK_CORE_EXPORT FileReaderRegistry { public: typedef us::ServiceReference ReaderReference; FileReaderRegistry(); ~FileReaderRegistry(); /** - * @brief Get the highest ranked mime-type for the given extension. + * @brief Get the highest ranked mime-type for the given file name. * @param extension A file name extension without a leading dot. * @param context * @return The highest ranked mime-type containing \c extension in * its extension list. */ - static MimeType GetMimeTypeForExtension(const std::string& extension, us::ModuleContext* context = us::GetModuleContext()); + static MimeType GetMimeTypeForFile(const std::string& path, us::ModuleContext* context = us::GetModuleContext()); static std::vector GetReferences(const MimeType& mimeType, us::ModuleContext* context = us::GetModuleContext()); mitk::IFileReader* GetReader(const ReaderReference& ref, us::ModuleContext* context = us::GetModuleContext()); std::vector GetReaders(const MimeType& mimeType, us::ModuleContext* context = us::GetModuleContext()); void UngetReader(mitk::IFileReader* reader); void UngetReaders(const std::vector& readers); private: // purposely not implemented FileReaderRegistry(const FileReaderRegistry&); FileReaderRegistry& operator=(const FileReaderRegistry&); std::map > m_ServiceObjects; }; } // namespace mitk #endif /* FileReaderRegistry_H_HEADER_INCLUDED_C1E7E521 */ diff --git a/Core/Code/IO/mitkFileWriterSelector.cpp b/Core/Code/IO/mitkFileWriterSelector.cpp index 86ff419f0b..77e59bf989 100644 --- a/Core/Code/IO/mitkFileWriterSelector.cpp +++ b/Core/Code/IO/mitkFileWriterSelector.cpp @@ -1,360 +1,356 @@ /*=================================================================== 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 "mitkFileWriterSelector.h" #include #include #include #include #include #include #include #include #include #include #include namespace mitk { struct FileWriterSelector::Item::Impl : us::SharedData { Impl() : m_FileWriter(NULL) , m_ConfidenceLevel(IFileWriter::Unsupported) , m_BaseDataIndex(0) , m_Id(-1) {} us::ServiceReference m_FileWriterRef; IFileWriter* m_FileWriter; IFileWriter::ConfidenceLevel m_ConfidenceLevel; std::size_t m_BaseDataIndex; MimeType m_MimeType; long m_Id; }; struct FileWriterSelector::Impl : us::SharedData { Impl() : m_BestId(-1) , m_SelectedId(m_BestId) {} Impl(const Impl& other) : us::SharedData(other) , m_BestId(-1) , m_SelectedId(m_BestId) {} FileWriterRegistry m_WriterRegistry; std::map m_Items; std::set m_MimeTypes; long m_BestId; long m_SelectedId; }; FileWriterSelector::FileWriterSelector(const FileWriterSelector& other) : m_Data(other.m_Data) { } FileWriterSelector::FileWriterSelector(const BaseData* baseData, const std::string& mimeType, const std::string& path) : m_Data(new Impl) { mitk::CoreServicePointer mimeTypeProvider(mitk::CoreServices::GetMimeTypeProvider()); std::string destMimeType = mimeType; if (destMimeType.empty() && !path.empty()) { - // try to derive a mime-type from the extension - std::string ext = itksys::SystemTools::GetFilenameExtension(path); - if (ext.size() > 1) + // try to derive a mime-type from the file + std::vector mimeTypes = mimeTypeProvider->GetMimeTypesForFile(path); + if (!mimeTypes.empty()) { - std::vector mimeTypes = mimeTypeProvider->GetMimeTypesForExtension(ext.substr(1)); - if (!mimeTypes.empty()) - { - destMimeType = mimeTypes.front().GetName(); - } - else - { - // if both mimeType is empty and path does not contain a known - // extension, we stop here - return; - } + destMimeType = mimeTypes.front().GetName(); + } + else if (!itksys::SystemTools::GetFilenameExtension(path).empty()) + { + // If there are no suitable mime-type for the file AND an extension + // was supplied, we stop here. + return; } } std::vector classHierarchy = baseData->GetClassHierarchy(); // Get all writers and their mime types for the given base data type std::vector refs = m_Data->m_WriterRegistry.GetReferences(baseData, destMimeType); Item bestItem; for (std::vector::const_iterator iter = refs.begin(), iterEnd = refs.end(); iter != iterEnd; ++iter) { std::string mimeTypeName = iter->GetProperty(IFileWriter::PROP_MIMETYPE()).ToString(); if (!mimeTypeName.empty()) { MimeType mimeType = mimeTypeProvider->GetMimeTypeForName(mimeTypeName); if (mimeType.IsValid()) { // There is a registered mime-type for this writer. Now get the confidence level // of this writer for writing the given base data object. IFileWriter* writer = m_Data->m_WriterRegistry.GetWriter(*iter); if (writer == NULL) continue; try { writer->SetInput(baseData); IFileWriter::ConfidenceLevel confidenceLevel = writer->GetConfidenceLevel(); if (confidenceLevel == IFileWriter::Unsupported) { continue; } std::string baseDataType = iter->GetProperty(IFileWriter::PROP_BASEDATA_TYPE()).ToString(); std::vector::iterator idxIter = std::find(classHierarchy.begin(), classHierarchy.end(), baseDataType); std::size_t baseDataIndex = std::numeric_limits::max(); if (idxIter != classHierarchy.end()) { baseDataIndex = std::distance(classHierarchy.begin(), idxIter); } Item item; item.d->m_FileWriterRef = *iter; item.d->m_FileWriter = writer; item.d->m_ConfidenceLevel = confidenceLevel; item.d->m_BaseDataIndex = baseDataIndex; item.d->m_MimeType = mimeType; item.d->m_Id = us::any_cast(iter->GetProperty(us::ServiceConstants::SERVICE_ID())); m_Data->m_Items.insert(std::make_pair(item.d->m_Id, item)); m_Data->m_MimeTypes.insert(mimeType); if (!bestItem.GetReference() || bestItem < item) { bestItem = item; } } catch (const us::BadAnyCastException& e) { MITK_WARN << "Unexpected: " << e.what(); } catch (const std::exception& e) { // Log the error but continue MITK_WARN << "IFileWriter::GetConfidenceLevel exception: " << e.what(); } } } } if (bestItem.GetReference()) { m_Data->m_BestId = bestItem.GetServiceId(); m_Data->m_SelectedId = m_Data->m_BestId; } } FileWriterSelector::~FileWriterSelector() { } FileWriterSelector& FileWriterSelector::operator=(const FileWriterSelector& other) { m_Data = other.m_Data; return *this; } bool FileWriterSelector::IsEmpty() const { return m_Data->m_Items.empty(); } std::vector FileWriterSelector::Get(const std::string& mimeType) const { std::vector result; for (std::map::const_iterator iter = m_Data->m_Items.begin(), iterEnd = m_Data->m_Items.end(); iter != iterEnd; ++iter) { if (mimeType.empty() || iter->second.GetMimeType().GetName() == mimeType) { result.push_back(iter->second); } } std::sort(result.begin(), result.end()); return result; } std::vector FileWriterSelector::Get() const { return Get(this->GetSelected().d->m_MimeType.GetName()); } FileWriterSelector::Item FileWriterSelector::Get(long id) const { std::map::const_iterator iter = m_Data->m_Items.find(id); if (iter != m_Data->m_Items.end()) { return iter->second; } return Item(); } FileWriterSelector::Item FileWriterSelector::GetDefault() const { return Get(m_Data->m_BestId); } long FileWriterSelector::GetDefaultId() const { return m_Data->m_BestId; } FileWriterSelector::Item FileWriterSelector::GetSelected() const { return Get(m_Data->m_SelectedId); } long FileWriterSelector::GetSelectedId() const { return m_Data->m_SelectedId; } bool FileWriterSelector::Select(const std::string& mimeType) { std::vector items = Get(mimeType); if (items.empty()) return false; return Select(items.back()); } bool FileWriterSelector::Select(const FileWriterSelector::Item& item) { return Select(item.d->m_Id); } bool FileWriterSelector::Select(long id) { if (id > -1) { if (m_Data->m_Items.find(id) == m_Data->m_Items.end()) { return false; } m_Data->m_SelectedId = id; return true; } return false; } std::vector FileWriterSelector::GetMimeTypes() const { std::vector result; result.reserve(m_Data->m_MimeTypes.size()); result.assign(m_Data->m_MimeTypes.begin(), m_Data->m_MimeTypes.end()); return result; } void FileWriterSelector::Swap(FileWriterSelector& fws) { m_Data.Swap(fws.m_Data); } FileWriterSelector::Item::Item(const FileWriterSelector::Item& other) : d(other.d) { } FileWriterSelector::Item::~Item() { } FileWriterSelector::Item& FileWriterSelector::Item::operator=(const FileWriterSelector::Item& other) { d = other.d; return *this; } IFileWriter* FileWriterSelector::Item::GetWriter() const { return d->m_FileWriter; } std::string FileWriterSelector::Item::GetDescription() const { us::Any descr = d->m_FileWriterRef.GetProperty(IFileWriter::PROP_DESCRIPTION()); if (descr.Empty()) return std::string(); return descr.ToString(); } IFileWriter::ConfidenceLevel FileWriterSelector::Item::GetConfidenceLevel() const { return d->m_ConfidenceLevel; } MimeType FileWriterSelector::Item::GetMimeType() const { return d->m_MimeType; } std::string FileWriterSelector::Item::GetBaseDataType() const { us::Any any = d->m_FileWriterRef.GetProperty(IFileWriter::PROP_BASEDATA_TYPE()); if (any.Empty()) return std::string(); return any.ToString(); } us::ServiceReference FileWriterSelector::Item::GetReference() const { return d->m_FileWriterRef; } long FileWriterSelector::Item::GetServiceId() const { return d->m_Id; } bool FileWriterSelector::Item::operator<(const FileWriterSelector::Item& other) const { // sort by confidence level first (ascending) if (d->m_ConfidenceLevel == other.d->m_ConfidenceLevel) { // sort by class hierarchy index (writers for more derived // based data types are considered a better match) if (d->m_BaseDataIndex == other.d->m_BaseDataIndex) { // sort by file writer service ranking return d->m_FileWriterRef < other.d->m_FileWriterRef; } return other.d->m_BaseDataIndex < d->m_BaseDataIndex; } return d->m_ConfidenceLevel < other.d->m_ConfidenceLevel; } FileWriterSelector::Item::Item() : d(new Impl()) {} void swap(FileWriterSelector& fws1, FileWriterSelector& fws2) { fws1.Swap(fws2); } } diff --git a/Core/Code/IO/mitkIOMimeTypes.cpp b/Core/Code/IO/mitkIOMimeTypes.cpp index cd2e7c6023..df0e75c388 100644 --- a/Core/Code/IO/mitkIOMimeTypes.cpp +++ b/Core/Code/IO/mitkIOMimeTypes.cpp @@ -1,225 +1,280 @@ /*=================================================================== 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 "mitkIOMimeTypes.h" #include "mitkCustomMimeType.h" +#include "itkGDCMImageIO.h" + namespace mitk { -std::vector IOMimeTypes::Get() +IOMimeTypes::DicomMimeType::DicomMimeType() + : CustomMimeType(DICOM_MIMETYPE_NAME()) +{ + this->AddExtension("gdcm"); + this->AddExtension("dcm"); + this->AddExtension("DCM"); + this->AddExtension("dc3"); + this->AddExtension("DC3"); + this->AddExtension("ima"); + this->AddExtension("img"); + + this->SetCategory(CATEGORY_IMAGES()); + this->SetComment("DICOM"); +} + +bool IOMimeTypes::DicomMimeType::AppliesTo(const std::string &path) const +{ + if (CustomMimeType::AppliesTo(path)) return true; + // Ask the GDCM ImageIO class directly + itk::GDCMImageIO::Pointer gdcmIO = itk::GDCMImageIO::New(); + return gdcmIO->CanReadFile(path.c_str()); +} + +IOMimeTypes::DicomMimeType* IOMimeTypes::DicomMimeType::Clone() const { - std::vector mimeTypes; + return new DicomMimeType(*this); +} + +std::vector IOMimeTypes::Get() +{ + std::vector mimeTypes; // order matters here (descending rank for mime types) - mimeTypes.push_back(NRRD_MIMETYPE()); - mimeTypes.push_back(NIFTI_MIMETYPE()); + mimeTypes.push_back(NRRD_MIMETYPE().Clone()); + mimeTypes.push_back(NIFTI_MIMETYPE().Clone()); + + mimeTypes.push_back(VTK_IMAGE_MIMETYPE().Clone()); + mimeTypes.push_back(VTK_PARALLEL_IMAGE_MIMETYPE().Clone()); + mimeTypes.push_back(VTK_IMAGE_LEGACY_MIMETYPE().Clone()); - mimeTypes.push_back(VTK_IMAGE_MIMETYPE()); - mimeTypes.push_back(VTK_PARALLEL_IMAGE_MIMETYPE()); - mimeTypes.push_back(VTK_IMAGE_LEGACY_MIMETYPE()); + mimeTypes.push_back(DICOM_MIMETYPE().Clone()); - mimeTypes.push_back(VTK_POLYDATA_MIMETYPE()); - mimeTypes.push_back(VTK_PARALLEL_POLYDATA_MIMETYPE()); - mimeTypes.push_back(VTK_POLYDATA_LEGACY_MIMETYPE()); + mimeTypes.push_back(VTK_POLYDATA_MIMETYPE().Clone()); + mimeTypes.push_back(VTK_PARALLEL_POLYDATA_MIMETYPE().Clone()); + mimeTypes.push_back(VTK_POLYDATA_LEGACY_MIMETYPE().Clone()); - mimeTypes.push_back(STEREOLITHOGRAPHY_MIMETYPE()); + mimeTypes.push_back(STEREOLITHOGRAPHY_MIMETYPE().Clone()); - mimeTypes.push_back(RAW_MIMETYPE()); - mimeTypes.push_back(POINTSET_MIMETYPE()); + mimeTypes.push_back(RAW_MIMETYPE().Clone()); + mimeTypes.push_back(POINTSET_MIMETYPE().Clone()); return mimeTypes; } CustomMimeType IOMimeTypes::VTK_IMAGE_MIMETYPE() { CustomMimeType mimeType(VTK_IMAGE_NAME()); mimeType.AddExtension("vti"); - mimeType.SetCategory("Images"); + mimeType.SetCategory(CATEGORY_IMAGES()); mimeType.SetComment("VTK Image"); return mimeType; } CustomMimeType IOMimeTypes::VTK_IMAGE_LEGACY_MIMETYPE() { CustomMimeType mimeType(VTK_IMAGE_LEGACY_NAME()); mimeType.AddExtension("vtk"); - mimeType.SetCategory("Images"); + mimeType.SetCategory(CATEGORY_IMAGES()); mimeType.SetComment("VTK Legacy Image"); return mimeType; } CustomMimeType IOMimeTypes::VTK_PARALLEL_IMAGE_MIMETYPE() { CustomMimeType mimeType(VTK_PARALLEL_IMAGE_NAME()); mimeType.AddExtension("pvti"); - mimeType.SetCategory("Images"); + mimeType.SetCategory(CATEGORY_IMAGES()); mimeType.SetComment("VTK Parallel Image"); return mimeType; } CustomMimeType IOMimeTypes::VTK_POLYDATA_MIMETYPE() { CustomMimeType mimeType(VTK_POLYDATA_NAME()); mimeType.AddExtension("vtp"); - mimeType.SetCategory("Surfaces"); + mimeType.SetCategory(CATEGORY_SURFACES()); mimeType.SetComment("VTK PolyData"); return mimeType; } CustomMimeType IOMimeTypes::VTK_POLYDATA_LEGACY_MIMETYPE() { CustomMimeType mimeType(VTK_POLYDATA_LEGACY_NAME()); mimeType.AddExtension("vtk"); - mimeType.SetCategory("Surfaces"); + mimeType.SetCategory(CATEGORY_SURFACES()); mimeType.SetComment("VTK Legacy PolyData"); return mimeType; } CustomMimeType IOMimeTypes::VTK_PARALLEL_POLYDATA_MIMETYPE() { CustomMimeType mimeType(VTK_PARALLEL_POLYDATA_NAME()); mimeType.AddExtension("pvtp"); - mimeType.SetCategory("Surfaces"); + mimeType.SetCategory(CATEGORY_SURFACES()); mimeType.SetComment("VTK Parallel PolyData"); return mimeType; } CustomMimeType IOMimeTypes::STEREOLITHOGRAPHY_MIMETYPE() { CustomMimeType mimeType(STEREOLITHOGRAPHY_NAME()); mimeType.AddExtension("stl"); - mimeType.SetCategory("Surfaces"); + mimeType.SetCategory(CATEGORY_SURFACES()); mimeType.SetComment("Stereolithography"); return mimeType; } std::string IOMimeTypes::STEREOLITHOGRAPHY_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".stl"; return name; } std::string IOMimeTypes::DEFAULT_BASE_NAME() { static std::string name = "application/vnd.mitk"; return name; } +std::string IOMimeTypes::CATEGORY_IMAGES() +{ + static std::string cat = "Images"; + return cat; +} + +std::string IOMimeTypes::CATEGORY_SURFACES() +{ + static std::string cat = "Surfaces"; + return cat; +} + std::string IOMimeTypes::VTK_IMAGE_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".vtk.image"; return name; } std::string IOMimeTypes::VTK_IMAGE_LEGACY_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".vtk.image.legacy"; return name; } std::string IOMimeTypes::VTK_PARALLEL_IMAGE_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".vtk.parallel.image"; return name; } std::string IOMimeTypes::VTK_POLYDATA_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".vtk.polydata"; return name; } std::string IOMimeTypes::VTK_POLYDATA_LEGACY_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".vtk.polydata.legacy"; return name; } std::string IOMimeTypes::VTK_PARALLEL_POLYDATA_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".vtk.parallel.polydata"; return name; } CustomMimeType IOMimeTypes::NRRD_MIMETYPE() { CustomMimeType mimeType(NRRD_MIMETYPE_NAME()); mimeType.AddExtension("nrrd"); mimeType.AddExtension("nhdr"); mimeType.SetCategory("Images"); mimeType.SetComment("NRRD"); return mimeType; } CustomMimeType IOMimeTypes::NIFTI_MIMETYPE() { CustomMimeType mimeType(NIFTI_MIMETYPE_NAME()); mimeType.AddExtension("nii"); mimeType.AddExtension("nii.gz"); mimeType.AddExtension("hdr"); mimeType.AddExtension("img"); mimeType.AddExtension("img.gz"); mimeType.AddExtension("img.gz"); mimeType.AddExtension("nia"); mimeType.SetCategory("Images"); mimeType.SetComment("Nifti"); return mimeType; } CustomMimeType IOMimeTypes::RAW_MIMETYPE() { CustomMimeType mimeType(RAW_MIMETYPE_NAME()); mimeType.AddExtension("raw"); mimeType.SetCategory("Images"); mimeType.SetComment("Raw data"); return mimeType; } +IOMimeTypes::DicomMimeType IOMimeTypes::DICOM_MIMETYPE() +{ + return DicomMimeType(); +} + std::string IOMimeTypes::NRRD_MIMETYPE_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".image.nrrd"; return name; } std::string IOMimeTypes::NIFTI_MIMETYPE_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".image.nifti"; return name; } std::string IOMimeTypes::RAW_MIMETYPE_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".image.raw"; return name; } +std::string IOMimeTypes::DICOM_MIMETYPE_NAME() +{ + static std::string name = DEFAULT_BASE_NAME() + ".image.dicom"; + return name; +} + CustomMimeType IOMimeTypes::POINTSET_MIMETYPE() { CustomMimeType mimeType(POINTSET_MIMETYPE_NAME()); mimeType.AddExtension("mps"); mimeType.SetCategory("Point Sets"); mimeType.SetComment("MITK Point Set"); return mimeType; } std::string IOMimeTypes::POINTSET_MIMETYPE_NAME() { static std::string name = DEFAULT_BASE_NAME() + ".pointset"; return name; } } diff --git a/Core/Code/IO/mitkIOMimeTypes.h b/Core/Code/IO/mitkIOMimeTypes.h index 7645aadeab..8898ba4fcd 100644 --- a/Core/Code/IO/mitkIOMimeTypes.h +++ b/Core/Code/IO/mitkIOMimeTypes.h @@ -1,77 +1,90 @@ /*=================================================================== 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 MITKIOMIMETYPES_H #define MITKIOMIMETYPES_H #include "mitkCustomMimeType.h" #include namespace mitk { -class IOMimeTypes +class MITK_CORE_EXPORT IOMimeTypes { public: - static std::vector Get(); + class MITK_CORE_EXPORT DicomMimeType : public CustomMimeType + { + public: + DicomMimeType(); + virtual bool AppliesTo(const std::string &path) const; + virtual DicomMimeType* Clone() const; + }; + + static std::vector Get(); static std::string DEFAULT_BASE_NAME(); // application/vnd.mitk + static std::string CATEGORY_IMAGES(); // Images + static std::string CATEGORY_SURFACES(); // Surfaces + // ------------------------------ VTK formats ---------------------------------- static CustomMimeType VTK_IMAGE_MIMETYPE(); // (mitk::Image) vti static CustomMimeType VTK_IMAGE_LEGACY_MIMETYPE(); // (mitk::Image) vtk static CustomMimeType VTK_PARALLEL_IMAGE_MIMETYPE(); // (mitk::Image) pvti static CustomMimeType VTK_POLYDATA_MIMETYPE(); // (mitk::Surface) vtp, vtk static CustomMimeType VTK_POLYDATA_LEGACY_MIMETYPE(); // (mitk::Surface) vtk static CustomMimeType VTK_PARALLEL_POLYDATA_MIMETYPE(); // (mitk::Surface) pvtp static CustomMimeType STEREOLITHOGRAPHY_MIMETYPE(); // (mitk::Surface) stl static std::string STEREOLITHOGRAPHY_NAME(); // DEFAULT_BASE_NAME.stl static std::string VTK_IMAGE_NAME(); // DEFAULT_BASE_NAME.vtk.image static std::string VTK_IMAGE_LEGACY_NAME(); // DEFAULT_BASE_NAME.vtk.image.legacy static std::string VTK_PARALLEL_IMAGE_NAME(); // DEFAULT_BASE_NAME.vtk.parallel.image static std::string VTK_POLYDATA_NAME(); // DEFAULT_BASE_NAME.vtk.polydata static std::string VTK_POLYDATA_LEGACY_NAME(); // DEFAULT_BASE_NAME.vtk.polydata.legacy static std::string VTK_PARALLEL_POLYDATA_NAME(); // DEFAULT_BASE_NAME.vtk.parallel.polydata // ------------------------- Image formats (ITK based) -------------------------- static CustomMimeType NRRD_MIMETYPE(); // nrrd, nhdr static CustomMimeType NIFTI_MIMETYPE(); static CustomMimeType RAW_MIMETYPE(); // raw + static DicomMimeType DICOM_MIMETYPE(); static std::string NRRD_MIMETYPE_NAME(); // DEFAULT_BASE_NAME.nrrd static std::string NIFTI_MIMETYPE_NAME(); static std::string RAW_MIMETYPE_NAME(); // DEFAULT_BASE_NAME.raw + static std::string DICOM_MIMETYPE_NAME(); // ------------------------------ MITK formats ---------------------------------- static CustomMimeType POINTSET_MIMETYPE(); // mps static std::string POINTSET_MIMETYPE_NAME(); // DEFAULT_BASE_NAME.pointset private: // purposely not implemented IOMimeTypes(); IOMimeTypes(const IOMimeTypes&); }; } #endif // MITKIOMIMETYPES_H diff --git a/Core/Code/IO/mitkIOUtil.cpp b/Core/Code/IO/mitkIOUtil.cpp index cbe827b419..e6efc63e21 100644 --- a/Core/Code/IO/mitkIOUtil.cpp +++ b/Core/Code/IO/mitkIOUtil.cpp @@ -1,1070 +1,1070 @@ /*=================================================================== 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 #include #include #include #include #include #include #include #include #include #include #include //ITK #include //VTK #include #include #include #include #include static std::string GetLastErrorStr() { #ifdef US_PLATFORM_POSIX return std::string(strerror(errno)); #else // Retrieve the system error message for the last-error code LPVOID lpMsgBuf; DWORD dw = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); std::string errMsg((LPCTSTR)lpMsgBuf); LocalFree(lpMsgBuf); return errMsg; #endif } #ifdef US_PLATFORM_WINDOWS #include #include // make the posix flags point to the obsolte bsd types on windows #define S_IRUSR S_IREAD #define S_IWUSR S_IWRITE #else #include #include #include #endif #include #include static const char validLetters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; // A cross-platform version of the mkstemps function static int mkstemps_compat(char* tmpl, int suffixlen) { static unsigned long long value = 0; int savedErrno = errno; // Lower bound on the number of temporary files to attempt to generate. #define ATTEMPTS_MIN (62 * 62 * 62) /* The number of times to attempt to generate a temporary file. To conform to POSIX, this must be no smaller than TMP_MAX. */ #if ATTEMPTS_MIN < TMP_MAX const unsigned int attempts = TMP_MAX; #else const unsigned int attempts = ATTEMPTS_MIN; #endif const int len = strlen(tmpl); if ((len - suffixlen) < 6 || strncmp(&tmpl[len - 6 - suffixlen], "XXXXXX", 6)) { errno = EINVAL; return -1; } /* This is where the Xs start. */ char* XXXXXX = &tmpl[len - 6 - suffixlen]; /* Get some more or less random data. */ #ifdef US_PLATFORM_WINDOWS { SYSTEMTIME stNow; FILETIME ftNow; // get system time GetSystemTime(&stNow); stNow.wMilliseconds = 500; if (!SystemTimeToFileTime(&stNow, &ftNow)) { errno = -1; return -1; } unsigned long long randomTimeBits = ((static_cast(ftNow.dwHighDateTime) << 32) | static_cast(ftNow.dwLowDateTime)); value = randomTimeBits ^ static_cast(GetCurrentThreadId()); } #else { struct timeval tv; gettimeofday(&tv, NULL); unsigned long long randomTimeBits = ((static_cast(tv.tv_usec) << 32) | static_cast(tv.tv_sec)); value = randomTimeBits ^ static_cast(getpid()); } #endif for (unsigned int count = 0; count < attempts; value += 7777, ++count) { unsigned long long v = value; /* Fill in the random bits. */ XXXXXX[0] = validLetters[v % 62]; v /= 62; XXXXXX[1] = validLetters[v % 62]; v /= 62; XXXXXX[2] = validLetters[v % 62]; v /= 62; XXXXXX[3] = validLetters[v % 62]; v /= 62; XXXXXX[4] = validLetters[v % 62]; v /= 62; XXXXXX[5] = validLetters[v % 62]; int fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); if (fd >= 0) { errno = savedErrno; return fd; } else if (errno != EEXIST) { return -1; } } /* We got out of the loop because we ran out of combinations to try. */ errno = EEXIST; return -1; } // A cross-platform version of the POSIX mkdtemp function static char* mkdtemps_compat(char* tmpl, int suffixlen) { static unsigned long long value = 0; int savedErrno = errno; // Lower bound on the number of temporary dirs to attempt to generate. #define ATTEMPTS_MIN (62 * 62 * 62) /* The number of times to attempt to generate a temporary dir. To conform to POSIX, this must be no smaller than TMP_MAX. */ #if ATTEMPTS_MIN < TMP_MAX const unsigned int attempts = TMP_MAX; #else const unsigned int attempts = ATTEMPTS_MIN; #endif const int len = strlen(tmpl); if ((len - suffixlen) < 6 || strncmp(&tmpl[len - 6 - suffixlen], "XXXXXX", 6)) { errno = EINVAL; return NULL; } /* This is where the Xs start. */ char* XXXXXX = &tmpl[len - 6 - suffixlen]; /* Get some more or less random data. */ #ifdef US_PLATFORM_WINDOWS { SYSTEMTIME stNow; FILETIME ftNow; // get system time GetSystemTime(&stNow); stNow.wMilliseconds = 500; if (!SystemTimeToFileTime(&stNow, &ftNow)) { errno = -1; return NULL; } unsigned long long randomTimeBits = ((static_cast(ftNow.dwHighDateTime) << 32) | static_cast(ftNow.dwLowDateTime)); value = randomTimeBits ^ static_cast(GetCurrentThreadId()); } #else { struct timeval tv; gettimeofday(&tv, NULL); unsigned long long randomTimeBits = ((static_cast(tv.tv_usec) << 32) | static_cast(tv.tv_sec)); value = randomTimeBits ^ static_cast(getpid()); } #endif unsigned int count = 0; for (; count < attempts; value += 7777, ++count) { unsigned long long v = value; /* Fill in the random bits. */ XXXXXX[0] = validLetters[v % 62]; v /= 62; XXXXXX[1] = validLetters[v % 62]; v /= 62; XXXXXX[2] = validLetters[v % 62]; v /= 62; XXXXXX[3] = validLetters[v % 62]; v /= 62; XXXXXX[4] = validLetters[v % 62]; v /= 62; XXXXXX[5] = validLetters[v % 62]; #ifdef US_PLATFORM_WINDOWS int fd = _mkdir (tmpl); //, _S_IREAD | _S_IWRITE | _S_IEXEC); #else int fd = mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); #endif if (fd >= 0) { errno = savedErrno; return tmpl; } else if (errno != EEXIST) { return NULL; } } /* We got out of the loop because we ran out of combinations to try. */ errno = EEXIST; return NULL; } //#endif //************************************************************** // mitk::IOUtil method definitions namespace mitk { const std::string IOUtil::DEFAULTIMAGEEXTENSION = ".nrrd"; const std::string IOUtil::DEFAULTSURFACEEXTENSION = ".stl"; const std::string IOUtil::DEFAULTPOINTSETEXTENSION = ".mps"; struct IOUtil::Impl { struct FixedReaderOptionsFunctor : public ReaderOptionsFunctorBase { FixedReaderOptionsFunctor(const IFileReader::Options& options) : m_Options(options) {} virtual bool operator()(LoadInfo& loadInfo) { IFileReader* reader = loadInfo.m_ReaderSelector.GetSelected().GetReader(); if (reader) { reader->SetOptions(m_Options); } return false; } private: const IFileReader::Options& m_Options; }; struct FixedWriterOptionsFunctor : public WriterOptionsFunctorBase { FixedWriterOptionsFunctor(const IFileReader::Options& options) : m_Options(options) {} virtual bool operator()(SaveInfo& saveInfo) { IFileWriter* writer = saveInfo.m_WriterSelector.GetSelected().GetWriter(); if (writer) { writer->SetOptions(m_Options); } return false; } private: const IFileWriter::Options& m_Options; }; static BaseData::Pointer LoadBaseDataFromFile(const std::string& path); static void SetDefaultDataNodeProperties(mitk::DataNode* node, const std::string& filePath = std::string()); }; #ifdef US_PLATFORM_WINDOWS std::string IOUtil::GetProgramPath() { char path[512]; std::size_t index = std::string(path, GetModuleFileName(NULL, path, 512)).find_last_of('\\'); return std::string(path, index); } #elif defined(US_PLATFORM_APPLE) #include std::string IOUtil::GetProgramPath() { char path[512]; uint32_t size = sizeof(path); if (_NSGetExecutablePath(path, &size) == 0) { std::size_t index = std::string(path).find_last_of('/'); std::string strPath = std::string(path, index); //const char* execPath = strPath.c_str(); //mitk::StandardFileLocations::GetInstance()->AddDirectoryForSearch(execPath,false); return strPath; } return std::string(); } #else #include #include #include std::string IOUtil::GetProgramPath() { std::stringstream ss; ss << "/proc/" << getpid() << "/exe"; char proc[512] = {0}; ssize_t ch = readlink(ss.str().c_str(), proc, 512); if (ch == -1) return std::string(); std::size_t index = std::string(proc).find_last_of('/'); return std::string(proc, index); } #endif char IOUtil::GetDirectorySeparator() { #ifdef US_PLATFORM_WINDOWS return '\\'; #else return '/'; #endif } std::string IOUtil::GetTempPath() { static std::string result; if (result.empty()) { #ifdef US_PLATFORM_WINDOWS char tempPathTestBuffer[1]; DWORD bufferLength = ::GetTempPath(1, tempPathTestBuffer); if (bufferLength == 0) { mitkThrow() << GetLastErrorStr(); } std::vector tempPath(bufferLength); bufferLength = ::GetTempPath(bufferLength, &tempPath[0]); if (bufferLength == 0) { mitkThrow() << GetLastErrorStr(); } result.assign(tempPath.begin(), tempPath.begin() + static_cast(bufferLength)); #else result = "/tmp/"; #endif } return result; } std::string IOUtil::CreateTemporaryFile(const std::string& templateName, std::string path) { ofstream tmpOutputStream; std::string returnValue = CreateTemporaryFile(tmpOutputStream,templateName,path); tmpOutputStream.close(); return returnValue; } std::string IOUtil::CreateTemporaryFile(std::ofstream& f, const std::string& templateName, std::string path) { return CreateTemporaryFile(f, std::ios_base::out | std::ios_base::trunc, templateName, path); } std::string IOUtil::CreateTemporaryFile(std::ofstream& f, std::ios_base::openmode mode, const std::string& templateName, std::string path) { if (path.empty()) { path = GetTempPath(); } path += GetDirectorySeparator() + templateName; std::vector dst_path(path.begin(), path.end()); dst_path.push_back('\0'); std::size_t lastX = path.find_last_of('X'); std::size_t firstX = path.find_last_not_of('X', lastX); int firstNonX = firstX == std::string::npos ? - 1 : firstX - 1; while (lastX != std::string::npos && (lastX - firstNonX) < 6) { lastX = path.find_last_of('X', firstX); firstX = path.find_last_not_of('X', lastX); firstNonX = firstX == std::string::npos ? - 1 : firstX - 1; } std::size_t suffixlen = lastX == std::string::npos ? path.size() : path.size() - lastX - 1; int fd = mkstemps_compat(&dst_path[0], suffixlen); if(fd != -1) { path.assign(dst_path.begin(), dst_path.end() - 1); f.open(path.c_str(), mode | std::ios_base::out | std::ios_base::trunc); close(fd); } else { mitkThrow() << "Creating temporary file " << &dst_path[0] << " failed: " << GetLastErrorStr(); } return path; } std::string IOUtil::CreateTemporaryDirectory(const std::string& templateName, std::string path) { if (path.empty()) { path = GetTempPath(); } path += GetDirectorySeparator() + templateName; std::vector dst_path(path.begin(), path.end()); dst_path.push_back('\0'); std::size_t lastX = path.find_last_of('X'); std::size_t firstX = path.find_last_not_of('X', lastX); int firstNonX = firstX == std::string::npos ? - 1 : firstX - 1; while (lastX != std::string::npos && (lastX - firstNonX) < 6) { lastX = path.find_last_of('X', firstX); firstX = path.find_last_not_of('X', lastX); firstNonX = firstX == std::string::npos ? - 1 : firstX - 1; } std::size_t suffixlen = lastX == std::string::npos ? path.size() : path.size() - lastX - 1; if(mkdtemps_compat(&dst_path[0], suffixlen) == NULL) { mitkThrow() << "Creating temporary directory " << &dst_path[0] << " failed: " << GetLastErrorStr(); } path.assign(dst_path.begin(), dst_path.end() - 1); return path; } DataStorage::SetOfObjects::Pointer IOUtil::Load(const std::string& path, DataStorage& storage) { std::vector paths; paths.push_back(path); return Load(paths, storage); } DataStorage::SetOfObjects::Pointer IOUtil::Load(const std::string& path, const IFileReader::Options& options, DataStorage& storage) { std::vector loadInfos; loadInfos.push_back(LoadInfo(path)); DataStorage::SetOfObjects::Pointer nodeResult = DataStorage::SetOfObjects::New(); Impl::FixedReaderOptionsFunctor optionsCallback(options); std::string errMsg = Load(loadInfos, nodeResult, &storage, &optionsCallback); if (!errMsg.empty()) { mitkThrow() << errMsg; } return nodeResult; } std::vector IOUtil::Load(const std::string& path) { std::vector paths; paths.push_back(path); return Load(paths); } std::vector IOUtil::Load(const std::string& path, const IFileReader::Options& options) { std::vector loadInfos; loadInfos.push_back(LoadInfo(path)); Impl::FixedReaderOptionsFunctor optionsCallback(options); std::string errMsg = Load(loadInfos, NULL, NULL, &optionsCallback); if (!errMsg.empty()) { mitkThrow() << errMsg; } return loadInfos.front().m_Output; } DataStorage::SetOfObjects::Pointer IOUtil::Load(const std::vector& paths, DataStorage& storage) { DataStorage::SetOfObjects::Pointer nodeResult = DataStorage::SetOfObjects::New(); std::vector loadInfos; for (std::vector::const_iterator iter = paths.begin(), iterEnd = paths.end(); iter != iterEnd; ++iter) { LoadInfo loadInfo(*iter); loadInfos.push_back(loadInfo); } std::string errMsg = Load(loadInfos, nodeResult, &storage, NULL); if (!errMsg.empty()) { mitkThrow() << errMsg; } return nodeResult; } std::vector IOUtil::Load(const std::vector& paths) { std::vector result; std::vector loadInfos; for (std::vector::const_iterator iter = paths.begin(), iterEnd = paths.end(); iter != iterEnd; ++iter) { LoadInfo loadInfo(*iter); loadInfos.push_back(loadInfo); } std::string errMsg = Load(loadInfos, NULL, NULL, NULL); if (!errMsg.empty()) { mitkThrow() << errMsg; } for (std::vector::const_iterator iter = loadInfos.begin(), iterEnd = loadInfos.end(); iter != iterEnd; ++iter) { result.insert(result.end(), iter->m_Output.begin(), iter->m_Output.end()); } return result; } int IOUtil::LoadFiles(const std::vector &fileNames, DataStorage& ds) { return static_cast(Load(fileNames, ds)->Size()); } DataStorage::Pointer IOUtil::LoadFiles(const std::vector& fileNames) { mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New(); Load(fileNames, *ds); return ds.GetPointer(); } BaseData::Pointer IOUtil::LoadBaseData(const std::string& path) { return Impl::LoadBaseDataFromFile(path); } BaseData::Pointer IOUtil::Impl::LoadBaseDataFromFile(const std::string& path) { std::vector baseDataList = Load(path); // The Load(path) call above should throw an exception if nothing could be loaded assert(!baseDataList.empty()); return baseDataList.front(); } DataNode::Pointer IOUtil::LoadDataNode(const std::string& path) { BaseData::Pointer baseData = Impl::LoadBaseDataFromFile(path); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(baseData); Impl::SetDefaultDataNodeProperties(node, path); return node; } Image::Pointer IOUtil::LoadImage(const std::string& path) { BaseData::Pointer baseData = Impl::LoadBaseDataFromFile(path); mitk::Image::Pointer image = dynamic_cast(baseData.GetPointer()); if(image.IsNull()) { mitkThrow() << path << " is not a mitk::Image but a " << baseData->GetNameOfClass(); } return image; } Surface::Pointer IOUtil::LoadSurface(const std::string& path) { BaseData::Pointer baseData = Impl::LoadBaseDataFromFile(path); mitk::Surface::Pointer surface = dynamic_cast(baseData.GetPointer()); if(surface.IsNull()) { mitkThrow() << path << " is not a mitk::Surface but a " << baseData->GetNameOfClass(); } return surface; } PointSet::Pointer IOUtil::LoadPointSet(const std::string& path) { BaseData::Pointer baseData = Impl::LoadBaseDataFromFile(path); mitk::PointSet::Pointer pointset = dynamic_cast(baseData.GetPointer()); if(pointset.IsNull()) { mitkThrow() << path << " is not a mitk::PointSet but a " << baseData->GetNameOfClass(); } return pointset; } std::string IOUtil::Load(std::vector& loadInfos, DataStorage::SetOfObjects* nodeResult, DataStorage* ds, ReaderOptionsFunctorBase* optionsCallback) { if (loadInfos.empty()) { return "No input files given"; } int filesToRead = loadInfos.size(); mitk::ProgressBar::GetInstance()->AddStepsToDo(2*filesToRead); std::string errMsg; std::map usedReaderItems; for(std::vector::iterator infoIter = loadInfos.begin(), infoIterEnd = loadInfos.end(); infoIter != infoIterEnd; ++infoIter) { std::vector readers = infoIter->m_ReaderSelector.Get(); if (readers.empty()) { errMsg += "No reader available for '" + infoIter->m_Path + "'\n"; continue; } bool callOptionsCallback = readers.size() > 1 || !readers.front().GetReader()->GetOptions().empty(); // check if we already used a reader which should be re-used std::vector currMimeTypes = infoIter->m_ReaderSelector.GetMimeTypes(); std::string selectedMimeType; for (std::vector::const_iterator mimeTypeIter = currMimeTypes.begin(), mimeTypeIterEnd = currMimeTypes.end(); mimeTypeIter != mimeTypeIterEnd; ++mimeTypeIter) { std::map::const_iterator oldSelectedItemIter = usedReaderItems.find(mimeTypeIter->GetName()); if (oldSelectedItemIter != usedReaderItems.end()) { // we found an already used item for a mime-type which is contained // in the current reader set, check all current readers if there service // id equals the old reader for (std::vector::const_iterator currReaderItem = readers.begin(), currReaderItemEnd = readers.end(); currReaderItem != currReaderItemEnd; ++currReaderItem) { if (currReaderItem->GetMimeType().GetName() == mimeTypeIter->GetName() && currReaderItem->GetServiceId() == oldSelectedItemIter->second.GetServiceId() && currReaderItem->GetConfidenceLevel() >= oldSelectedItemIter->second.GetConfidenceLevel()) { // okay, we used the same reader already, re-use its options selectedMimeType = mimeTypeIter->GetName(); callOptionsCallback = false; infoIter->m_ReaderSelector.Select(oldSelectedItemIter->second.GetServiceId()); infoIter->m_ReaderSelector.GetSelected().GetReader()->SetOptions( oldSelectedItemIter->second.GetReader()->GetOptions()); break; } } if (!selectedMimeType.empty()) break; } } if (callOptionsCallback && optionsCallback) { callOptionsCallback = (*optionsCallback)(*infoIter); if (!callOptionsCallback && !infoIter->m_Cancel) { usedReaderItems.erase(selectedMimeType); FileReaderSelector::Item selectedItem = infoIter->m_ReaderSelector.GetSelected(); usedReaderItems.insert(std::make_pair(selectedItem.GetMimeType().GetName(), selectedItem)); } } if (infoIter->m_Cancel) { errMsg += "Reading operation(s) cancelled."; break; } IFileReader* reader = infoIter->m_ReaderSelector.GetSelected().GetReader(); if (reader == NULL) { errMsg += "Unexpected NULL reader."; break; } // Do the actual reading try { DataStorage::SetOfObjects::Pointer nodes; if (ds != NULL) { nodes = reader->Read(*ds); } else { nodes = DataStorage::SetOfObjects::New(); std::vector baseData = reader->Read(); for (std::vector::iterator iter = baseData.begin(); iter != baseData.end(); ++iter) { if (iter->IsNotNull()) { mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(*iter); nodes->InsertElement(nodes->Size(), node); } } } for (DataStorage::SetOfObjects::ConstIterator nodeIter = nodes->Begin(), nodeIterEnd = nodes->End(); nodeIter != nodeIterEnd; ++nodeIter) { const mitk::DataNode::Pointer& node = nodeIter->Value(); mitk::BaseData::Pointer data = node->GetData(); if (data.IsNull()) { continue; } mitk::StringProperty::Pointer pathProp = mitk::StringProperty::New(infoIter->m_Path); data->SetProperty("path", pathProp); infoIter->m_Output.push_back(data); if (nodeResult) { nodeResult->push_back(nodeIter->Value()); } } if (infoIter->m_Output.empty() || (nodeResult && nodeResult->Size() == 0)) { errMsg += "Unknown read error occurred reading " + infoIter->m_Path; } } catch (const std::exception& e) { errMsg += "Exception occured when reading file " + infoIter->m_Path + ":\n" + e.what() + "\n\n"; } mitk::ProgressBar::GetInstance()->Progress(2); --filesToRead; } if (!errMsg.empty()) { MITK_ERROR << errMsg; } mitk::ProgressBar::GetInstance()->Progress(2*filesToRead); return errMsg; } void IOUtil::Save(const BaseData* data, const std::string& path) { Save(data, path, IFileWriter::Options()); } void IOUtil::Save(const BaseData* data, const std::string& path, const IFileWriter::Options& options) { Save(data, std::string(), path, options); } void IOUtil::Save(const BaseData* data, const std::string& mimeType, const std::string& path, bool addExtension) { Save(data, mimeType, path, IFileWriter::Options(), addExtension); } void IOUtil::Save(const BaseData* data, const std::string& mimeType, const std::string& path, const IFileWriter::Options& options, bool addExtension) { std::string errMsg; if (options.empty()) { errMsg = Save(data, mimeType, path, NULL, addExtension); } else { Impl::FixedWriterOptionsFunctor optionsCallback(options); errMsg = Save(data, mimeType, path, &optionsCallback, addExtension); } if (!errMsg.empty()) { mitkThrow() << errMsg; } } void IOUtil::Save(std::vector& saveInfos) { std::string errMsg = Save(saveInfos, NULL); if (!errMsg.empty()) { mitkThrow() << errMsg; } } bool IOUtil::SaveImage(mitk::Image::Pointer image, const std::string& path) { Save(image, path); return true; } bool IOUtil::SaveSurface(Surface::Pointer surface, const std::string& path) { Save(surface, path); return true; } bool IOUtil::SavePointSet(PointSet::Pointer pointset, const std::string& path) { Save(pointset, path); return true; } bool IOUtil::SaveBaseData( mitk::BaseData* data, const std::string& path) { Save(data, path); return true; } std::string IOUtil::Save(const BaseData* data, const std::string& mimeTypeName, const std::string& path, WriterOptionsFunctorBase* optionsCallback, bool addExtension) { if (path.empty()) { return "No output filename given"; } mitk::CoreServicePointer mimeTypeProvider(mitk::CoreServices::GetMimeTypeProvider()); MimeType mimeType = mimeTypeProvider->GetMimeTypeForName(mimeTypeName); SaveInfo saveInfo(data, mimeType, path); std::string ext = itksys::SystemTools::GetFilenameExtension(path); if (saveInfo.m_WriterSelector.IsEmpty()) { - return std::string("No suitable writer found for the current data of type ") + data->GetNameOfClass() + + return std::string("No suitable writer found for the current data of type ") + data->GetNameOfClass() + (mimeType.IsValid() ? (std::string(" and mime-type ") + mimeType.GetName()) : std::string()) + (ext.empty() ? std::string() : (std::string(" with extension ") + ext)); } // Add an extension if not already specified if (ext.empty() && addExtension) { ext = saveInfo.m_MimeType.GetExtensions().empty() ? std::string() : "." + saveInfo.m_MimeType.GetExtensions().front(); } std::vector infos; infos.push_back(saveInfo); return Save(infos, optionsCallback); } std::string IOUtil::Save(std::vector& saveInfos, WriterOptionsFunctorBase* optionsCallback) { if (saveInfos.empty()) { return "No data for saving available"; } int filesToWrite = saveInfos.size(); mitk::ProgressBar::GetInstance()->AddStepsToDo(2*filesToWrite); std::string errMsg; std::set usedSaveInfos; for (std::vector::iterator infoIter = saveInfos.begin(), infoIterEnd = saveInfos.end(); infoIter != infoIterEnd; ++infoIter) { const std::string baseDataType = infoIter->m_BaseData->GetNameOfClass(); std::vector writers = infoIter->m_WriterSelector.Get(); // Error out if no compatible Writer was found if (writers.empty()) { errMsg += std::string("No writer available for ") + baseDataType + " data.\n"; continue; } bool callOptionsCallback = writers.size() > 1 || !writers[0].GetWriter()->GetOptions().empty(); // check if we already used a writer for this base data type // which should be re-used std::set::const_iterator oldSaveInfoIter = usedSaveInfos.find(*infoIter); if (oldSaveInfoIter != usedSaveInfos.end()) { // we previously saved a base data object of the same data with the same mime-type, // check if the same writer is contained in the current writer set and if the // confidence level matches FileWriterSelector::Item oldSelectedItem = oldSaveInfoIter->m_WriterSelector.Get(oldSaveInfoIter->m_WriterSelector.GetSelectedId()); for (std::vector::const_iterator currWriterItem = writers.begin(), currWriterItemEnd = writers.end(); currWriterItem != currWriterItemEnd; ++currWriterItem) { if (currWriterItem->GetServiceId() == oldSelectedItem.GetServiceId() && currWriterItem->GetConfidenceLevel() >= oldSelectedItem.GetConfidenceLevel()) { // okay, we used the same writer already, re-use its options callOptionsCallback = false; infoIter->m_WriterSelector.Select(oldSaveInfoIter->m_WriterSelector.GetSelectedId()); infoIter->m_WriterSelector.GetSelected().GetWriter()->SetOptions( oldSelectedItem.GetWriter()->GetOptions()); break; } } } if (callOptionsCallback && optionsCallback) { callOptionsCallback = (*optionsCallback)(*infoIter); if (!callOptionsCallback && !infoIter->m_Cancel) { usedSaveInfos.erase(*infoIter); usedSaveInfos.insert(*infoIter); } } if (infoIter->m_Cancel) { errMsg += "Writing operation(s) cancelled."; break; } IFileWriter* writer = infoIter->m_WriterSelector.GetSelected().GetWriter(); if (writer == NULL) { errMsg += "Unexpected NULL writer."; break; } // Do the actual writing try { writer->SetOutputLocation(infoIter->m_Path); writer->Write(); } catch(const std::exception& e) { errMsg += std::string("Exception occurred when writing to ") + infoIter->m_Path + ":\n" + e.what() + "\n"; } mitk::ProgressBar::GetInstance()->Progress(2); --filesToWrite; } if (!errMsg.empty()) { MITK_ERROR << errMsg; } mitk::ProgressBar::GetInstance()->Progress(2*filesToWrite); return errMsg; } // This method can be removed after the deprecated LoadDataNode() method was removed void IOUtil::Impl::SetDefaultDataNodeProperties(DataNode* node, const std::string& filePath) { // path mitk::StringProperty::Pointer pathProp = mitk::StringProperty::New( itksys::SystemTools::GetFilenamePath(filePath) ); node->SetProperty(StringProperty::PATH, pathProp); // name already defined? mitk::StringProperty::Pointer nameProp = dynamic_cast(node->GetProperty("name")); if(nameProp.IsNull() || (strcmp(nameProp->GetValue(),"No Name!")==0)) { // name already defined in BaseData mitk::StringProperty::Pointer baseDataNameProp = dynamic_cast(node->GetData()->GetProperty("name").GetPointer() ); if(baseDataNameProp.IsNull() || (strcmp(baseDataNameProp->GetValue(),"No Name!")==0)) { // name neither defined in node, nor in BaseData -> name = filename nameProp = mitk::StringProperty::New( itksys::SystemTools::GetFilenameWithoutExtension(filePath)); node->SetProperty("name", nameProp); } else { // name defined in BaseData! nameProp = mitk::StringProperty::New(baseDataNameProp->GetValue()); node->SetProperty("name", nameProp); } } // visibility if(!node->GetProperty("visible")) { node->SetVisibility(true); } } IOUtil::SaveInfo::SaveInfo(const BaseData* baseData, const MimeType& mimeType, const std::string& path) : m_BaseData(baseData) , m_WriterSelector(baseData, mimeType.GetName(), path) , m_MimeType(mimeType.IsValid() ? mimeType // use the original mime-type : (m_WriterSelector.IsEmpty() ? mimeType // no writer found, use the original invalid mime-type : m_WriterSelector.GetDefault().GetMimeType() // use the found default mime-type ) ) , m_Path(path) , m_Cancel(false) { } bool IOUtil::SaveInfo::operator<(const IOUtil::SaveInfo& other) const { int r = strcmp(m_BaseData->GetNameOfClass(), other.m_BaseData->GetNameOfClass()); if (r == 0) { return m_WriterSelector.GetSelected().GetMimeType() < other.m_WriterSelector.GetSelected().GetMimeType(); } return r < 0; } IOUtil::LoadInfo::LoadInfo(const std::string& path) : m_Path(path) , m_ReaderSelector(path) , m_Cancel(false) { } } diff --git a/Core/Code/IO/mitkMimeType.cpp b/Core/Code/IO/mitkMimeType.cpp index 005d7d4092..e1bdf713e8 100644 --- a/Core/Code/IO/mitkMimeType.cpp +++ b/Core/Code/IO/mitkMimeType.cpp @@ -1,136 +1,138 @@ /*=================================================================== 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 "mitkMimeType.h" #include "mitkCustomMimeType.h" +#include + namespace mitk { struct MimeType::Impl : us::SharedData { Impl() - : m_Rank(-1) + : m_CustomMimeType(new CustomMimeType()) + , m_Rank(-1) , m_Id(-1) {} Impl(const CustomMimeType& x, int rank, long id) - : m_Name(x.GetName()) - , m_Category(x.GetCategory()) - , m_Extensions(x.GetExtensions()) - , m_Comment(x.GetComment()) + : m_CustomMimeType(x.Clone()) , m_Rank(rank) , m_Id(id) {} - std::string m_Name; - std::string m_Category; - std::vector m_Extensions; - std::string m_Comment; + std::auto_ptr m_CustomMimeType; int m_Rank; long m_Id; }; MimeType::MimeType() : m_Data(new Impl) { } MimeType::MimeType(const MimeType& other) : m_Data(other.m_Data) { } MimeType::MimeType(const CustomMimeType& x, int rank, long id) : m_Data(new Impl(x, rank, id)) { } MimeType::~MimeType() { } MimeType& MimeType::operator=(const MimeType& other) { m_Data = other.m_Data; return *this; } bool MimeType::operator==(const MimeType& other) const { - return m_Data->m_Name == other.GetName(); + return this->GetName() == other.GetName(); } bool MimeType::operator<(const MimeType& other) const { if (m_Data->m_Rank != other.m_Data->m_Rank) { return m_Data->m_Rank < other.m_Data->m_Rank; } return other.m_Data->m_Id < m_Data->m_Id; } std::string MimeType::GetName() const { - return m_Data->m_Name; + return m_Data->m_CustomMimeType->GetName(); } std::string MimeType::GetCategory() const { - return m_Data->m_Category; + return m_Data->m_CustomMimeType->GetCategory(); } std::vector MimeType::GetExtensions() const { - return m_Data->m_Extensions; + return m_Data->m_CustomMimeType->GetExtensions(); } std::string MimeType::GetComment() const { - return m_Data->m_Comment; + return m_Data->m_CustomMimeType->GetComment(); +} + +bool MimeType::AppliesTo(const std::string& path) const +{ + return m_Data->m_CustomMimeType->AppliesTo(path); } bool MimeType::IsValid() const { - return m_Data.Data() != NULL && !m_Data->m_Name.empty(); + return m_Data.Data() != NULL && m_Data->m_CustomMimeType.get() != NULL && !m_Data->m_CustomMimeType->GetName().empty(); } void MimeType::Swap(MimeType& m) { m_Data.Swap(m.m_Data); } void swap(MimeType& m1, MimeType& m2) { m1.Swap(m2); } std::ostream& operator<<(std::ostream& os, const MimeType& mimeType) { os << mimeType.GetName() << " (" << mimeType.GetCategory() << ", " << mimeType.GetComment() << ") "; std::vector extensions = mimeType.GetExtensions(); for (std::vector::const_iterator iter = extensions.begin(), endIter = extensions.end(); iter != endIter; ++iter) { if (iter != extensions.begin()) os << ", "; os << *iter; } return os; } } diff --git a/Core/Code/IO/mitkMimeType.h b/Core/Code/IO/mitkMimeType.h index 17abd4d2e6..299294a339 100644 --- a/Core/Code/IO/mitkMimeType.h +++ b/Core/Code/IO/mitkMimeType.h @@ -1,78 +1,80 @@ /*=================================================================== 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 MITKMIMETYPE_H #define MITKMIMETYPE_H #include #include #include #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4251) #endif namespace mitk { class CustomMimeType; class MITK_CORE_EXPORT MimeType { public: MimeType(); MimeType(const MimeType& other); MimeType(const CustomMimeType& x, int rank, long id); ~MimeType(); MimeType& operator=(const MimeType& other); bool operator==(const MimeType& other) const; bool operator<(const MimeType& other) const; std::string GetName() const; std::string GetCategory() const; std::vector GetExtensions() const; std::string GetComment() const; + bool AppliesTo(const std::string& path) const; + bool IsValid() const; void Swap(MimeType& m); private: struct Impl; // Use C++11 shared_ptr instead us::SharedDataPointer m_Data; }; void swap(MimeType& m1, MimeType& m2); std::ostream& operator<<(std::ostream& os, const MimeType& mimeType); } #ifdef _MSC_VER #pragma warning(pop) #endif #endif // MITKMIMETYPE_H diff --git a/Core/Code/Interfaces/mitkIMimeTypeProvider.h b/Core/Code/Interfaces/mitkIMimeTypeProvider.h index f8431a2ccd..b3321ad798 100644 --- a/Core/Code/Interfaces/mitkIMimeTypeProvider.h +++ b/Core/Code/Interfaces/mitkIMimeTypeProvider.h @@ -1,73 +1,71 @@ /*=================================================================== 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 MITKIMIMETYPEPROVIDER_H #define MITKIMIMETYPEPROVIDER_H #include #include #include #include #include namespace mitk { /** * @brief The IMimeTypeProvider service interface allows to query all registered * mime types. * * Mime types are added to the system by registering a service object of type * CustomMimeType and the registered mime types can be queried bei either using direct * look-ups in the service registry or calling the methods of this service interface. * * This service interface also allows to infer the mime type of a file on the file * system. The heuristics for infering the actual mime type is implementation specific. * * @note This is a core service * * @sa CustomMimeType * @sa CoreServices::GetMimeTypeProvider() */ struct MITK_CORE_EXPORT IMimeTypeProvider { virtual ~IMimeTypeProvider(); virtual std::vector GetMimeTypes() const = 0; virtual std::vector GetMimeTypesForFile(const std::string& filePath) const = 0; - virtual std::vector GetMimeTypesForExtension(const std::string& extension) const = 0; - virtual std::vector GetMimeTypesForCategory(const std::string& category) const = 0; virtual MimeType GetMimeTypeForName(const std::string& name) const = 0; /** * @brief Get a sorted and unique list of mime-type categories. * @return A sorted, unique list of mime-type categories. */ virtual std::vector GetCategories() const = 0; }; } US_DECLARE_SERVICE_INTERFACE(mitk::IMimeTypeProvider, "org.mitk.IMimeTypeProvider") #endif // MITKIMIMETYPEPROVIDER_H diff --git a/Core/Code/Internal/mitkCoreActivator.cpp b/Core/Code/Internal/mitkCoreActivator.cpp index c919b2e87b..4d87b429d7 100644 --- a/Core/Code/Internal/mitkCoreActivator.cpp +++ b/Core/Code/Internal/mitkCoreActivator.cpp @@ -1,443 +1,464 @@ /*=================================================================== 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 "mitkCoreActivator.h" // File IO #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mitkLegacyFileWriterService.h" #include +#include // Micro Services #include #include #include #include #include #include #include #include #include #include void HandleMicroServicesMessages(us::MsgType type, const char* msg) { switch (type) { case us::DebugMsg: MITK_DEBUG << msg; break; case us::InfoMsg: MITK_INFO << msg; break; case us::WarningMsg: MITK_WARN << msg; break; case us::ErrorMsg: MITK_ERROR << msg; break; } } void AddMitkAutoLoadPaths(const std::string& programPath) { us::ModuleSettings::AddAutoLoadPath(programPath); #ifdef __APPLE__ // Walk up three directories since that is where the .dylib files are located // for build trees. std::string additionalPath = programPath; bool addPath = true; for(int i = 0; i < 3; ++i) { std::size_t index = additionalPath.find_last_of('/'); if (index != std::string::npos) { additionalPath = additionalPath.substr(0, index); } else { addPath = false; break; } } if (addPath) { us::ModuleSettings::AddAutoLoadPath(additionalPath); } #endif } class ShaderRepositoryTracker : public us::ServiceTracker { public: ShaderRepositoryTracker() : Superclass(us::GetModuleContext()) { } virtual void Close() { us::GetModuleContext()->RemoveModuleListener(this, &ShaderRepositoryTracker::HandleModuleEvent); Superclass::Close(); } virtual void Open() { us::GetModuleContext()->AddModuleListener(this, &ShaderRepositoryTracker::HandleModuleEvent); Superclass::Open(); } private: typedef us::ServiceTracker Superclass; TrackedType AddingService(const ServiceReferenceType &reference) { mitk::IShaderRepository* shaderRepo = Superclass::AddingService(reference); if (shaderRepo) { // Add all existing shaders from modules to the new shader repository. // If the shader repository is registered in a modules activator, the // GetLoadedModules() function call below will also return the module // which is currently registering the repository. The HandleModuleEvent // method contains code to avoid double registrations due to a fired // ModuleEvent::LOADED event after the activators Load() method finished. std::vector modules = us::ModuleRegistry::GetLoadedModules(); for (std::vector::const_iterator iter = modules.begin(), endIter = modules.end(); iter != endIter; ++iter) { this->AddModuleShaderToRepository(*iter, shaderRepo); } m_ShaderRepositories.push_back(shaderRepo); } return shaderRepo; } void RemovedService(const ServiceReferenceType& /*reference*/, TrackedType tracked) { m_ShaderRepositories.erase(std::remove(m_ShaderRepositories.begin(), m_ShaderRepositories.end(), tracked), m_ShaderRepositories.end()); } void HandleModuleEvent(const us::ModuleEvent moduleEvent) { if (moduleEvent.GetType() == us::ModuleEvent::LOADED) { std::vector shaderRepos; for (std::map > >::const_iterator shaderMapIter = m_ModuleIdToShaderIds.begin(), shaderMapEndIter = m_ModuleIdToShaderIds.end(); shaderMapIter != shaderMapEndIter; ++shaderMapIter) { if (shaderMapIter->second.find(moduleEvent.GetModule()->GetModuleId()) == shaderMapIter->second.end()) { shaderRepos.push_back(shaderMapIter->first); } } AddModuleShadersToRepositories(moduleEvent.GetModule(), shaderRepos); } else if (moduleEvent.GetType() == us::ModuleEvent::UNLOADED) { RemoveModuleShadersFromRepositories(moduleEvent.GetModule(), m_ShaderRepositories); } } void AddModuleShadersToRepositories(us::Module* module, const std::vector& shaderRepos) { // search and load shader files std::vector shaderResources = module->FindResources("Shaders", "*.xml", true); for (std::vector::iterator i = shaderResources.begin(); i != shaderResources.end(); ++i) { if (*i) { us::ModuleResourceStream rs(*i); for (std::vector::const_iterator shaderRepoIter = shaderRepos.begin(), shaderRepoEndIter = shaderRepos.end(); shaderRepoIter != shaderRepoEndIter; ++shaderRepoIter) { int id = (*shaderRepoIter)->LoadShader(rs, i->GetBaseName()); if (id >= 0) { m_ModuleIdToShaderIds[*shaderRepoIter][module->GetModuleId()].push_back(id); } } rs.seekg(0, std::ios_base::beg); } } } void AddModuleShaderToRepository(us::Module* module, mitk::IShaderRepository* shaderRepo) { std::vector shaderRepos; shaderRepos.push_back(shaderRepo); this->AddModuleShadersToRepositories(module, shaderRepos); } void RemoveModuleShadersFromRepositories(us::Module* module, const std::vector& shaderRepos) { for (std::vector::const_iterator shaderRepoIter = shaderRepos.begin(), shaderRepoEndIter = shaderRepos.end(); shaderRepoIter != shaderRepoEndIter; ++shaderRepoIter) { std::map >& moduleIdToShaderIds = m_ModuleIdToShaderIds[*shaderRepoIter]; std::map >::iterator shaderIdsIter = moduleIdToShaderIds.find(module->GetModuleId()); if (shaderIdsIter != moduleIdToShaderIds.end()) { for (std::vector::iterator idIter = shaderIdsIter->second.begin(); idIter != shaderIdsIter->second.end(); ++idIter) { (*shaderRepoIter)->UnloadShader(*idIter); } moduleIdToShaderIds.erase(shaderIdsIter); } } } private: // Maps to each shader repository a map containing module ids and related // shader registration ids std::map > > m_ModuleIdToShaderIds; std::vector m_ShaderRepositories; }; class FixedNiftiImageIO : public itk::NiftiImageIO { public: /** Standard class typedefs. */ typedef FixedNiftiImageIO Self; typedef itk::NiftiImageIO Superclass; typedef itk::SmartPointer< Self > Pointer; /** Method for creation through the object factory. */ itkNewMacro(Self) /** Run-time type information (and related methods). */ itkTypeMacro(FixedNiftiImageIO, Superclass) virtual bool SupportsDimension(unsigned long dim) { return dim > 1 && dim < 5; } }; void MitkCoreActivator::Load(us::ModuleContext* context) { // Handle messages from CppMicroServices us::installMsgHandler(HandleMicroServicesMessages); this->m_Context = context; // Add the current application directory to the auto-load paths. // This is useful for third-party executables. std::string programPath = mitk::IOUtil::GetProgramPath(); if (programPath.empty()) { MITK_WARN << "Could not get the program path."; } else { AddMitkAutoLoadPaths(programPath); } m_ShaderRepositoryTracker.reset(new ShaderRepositoryTracker); //m_RenderingManager = mitk::RenderingManager::New(); //context->RegisterService(renderingManager.GetPointer()); m_PlanePositionManager.reset(new mitk::PlanePositionManagerService); context->RegisterService(m_PlanePositionManager.get()); m_PropertyAliases.reset(new mitk::PropertyAliases); context->RegisterService(m_PropertyAliases.get()); m_PropertyDescriptions.reset(new mitk::PropertyDescriptions); context->RegisterService(m_PropertyDescriptions.get()); m_PropertyExtensions.reset(new mitk::PropertyExtensions); context->RegisterService(m_PropertyExtensions.get()); m_PropertyFilters.reset(new mitk::PropertyFilters); context->RegisterService(m_PropertyFilters.get()); m_MimeTypeProvider.reset(new mitk::MimeTypeProvider); m_MimeTypeProvider->Start(); m_MimeTypeProviderReg = context->RegisterService(m_MimeTypeProvider.get()); this->RegisterDefaultMimeTypes(); this->RegisterItkReaderWriter(); this->RegisterVtkReaderWriter(); // Add custom Reader / Writer Services m_FileReaders.push_back(new mitk::PointSetReaderService()); m_FileWriters.push_back(new mitk::PointSetWriterService()); m_FileReaders.push_back(new mitk::RawImageFileReaderService()); m_ShaderRepositoryTracker->Open(); /* There IS an option to exchange ALL vtkTexture instances against vtkNeverTranslucentTextureFactory. This code is left here as a reminder, just in case we might need to do that some time. vtkNeverTranslucentTextureFactory* textureFactory = vtkNeverTranslucentTextureFactory::New(); vtkObjectFactory::RegisterFactory( textureFactory ); textureFactory->Delete(); */ this->RegisterLegacyWriter(); } void MitkCoreActivator::Unload(us::ModuleContext* ) { for(std::vector::iterator iter = m_FileReaders.begin(), endIter = m_FileReaders.end(); iter != endIter; ++iter) { delete *iter; } for(std::vector::iterator iter = m_FileWriters.begin(), endIter = m_FileWriters.end(); iter != endIter; ++iter) { delete *iter; } for(std::vector::iterator iter = m_FileIOs.begin(), endIter = m_FileIOs.end(); iter != endIter; ++iter) { delete *iter; } for(std::vector::iterator iter = m_LegacyWriters.begin(), endIter = m_LegacyWriters.end(); iter != endIter; ++iter) { delete *iter; } // The mitk::ModuleContext* argument of the Unload() method // will always be 0 for the Mitk library. It makes no sense // to use it at this stage anyway, since all libraries which // know about the module system have already been unloaded. // we need to close the internal service tracker of the // MimeTypeProvider class here. Otherwise it // would hold on to the ModuleContext longer than it is // actually valid. m_MimeTypeProviderReg.Unregister(); m_MimeTypeProvider->Stop(); + for (std::vector::const_iterator mimeTypeIter = m_DefaultMimeTypes.begin(), + iterEnd = m_DefaultMimeTypes.end(); mimeTypeIter != iterEnd; ++mimeTypeIter) + { + delete *mimeTypeIter; + } + m_ShaderRepositoryTracker->Close(); } void MitkCoreActivator::RegisterDefaultMimeTypes() { // Register some default mime-types - std::vector mimeTypes = mitk::IOMimeTypes::Get(); - for (std::vector::const_iterator mimeTypeIter = mimeTypes.begin(), + std::vector mimeTypes = mitk::IOMimeTypes::Get(); + for (std::vector::const_iterator mimeTypeIter = mimeTypes.begin(), iterEnd = mimeTypes.end(); mimeTypeIter != iterEnd; ++mimeTypeIter) { m_DefaultMimeTypes.push_back(*mimeTypeIter); - m_Context->RegisterService(&m_DefaultMimeTypes.back()); + m_Context->RegisterService(m_DefaultMimeTypes.back()); } } void MitkCoreActivator::RegisterItkReaderWriter() { std::list allobjects = itk::ObjectFactoryBase::CreateAllInstance("itkImageIOBase"); + + itk::ImageIOBase* itkGdcmIO = NULL; for (std::list::iterator i = allobjects.begin(), endIter = allobjects.end(); i != endIter; ++i) { itk::ImageIOBase* io = dynamic_cast(i->GetPointer()); // NiftiImageIO does not provide a correct "SupportsDimension()" methods // and the supported read/write extensions are not ordered correctly if (dynamic_cast(io)) continue; + // Use a custom mime-type for GDCMImageIO below + if (dynamic_cast(i->GetPointer())) + { + itkGdcmIO = io; + continue; + } + if (io) { m_FileIOs.push_back(new mitk::ItkImageIO(io)); } else { MITK_WARN << "Error ImageIO factory did not return an ImageIOBase: " << ( *i )->GetNameOfClass(); } } - mitk::ItkImageIO* io = new mitk::ItkImageIO(mitk::CustomMimeType(mitk::IOMimeTypes::NIFTI_MIMETYPE_NAME()), - new FixedNiftiImageIO(), 0); - m_FileIOs.push_back(io); + FixedNiftiImageIO::Pointer itkNiftiIO = FixedNiftiImageIO::New(); + mitk::ItkImageIO* niftiIO = new mitk::ItkImageIO(mitk::CustomMimeType(mitk::IOMimeTypes::NIFTI_MIMETYPE_NAME()), + itkNiftiIO.GetPointer(), 0); + m_FileIOs.push_back(niftiIO); + + mitk::ItkImageIO* gdcmIO = new mitk::ItkImageIO(mitk::CustomMimeType(mitk::IOMimeTypes::DICOM_MIMETYPE_NAME()), + itkGdcmIO, 0); + m_FileIOs.push_back(gdcmIO); } void MitkCoreActivator::RegisterVtkReaderWriter() { m_FileIOs.push_back(new mitk::SurfaceVtkXmlIO()); m_FileIOs.push_back(new mitk::SurfaceStlIO()); m_FileIOs.push_back(new mitk::SurfaceVtkLegacyIO()); m_FileIOs.push_back(new mitk::ImageVtkXmlIO()); m_FileIOs.push_back(new mitk::ImageVtkLegacyIO()); } void MitkCoreActivator::RegisterLegacyWriter() { std::list allobjects = itk::ObjectFactoryBase::CreateAllInstance("IOWriter"); for( std::list::iterator i = allobjects.begin(); i != allobjects.end(); ++i) { mitk::FileWriter::Pointer io = dynamic_cast(i->GetPointer()); if(io) { std::string description = std::string("Legacy ") + io->GetNameOfClass() + " Reader"; mitk::IFileWriter* writer = new mitk::LegacyFileWriterService(io, description); m_LegacyWriters.push_back(writer); } else { MITK_ERROR << "Error IOWriter override is not of type mitk::FileWriter: " << (*i)->GetNameOfClass() << std::endl; } } } US_EXPORT_MODULE_ACTIVATOR(MitkCore, MitkCoreActivator) // Call CppMicroservices initialization code at the end of the file. // This especially ensures that VTK object factories have already // been registered (VTK initialization code is injected by implicitly // include VTK header files at the top of this file). US_INITIALIZE_MODULE("MitkCore", "MitkCore") diff --git a/Core/Code/Internal/mitkCoreActivator.h b/Core/Code/Internal/mitkCoreActivator.h index 2e47d4e9ce..37a01eea4a 100644 --- a/Core/Code/Internal/mitkCoreActivator.h +++ b/Core/Code/Internal/mitkCoreActivator.h @@ -1,87 +1,87 @@ /*=================================================================== 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 MITKCOREACTIVATOR_H_ #define MITKCOREACTIVATOR_H_ // File IO #include #include #include #include #include #include #include #include #include #include // Micro Services #include #include #include #include #include /* * This is the module activator for the "Mitk" module. It registers core services * like ... */ class MitkCoreActivator : public us::ModuleActivator { public: void Load(us::ModuleContext* context); void Unload(us::ModuleContext* ); private: void HandleModuleEvent(const us::ModuleEvent moduleEvent); void RegisterDefaultMimeTypes(); void RegisterItkReaderWriter(); void RegisterVtkReaderWriter(); void RegisterLegacyWriter(); std::auto_ptr > m_ShaderRepositoryTracker; //mitk::RenderingManager::Pointer m_RenderingManager; std::auto_ptr m_PlanePositionManager; std::auto_ptr m_PropertyAliases; std::auto_ptr m_PropertyDescriptions; std::auto_ptr m_PropertyExtensions; std::auto_ptr m_PropertyFilters; std::auto_ptr m_MimeTypeProvider; // File IO std::vector m_FileReaders; std::vector m_FileWriters; std::vector m_FileIOs; std::vector m_LegacyWriters; - std::vector m_DefaultMimeTypes; + std::vector m_DefaultMimeTypes; us::ServiceRegistration m_MimeTypeProviderReg; us::ModuleContext* m_Context; }; #endif // MITKCOREACTIVATOR_H_ diff --git a/Core/Code/Internal/mitkFileReaderWriterBase.cpp b/Core/Code/Internal/mitkFileReaderWriterBase.cpp index cf0eb215f7..5dd58f3b17 100644 --- a/Core/Code/Internal/mitkFileReaderWriterBase.cpp +++ b/Core/Code/Internal/mitkFileReaderWriterBase.cpp @@ -1,261 +1,261 @@ /*=================================================================== 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 "mitkFileReaderWriterBase.h" #include "mitkLogMacros.h" #include "mitkCoreServices.h" #include "mitkIMimeTypeProvider.h" #include "mitkIOMimeTypes.h" #include #include namespace mitk { FileReaderWriterBase::FileReaderWriterBase() : m_Ranking(0) , m_MimeTypePrefix(IOMimeTypes::DEFAULT_BASE_NAME() + ".") { } FileReaderWriterBase::~FileReaderWriterBase() { this->UnregisterMimeType(); } FileReaderWriterBase::FileReaderWriterBase(const FileReaderWriterBase& other) : m_Description(other.m_Description) , m_Ranking(other.m_Ranking) , m_MimeTypePrefix(other.m_MimeTypePrefix) , m_Options(other.m_Options) , m_DefaultOptions(other.m_DefaultOptions) - , m_CustomMimeType(other.m_CustomMimeType) + , m_CustomMimeType(other.m_CustomMimeType->Clone()) { } FileReaderWriterBase::Options FileReaderWriterBase::GetOptions() const { Options options = m_Options; options.insert(m_DefaultOptions.begin(), m_DefaultOptions.end()); return options; } us::Any FileReaderWriterBase::GetOption(const std::string& name) const { Options::const_iterator iter = m_Options.find(name); if (iter != m_Options.end()) { return iter->second; } iter = m_DefaultOptions.find(name); if (iter != m_DefaultOptions.end()) { return iter->second; } return us::Any(); } void FileReaderWriterBase::SetOptions(const FileReaderWriterBase::Options& options) { for(Options::const_iterator iter = options.begin(), iterEnd = options.end(); iter != iterEnd; ++iter) { this->SetOption(iter->first, iter->second); } } void FileReaderWriterBase::SetOption(const std::string& name, const us::Any& value) { if (m_DefaultOptions.find(name) == m_DefaultOptions.end()) { MITK_WARN << "Ignoring unknown IFileReader option '" << name << "'"; } else { if (value.Empty()) { // an empty Any signals 'reset to default value' m_Options.erase(name); } else { m_Options[name] = value; } } } void FileReaderWriterBase::SetDefaultOptions(const FileReaderWriterBase::Options& defaultOptions) { m_DefaultOptions = defaultOptions; } FileReaderWriterBase::Options FileReaderWriterBase::GetDefaultOptions() const { return m_DefaultOptions; } void FileReaderWriterBase::SetRanking(int ranking) { m_Ranking = ranking; } int FileReaderWriterBase::GetRanking() const { return m_Ranking; } void FileReaderWriterBase::SetMimeType(const CustomMimeType& mimeType) { - m_CustomMimeType = mimeType; + m_CustomMimeType.reset(mimeType.Clone()); } -CustomMimeType FileReaderWriterBase::GetMimeType() const +const CustomMimeType* FileReaderWriterBase::GetMimeType() const { - return m_CustomMimeType; + return m_CustomMimeType.get(); } -CustomMimeType& FileReaderWriterBase::GetMimeType() +CustomMimeType* FileReaderWriterBase::GetMimeType() { - return m_CustomMimeType; + return m_CustomMimeType.get(); } MimeType FileReaderWriterBase::GetRegisteredMimeType() const { MimeType result; if (!m_MimeTypeReg) { - if (!m_CustomMimeType.GetName().empty()) + if (!m_CustomMimeType->GetName().empty()) { CoreServicePointer mimeTypeProvider( CoreServices::GetMimeTypeProvider(us::GetModuleContext())); - return mimeTypeProvider->GetMimeTypeForName(m_CustomMimeType.GetName()); + return mimeTypeProvider->GetMimeTypeForName(m_CustomMimeType->GetName()); } return result; } us::ServiceReferenceU reference = m_MimeTypeReg.GetReference(); try { int rank = 0; us::Any rankProp = reference.GetProperty(us::ServiceConstants::SERVICE_RANKING()); if (!rankProp.Empty()) { rank = us::any_cast(rankProp); } long id = us::any_cast(reference.GetProperty(us::ServiceConstants::SERVICE_ID())); - result = MimeType(m_CustomMimeType, rank, id); + result = MimeType(*m_CustomMimeType, rank, id); } catch (const us::BadAnyCastException& e) { MITK_WARN << "Unexpected exception: " << e.what(); } return result; } void FileReaderWriterBase::SetMimeTypePrefix(const std::string& prefix) { m_MimeTypePrefix = prefix; } std::string FileReaderWriterBase::GetMimeTypePrefix() const { return m_MimeTypePrefix; } void FileReaderWriterBase::SetDescription(const std::string& description) { m_Description = description; } std::string FileReaderWriterBase::GetDescription() const { return m_Description; } void FileReaderWriterBase::AddProgressCallback(const FileReaderWriterBase::ProgressCallback& callback) { m_ProgressMessage += callback; } void FileReaderWriterBase::RemoveProgressCallback(const FileReaderWriterBase::ProgressCallback& callback) { m_ProgressMessage -= callback; } us::ServiceRegistration FileReaderWriterBase::RegisterMimeType(us::ModuleContext* context) { if (context == NULL) throw std::invalid_argument("The context argument must not be NULL."); CoreServicePointer mimeTypeProvider(CoreServices::GetMimeTypeProvider(context)); - const std::vector extensions = m_CustomMimeType.GetExtensions(); + const std::vector extensions = m_CustomMimeType->GetExtensions(); // If the mime type name is set and the list of extensions is empty, // look up the mime type in the registry and print a warning if // there is none - if (!m_CustomMimeType.GetName().empty() && extensions.empty()) + if (!m_CustomMimeType->GetName().empty() && extensions.empty()) { - if(!mimeTypeProvider->GetMimeTypeForName(m_CustomMimeType.GetName()).IsValid()) + if(!mimeTypeProvider->GetMimeTypeForName(m_CustomMimeType->GetName()).IsValid()) { - MITK_WARN << "Registering a MITK reader or writer with an unknown MIME type " << m_CustomMimeType.GetName(); + MITK_WARN << "Registering a MITK reader or writer with an unknown MIME type " << m_CustomMimeType->GetName(); } return m_MimeTypeReg; } // If the mime type name and extensions list is empty, print a warning - if(m_CustomMimeType.GetName().empty() && extensions.empty()) + if(m_CustomMimeType->GetName().empty() && extensions.empty()) { MITK_WARN << "Trying to register a MITK reader or writer with an empty mime type name and empty extension list."; return m_MimeTypeReg; } // extensions is not empty - if(m_CustomMimeType.GetName().empty()) + if(m_CustomMimeType->GetName().empty()) { // Create a synthetic mime type name from the // first extension in the list - m_CustomMimeType.SetName(m_MimeTypePrefix + extensions.front()); + m_CustomMimeType->SetName(m_MimeTypePrefix + extensions.front()); } // Register a new mime type //us::ServiceProperties props; //props["name"] = m_CustomMimeType.GetName(); //props["extensions"] = m_CustomMimeType.GetExtensions(); - m_MimeTypeReg = context->RegisterService(&m_CustomMimeType); + m_MimeTypeReg = context->RegisterService(m_CustomMimeType.get()); return m_MimeTypeReg; } void FileReaderWriterBase::UnregisterMimeType() { if (m_MimeTypeReg) { try { m_MimeTypeReg.Unregister(); } catch (const std::logic_error&) { // service already unregistered } } } } diff --git a/Core/Code/Internal/mitkFileReaderWriterBase.h b/Core/Code/Internal/mitkFileReaderWriterBase.h index bfba2751e3..b705cb7d37 100644 --- a/Core/Code/Internal/mitkFileReaderWriterBase.h +++ b/Core/Code/Internal/mitkFileReaderWriterBase.h @@ -1,113 +1,115 @@ /*=================================================================== 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 MITKFILEREADERWRITERBASE_H #define MITKFILEREADERWRITERBASE_H #include #include #include #include #include +#include + namespace mitk { class FileReaderWriterBase { public: typedef std::map Options; typedef mitk::MessageAbstractDelegate1 ProgressCallback; FileReaderWriterBase(); virtual ~FileReaderWriterBase(); Options GetOptions() const; us::Any GetOption(const std::string &name) const; void SetOptions(const Options& options); void SetOption(const std::string& name, const us::Any& value); void SetDefaultOptions(const Options& defaultOptions); Options GetDefaultOptions() const; /** * \brief Set the service ranking for this file reader. * * Default is zero and should only be chosen differently for a reason. * The ranking is used to determine which reader to use if several * equivalent readers have been found. * It may be used to replace a default reader from MITK in your own project. * E.g. if you want to use your own reader for nrrd files instead of the default, * implement it and give it a higher ranking than zero. */ void SetRanking(int ranking); int GetRanking() const; void SetMimeType(const CustomMimeType& mimeType); - CustomMimeType GetMimeType() const; - CustomMimeType& GetMimeType(); + const CustomMimeType* GetMimeType() const; + CustomMimeType* GetMimeType(); MimeType GetRegisteredMimeType() const; void SetMimeTypePrefix(const std::string& prefix); std::string GetMimeTypePrefix() const; void SetDescription(const std::string& description); std::string GetDescription() const; void AddProgressCallback(const ProgressCallback& callback); void RemoveProgressCallback(const ProgressCallback& callback); us::ServiceRegistration RegisterMimeType(us::ModuleContext* context); void UnregisterMimeType(); protected: FileReaderWriterBase(const FileReaderWriterBase& other); std::string m_Description; int m_Ranking; std::string m_MimeTypePrefix; /** * \brief Options supported by this reader. Set sensible default values! * * Can be left emtpy if no special options are required. */ Options m_Options; Options m_DefaultOptions; //us::PrototypeServiceFactory* m_PrototypeFactory; Message1 m_ProgressMessage; - CustomMimeType m_CustomMimeType; + std::auto_ptr m_CustomMimeType; us::ServiceRegistration m_MimeTypeReg; private: // purposely not implemented FileReaderWriterBase& operator=(const FileReaderWriterBase& other); }; } #endif // MITKFILEREADERWRITERBASE_H diff --git a/Core/Code/Internal/mitkMimeTypeProvider.cpp b/Core/Code/Internal/mitkMimeTypeProvider.cpp index 0ca97fe3d9..df02eb26c7 100644 --- a/Core/Code/Internal/mitkMimeTypeProvider.cpp +++ b/Core/Code/Internal/mitkMimeTypeProvider.cpp @@ -1,198 +1,186 @@ /*=================================================================== 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 "mitkMimeTypeProvider.h" #include "mitkLogMacros.h" #include #include #include #ifdef _MSC_VER #pragma warning(disable:4503) // decorated name length exceeded, name was truncated #pragma warning(disable:4355) #endif namespace mitk { MimeTypeProvider::MimeTypeProvider() : m_Tracker(NULL) { } MimeTypeProvider::~MimeTypeProvider() { delete m_Tracker; } void MimeTypeProvider::Start() { if (m_Tracker == NULL) { m_Tracker = new us::ServiceTracker(us::GetModuleContext(), this); } m_Tracker->Open(); } void MimeTypeProvider::Stop() { m_Tracker->Close(); } std::vector MimeTypeProvider::GetMimeTypes() const { std::vector result; for (std::map::const_iterator iter = m_NameToMimeType.begin(), end = m_NameToMimeType.end(); iter != end; ++iter) { result.push_back(iter->second); } return result; } std::vector MimeTypeProvider::GetMimeTypesForFile(const std::string& filePath) const -{ - // For now, just use the file extension to look-up the registered mime-types. - std::string extension = itksys::SystemTools::GetFilenameExtension(filePath); - if (!extension.empty()) - { - extension = extension.substr(1, extension.size()-1); - } - return this->GetMimeTypesForExtension(extension); -} - -std::vector MimeTypeProvider::GetMimeTypesForExtension(const std::string& extension) const { std::vector result; for (std::map::const_iterator iter = m_NameToMimeType.begin(), iterEnd = m_NameToMimeType.end(); iter != iterEnd; ++iter) { - const std::vector extensions = iter->second.GetExtensions(); - if (std::find(extensions.begin(), extensions.end(), extension) != extensions.end()) + if (iter->second.AppliesTo(filePath)) { result.push_back(iter->second); } } std::sort(result.begin(), result.end()); std::reverse(result.begin(), result.end()); return result; } std::vector MimeTypeProvider::GetMimeTypesForCategory(const std::string& category) const { std::vector result; for (std::map::const_iterator iter = m_NameToMimeType.begin(), end = m_NameToMimeType.end(); iter != end; ++iter) { if (iter->second.GetCategory() == category) { result.push_back(iter->second); } } return result; } MimeType MimeTypeProvider::GetMimeTypeForName(const std::string& name) const { std::map::const_iterator iter = m_NameToMimeType.find(name); if (iter != m_NameToMimeType.end()) return iter->second; return MimeType(); } std::vector MimeTypeProvider::GetCategories() const { std::vector result; for (std::map::const_iterator iter = m_NameToMimeType.begin(), end = m_NameToMimeType.end(); iter != end; ++iter) { std::string category = iter->second.GetCategory(); if (!category.empty()) { result.push_back(category); } } std::sort(result.begin(), result.end()); result.erase(std::unique(result.begin(), result.end()), result.end()); return result; } MimeTypeProvider::TrackedType MimeTypeProvider::AddingService(const ServiceReferenceType& reference) { MimeType result = this->GetMimeType(reference); if (result.IsValid()) { std::string name = result.GetName(); m_NameToMimeTypes[name].insert(result); // get the highest ranked mime-type m_NameToMimeType[name] = *(m_NameToMimeTypes[name].rbegin()); } return result; } void MimeTypeProvider::ModifiedService(const ServiceReferenceType& /*reference*/, TrackedType /*mimetype*/) { // should we track changes in the ranking property? } void MimeTypeProvider::RemovedService(const ServiceReferenceType& /*reference*/, TrackedType mimeType) { std::string name = mimeType.GetName(); std::set& mimeTypes = m_NameToMimeTypes[name]; mimeTypes.erase(mimeType); if (mimeTypes.empty()) { m_NameToMimeTypes.erase(name); m_NameToMimeType.erase(name); } else { // get the highest ranked mime-type m_NameToMimeType[name] = *(mimeTypes.rbegin()); } } MimeType MimeTypeProvider::GetMimeType(const ServiceReferenceType& reference) const { MimeType result; if (!reference) return result; CustomMimeType* mimeType = us::GetModuleContext()->GetService(reference); if (mimeType != NULL) { try { int rank = 0; us::Any rankProp = reference.GetProperty(us::ServiceConstants::SERVICE_RANKING()); if (!rankProp.Empty()) { rank = us::any_cast(rankProp); } long id = us::any_cast(reference.GetProperty(us::ServiceConstants::SERVICE_ID())); result = MimeType(*mimeType, rank, id); } catch (const us::BadAnyCastException& e) { MITK_WARN << "Unexpected exception: " << e.what(); } us::GetModuleContext()->UngetService(reference); } return result; } } diff --git a/Core/Code/Internal/mitkMimeTypeProvider.h b/Core/Code/Internal/mitkMimeTypeProvider.h index 59d1152e08..9e7de95120 100644 --- a/Core/Code/Internal/mitkMimeTypeProvider.h +++ b/Core/Code/Internal/mitkMimeTypeProvider.h @@ -1,86 +1,85 @@ /*=================================================================== 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 MITKMIMETYPEPROVIDER_H #define MITKMIMETYPEPROVIDER_H #include "mitkIMimeTypeProvider.h" #include "mitkCustomMimeType.h" #include "usServiceTracker.h" #include "usServiceTrackerCustomizer.h" #include namespace mitk { struct MimeTypeTrackerTypeTraits : public us::TrackedTypeTraitsBase { typedef MimeType TrackedType; static bool IsValid(const TrackedType& t) { return t.IsValid(); } static TrackedType DefaultValue() { return TrackedType(); } static void Dispose(TrackedType& /*t*/) { } }; class MimeTypeProvider : public IMimeTypeProvider, private us::ServiceTrackerCustomizer { public: MimeTypeProvider(); ~MimeTypeProvider(); void Start(); void Stop(); virtual std::vector GetMimeTypes() const; virtual std::vector GetMimeTypesForFile(const std::string& filePath) const; - virtual std::vector GetMimeTypesForExtension(const std::string& extension) const; virtual std::vector GetMimeTypesForCategory(const std::string& category) const; virtual MimeType GetMimeTypeForName(const std::string& name) const; virtual std::vector GetCategories() const; private: virtual TrackedType AddingService(const ServiceReferenceType& reference); virtual void ModifiedService(const ServiceReferenceType& reference, TrackedType service); virtual void RemovedService(const ServiceReferenceType& reference, TrackedType service); MimeType GetMimeType(const ServiceReferenceType& reference) const; us::ServiceTracker* m_Tracker; typedef std::map > MapType; MapType m_NameToMimeTypes; std::map m_NameToMimeType; }; } #endif // MITKMIMETYPEPROVIDER_H diff --git a/Core/Code/Testing/mitkPointSetReaderTest.cpp b/Core/Code/Testing/mitkPointSetReaderTest.cpp index 6967e3f01d..5d8ccfdda0 100644 --- a/Core/Code/Testing/mitkPointSetReaderTest.cpp +++ b/Core/Code/Testing/mitkPointSetReaderTest.cpp @@ -1,69 +1,69 @@ /*=================================================================== 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 "mitkPointSet.h" #include "mitkTestingMacros.h" #include "mitkFileReaderRegistry.h" #include "mitkMimeType.h" /** * Test for the class "mitkPointSetReader". * * 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 data set for the tests (see CMakeLists.txt). */ int mitkPointSetReaderTest(int argc , char* argv[]) { // always start with this! MITK_TEST_BEGIN("PointSetReader") MITK_TEST_CONDITION_REQUIRED(argc == 2,"Testing invocation") mitk::FileReaderRegistry readerRegistry; // Get PointSet reader(s) - std::vector readers = readerRegistry.GetReaders(mitk::FileReaderRegistry::GetMimeTypeForExtension("mps")); + std::vector readers = readerRegistry.GetReaders(mitk::FileReaderRegistry::GetMimeTypeForFile("mps")); MITK_TEST_CONDITION_REQUIRED(!readers.empty(), "Testing for registered readers") for (std::vector::const_iterator iter = readers.begin(), end = readers.end(); iter != end; ++iter) { std::string testName = "test1"; mitk::IFileReader* reader = *iter; reader->SetInput(testName); // testing file reading with invalid data MITK_TEST_CONDITION_REQUIRED(reader->GetConfidenceLevel() == mitk::IFileReader::Unsupported, "Testing confidence level with invalid input file name!"); CPPUNIT_ASSERT_THROW(reader->Read(), mitk::Exception); // testing file reading with valid data std::string filePath = argv[1]; reader->SetInput(filePath); MITK_TEST_CONDITION_REQUIRED( reader->GetConfidenceLevel() == mitk::IFileReader::Supported, "Testing confidence level with valid input file name!"); std::vector data = reader->Read(); MITK_TEST_CONDITION_REQUIRED( !data.empty(), "Testing non-empty data with valid input file name!"); // evaluate if the read point set is correct mitk::PointSet::Pointer resultPS = dynamic_cast(data.front().GetPointer()); MITK_TEST_CONDITION_REQUIRED( resultPS.IsNotNull(), "Testing correct BaseData type"); MITK_TEST_CONDITION_REQUIRED( resultPS->GetTimeSteps() == 14, "Testing output time step generation!"); // CAVE: Only valid with the specified test data! MITK_TEST_CONDITION_REQUIRED( resultPS->GetPointSet(resultPS->GetTimeSteps()-1)->GetNumberOfPoints() == 0, "Testing output time step generation with empty time step!"); // CAVE: Only valid with the specified test data! } // always end with this! MITK_TEST_END() } diff --git a/Modules/QtWidgets/QmitkIOUtil.cpp b/Modules/QtWidgets/QmitkIOUtil.cpp index d69d66a633..9397c0d79b 100644 --- a/Modules/QtWidgets/QmitkIOUtil.cpp +++ b/Modules/QtWidgets/QmitkIOUtil.cpp @@ -1,527 +1,527 @@ /*=================================================================== 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 "QmitkIOUtil.h" #include #include #include #include "mitkCoreServices.h" #include "mitkIMimeTypeProvider.h" #include "mitkMimeType.h" #include "mitkCustomMimeType.h" #include "mitkFileReaderRegistry.h" #include "mitkFileWriterRegistry.h" #include "QmitkFileReaderOptionsDialog.h" #include "QmitkFileWriterOptionsDialog.h" // QT #include #include #include #include //ITK #include #include struct QmitkIOUtil::Impl { struct ReaderOptionsDialogFunctor : public ReaderOptionsFunctorBase { virtual bool operator()(LoadInfo& loadInfo) { QmitkFileReaderOptionsDialog dialog(loadInfo); if (dialog.exec() == QDialog::Accepted) { return !dialog.ReuseOptions(); } else { loadInfo.m_Cancel = true; return true; } } }; struct WriterOptionsDialogFunctor : public WriterOptionsFunctorBase { virtual bool operator()(SaveInfo& saveInfo) { QmitkFileWriterOptionsDialog dialog(saveInfo); if (dialog.exec() == QDialog::Accepted) { return !dialog.ReuseOptions(); } else { saveInfo.m_Cancel = true; return true; } } }; }; struct MimeTypeComparison : public std::unary_function { MimeTypeComparison(const std::string& mimeTypeName) : m_Name(mimeTypeName) {} bool operator()(const mitk::MimeType& mimeType) const { return mimeType.GetName() == m_Name; } const std::string m_Name; }; QString QmitkIOUtil::GetFileOpenFilterString() { QString filters; mitk::CoreServicePointer mimeTypeProvider(mitk::CoreServices::GetMimeTypeProvider()); std::vector categories = mimeTypeProvider->GetCategories(); for (std::vector::iterator cat = categories.begin(); cat != categories.end(); ++cat) { QSet filterExtensions; std::vector mimeTypes = mimeTypeProvider->GetMimeTypesForCategory(*cat); for (std::vector::iterator mt = mimeTypes.begin(); mt != mimeTypes.end(); ++mt) { std::vector extensions = mt->GetExtensions(); for (std::vector::iterator ext = extensions.begin(); ext != extensions.end(); ++ext) { filterExtensions << QString::fromStdString(*ext); } } QString filter = QString::fromStdString(*cat) + " ("; foreach(const QString& extension, filterExtensions) { filter += "*." + extension + " "; } filter = filter.replace(filter.size()-1, 1, ')'); filters += ";;" + filter; } filters.prepend("All (*.*)"); return filters; } QList QmitkIOUtil::Load(const QStringList& paths, QWidget* parent) { std::vector loadInfos; foreach(const QString& file, paths) { loadInfos.push_back(LoadInfo(file.toStdString())); } Impl::ReaderOptionsDialogFunctor optionsCallback; std::string errMsg = Load(loadInfos, NULL, NULL, &optionsCallback); if (!errMsg.empty()) { QMessageBox::warning(parent, "Error reading files", QString::fromStdString(errMsg)); mitkThrow() << errMsg; } QList qResult; for(std::vector::const_iterator iter = loadInfos.begin(), iterEnd = loadInfos.end(); iter != iterEnd; ++iter) { for (std::vector::const_iterator dataIter = iter->m_Output.begin(), dataIterEnd = iter->m_Output.end(); dataIter != dataIterEnd; ++dataIter) { qResult << *dataIter; } } return qResult; } mitk::DataStorage::SetOfObjects::Pointer QmitkIOUtil::Load(const QStringList& paths, mitk::DataStorage& storage, QWidget* parent) { std::vector loadInfos; foreach(const QString& file, paths) { loadInfos.push_back(LoadInfo(file.toStdString())); } mitk::DataStorage::SetOfObjects::Pointer nodeResult = mitk::DataStorage::SetOfObjects::New(); Impl::ReaderOptionsDialogFunctor optionsCallback; std::string errMsg = Load(loadInfos, nodeResult, &storage, &optionsCallback); if (!errMsg.empty()) { QMessageBox::warning(parent, "Error reading files", QString::fromStdString(errMsg)); mitkThrow() << errMsg; } return nodeResult; } QList QmitkIOUtil::Load(const QString& path, QWidget* parent) { QStringList paths; paths << path; return Load(paths, parent); } mitk::DataStorage::SetOfObjects::Pointer QmitkIOUtil::Load(const QString& path, mitk::DataStorage& storage, QWidget* parent) { QStringList paths; paths << path; return Load(paths, storage, parent); } QString QmitkIOUtil::Save(const mitk::BaseData* data, const QString& defaultBaseName, const QString& defaultPath, QWidget* parent) { std::vector dataVector; dataVector.push_back(data); QStringList defaultBaseNames; defaultBaseNames.push_back(defaultBaseName); return Save(dataVector, defaultBaseNames, defaultPath, parent).back(); } QStringList QmitkIOUtil::Save(const std::vector& data, const QStringList& defaultBaseNames, const QString& defaultPath, QWidget* parent) { QStringList fileNames; QString currentPath = defaultPath; std::vector saveInfos; int counter = 0; for(std::vector::const_iterator dataIter = data.begin(), dataIterEnd = data.end(); dataIter != dataIterEnd; ++dataIter, ++counter) { SaveInfo saveInfo(*dataIter, mitk::MimeType(), std::string()); SaveFilter filters(saveInfo); // If there is only the "__all__" filter string, it means there is no writer for this base data if (filters.Size() < 2) { QMessageBox::warning(parent, "Saving not possible", QString("No writer available for type \"%1\"").arg( QString::fromStdString((*dataIter)->GetNameOfClass()))); continue; } // Construct a default path and file name QString filterString = filters.ToString(); QString selectedFilter = filters.GetDefaultFilter(); QString fileName = currentPath; QString dialogTitle = "Save " + QString::fromStdString((*dataIter)->GetNameOfClass()); if (counter < defaultBaseNames.size()) { dialogTitle += " \"" + defaultBaseNames[counter] + "\""; fileName += QDir::separator() + defaultBaseNames[counter]; // We do not append an extension to the file name by default. The extension // is chosen by the user by either selecting a filter or writing the // extension in the file name himself (in the file save dialog). /* QString defaultExt = filters.GetDefaultExtension(); if (!defaultExt.isEmpty()) { fileName += "." + defaultExt; } */ } // Ask the user for a file name QString nextName = QFileDialog::getSaveFileName(parent, dialogTitle, fileName, filterString, &selectedFilter); if (nextName.isEmpty()) { // We stop asking for further file names, but we still save the // data where the user already confirmed the save dialog. break; } fileName = nextName; QFileInfo fileInfo(fileName); currentPath = fileInfo.absolutePath(); QString suffix = fileInfo.completeSuffix(); mitk::MimeType mimeType = filters.GetMimeTypeForFilter(selectedFilter); mitk::CoreServicePointer mimeTypeProvider(mitk::CoreServices::GetMimeTypeProvider()); // If the filename contains a suffix, use it but check if it is valid if (!suffix.isEmpty()) { - std::vector availableTypes = mimeTypeProvider->GetMimeTypesForExtension(suffix.toStdString()); + std::vector availableTypes = mimeTypeProvider->GetMimeTypesForFile(fileName.toStdString()); // Check if the selected mime-type is related to the specified suffix (file extension). // If not, get the best matching mime-type for the suffix. if (std::find(availableTypes.begin(), availableTypes.end(), mimeType) == availableTypes.end()) { mimeType = mitk::MimeType(); for (std::vector::const_iterator availIter = availableTypes.begin(), availIterEnd = availableTypes.end(); availIter != availIterEnd; ++availIter) { if (filters.ContainsMimeType(availIter->GetName())) { mimeType = *availIter; break; } } } if (!mimeType.IsValid()) { // The extension is not valid (no mime-type found), bail out QMessageBox::warning(parent, "Saving not possible", QString("Extension \"%1\" unknown for type \"%2\"") .arg(suffix) .arg(QString::fromStdString((*dataIter)->GetNameOfClass()))); continue; } } else { // Create a default suffix, unless the file already exists and the user // already confirmed to overwrite it (without using a suffix) if (mimeType == SaveFilter::ALL_MIMETYPE()) { // Use the highest ranked mime-type from the list mimeType = filters.GetDefaultMimeType(); } if (!fileInfo.exists()) { suffix = QString::fromStdString(mimeType.GetExtensions().front()); fileName += "." + suffix; // We changed the file name (added a suffix) so ask in case // the file aready exists. fileInfo = QFileInfo(fileName); if (fileInfo.exists()) { if (!fileInfo.isFile()) { QMessageBox::warning(parent, "Saving not possible", QString("The path \"%1\" is not a file").arg(fileName)); continue; } if (QMessageBox::question(parent, "Replace File", QString("A file named \"%1\" already exists. Do you want to replace it?").arg(fileName)) == QMessageBox::No) { continue; } } } } if (!QFileInfo(fileInfo.absolutePath()).isWritable()) { QMessageBox::warning(parent, "Saving not possible", QString("The path \"%1\" is not writable").arg(fileName)); continue; } fileNames.push_back(fileName); saveInfo.m_Path = fileName.toStdString(); saveInfo.m_MimeType = mimeType; // pre-select the best writer for the chosen mime-type saveInfo.m_WriterSelector.Select(mimeType.GetName()); saveInfos.push_back(saveInfo); } if (!saveInfos.empty()) { Impl::WriterOptionsDialogFunctor optionsCallback; std::string errMsg = Save(saveInfos, &optionsCallback); if (!errMsg.empty()) { QMessageBox::warning(parent, "Error writing files", QString::fromStdString(errMsg)); mitkThrow() << errMsg; } } return fileNames; } void QmitkIOUtil::SaveBaseDataWithDialog(mitk::BaseData* data, std::string fileName, QWidget* /*parent*/) { Save(data, fileName); } void QmitkIOUtil::SaveSurfaceWithDialog(mitk::Surface::Pointer surface, std::string fileName, QWidget* /*parent*/) { Save(surface, fileName); } void QmitkIOUtil::SaveImageWithDialog(mitk::Image::Pointer image, std::string fileName, QWidget* /*parent*/) { Save(image, fileName); } void QmitkIOUtil::SavePointSetWithDialog(mitk::PointSet::Pointer pointset, std::string fileName, QWidget* /*parent*/) { Save(pointset, fileName); } struct QmitkIOUtil::SaveFilter::Impl { Impl(const mitk::IOUtil::SaveInfo& saveInfo) : m_SaveInfo(saveInfo) { // Add an artifical filter for "All" m_MimeTypes.push_back(ALL_MIMETYPE()); m_FilterStrings.push_back("All (*.*)"); // Get all writers and their mime types for the given base data type // (this is sorted already) std::vector mimeTypes = saveInfo.m_WriterSelector.GetMimeTypes(); for (std::vector::const_reverse_iterator iter = mimeTypes.rbegin(), iterEnd = mimeTypes.rend(); iter != iterEnd; ++iter) { QSet filterExtensions; mitk::MimeType mimeType = *iter; std::vector extensions = mimeType.GetExtensions(); for (std::vector::iterator extIter = extensions.begin(), extIterEnd = extensions.end(); extIter != extIterEnd; ++extIter) { filterExtensions << QString::fromStdString(*extIter); } if (m_DefaultExtension.isEmpty()) { m_DefaultExtension = QString::fromStdString(extensions.front()); } QString filter = QString::fromStdString(mimeType.GetComment()) + " ("; foreach(const QString& extension, filterExtensions) { filter += "*." + extension + " "; } filter = filter.replace(filter.size()-1, 1, ')'); m_MimeTypes.push_back(mimeType); m_FilterStrings.push_back(filter); } } const mitk::IOUtil::SaveInfo m_SaveInfo; std::vector m_MimeTypes; QStringList m_FilterStrings; QString m_DefaultExtension; }; mitk::MimeType QmitkIOUtil::SaveFilter::ALL_MIMETYPE() { static mitk::CustomMimeType allMimeType(std::string("__all__")); return mitk::MimeType(allMimeType, -1, -1); } QmitkIOUtil::SaveFilter::SaveFilter(const QmitkIOUtil::SaveFilter& other) : d(new Impl(*other.d)) { } QmitkIOUtil::SaveFilter::SaveFilter(const SaveInfo& saveInfo) : d(new Impl(saveInfo)) { } QmitkIOUtil::SaveFilter& QmitkIOUtil::SaveFilter::operator=(const QmitkIOUtil::SaveFilter& other) { d.reset(new Impl(*other.d)); return *this; } QString QmitkIOUtil::SaveFilter::GetFilterForMimeType(const std::string& mimeType) const { std::vector::const_iterator iter = std::find_if(d->m_MimeTypes.begin(), d->m_MimeTypes.end(), MimeTypeComparison(mimeType)); if (iter == d->m_MimeTypes.end()) { return QString(); } int index = static_cast(iter - d->m_MimeTypes.begin()); if (index < 0 || index >= d->m_FilterStrings.size()) { return QString(); } return d->m_FilterStrings[index]; } mitk::MimeType QmitkIOUtil::SaveFilter::GetMimeTypeForFilter(const QString& filter) const { int index = d->m_FilterStrings.indexOf(filter); if (index < 0) { return mitk::MimeType(); } return d->m_MimeTypes[index]; } QString QmitkIOUtil::SaveFilter::GetDefaultFilter() const { if (d->m_FilterStrings.size() > 1) { return d->m_FilterStrings.at(1); } else if (d->m_FilterStrings.size() > 0) { return d->m_FilterStrings.front(); } return QString(); } QString QmitkIOUtil::SaveFilter::GetDefaultExtension() const { return d->m_DefaultExtension; } mitk::MimeType QmitkIOUtil::SaveFilter::GetDefaultMimeType() const { if (d->m_MimeTypes.size() > 1) { return d->m_MimeTypes.at(1); } else if (d->m_MimeTypes.size() > 0) { return d->m_MimeTypes.front(); } return mitk::MimeType(); } QString QmitkIOUtil::SaveFilter::ToString() const { return d->m_FilterStrings.join(";;"); } int QmitkIOUtil::SaveFilter::Size() const { return d->m_FilterStrings.size(); } bool QmitkIOUtil::SaveFilter::IsEmpty() const { return d->m_FilterStrings.isEmpty(); } bool QmitkIOUtil::SaveFilter::ContainsMimeType(const std::string& mimeType) { return std::find_if(d->m_MimeTypes.begin(), d->m_MimeTypes.end(), MimeTypeComparison(mimeType)) != d->m_MimeTypes.end(); }