void SurfaceVtkLegacyIO::Write() { ValidateOutputLocation(); const Surface* input = dynamic_cast<const Surface*>(this->GetInput()); const unsigned int timesteps = input->GetTimeGeometry()->CountTimeSteps(); for(unsigned int t = 0; t < timesteps; ++t) { std::string fileName; vtkSmartPointer<vtkPolyData> polyData = this->GetPolyData(t, fileName); vtkSmartPointer<vtkPolyDataWriter> writer = vtkSmartPointer<vtkPolyDataWriter>::New(); writer->SetInputData(polyData); // The legacy vtk poly data writer cannot write to streams LocalFile localFile(this); writer->SetFileName(localFile.GetFileName().c_str()); if (writer->Write() == 0 || writer->GetErrorCode() != 0 ) { mitkThrow() << "Error during surface writing: " << vtkErrorCode::GetStringFromErrorCode(writer->GetErrorCode()); } if (this->GetOutputStream() && input->GetTimeGeometry()->CountTimeSteps() > 1) { MITK_WARN << "Writing multiple time-steps to output streams is not supported. " << "Only the first time-step will be written"; break; } } }
void ImageVtkLegacyIO::Write() { ValidateOutputLocation(); const Image* input = dynamic_cast<const Image*>(this->GetInput()); vtkSmartPointer<vtkStructuredPointsWriter> writer = vtkSmartPointer<vtkStructuredPointsWriter>::New(); // The legacy vtk image writer cannot write to streams LocalFile localFile(this); writer->SetFileName(localFile.GetFileName().c_str()); if (us::any_cast<bool> (GetWriterOption("Save as binary file"))) { writer->SetFileTypeToBinary(); } ImageVtkReadAccessor vtkReadAccessor(Image::ConstPointer(input), NULL, input->GetVtkImageData()); writer->SetInputData(const_cast<vtkImageData*>(vtkReadAccessor.GetVtkImageData())); if (writer->Write() == 0 || writer->GetErrorCode() != 0 ) { mitkThrow() << "vtkStructuredPointesWriter error: " << vtkErrorCode::GetStringFromErrorCode(writer->GetErrorCode()); } }
void mitk::LegacyFileWriterService::Write() { if (m_LegacyWriter.IsNull()) mitkThrow() << "LegacyFileWriterService was incorrectly initialized: Has no LegacyFileWriter."; ValidateOutputLocation(); LocalFile localFile(this); m_LegacyWriter->SetFileName(localFile.GetFileName().c_str()); m_LegacyWriter->SetInput(const_cast<BaseData *>(this->GetInput())); m_LegacyWriter->Write(); }
void LabelSetImageIO::Write() { ValidateOutputLocation(); const LabelSetImage* input = static_cast<const LabelSetImage*>(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::Pointer 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(); 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<double, 4u> 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<double, 4u> 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<itk::ImageIOBase::IOComponentType>(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<double, 4u> 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<double> 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<std::string>(nrrdImageIo->GetMetaDataDictionary(), std::string(keybuffer), std::string(valbuffer)); sprintf(keybuffer, "layers"); sprintf(valbuffer, "%1d", input->GetNumberOfLayers()); itk::EncapsulateMetaData<std::string>(nrrdImageIo->GetMetaDataDictionary(), std::string(keybuffer), std::string(valbuffer)); for (unsigned int layerIdx = 0; layerIdx<input->GetNumberOfLayers(); layerIdx++) { sprintf(keybuffer, "layer_%03d", layerIdx); // layer idx sprintf(valbuffer, "%1d", input->GetNumberOfLabels(layerIdx)); // number of labels for the layer itk::EncapsulateMetaData<std::string>(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<TiXmlDocument> 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<std::string>(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; } }
void DICOMSegmentationIO::Write() { ValidateOutputLocation(); mitk::LocaleSwitch localeSwitch("C"); LocalFile localFile(this); const std::string path = localFile.GetFileName(); auto input = dynamic_cast<const LabelSetImage *>(this->GetInput()); if (input == nullptr) mitkThrow() << "Cannot write non-image data"; // Get DICOM information from referenced image vector<DcmDataset *> dcmDatasets; DcmFileFormat *readFileFormat = new DcmFileFormat(); try { // TODO: Generate dcmdataset witk DICOM tags from property list; ATM the source are the filepaths from the // property list mitk::StringLookupTableProperty::Pointer filesProp = dynamic_cast<mitk::StringLookupTableProperty *>(input->GetProperty("files").GetPointer()); if (filesProp.IsNull()) { mitkThrow() << "No property with dicom file path."; return; } StringLookupTable filesLut = filesProp->GetValue(); const StringLookupTable::LookupTableType &lookUpTableMap = filesLut.GetLookupTable(); for (auto it : lookUpTableMap) { const char *fileName = (it.second).c_str(); if (readFileFormat->loadFile(fileName, EXS_Unknown).good()) dcmDatasets.push_back(readFileFormat->getAndRemoveDataset()); } } catch (const std::exception &e) { MITK_ERROR << "An error occurred while getting the dicom informations: " << e.what() << endl; return; } // Iterate over all layers. For each a dcm file will be generated for (unsigned int layer = 0; layer < input->GetNumberOfLayers(); ++layer) { vector<itkInternalImageType::Pointer> segmentations; try { // Cast mitk layer image to itk ImageToItk<itkInputImageType>::Pointer imageToItkFilter = ImageToItk<itkInputImageType>::New(); // BUG: It must be the layer image, but there are some errors with it (dcmqi: generate the dcmSeg "No frame data // available") --> input->GetLayerImage(layer) imageToItkFilter->SetInput(input); imageToItkFilter->Update(); // Cast from original itk type to dcmqi input itk image type typedef itk::CastImageFilter<itkInputImageType, itkInternalImageType> castItkImageFilterType; castItkImageFilterType::Pointer castFilter = castItkImageFilterType::New(); castFilter->SetInput(imageToItkFilter->GetOutput()); castFilter->Update(); itkInternalImageType::Pointer itkLabelImage = castFilter->GetOutput(); itkLabelImage->DisconnectPipeline(); // Iterate over all labels. For each a segmentation image will be created const LabelSet *labelSet = input->GetLabelSet(layer); for (auto itLabel = labelSet->IteratorConstBegin(); itLabel != labelSet->IteratorConstEnd(); ++itLabel) { // Thresold over the image with the given label value itk::ThresholdImageFilter<itkInternalImageType>::Pointer thresholdFilter = itk::ThresholdImageFilter<itkInternalImageType>::New(); thresholdFilter->SetInput(itkLabelImage); thresholdFilter->ThresholdOutside(itLabel->first, itLabel->first); thresholdFilter->SetOutsideValue(0); thresholdFilter->Update(); itkInternalImageType::Pointer segmentImage = thresholdFilter->GetOutput(); segmentImage->DisconnectPipeline(); segmentations.push_back(segmentImage); } } catch (const itk::ExceptionObject &e) { MITK_ERROR << e.GetDescription() << endl; return; } // Create segmentation meta information const std::string &tmpMetaInfoFile = this->CreateMetaDataJsonFile(layer); MITK_INFO << "Writing image: " << path << std::endl; try { // Convert itk segmentation images to dicom image dcmqi::ImageSEGConverter *converter = new dcmqi::ImageSEGConverter(); DcmDataset *result = converter->itkimage2dcmSegmentation(dcmDatasets, segmentations, tmpMetaInfoFile); // Write dicom file DcmFileFormat dcmFileFormat(result); std::string filePath = path.substr(0, path.find_last_of(".")); // If there is more than one layer, we have to write more than 1 dicom file if (input->GetNumberOfLayers() != 1) filePath = filePath + std::to_string(layer) + ".dcm"; else filePath = filePath + ".dcm"; dcmFileFormat.saveFile(filePath.c_str(), EXS_LittleEndianExplicit); // Clean up if (converter != nullptr) delete converter; if (result != nullptr) delete result; } catch (const std::exception &e) { MITK_ERROR << "An error occurred during writing the DICOM Seg: " << e.what() << endl; return; } } // Write a dcm file for the next layer // End of image writing; clean up if (readFileFormat) delete readFileFormat; for (auto obj : dcmDatasets) delete obj; dcmDatasets.clear(); }