Esempio n. 1
0
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;
    }
  }
}
Esempio n. 2
0
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();
}
Esempio n. 4
0
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();
  }