diff --git a/Modules/Multilabel/mitkLabelSetImageConverter.cpp b/Modules/Multilabel/mitkLabelSetImageConverter.cpp index e8951b8f8f..48910a74fd 100644 --- a/Modules/Multilabel/mitkLabelSetImageConverter.cpp +++ b/Modules/Multilabel/mitkLabelSetImageConverter.cpp @@ -1,133 +1,134 @@ /*=================================================================== 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 TPixel, unsigned int VImageDimension > void VectorOfMitkImagesToMitkVectorImage(const itk::Image* source, mitk::Image::Pointer &output, mitk::LabelSetImage::ConstPointer input) { 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 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()); + output->SetGeometry(input->GetGeometry()->Clone()); } 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/mitkLabelSetImageIO.cpp b/Modules/Multilabel/mitkLabelSetImageIO.cpp index 8fc9341831..5d7fb60476 100644 --- a/Modules/Multilabel/mitkLabelSetImageIO.cpp +++ b/Modules/Multilabel/mitkLabelSetImageIO.cpp @@ -1,541 +1,691 @@ /*=================================================================== 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; } -template -void TemplatedWrite(const itk::Image< TPixel, VDimensions> * source, const LabelSetImage* input, std::string filename) -{ - mitkThrow() << "Tried to write non-vector labelsetimage"; -} - -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(source->GetMetaDataDictionary(), std::string(keybuffer), std::string(valbuffer)); - - sprintf( keybuffer, "layers"); - sprintf( valbuffer, "%1d", input->GetNumberOfLayers()); - 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(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(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(source); - - 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); + // image write + if ( inputVector.IsNull() ) + { + mitkThrow() << "Cannot write non-image data"; + } + + itk::NrrdImageIO::Pointer nrrdImageIo = itk::NrrdImageIO::New(); + + // Clone the image geometry, because we might have to change it + // for writing purposes + BaseGeometry::Pointer geometry = inputVector->GetGeometry()->Clone(); + + // Check if geometry information will be lost + if (inputVector->GetDimension() == 2 && + !geometry->Is2DConvertable()) + { + MITK_WARN << "Saving a 2D image with 3D geometry information. Geometry information will be lost! You might consider using Convert2Dto3DImageFilter before saving."; + + // set matrix to identity + mitk::AffineTransform3D::Pointer affTrans = mitk::AffineTransform3D::New(); + affTrans->SetIdentity(); + mitk::Vector3D spacing = geometry->GetSpacing(); + mitk::Point3D origin = geometry->GetOrigin(); + geometry->SetIndexToWorldTransform(affTrans); + geometry->SetSpacing(spacing); + geometry->SetOrigin(origin); + } + LocalFile localFile(this); + const std::string path = localFile.GetFileName(); - AccessByItk_2(inputVector, TemplatedWrite, input, localFile.GetFileName()); + MITK_INFO << "Writing image: " << path << std::endl; + + try + { + // Implementation of writer using itkImageIO directly. This skips the use + // of templated itkImageFileWriter, which saves the multiplexing on MITK side. + + const unsigned int dimension = inputVector->GetDimension(); + const unsigned int* const dimensions = inputVector->GetDimensions(); + const mitk::PixelType pixelType = inputVector->GetPixelType(); + const mitk::Vector3D mitkSpacing = geometry->GetSpacing(); + const mitk::Point3D mitkOrigin = geometry->GetOrigin(); + + // Due to templating in itk, we are forced to save a 4D spacing and 4D Origin, + // though they are not supported in MITK + itk::Vector spacing4D; + spacing4D[0] = mitkSpacing[0]; + spacing4D[1] = mitkSpacing[1]; + spacing4D[2] = mitkSpacing[2]; + spacing4D[3] = 1; // There is no support for a 4D spacing. However, we should have a valid value here + + itk::Vector origin4D; + origin4D[0] = mitkOrigin[0]; + origin4D[1] = mitkOrigin[1]; + origin4D[2] = mitkOrigin[2]; + origin4D[3] = 0; // There is no support for a 4D origin. However, we should have a valid value here + + // Set the necessary information for imageIO + nrrdImageIo->SetNumberOfDimensions(dimension); + nrrdImageIo->SetPixelType(pixelType.GetPixelType()); + nrrdImageIo->SetComponentType(pixelType.GetComponentType() < PixelComponentUserType ? + static_cast(pixelType.GetComponentType()) : + itk::ImageIOBase::UNKNOWNCOMPONENTTYPE); + nrrdImageIo->SetNumberOfComponents(pixelType.GetNumberOfComponents()); + + itk::ImageIORegion ioRegion(dimension); + + for (unsigned int i = 0; i < dimension; i++) + { + nrrdImageIo->SetDimensions(i, dimensions[i]); + nrrdImageIo->SetSpacing(i, spacing4D[i]); + nrrdImageIo->SetOrigin(i, origin4D[i]); + + mitk::Vector3D mitkDirection; + mitkDirection.SetVnlVector(geometry->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(i)); + itk::Vector direction4D; + direction4D[0] = mitkDirection[0]; + direction4D[1] = mitkDirection[1]; + direction4D[2] = mitkDirection[2]; + + // MITK only supports a 3x3 direction matrix. Due to templating in itk, however, we must + // save a 4x4 matrix for 4D images. in this case, add an homogneous component to the matrix. + if (i == 3) + { + direction4D[3] = 1; // homogenous component + } + else + { + direction4D[3] = 0; + } + vnl_vector axisDirection(dimension); + for (unsigned int j = 0; j < dimension; j++) + { + axisDirection[j] = direction4D[j] / spacing4D[i]; + } + nrrdImageIo->SetDirection(i, axisDirection); + + ioRegion.SetSize(i, inputVector->GetLargestPossibleRegion().GetSize(i)); + ioRegion.SetIndex(i, inputVector->GetLargestPossibleRegion().GetIndex(i)); + } + + //use compression if available + nrrdImageIo->UseCompressionOn(); + + nrrdImageIo->SetIORegion(ioRegion); + nrrdImageIo->SetFileName(path); + + // label set specific meta data + char keybuffer[512]; + char valbuffer[512]; + + sprintf(keybuffer, "modality"); + sprintf(valbuffer, "org.mitk.image.multilabel"); + itk::EncapsulateMetaData(nrrdImageIo->GetMetaDataDictionary(), std::string(keybuffer), std::string(valbuffer)); + + sprintf(keybuffer, "layers"); + sprintf(valbuffer, "%1d", input->GetNumberOfLayers()); + itk::EncapsulateMetaData(nrrdImageIo->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(nrrdImageIo->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(nrrdImageIo->GetMetaDataDictionary(), std::string(keybuffer), printer.Str()); + ++iter; + ++count; + } + } + // end label set specific meta data + + ImageReadAccessor imageAccess(inputVector); + nrrdImageIo->Write(imageAccess.GetData()); + } + catch (const std::exception& e) + { + mitkThrow() << e.what(); + } + // end image write 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."; } } - std::string filename = this->GetLocalFileName(); + // begin regular image loading, adapted from mitkItkImageIO + itk::NrrdImageIO::Pointer nrrdImageIO = itk::NrrdImageIO::New(); + Image::Pointer image = Image::New(); + + const unsigned int MINDIM = 2; + const unsigned int MAXDIM = 4; + + const std::string path = this->GetLocalFileName(); - itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO(filename.c_str(), itk::ImageIOFactory::ReadMode); - if (imageIO.IsNull()) + MITK_INFO << "loading " << path << " via itk::ImageIOFactory... " << std::endl; + + // Check to see if we can read the file given the name or prefix + if (path.empty()) { - mitkThrow() << "Could not create itk::ImageIOBase object for filename " << filename; + mitkThrow() << "Empty filename in mitk::ItkImageIO "; } // Got to allocate space for the image. Determine the characteristics of // the image. - imageIO->SetFileName(filename.c_str()); - imageIO->ReadImageInformation(); + nrrdImageIO->SetFileName(path); + nrrdImageIO->ReadImageInformation(); - //LabelSetImage::VectorImageType::Pointer vectorImage; + unsigned int ndim = nrrdImageIO->GetNumberOfDimensions(); + if (ndim < MINDIM || ndim > MAXDIM) + { + MITK_WARN << "Sorry, only dimensions 2, 3 and 4 are supported. The given file has " << ndim << " dimensions! Reading as 4D."; + ndim = MAXDIM; + } - //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!"; - //} + itk::ImageIORegion ioRegion(ndim); + itk::ImageIORegion::SizeType ioSize = ioRegion.GetSize(); + itk::ImageIORegion::IndexType ioStart = ioRegion.GetIndex(); - //vectorImage = reader->GetOutput(); + unsigned int dimensions[MAXDIM]; + dimensions[0] = 0; + dimensions[1] = 0; + dimensions[2] = 0; + dimensions[3] = 0; - //if (vectorImage.IsNull()) - // mitkThrow() << "Could not retrieve the vector image."; + ScalarType spacing[MAXDIM]; + spacing[0] = 1.0f; + spacing[1] = 1.0f; + spacing[2] = 1.0f; + spacing[3] = 1.0f; - //LabelSetImage::Pointer output = LabelSetImage::New(); + Point3D origin; + origin.Fill(0); - //ImageType::Pointer auxImg = ImageType::New(); - //auxImg->SetSpacing( vectorImage->GetSpacing() ); - //auxImg->SetOrigin( vectorImage->GetOrigin() ); - //auxImg->SetDirection( vectorImage->GetDirection() ); - //auxImg->SetRegions( vectorImage->GetLargestPossibleRegion() ); - //auxImg->Allocate(); + unsigned int i; + for (i = 0; i < ndim; ++i) + { + ioStart[i] = 0; + ioSize[i] = nrrdImageIO->GetDimensions(i); + if (iGetDimensions(i); + spacing[i] = nrrdImageIO->GetSpacing(i); + if (spacing[i] <= 0) + spacing[i] = 1.0f; + } + if (i<3) + { + origin[i] = nrrdImageIO->GetOrigin(i); + } + } - //// initialize output image based on vector image meta information - //output->InitializeByItk( auxImg.GetPointer() ); + ioRegion.SetSize(ioSize); + ioRegion.SetIndex(ioStart); + + MITK_INFO << "ioRegion: " << ioRegion << std::endl; + nrrdImageIO->SetIORegion(ioRegion); + void* buffer = new unsigned char[nrrdImageIO->GetImageSizeInBytes()]; + nrrdImageIO->Read(buffer); + + image->Initialize(MakePixelType(nrrdImageIO), ndim, dimensions); + image->SetImportChannel(buffer, 0, Image::ManageMemory); + + // access direction of itk::Image and include spacing + mitk::Matrix3D matrix; + matrix.SetIdentity(); + unsigned int j, itkDimMax3 = (ndim >= 3 ? 3 : ndim); + for (i = 0; i < itkDimMax3; ++i) + for (j = 0; j < itkDimMax3; ++j) + matrix[i][j] = nrrdImageIO->GetDirection(j)[i]; + + // re-initialize PlaneGeometry with origin and direction + PlaneGeometry* planeGeometry = image->GetSlicedGeometry(0)->GetPlaneGeometry(0); + planeGeometry->SetOrigin(origin); + planeGeometry->GetIndexToWorldTransform()->SetMatrix(matrix); + + // re-initialize SlicedGeometry3D + SlicedGeometry3D* slicedGeometry = image->GetSlicedGeometry(0); + slicedGeometry->InitializeEvenlySpaced(planeGeometry, image->GetDimension(2)); + slicedGeometry->SetSpacing(spacing); + + MITK_INFO << slicedGeometry->GetCornerPoint(false, false, false); + MITK_INFO << slicedGeometry->GetCornerPoint(true, true, true); + + // re-initialize TimeGeometry + ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New(); + timeGeometry->Initialize(slicedGeometry, image->GetDimension(3)); + image->SetTimeGeometry(timeGeometry); + + buffer = NULL; + MITK_INFO << "number of image components: " << image->GetPixelType().GetNumberOfComponents() << std::endl; + + const itk::MetaDataDictionary& dictionary = nrrdImageIO->GetMetaDataDictionary(); + for (itk::MetaDataDictionary::ConstIterator iter = dictionary.Begin(), iterEnd = dictionary.End(); + iter != iterEnd; ++iter) + { + std::string key = std::string("meta.") + iter->first; + if (iter->second->GetMetaDataObjectTypeInfo() == typeid(std::string)) + { + std::string value = dynamic_cast*>(iter->second.GetPointer())->GetMetaDataObjectValue(); + image->SetProperty(key.c_str(), mitk::StringProperty::New(value)); + } + } - //itk::MetaDataDictionary imgMetaDictionary = vectorImage->GetMetaDataDictionary(); + // end regular image loading + // get labels and add them as properties to the image //char keybuffer[256]; - //int numberOfLayers = GetIntByKey(imgMetaDictionary,"layers"); + //int numberOfLayers = GetIntByKey(dictionary, "layers"); //std::string _xmlStr; //mitk::Label::Pointer label; - //for( int layerIdx=0; layerIdx < numberOfLayers; layerIdx++) + //for (int layerIdx = 0; layerIdx < numberOfLayers; layerIdx++) //{ - // sprintf( keybuffer, "layer_%03d", layerIdx ); - // int numberOfLabels = GetIntByKey(imgMetaDictionary,keybuffer); + // sprintf(keybuffer, "layer_%03d", layerIdx); + // int numberOfLabels = GetIntByKey(imgMetaDictionary, keybuffer); // mitk::LabelSet::Pointer labelSet = mitk::LabelSet::New(); - // for(int labelIdx=0; labelIdx < numberOfLabels; labelIdx++) + // for (int labelIdx = 0; labelIdx < numberOfLabels; labelIdx++) // { // TiXmlDocument doc; - // sprintf( keybuffer, "label_%03d_%05d", layerIdx, labelIdx ); - // _xmlStr = GetStringByKey(imgMetaDictionary,keybuffer); + // 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 + // 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); + LabelSetImage::Pointer output = LabelSetImageConverter::ConvertImageToLabelSetImage(image); + + MITK_INFO << "...finished!" << std::endl; 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