diff --git a/Modules/Multilabel/mitkLabelSetImageConverter.cpp b/Modules/Multilabel/mitkLabelSetImageConverter.cpp index c3bc05a517..e8951b8f8f 100644 --- a/Modules/Multilabel/mitkLabelSetImageConverter.cpp +++ b/Modules/Multilabel/mitkLabelSetImageConverter.cpp @@ -1,133 +1,133 @@ /*=================================================================== 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 "mitkLabelSetImageConverter.h" // mitk includes #include "mitkImageAccessByItk.h" #include "mitkImageCast.h" #include // itk includes #include "itkImage.h" #include "itkVectorImage.h" #include #include -template < typename ImageType > -void VectorOfMitkImagesToMitkVectorImage(ImageType* source, mitk::Image::Pointer &output, mitk::LabelSetImage::Pointer input) +template < typename TPixel, unsigned int VImageDimension > +void VectorOfMitkImagesToMitkVectorImage(const itk::Image* source, mitk::Image::Pointer &output, mitk::LabelSetImage::ConstPointer input) { - typedef itk::ComposeImageFilter< ImageType > ComposeFilterType; + typedef itk::ComposeImageFilter< itk::Image > ComposeFilterType; unsigned int numberOfLayers = input->GetNumberOfLayers(); ComposeFilterType::Pointer vectorImageComposer = ComposeFilterType::New(); for (unsigned int layer(0); layer < numberOfLayers; layer++) { - typename ImageType::Pointer itkCurrentLayer; + typename itk::Image::Pointer itkCurrentLayer; mitk::CastToItkImage(input->GetLayerImage(layer), itkCurrentLayer); vectorImageComposer->SetInput(layer, itkCurrentLayer); } try { vectorImageComposer->Update(); } catch (const itk::ExceptionObject& e) { MITK_ERROR << "Caugt exception while updating compose filter: " << e.what(); } output = mitk::GrabItkImageMemory(vectorImageComposer->GetOutput()); } -mitk::Image::Pointer mitk::LabelSetImageConverter::ConvertLabelSetImageToImage(const mitk::LabelSetImage::Pointer input) +mitk::Image::Pointer mitk::LabelSetImageConverter::ConvertLabelSetImageToImage(const mitk::LabelSetImage::ConstPointer input) { unsigned int numberOfLayers = input->GetNumberOfLayers(); if (numberOfLayers == 0) { mitkThrow() << "Tried to convert LabelSetImage without layers"; } mitk::Image::Pointer output; AccessByItk_2(input->GetLayerImage(0), VectorOfMitkImagesToMitkVectorImage, output, input); return output; } template void MitkImageToMitkLabelSetImage(itk::Image< TPixel, VDimensions> * source, mitk::LabelSetImage::Pointer &output) { // do nothing for non-vector images } template void MitkImageToMitkLabelSetImage(itk::VectorImage< TPixel, VDimensions> * source, mitk::LabelSetImage::Pointer &output) { typedef itk::VectorImage< TPixel, VDimensions > VectorImageType; typedef itk::Image< TPixel, VDimensions > ImageType; typedef itk::VectorIndexSelectionCastImageFilter< VectorImageType, ImageType > VectorIndexSelectorType; unsigned int numberOfComponents = source->GetVectorLength(); if (numberOfComponents < 1) { mitkThrow() << "At least one Component is required." } typename VectorIndexSelectorType::Pointer vectorIndexSelector = typename VectorIndexSelectorType::New(); VectorIndexSelector->SetIndex(0); VectorIndexSelector->SetInput(source); mitk::Image::Pointer tempImage; mitk::GrabItkImageMemory(VectorIndexSelector->GetOutput(), tempImage); output = mitk::LabelSetImage::New(); output->InitializeByLabeledImage(tempImage); for (unsigned int layer = 1; layer < numberOfComponents; ++layer) { typename VectorIndexSelectorType::Pointer vectorIndexSelectorLoop = typename VectorIndexSelectorType::New(); VectorIndexSelectorLoop->SetIndex(layer); VectorIndexSelector->SetInput(source); mitk::Image::Pointer loopImage; mitk::GrabItkImageMemory(vectorIndexSelectorLoop->GetOutput(), loopImage); output->AddLayer(loopImage); } } mitk::LabelSetImage::Pointer mitk::LabelSetImageConverter::ConvertImageToLabelSetImage(const mitk::Image::Pointer input) { mitk::LabelSetImage::Pointer output; AccessByItk_1(input, MitkImageToMitkLabelSetImage, output); // if no vector image was detected if ( output.IsNull() ) { output = mitk::LabelSetImage::New(); output->InitializeByLabeledImage( input ); } return output; } diff --git a/Modules/Multilabel/mitkLabelSetImageConverter.h b/Modules/Multilabel/mitkLabelSetImageConverter.h index 128d8691a9..86f687ad85 100644 --- a/Modules/Multilabel/mitkLabelSetImageConverter.h +++ b/Modules/Multilabel/mitkLabelSetImageConverter.h @@ -1,54 +1,54 @@ /*=================================================================== 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 __mitkLabelSetImageConverter_H_ #define __mitkLabelSetImageConverter_H_ // for export #include "MitkMultilabelExports.h" // mitk includes #include "mitkImage.h" #include "mitkLabelSetImage.h" namespace mitk { /** * \brief Converts mitkLabelSetImage into a mitk::Image containing an itk::VectorImage * * Convenience class to avoid the dimension templating hassle. */ class MITKMULTILABEL_EXPORT LabelSetImageConverter { public: /// \brief Converts a mitk::LabelSetImage to an a itk::VectorImage containing mitk::Image, templating is internal - static mitk::Image::Pointer ConvertLabelSetImageToImage( const mitk::LabelSetImage::Pointer input ); + static mitk::Image::Pointer ConvertLabelSetImageToImage( const mitk::LabelSetImage::ConstPointer input ); /// \brief Converst a mitk::Image to a mitk::LabelSetImage, templating and differentation between itk::Image and itk::VectorImage is internal static mitk::LabelSetImage::Pointer ConvertImageToLabelSetImage( const mitk::Image::Pointer input ); protected: }; } // namespace mitk #endif // __mitkLabelSetImageConverter_H_ diff --git a/Modules/Multilabel/mitkLabelSetImageIO.cpp b/Modules/Multilabel/mitkLabelSetImageIO.cpp index ceb185a674..8fc9341831 100644 --- a/Modules/Multilabel/mitkLabelSetImageIO.cpp +++ b/Modules/Multilabel/mitkLabelSetImageIO.cpp @@ -1,512 +1,541 @@ /*=================================================================== 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 __mitkLabelSetImageWriter__cpp #define __mitkLabelSetImageWriter__cpp #include "mitkBasePropertySerializer.h" #include "mitkIOMimeTypes.h" #include "mitkLabelSetImageIO.h" +#include "mitkLabelSetImageConverter.h" // itk #include "itkMetaDataDictionary.h" #include "itkMetaDataObject.h" #include "itkNrrdImageIO.h" #include "itkImageFileWriter.h" #include "itkImageFileReader.h" +#include "mitkImageAccessByItk.h" #include "tinyxml.h" namespace mitk { LabelSetImageIO::LabelSetImageIO() : AbstractFileIO(LabelSetImage::GetStaticNameOfClass(), IOMimeTypes::NRRD_MIMETYPE(), "MITK Multilabel Image") { AbstractFileWriter::SetRanking(10); AbstractFileReader::SetRanking(10); this->RegisterService(); } IFileIO::ConfidenceLevel LabelSetImageIO::GetWriterConfidenceLevel() const { if (AbstractFileIO::GetWriterConfidenceLevel() == Unsupported) return Unsupported; const LabelSetImage* input = static_cast(this->GetInput()); if (input) return Supported; else return Unsupported; } -void LabelSetImageIO::Write() +template +void TemplatedWrite(const itk::Image< TPixel, VDimensions> * source, const LabelSetImage* input, std::string filename) { - ValidateOutputLocation(); - - const LabelSetImage* input = static_cast(this->GetInput()); - - const std::string& locale = "C"; - const std::string& currLocale = setlocale( LC_ALL, NULL ); - - if ( locale.compare(currLocale)!=0 ) - { - try - { - setlocale(LC_ALL, locale.c_str()); - } - catch(...) - { - mitkThrow() << "Could not set locale " << currLocale; - } - } - - typedef itk::ImageFileWriter WriterType; + mitkThrow() << "Tried to write non-vector labelsetimage"; +} - VectorImageType::Pointer vectorImage = input->GetVectorImage(true); // force update +template +void TemplatedWrite(const itk::VectorImage< TPixel, VDimensions> * source, const LabelSetImage* input, std::string filename) +{ + typedef itk::ImageFileWriter< itk::VectorImage< TPixel, VDimensions> > WriterType; char keybuffer[512]; char valbuffer[512]; sprintf( keybuffer, "modality"); sprintf( valbuffer, "org.mitk.image.multilabel"); - itk::EncapsulateMetaData(vectorImage->GetMetaDataDictionary(),std::string(keybuffer), std::string(valbuffer)); + itk::EncapsulateMetaData(source->GetMetaDataDictionary(), std::string(keybuffer), std::string(valbuffer)); sprintf( keybuffer, "layers"); sprintf( valbuffer, "%1d", input->GetNumberOfLayers()); - itk::EncapsulateMetaData(vectorImage->GetMetaDataDictionary(),std::string(keybuffer), std::string(valbuffer)); + itk::EncapsulateMetaData(source->GetMetaDataDictionary(), std::string(keybuffer), std::string(valbuffer)); for (unsigned int layerIdx=0; layerIdxGetNumberOfLayers(); layerIdx++) { sprintf( keybuffer, "layer_%03d", layerIdx ); // layer idx sprintf( valbuffer, "%1d", input->GetNumberOfLabels(layerIdx)); // number of labels for the layer - itk::EncapsulateMetaData(vectorImage->GetMetaDataDictionary(),std::string(keybuffer), std::string(valbuffer)); + itk::EncapsulateMetaData(source->GetMetaDataDictionary(), std::string(keybuffer), std::string(valbuffer)); mitk::LabelSet::LabelContainerConstIteratorType iter = input->GetLabelSet(layerIdx)->IteratorConstBegin(); unsigned int count(0); while (iter != input->GetLabelSet(layerIdx)->IteratorConstEnd()) { std::auto_ptr document; document.reset(new TiXmlDocument()); TiXmlDeclaration* decl = new TiXmlDeclaration( "1.0", "", "" ); // TODO what to write here? encoding? etc.... document->LinkEndChild( decl ); TiXmlElement * labelElem = GetLabelAsTiXmlElement(iter->second); document->LinkEndChild( labelElem ); TiXmlPrinter printer; printer.SetIndent(""); printer.SetLineBreak(""); document->Accept(&printer); sprintf( keybuffer, "org.mitk.label_%03u_%05u", layerIdx, count ); - itk::EncapsulateMetaData(vectorImage->GetMetaDataDictionary(),std::string(keybuffer), printer.Str()); + itk::EncapsulateMetaData(source->GetMetaDataDictionary(), std::string(keybuffer), printer.Str()); ++iter; ++count; } } itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); io->SetFileType( itk::ImageIOBase::Binary ); io->UseCompressionOn(); WriterType::Pointer nrrdWriter = WriterType::New(); nrrdWriter->UseInputMetaDataDictionaryOn(); - nrrdWriter->SetInput(vectorImage); + nrrdWriter->SetInput(source); - LocalFile localFile(this); - nrrdWriter->SetFileName(localFile.GetFileName().c_str()); + nrrdWriter->SetFileName(filename.c_str()); nrrdWriter->UseCompressionOn(); nrrdWriter->SetImageIO(io); try { nrrdWriter->Update(); } catch (itk::ExceptionObject e) { MITK_ERROR << "Could not write segmentation session. See error log for details."; mitkThrow() << e.GetDescription(); } +} + +void LabelSetImageIO::Write() +{ + ValidateOutputLocation(); + + const LabelSetImage* input = static_cast(this->GetInput()); + + const std::string& locale = "C"; + const std::string& currLocale = setlocale( LC_ALL, NULL ); + + if ( locale.compare(currLocale)!=0 ) + { + try + { + setlocale(LC_ALL, locale.c_str()); + } + catch(...) + { + mitkThrow() << "Could not set locale " << currLocale; + } + } + + mitk::Image::ConstPointer inputVector = mitk::LabelSetImageConverter::ConvertLabelSetImageToImage(input); + + LocalFile localFile(this); + + AccessByItk_2(inputVector, TemplatedWrite, input, localFile.GetFileName()); + try { setlocale(LC_ALL, currLocale.c_str()); } catch(...) { mitkThrow() << "Could not reset locale " << currLocale; } } IFileIO::ConfidenceLevel LabelSetImageIO::GetReaderConfidenceLevel() const { if (AbstractFileIO::GetReaderConfidenceLevel() == Unsupported) return Unsupported; const std::string fileName = this->GetLocalFileName(); itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); io->SetFileName(fileName); io->ReadImageInformation(); itk::MetaDataDictionary imgMetaDataDictionary = io->GetMetaDataDictionary(); std::string value (""); itk::ExposeMetaData (imgMetaDataDictionary, "modality", value); if (value.compare("org.mitk.image.multilabel") == 0) { return Supported; } else return Unsupported; } std::vector LabelSetImageIO::Read() { const std::string& locale = "C"; const std::string& currLocale = setlocale( LC_ALL, NULL ); if ( locale.compare(currLocale)!=0 ) { try { setlocale(LC_ALL, locale.c_str()); } catch(...) { mitkThrow() << "Could not set locale."; } } - LabelSetImage::VectorImageType::Pointer vectorImage; - - typedef itk::ImageFileReader FileReaderType; - FileReaderType::Pointer reader = FileReaderType::New(); - reader->SetFileName(this->GetLocalFileName()); - itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); - reader->SetImageIO(io); - try - { - reader->Update(); - } - catch(itk::ExceptionObject& e) - { - mitkThrow() << e.GetDescription(); - } - catch(...) - { - mitkThrow() << "Unknown exception caught!"; - } - - vectorImage = reader->GetOutput(); - - if (vectorImage.IsNull()) - mitkThrow() << "Could not retrieve the vector image."; - - LabelSetImage::Pointer output = LabelSetImage::New(); - - ImageType::Pointer auxImg = ImageType::New(); - auxImg->SetSpacing( vectorImage->GetSpacing() ); - auxImg->SetOrigin( vectorImage->GetOrigin() ); - auxImg->SetDirection( vectorImage->GetDirection() ); - auxImg->SetRegions( vectorImage->GetLargestPossibleRegion() ); - auxImg->Allocate(); - - // initialize output image based on vector image meta information - output->InitializeByItk( auxImg.GetPointer() ); - - itk::MetaDataDictionary imgMetaDictionary = vectorImage->GetMetaDataDictionary(); + std::string filename = this->GetLocalFileName(); - char keybuffer[256]; - - int numberOfLayers = GetIntByKey(imgMetaDictionary,"layers"); - std::string _xmlStr; - mitk::Label::Pointer label; - - for( int layerIdx=0; layerIdx < numberOfLayers; layerIdx++) + itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO(filename.c_str(), itk::ImageIOFactory::ReadMode); + if (imageIO.IsNull()) { - sprintf( keybuffer, "layer_%03d", layerIdx ); - int numberOfLabels = GetIntByKey(imgMetaDictionary,keybuffer); - - mitk::LabelSet::Pointer labelSet = mitk::LabelSet::New(); - - for(int labelIdx=0; labelIdx < numberOfLabels; labelIdx++) - { - TiXmlDocument doc; - sprintf( keybuffer, "label_%03d_%05d", layerIdx, labelIdx ); - _xmlStr = GetStringByKey(imgMetaDictionary,keybuffer); - doc.Parse(_xmlStr.c_str()); - - TiXmlElement * labelElem = doc.FirstChildElement("Label"); - if (labelElem == 0) - mitkThrow() << "Error parsing NRRD header for mitk::LabelSetImage IO"; - - label = LoadLabelFromTiXmlDocument(labelElem); - - if(label->GetValue() == 0) // set exterior label is needed to hold exterior information - output->SetExteriorLabel(label); - labelSet->AddLabel(label); - } - output->AddLayer(labelSet); + mitkThrow() << "Could not create itk::ImageIOBase object for filename " << filename; } - // set vector image - output->SetVectorImage(vectorImage); + // Got to allocate space for the image. Determine the characteristics of + // the image. + imageIO->SetFileName(filename.c_str()); + imageIO->ReadImageInformation(); + + //LabelSetImage::VectorImageType::Pointer vectorImage; + + //typedef itk::ImageFileReader FileReaderType; + //FileReaderType::Pointer reader = FileReaderType::New(); + //reader->SetFileName(this->GetLocalFileName()); + //itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); + //reader->SetImageIO(io); + //try + //{ + // reader->Update(); + //} + //catch(itk::ExceptionObject& e) + //{ + // mitkThrow() << e.GetDescription(); + //} + //catch(...) + //{ + // mitkThrow() << "Unknown exception caught!"; + //} + + //vectorImage = reader->GetOutput(); + + //if (vectorImage.IsNull()) + // mitkThrow() << "Could not retrieve the vector image."; + + //LabelSetImage::Pointer output = LabelSetImage::New(); + + //ImageType::Pointer auxImg = ImageType::New(); + //auxImg->SetSpacing( vectorImage->GetSpacing() ); + //auxImg->SetOrigin( vectorImage->GetOrigin() ); + //auxImg->SetDirection( vectorImage->GetDirection() ); + //auxImg->SetRegions( vectorImage->GetLargestPossibleRegion() ); + //auxImg->Allocate(); + + //// initialize output image based on vector image meta information + //output->InitializeByItk( auxImg.GetPointer() ); + + //itk::MetaDataDictionary imgMetaDictionary = vectorImage->GetMetaDataDictionary(); + + //char keybuffer[256]; + + //int numberOfLayers = GetIntByKey(imgMetaDictionary,"layers"); + //std::string _xmlStr; + //mitk::Label::Pointer label; + + //for( int layerIdx=0; layerIdx < numberOfLayers; layerIdx++) + //{ + // sprintf( keybuffer, "layer_%03d", layerIdx ); + // int numberOfLabels = GetIntByKey(imgMetaDictionary,keybuffer); + + // mitk::LabelSet::Pointer labelSet = mitk::LabelSet::New(); + + // for(int labelIdx=0; labelIdx < numberOfLabels; labelIdx++) + // { + // TiXmlDocument doc; + // sprintf( keybuffer, "label_%03d_%05d", layerIdx, labelIdx ); + // _xmlStr = GetStringByKey(imgMetaDictionary,keybuffer); + // doc.Parse(_xmlStr.c_str()); + + // TiXmlElement * labelElem = doc.FirstChildElement("Label"); + // if (labelElem == 0) + // mitkThrow() << "Error parsing NRRD header for mitk::LabelSetImage IO"; + + // label = LoadLabelFromTiXmlDocument(labelElem); + + // if(label->GetValue() == 0) // set exterior label is needed to hold exterior information + // output->SetExteriorLabel(label); + // labelSet->AddLabel(label); + // } + // output->AddLayer(labelSet); + //} + + //// set vector image + //output->SetVectorImage(vectorImage); try { setlocale(LC_ALL, currLocale.c_str()); } catch(...) { mitkThrow() << "Could not reset locale!"; } std::vector result; - result.push_back(output.GetPointer()); + //result.push_back(output.GetPointer()); return result; } int LabelSetImageIO::GetIntByKey(const itk::MetaDataDictionary & dic,const std::string & str) { std::vector imgMetaKeys = dic.GetKeys(); std::vector::const_iterator itKey = imgMetaKeys.begin(); std::string metaString(""); for (; itKey != imgMetaKeys.end(); itKey ++) { itk::ExposeMetaData (dic, *itKey, metaString); if (itKey->find(str.c_str()) != std::string::npos) { return atoi(metaString.c_str()); } } return 0; } std::string LabelSetImageIO::GetStringByKey(const itk::MetaDataDictionary & dic,const std::string & str) { std::vector imgMetaKeys = dic.GetKeys(); std::vector::const_iterator itKey = imgMetaKeys.begin(); std::string metaString(""); for (; itKey != imgMetaKeys.end(); itKey ++) { itk::ExposeMetaData (dic, *itKey, metaString); if (itKey->find(str.c_str()) != std::string::npos) { return metaString; } } return metaString; } Label::Pointer LabelSetImageIO::LoadLabelFromTiXmlDocument(TiXmlElement * labelElem) { // reread TiXmlElement * propElem = labelElem->FirstChildElement("property"); std::string name; mitk::BaseProperty::Pointer prop; mitk::Label::Pointer label = mitk::Label::New(); while(propElem) { LabelSetImageIO::PropertyFromXmlElem( name, prop, propElem ); label->SetProperty( name, prop ); propElem = propElem->NextSiblingElement( "property" ); } return label.GetPointer(); } bool LabelSetImageIO::PropertyFromXmlElem(std::string& key, mitk::BaseProperty::Pointer& prop, TiXmlElement* elem) { std::string type; elem->QueryStringAttribute("type", &type); elem->QueryStringAttribute("key", &key); // construct name of serializer class std::string serializername(type); serializername += "Serializer"; std::list allSerializers = itk::ObjectFactoryBase::CreateAllInstance(serializername.c_str()); if (allSerializers.size() < 1) MITK_ERROR << "No serializer found for " << type << ". Skipping object"; if (allSerializers.size() > 1) MITK_WARN << "Multiple deserializers found for " << type << "Using arbitrarily the first one."; for ( std::list::iterator iter = allSerializers.begin(); iter != allSerializers.end(); ++iter ) { if (BasePropertySerializer* serializer = dynamic_cast( iter->GetPointer() ) ) { try { prop = serializer->Deserialize(elem->FirstChildElement()); } catch (std::exception& e) { MITK_ERROR << "Deserializer " << serializer->GetNameOfClass() << " failed: " << e.what(); return false; } break; } } if(prop.IsNull()) return false; return true; } void LabelSetImageIO::LoadLabelSetImagePreset(const std::string & presetFilename, mitk::LabelSetImage::Pointer& inputImage ) { std::unique_ptr presetXmlDoc(new TiXmlDocument()); bool ok = presetXmlDoc->LoadFile(presetFilename); if ( !ok ) return; TiXmlElement * presetElem = presetXmlDoc->FirstChildElement("LabelSetImagePreset"); if(!presetElem) { MITK_INFO << "No valid preset XML"; return; } int numberOfLayers; presetElem->QueryIntAttribute("layers", &numberOfLayers); for(int i = 0 ; i < numberOfLayers; i++) { TiXmlElement * layerElem = presetElem->FirstChildElement("Layer"); int numberOfLabels; layerElem->QueryIntAttribute("labels", &numberOfLabels); if(inputImage->GetLabelSet(i) == NULL) inputImage->AddLayer(); TiXmlElement * labelElement = layerElem->FirstChildElement("Label"); if(labelElement == NULL) break; for(int j = 0 ; j < numberOfLabels; j++) { mitk::Label::Pointer label = mitk::LabelSetImageIO::LoadLabelFromTiXmlDocument(labelElement); inputImage->GetLabelSet()->AddLabel(label); labelElement = labelElement->NextSiblingElement("Label"); if(labelElement == NULL) break; } } } LabelSetImageIO* LabelSetImageIO::IOClone() const { return new LabelSetImageIO(*this); } TiXmlElement * LabelSetImageIO::GetLabelAsTiXmlElement(Label * label) { TiXmlElement* labelElem = new TiXmlElement("Label"); // add XML contents const PropertyList::PropertyMap* propmap = label->GetMap(); for ( PropertyList::PropertyMap::const_iterator iter = propmap->begin(); iter != propmap->end(); ++iter ) { std::string key = iter->first; const BaseProperty* property = iter->second; TiXmlElement* element = PropertyToXmlElem( key, property ); if (element) labelElem->LinkEndChild( element ); } return labelElem; } TiXmlElement* LabelSetImageIO::PropertyToXmlElem( const std::string& key, const BaseProperty* property ) { TiXmlElement* keyelement = new TiXmlElement("property"); keyelement->SetAttribute("key", key); keyelement->SetAttribute("type", property->GetNameOfClass()); // construct name of serializer class std::string serializername(property->GetNameOfClass()); serializername += "Serializer"; std::list allSerializers = itk::ObjectFactoryBase::CreateAllInstance(serializername.c_str()); if (allSerializers.size() < 1) MITK_ERROR << "No serializer found for " << property->GetNameOfClass() << ". Skipping object"; if (allSerializers.size() > 1) MITK_WARN << "Multiple serializers found for " << property->GetNameOfClass() << "Using arbitrarily the first one."; for ( std::list::iterator iter = allSerializers.begin(); iter != allSerializers.end(); ++iter ) { if (BasePropertySerializer* serializer = dynamic_cast( iter->GetPointer() ) ) { serializer->SetProperty(property); try { TiXmlElement* valueelement = serializer->Serialize(); if (valueelement) keyelement->LinkEndChild( valueelement ); } catch (std::exception& e) { MITK_ERROR << "Serializer " << serializer->GetNameOfClass() << " failed: " << e.what(); } break; } } return keyelement; } bool LabelSetImageIO::SaveLabelSetImagePreset(const std::string & presetFilename, LabelSetImage::Pointer & inputImage) { TiXmlDocument * presetXmlDoc = new TiXmlDocument(); TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "" ); presetXmlDoc->LinkEndChild( decl ); TiXmlElement * presetElement = new TiXmlElement("LabelSetImagePreset"); presetElement->SetAttribute("layers", inputImage->GetNumberOfLayers()); presetXmlDoc->LinkEndChild(presetElement); for (unsigned int layerIdx=0; layerIdxGetNumberOfLayers(); layerIdx++) { TiXmlElement * layerElement = new TiXmlElement("Layer"); layerElement->SetAttribute("index", layerIdx); layerElement->SetAttribute("labels", inputImage->GetNumberOfLabels(layerIdx)); presetElement->LinkEndChild(layerElement); for (unsigned int labelIdx=0; labelIdxGetNumberOfLabels(layerIdx); labelIdx++) { TiXmlElement * labelAsXml = LabelSetImageIO::GetLabelAsTiXmlElement(inputImage->GetLabel(labelIdx,layerIdx)); layerElement->LinkEndChild(labelAsXml); } } bool wasSaved = presetXmlDoc->SaveFile(presetFilename); delete presetXmlDoc; return wasSaved; } } //namespace #endif //__mitkLabelSetImageWriter__cpp diff --git a/Modules/Multilabel/mitkLabelSetImageIO.h b/Modules/Multilabel/mitkLabelSetImageIO.h index 749486cf41..4e2352f4ad 100644 --- a/Modules/Multilabel/mitkLabelSetImageIO.h +++ b/Modules/Multilabel/mitkLabelSetImageIO.h @@ -1,81 +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 __mitkLabelSetImageWriter_h #define __mitkLabelSetImageWriter_h #include "MitkMultilabelExports.h" #include #include namespace mitk { /** * Writes a LabelSetImage to a file * @ingroup Process */ // The export macro should be removed. Currently, the unit // tests directly instantiate this class. class MITKMULTILABEL_EXPORT LabelSetImageIO : public mitk::AbstractFileIO { public: typedef LabelSetImage::PixelType PixelType; typedef LabelSetImage::LabelSetImageType ImageType; - typedef LabelSetImage::VectorImageType VectorImageType; typedef mitk::LabelSetImage InputType; LabelSetImageIO(); // -------------- AbstractFileReader ------------- using AbstractFileReader::Read; /** * @brief Reads a number of mitk::LabelSetImages from the file system * @return a vector of mitk::LabelSetImages * @throws throws an mitk::Exception if an error ocurrs during parsing the nrrd header */ virtual std::vector Read() override; virtual ConfidenceLevel GetReaderConfidenceLevel() const override; // -------------- AbstractFileWriter ------------- virtual void Write() override; virtual ConfidenceLevel GetWriterConfidenceLevel() const override; // -------------- LabelSetImageIO specific functions ------------- static bool SaveLabelSetImagePreset(const std::string & presetFilename, mitk::LabelSetImage::Pointer & inputImage); int GetIntByKey(const itk::MetaDataDictionary &dic, const std::string &str); std::string GetStringByKey(const itk::MetaDataDictionary &dic, const std::string &str); static Label::Pointer LoadLabelFromTiXmlDocument(TiXmlElement *labelElem); static void LoadLabelSetImagePreset(const std::string &presetFilename, mitk::LabelSetImage::Pointer &inputImage); private: LabelSetImageIO* IOClone() const override; static TiXmlElement *GetLabelAsTiXmlElement(Label *label); static TiXmlElement * PropertyToXmlElem( const std::string& key, const BaseProperty* property ); static bool PropertyFromXmlElem(std::string& key, mitk::BaseProperty::Pointer& prop, TiXmlElement* elem); }; } // end of namespace mitk #endif // __mitkLabelSetImageWriter_h