std::vector<BaseData::Pointer> DICOMSegmentationIO::Read()
  {
    mitk::LocaleSwitch localeSwitch("C");

    LabelSetImage::Pointer labelSetImage;
    std::vector<BaseData::Pointer> result;

    const std::string path = this->GetLocalFileName();

    MITK_INFO << "loading " << path << std::endl;

    if (path.empty())
      mitkThrow() << "Empty filename in mitk::ItkImageIO ";

    try
    {
      // Get the dcm data set from file path
      DcmFileFormat dcmFileFormat;
      OFCondition status = dcmFileFormat.loadFile(path.c_str());
      if (status.bad())
        mitkThrow() << "Can't read the input file!";

      DcmDataset *dataSet = dcmFileFormat.getDataset();
      if (dataSet == nullptr)
        mitkThrow() << "Can't read data from input file!";

      // Read the DICOM SEG images (segItkImages) and DICOM tags (metaInfo)
      dcmqi::ImageSEGConverter *converter = new dcmqi::ImageSEGConverter();
      pair<map<unsigned, ImageType::Pointer>, string> dcmqiOutput = converter->dcmSegmentation2itkimage(dataSet);

      map<unsigned, ImageType::Pointer> segItkImages = dcmqiOutput.first;

      // For each itk image add a layer to the LabelSetImage output
      for (auto &element : segItkImages)
      {
        // Get the labeled image and cast it to mitkImage
        typedef itk::CastImageFilter<itkInternalImageType, itkInputImageType> castItkImageFilterType;
        castItkImageFilterType::Pointer castFilter = castItkImageFilterType::New();
        castFilter->SetInput(element.second);
        castFilter->Update();

        Image::Pointer layerImage;
        CastToMitkImage(castFilter->GetOutput(), layerImage);

        // Get pixel value of the label
        itkInternalImageType::ValueType segValue = 1;
        typedef itk::ImageRegionIterator<const itkInternalImageType> IteratorType;
        // Iterate over the image to find the pixel value of the label
        IteratorType iter(element.second, element.second->GetLargestPossibleRegion());
        iter.GoToBegin();
        while (!iter.IsAtEnd())
        {
          itkInputImageType::PixelType value = iter.Get();
          if (value != 0)
          {
            segValue = value;
            break;
          }
          ++iter;
        }

        dcmqi::JSONSegmentationMetaInformationHandler metaInfo(dcmqiOutput.second.c_str());
        metaInfo.read();
        MITK_INFO << "Input " << metaInfo.getJSONOutputAsString();
        // TODO: Read all DICOM Tags

        // Get the label information from segment attributes
        vector<map<unsigned, dcmqi::SegmentAttributes *>>::const_iterator segmentIter =
          metaInfo.segmentsAttributesMappingList.begin();
        map<unsigned, dcmqi::SegmentAttributes *> segmentMap = (*segmentIter);
        map<unsigned, dcmqi::SegmentAttributes *>::const_iterator segmentMapIter = (*segmentIter).begin();
        dcmqi::SegmentAttributes *segmentAttr = (*segmentMapIter).second;

        OFString labelName;

        if (segmentAttr->getSegmentedPropertyTypeCodeSequence() != nullptr)
          segmentAttr->getSegmentedPropertyTypeCodeSequence()->getCodeMeaning(labelName);
        else
        {
          labelName = std::to_string(segmentAttr->getLabelID()).c_str();
          if (labelName.empty())
            labelName = "Unnamed";
        }

        float tmp[3] = {0.0, 0.0, 0.0};
        if (segmentAttr->getRecommendedDisplayRGBValue() != nullptr)
        {
          tmp[0] = segmentAttr->getRecommendedDisplayRGBValue()[0] / 255.0;
          tmp[1] = segmentAttr->getRecommendedDisplayRGBValue()[1] / 255.0;
          tmp[2] = segmentAttr->getRecommendedDisplayRGBValue()[2] / 255.0;
        }

        // If labelSetImage do not exists (first image)
        if (labelSetImage.IsNull())
        {
          // Initialize the labelSetImage with the read image
          labelSetImage = LabelSetImage::New();
          labelSetImage->InitializeByLabeledImage(layerImage);
          // Already a label was generated, so set the information to this
          Label *activeLabel = labelSetImage->GetActiveLabel(labelSetImage->GetActiveLayer());
          activeLabel->SetName(labelName.c_str());
          activeLabel->SetColor(Color(tmp));
          activeLabel->SetValue(segValue);
        }
        else
        {
          // Add a new layer to the labelSetImage. Background label is set automatically
          labelSetImage->AddLayer(layerImage);

          // Add new label
          Label *newLabel = new Label;
          newLabel->SetName(labelName.c_str());
          newLabel->SetColor(Color(tmp));
          newLabel->SetValue(segValue);

          labelSetImage->GetLabelSet(labelSetImage->GetActiveLayer())->AddLabel(newLabel);
        }

        ++segmentIter;
      }
      // Clean up
      if (converter != nullptr)
        delete converter;
    }
    catch (const std::exception &e)
    {
      MITK_ERROR << "An error occurred while reading the DICOM Seg file: " << e.what();
      return result;
    }

    // Set active layer to th first layer of the labelset image
    if (labelSetImage->GetNumberOfLayers() > 1 && labelSetImage->GetActiveLayer() != 0)
      labelSetImage->SetActiveLayer(0);

    result.push_back(labelSetImage.GetPointer());

    return result;
  }
예제 #2
0
bool Dicom::DicomReader::OpenDicoms(const std::list<std::string>& dcms)
{
	if (m_pImageData)
	{
		//已经打开了数据
		return false;
	}

	std::map<int,DcmFileFormat*> mapDcms;

	int iMaxLayer = -1;
	int iMinLayer = INT_MAX;

	{
		//获取图像数据
		std::list<std::string>::const_iterator iter = dcms.begin();
		while (iter != dcms.end())
		{
			DcmFileFormat* pDcmFile = new DcmFileFormat();
			OFCondition cond = pDcmFile->loadFile(iter->c_str());
			if (cond.bad())
			{
				delete pDcmFile;
				++iter;
				continue;
			}

			DcmDataset* pDataset = pDcmFile->getDataset();

			Uint16 iC = 0, iR = 0, iB = 0;
			pDataset->findAndGetUint16(DCM_Columns, iC);
			pDataset->findAndGetUint16(DCM_Rows, iR);
			pDataset->findAndGetUint16(DCM_BitsAllocated, iB);
			if (mapDcms.size()<1)
			{
				m_iColumns = iC;
				m_iRows = iR;
				m_iBits = iB;
			}

			if (iC != m_iColumns || iR != m_iRows || iB != m_iBits)
			{
				delete pDcmFile;
				++iter;
				continue;
			}

			Sint32 iL = -1;

			pDataset->findAndGetSint32(DCM_InstanceNumber, iL);
			if (iL>-1 && mapDcms.find(iL) == mapDcms.end())
			{
				mapDcms[iL] = pDcmFile;
				if (iL > iMaxLayer)
					iMaxLayer = iL;
				if (iL < iMinLayer)
					iMinLayer = iL;
			}
			else
			{
				delete pDcmFile;
			}

			++iter;
		}

		if (m_iBits != 16)
			return false;
	}


	//总层数
	m_iLayers = iMaxLayer-iMinLayer+1;
	m_pImageData = new Image::ImageData<short>(m_iRows, m_iColumns, m_iLayers);
	Image::ImageData<short>* pImageShort = reinterpret_cast<Image::ImageData<short>*>(m_pImageData);
	char* pDataPtr = m_pImageData->GetDataPtr();

	{
		//设置图像数据
		std::map<int, DcmFileFormat*>::iterator iter = mapDcms.begin();
		while (iter != mapDcms.end())
		{
			DcmFileFormat* pDcmFile = iter->second;
			DcmDataset* pDataSet = pDcmFile->getDataset();
			{
				const Uint16* pSrcData = NULL;
				unsigned long iCount = 0;
				pDataSet->findAndGetUint16Array(DCM_PixelData, pSrcData, &iCount);
				if (iCount == pImageShort->GetX()*pImageShort->GetY())
				{
					memcpy(pDataPtr+(iCount*2*(iter->first-iMinLayer)), pSrcData, iCount * 2);
				}
				else
				{
					assert("Read dicom error!");
				}
			}
			delete pDcmFile;

			++iter;
		}

		mapDcms.clear();
	}

	m_pImageData->UpdateData();

	return true;
}
예제 #3
0
int gendicom(const char* file_name, const std::vector<float> &data,
             unsigned int rows, unsigned int cols)
{

char uid[100];
DcmFileFormat fileformat;
DcmDataset *dataset = fileformat.getDataset();
OFCondition result = EC_Normal;

if (result.good()) result = dataset->putAndInsertString(DCM_SOPClassUID, UID_SecondaryCaptureImageStorage);

//if (result.good()) result = dataset->putAndInsertString(DCM_MediaStorageSOPClassUID, UID_SecondaryCaptureImageStorage); //same as SOP
if (result.good()) result = dataset->putAndInsertString(DCM_SOPInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT));
//if (result.good()) result = dataset->putAndInsertString(DCM_MediaStorageSOPInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT));
if (result.good()) result = dataset->putAndInsertString(DCM_SeriesInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT));
if (result.good()) result = dataset->putAndInsertString(DCM_StudyInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT));
//if (result.good()) result = dataset->putAndInsertString(DCM_TransferSyntaxUID, UID_LittleEndianExplicitTransferSyntax);

//if (result.good()) result = dataset->putAndInsertUint16(DCM_FileMetaInformationVersion, 1);

if (result.good()) result = dataset->putAndInsertString(DCM_ImageType, "DERIVED");
if (result.good()) result = dataset->putAndInsertString(DCM_Modality, "MR");
if (result.good()) result = dataset->putAndInsertString(DCM_ConversionType, "WSD");
if (result.good()) result = dataset->putAndInsertString(DCM_DerivationDescription, "IRGN Processed MR Reconstruction");
if (result.good()) result = dataset->putAndInsertString(DCM_SecondaryCaptureDeviceManufacturer, "IMT TUGRAZ");
if (result.good()) result = dataset->putAndInsertString(DCM_SecondaryCaptureDeviceManufacturerModelName, "IMT Cuda Workstation");
if (result.good()) result = dataset->putAndInsertString(DCM_PatientName, "Doe^John");

// set instance creation date and time
OFString s;
if (result.good()) result = DcmDate::getCurrentDate(s);
if (result.good()) result = dataset->putAndInsertOFStringArray(DCM_InstanceCreationDate, s);
if (result.good()) result = DcmTime::getCurrentTime(s);
if (result.good()) result = dataset->putAndInsertOFStringArray(DCM_InstanceCreationTime, s);


//--- Write image-data ---
std::vector<Uint16> uint16_data;

float val=0;
float min_val;
float max_val = *std::max_element(data.begin(),data.end());
for(unsigned int i=0; i<data.size(); ++i)
{
  val = (data[i]/max_val)*65535;
  uint16_data.push_back(Uint16(val));
}

max_val = *std::max_element(uint16_data.begin(),uint16_data.end());
min_val = *std::min_element(uint16_data.begin(),uint16_data.end());
std::cout<<"\n max-val: "<<max_val;
std::cout<<"\n min-val: "<<min_val;

unsigned bits=16;
Uint16 bitsAllocated=((bits-1)/8+1)*8;
Uint16 bitsStored=bits;
Uint16 highBit=bits-1;
if (result.good()) result = dataset->putAndInsertUint16(DCM_BitsAllocated, bitsAllocated);
if (result.good()) result = dataset->putAndInsertUint16(DCM_BitsStored, bitsStored);
if (result.good()) result = dataset->putAndInsertUint16(DCM_HighBit, highBit);

if (result.good()) result = dataset->putAndInsertUint16(DCM_Rows, rows);
if (result.good()) result = dataset->putAndInsertUint16(DCM_Columns, cols);

if (result.good()) result = dataset->putAndInsertUint16(DCM_PixelRepresentation, 0);  // 1 signed, 0 unsigned
if (result.good()) result = dataset->putAndInsertOFStringArray(DCM_PhotometricInterpretation, "MONOCHROME2");
if (result.good()) result = dataset->putAndInsertUint16(DCM_SamplesPerPixel, 1);

if (result.good()) result = dataset->putAndInsertUint16(DCM_SmallestImagePixelValue, min_val);
if (result.good()) result = dataset->putAndInsertUint16(DCM_LargestImagePixelValue, max_val);

Uint8* pixelData = (Uint8*)&uint16_data[0];
Uint32 pixelLength;

pixelLength = uint16_data.size()*2;   //number of elements in vector * 2bytes (for Uint16)

dataset->putAndInsertUint8Array(DCM_PixelData, pixelData, pixelLength);
OFCondition status = fileformat.saveFile(file_name, EXS_LittleEndianExplicit);

if (result.bad())
  std::cerr << "Error: cannot write DICOM file (" << result.text() << ")" << std::endl;

if (status.bad())
  std::cerr << "Error: cannot write DICOM file (" << status.text() << ")" << std::endl;

return 0;

}
예제 #4
0
    std::vector<itk::SmartPointer<BaseData> > RTDoseReader::Read()
    {
        std::vector<itk::SmartPointer<mitk::BaseData> > result;

        DICOMTag referencedRTPlan(0x300c, 0x0002);
        mitk::IDICOMTagsOfInterest* toiSrv = GetDicomTagsOfInterestService();
        if (toiSrv)
        {
            toiSrv->AddTagOfInterest(referencedRTPlan);
        }

        std::string location = GetInputLocation();
        mitk::DICOMFileReaderSelector::Pointer selector = mitk::DICOMFileReaderSelector::New();
        selector->LoadBuiltIn3DConfigs();
        selector->SetInputFiles({ location });

        mitk::DICOMFileReader::Pointer reader = selector->GetFirstReaderWithMinimumNumberOfOutputImages();
        reader->SetAdditionalTagsOfInterest(toiSrv->GetTagsOfInterest());

        reader->SetInputFiles({ location });
        reader->AnalyzeInputFiles();
        reader->LoadImages();

        if (reader->GetNumberOfOutputs() == 0){
            MITK_ERROR << "Could not determine a DICOM reader for this file" << std::endl;
            return result;
        }

        const mitk::DICOMImageBlockDescriptor& desc = reader->GetOutput(0);

        mitk::Image::Pointer originalImage = desc.GetMitkImage();

        if (originalImage.IsNull())
        {
            MITK_ERROR << "Error reading the RTDOSE file in mitk::DicomFileReader" << std::endl;
            return result;
        }

        DcmFileFormat fileformat;
        OFCondition outp = fileformat.loadFile(location.c_str(), EXS_Unknown);
        if (outp.bad())
        {
            MITK_ERROR << "Error reading the RTDOSE file in DCMTK" << std::endl;
            return result;
        }
        DcmDataset *dataset = fileformat.getDataset();

        DRTDoseIOD doseObject;
        OFCondition DCMTKresult = doseObject.read(*dataset);

        if (DCMTKresult.bad())
        {
            MITK_ERROR << "Error reading the RTDOSE file in DCMTK" << std::endl;
            return result;
        }

        OFString gridScaling;
        Float32 gridscale;

        doseObject.getDoseGridScaling(gridScaling);
        gridscale = OFStandard::atof(gridScaling.c_str());

        AccessByItk_1(originalImage, MultiplyGridScaling, gridscale);

        auto statistics = this->scaledDoseImage->GetStatistics();
        double maxDose = statistics->GetScalarValueMax();

        this->scaledDoseImage->SetPropertyList(originalImage->GetPropertyList());
        this->scaledDoseImage->SetProperty(mitk::RTConstants::PRESCRIBED_DOSE_PROPERTY_NAME.c_str(), mitk::GenericProperty<double>::New(0.8*maxDose));

        result.push_back(this->scaledDoseImage.GetPointer());
        return result;
    }
예제 #5
0
    mitk::DataNode::Pointer RTDoseReader::LoadRTDose(const char* filename)
    {
        DICOMTag referencedRTPlan(0x300c, 0x0002);
        mitk::IDICOMTagsOfInterest* toiSrv = GetDicomTagsOfInterestService();
        if (toiSrv)
        {
            toiSrv->AddTagOfInterest(referencedRTPlan);
        }

        mitk::StringList oneFile = { filename };
        mitk::DICOMFileReaderSelector::Pointer selector = mitk::DICOMFileReaderSelector::New();
        selector->LoadBuiltIn3DConfigs();
        selector->SetInputFiles(oneFile);

        mitk::DICOMFileReader::Pointer reader = selector->GetFirstReaderWithMinimumNumberOfOutputImages();
        reader->SetAdditionalTagsOfInterest(toiSrv->GetTagsOfInterest());

        reader->SetInputFiles(oneFile);
        reader->AnalyzeInputFiles();
        reader->LoadImages();

        if (reader->GetNumberOfOutputs() == 0){
            MITK_ERROR << "Error reading the dicom file" << std::endl;
            return nullptr;
        }

        const mitk::DICOMImageBlockDescriptor& desc = reader->GetOutput(0);

        mitk::Image::Pointer originalImage = desc.GetMitkImage();

        if (originalImage.IsNull())
        {
            MITK_ERROR << "Error reading the dcm file" << std::endl;
            return nullptr;
        }

        DcmFileFormat fileformat;
        OFCondition outp = fileformat.loadFile(filename, EXS_Unknown);
        if (outp.bad())
        {
            MITK_ERROR << "Can't read the RTDOSE file" << std::endl;
        }
        DcmDataset *dataset = fileformat.getDataset();

        DRTDoseIOD doseObject;
        OFCondition result = doseObject.read(*dataset);

        if(result.bad())
        {
            MITK_ERROR << "Error reading the Dataset" << std::endl;
            return nullptr;
        }

        OFString gridScaling;
        Float32 gridscale;

        doseObject.getDoseGridScaling(gridScaling);
        gridscale = OFStandard::atof(gridScaling.c_str());

        AccessByItk_1(originalImage, MultiplyGridScaling, gridscale);

        auto statistics = this->scaledDoseImage->GetStatistics();
        double maxDose = statistics->GetScalarValueMax();

        this->scaledDoseImage->SetPropertyList(originalImage->GetPropertyList());
        this->scaledDoseImage->SetProperty(mitk::RTConstants::PRESCRIBED_DOSE_PROPERTY_NAME.c_str(), mitk::GenericProperty<double>::New(0.8*maxDose));

        mitk::DataNode::Pointer originalNode = mitk::DataNode::New();

        originalNode->SetName("RT Dose");
        originalNode->SetData(this->scaledDoseImage);
        originalNode->SetFloatProperty(mitk::RTConstants::REFERENCE_DOSE_PROPERTY_NAME.c_str(), 40.0);

        return originalNode;
  }
예제 #6
0
void mitk::FiberBundleDicomWriter::Write()
{
  try
  {
    mitk::FiberBundle::ConstPointer fib = dynamic_cast<const mitk::FiberBundle*>(this->GetInput());
    vtkPolyData* poly = fib->GetFiberPolyData();
    mitk::PropertyList* p_list = fib->GetPropertyList();

    std::string patient_id = "";
    if (!p_list->GetStringProperty("DICOM.patient_id", patient_id))
      patient_id = "-";
    std::string patient_name = "";
    if (!p_list->GetStringProperty("DICOM.patient_name", patient_name))
      patient_name = "-";
    std::string study_instance_uid = "";
    if (!p_list->GetStringProperty("DICOM.study_instance_uid", study_instance_uid))
      study_instance_uid = "-";
    std::string series_instance_uid = "";
    if (!p_list->GetStringProperty("DICOM.series_instance_uid", series_instance_uid))
      series_instance_uid = "-";
    std::string sop_instance_uid = "";
    if (!p_list->GetStringProperty("DICOM.sop_instance_uid", sop_instance_uid))
      sop_instance_uid = "-";
    std::string frame_of_reference_uid = "";
    if (!p_list->GetStringProperty("DICOM.frame_of_reference_uid", frame_of_reference_uid))
      frame_of_reference_uid = "-";
    std::string algo_code_value = "";
    if (!p_list->GetStringProperty("DICOM.algo_code.value", algo_code_value))
      algo_code_value = "-";
    std::string algo_code_meaning = "";
    if (!p_list->GetStringProperty("DICOM.algo_code.meaning", algo_code_meaning))
      algo_code_meaning = "-";
    std::string model_code_value = "";
    if (!p_list->GetStringProperty("DICOM.model_code.value", model_code_value))
      model_code_value = "-";
    std::string model_code_meaning = "";
    if (!p_list->GetStringProperty("DICOM.model_code.meaning", model_code_meaning))
      model_code_meaning = "-";
    std::string anatomy_value = "";
    if (!p_list->GetStringProperty("DICOM.anatomy.value", anatomy_value))
      anatomy_value = "-";
    std::string anatomy_meaning = "";
    if (!p_list->GetStringProperty("DICOM.anatomy.meaning", anatomy_meaning))
      anatomy_meaning = "-";

    const std::string& locale = "C";
    const std::string& currLocale = setlocale( LC_ALL, nullptr );
    setlocale(LC_ALL, locale.c_str());

    // Instance Number, Label, Description, Creator's Name
    ContentIdentificationMacro id("1", "TRACTOGRAM", "Tractogram processed with MITK Diffusion", "MIC@DKFZ");

    // Manufacturer, model name, serial number, software version(s)
    IODEnhGeneralEquipmentModule::EquipmentInfo equipment("MIC@DKFZ", "dcmtract library", "0815", OFFIS_DCMTK_VERSION_STRING);
    IODReferences refs;

    // We need at least one image reference this Tractography Results object is based on.
    // We provide: Patient ID, Study Instance UID, Series Instance UID, SOP Instance UID, SOP Class UID
    IODImageReference* ref = new IODImageReference(patient_id.c_str(), study_instance_uid.c_str(), series_instance_uid.c_str(), sop_instance_uid.c_str(), UID_MRImageStorage);
    refs.add(ref);

    std::time_t t = std::time(nullptr);
    char date_buffer[20];
    std::strftime(date_buffer, sizeof(date_buffer), "%Y%m%d", std::gmtime(&t));
    char time_buffer[20];
    std::strftime(time_buffer, sizeof(time_buffer), "%H%M%S", std::gmtime(&t));
    OFString contentDate(date_buffer);
    OFString contentTime(time_buffer);

    OFString val = "-";
    TrcTractographyResults *trc = nullptr;
    TrcTractographyResults::create(id, contentDate, contentTime, equipment, refs, trc);
    trc->getStudy().setStudyInstanceUID(study_instance_uid.c_str());
    trc->getSeries().setSeriesInstanceUID(series_instance_uid.c_str());
    trc->getSOPCommon().setSOPInstanceUID(sop_instance_uid.c_str());
    trc->getSeries().getSeriesInstanceUID(val);

    // Create track set
    CodeWithModifiers anatomy("");
    anatomy.set(anatomy_value.c_str(), "SRT", anatomy_meaning.c_str());

    // Every CodeSequenceMacro has: Code Value, Coding Scheme Designator, Code Meaning
    CodeSequenceMacro diffusionModel(model_code_value.c_str(), "DCM", model_code_meaning.c_str());
    CodeSequenceMacro algorithmId(algo_code_value.c_str(), "DCM", algo_code_meaning.c_str());
    TrcTrackSet *set = nullptr;
    trc->addTrackSet("TRACTOGRAM", "Tractogram processed with MITK Diffusion", anatomy, diffusionModel, algorithmId, set);

    // Create trackset
    Uint16 cieLabColor[3]; // color the whole track with this color; we use some blue
    cieLabColor[0] = 30000; // L
    cieLabColor[1] = 0 ; // a
    cieLabColor[2] = 0 ; // b
    std::vector< Float32* > tracts;

    for (unsigned int i=0; i<fib->GetNumFibers(); i++)
    {
        vtkCell* cell = poly->GetCell(i);
        int numPoints = cell->GetNumberOfPoints();
        vtkPoints* points = cell->GetPoints();

        Float32* pointData = new Float32[numPoints*3];
        for(int i=0; i<numPoints ;i++)
        {
            double* p = points->GetPoint(i);

            pointData[i*3] = p[0];
            pointData[i*3+1] = p[1];
            pointData[i*3+2] = p[2];
        }
        tracts.push_back(pointData);

        TrcTrack* track = nullptr;
        set->addTrack(pointData, numPoints, cieLabColor, 1 /* numColors */, track);
    }

    // Frame of Reference is required; could be the same as from related MR series
    trc->getFrameOfReference().setFrameOfReferenceUID(frame_of_reference_uid.c_str());

    // Set some optional data
    trc->getPatient().setPatientID(patient_id.c_str());
    trc->getPatient().setPatientName(patient_name.c_str());
    trc->getSeries().setSeriesDescription("Tractogram processed with MITK Diffusion");

    // Save file
    OFCondition result = trc->saveFile(this->GetOutputLocation().c_str());
    delete trc;
    if (result.bad())
      mitkThrow() << "Unable to save tractography as DICOM file: " << result.text();

    for (Float32* tract : tracts)
      delete [] tract;

    setlocale(LC_ALL, currLocale.c_str());
    MITK_INFO << "DICOM Fiber bundle written to " << this->GetOutputLocation();
  }
  catch(...)
  {
    throw;
  }
}
예제 #7
0
void
Association
::associate(Network & network)
{
    if(!network.is_initialized())
    {
        throw Exception("Network is not initialized");
    }

    if(this->is_associated())
    {
        throw Exception("Already associated");
    }

    OFCondition condition;

    T_ASC_Parameters * params;
    condition = ASC_createAssociationParameters(&params, ASC_MAXIMUMPDUSIZE);
    if(condition.bad())
    {
        throw Exception(condition);
    }

    condition = ASC_setAPTitles(params,
        this->_own_ae_title.c_str(), this->_peer_ae_title.c_str(), NULL);
    if(condition.bad())
    {
        ASC_destroyAssociationParameters(&params);
        throw Exception(condition);
    }

    std::string localhost(128, '\0');
    gethostname(&localhost[0], localhost.size()-1);

    std::ostringstream peer;
    peer << this->_peer_host_name << ":" << this->_peer_port;

    condition = ASC_setPresentationAddresses(params,
        "localhost", peer.str().c_str());
    if(condition.bad())
    {
        ASC_destroyAssociationParameters(&params);
        throw Exception(condition);
    }

    unsigned int context_id = 1;
    for(auto const & context: this->_presentation_contexts)
    {
        char const ** transfer_syntaxes = new char const *[context.transfer_syntaxes.size()];
        for(std::size_t i = 0; i < context.transfer_syntaxes.size(); ++i)
        {
            transfer_syntaxes[i] = context.transfer_syntaxes[i].c_str();
        }

        condition = ASC_addPresentationContext(params,
            context_id, context.abstract_syntax.c_str(),
            transfer_syntaxes, context.transfer_syntaxes.size(), context.role);
        if(condition.bad())
        {
            ASC_destroyAssociationParameters(&params);
            throw Exception(condition);
        }

        context_id += 2;
    }

    if(this->_user_identity_type == UserIdentityType::None)
    {
        // Nothing to do.
    }
    else if(this->_user_identity_type == UserIdentityType::Username)
    {
        condition = ASC_setIdentRQUserOnly(params,
            this->_user_identity_primary_field.c_str());
    }
    else if(this->_user_identity_type == UserIdentityType::UsernameAndPassword)
    {
        condition = ASC_setIdentRQUserOnly(params,
            this->_user_identity_primary_field.c_str(),
            this->_user_identity_secondary_field.c_str());
    }
    else if(this->_user_identity_type == UserIdentityType::Kerberos)
    {
        condition = ASC_setIdentRQKerberos(params,
            this->_user_identity_primary_field.c_str(),
            this->_user_identity_primary_field.size());
    }
    else if(this->_user_identity_type == UserIdentityType::SAML)
    {
        condition = ASC_setIdentRQSaml(params,
            this->_user_identity_primary_field.c_str(),
            this->_user_identity_primary_field.size());
    }
    else
    {
        ASC_destroyAssociationParameters(&params);
        throw Exception("Unknown identity type");
    }

    if(condition.bad())
    {
        ASC_destroyAssociationParameters(&params);
        throw Exception(condition);
    }

    condition = ASC_requestAssociation(
        network.get_network(), params, &this->_association);
    if(condition.bad())
    {
        OFString empty;

        if(condition == DUL_ASSOCIATIONREJECTED)
        {
            T_ASC_RejectParameters rej;
            ASC_getRejectParameters(params, &rej);

            ASC_destroyAssociationParameters(&params);
            throw Exception(ASC_printRejectParameters(empty, &rej).c_str());
        }
        else
        {
            ASC_destroyAssociationParameters(&params);
            throw Exception(DimseCondition::dump(empty, condition).c_str());
        }
    }
}
예제 #8
0
void
Association
::receive(Network &network,
          std::function<bool (const Association &)> authenticator,
          std::vector<std::string> const & aetitles,
          bool accept_all)
{
    if(!network.is_initialized())
    {
        throw Exception("Network is not initialized");
    }

    if(this->is_associated())
    {
        throw Exception("Already associated");
    }

    OFCondition condition;

    condition = ASC_receiveAssociation(
        network.get_network(), &this->_association, ASC_DEFAULTMAXPDU);
    if(condition.bad())
    {
        throw Exception(condition);
    }

    T_ASC_Parameters * const params = this->_association->params;
    DUL_ASSOCIATESERVICEPARAMETERS const dul = params->DULparams;
    // No peer port should be defined when receiving
    this->_peer_host_name = dul.callingPresentationAddress;
    this->_peer_port = 0;
    this->_peer_ae_title = dul.callingAPTitle;
    this->_own_ae_title = dul.calledAPTitle;

    // check Peer ae title
    // '*' => everybody allowed
    if (std::find(aetitles.begin(), aetitles.end(), "*") == aetitles.end() &&
        std::find(aetitles.begin(), aetitles.end(),
                  this->_peer_ae_title.c_str()) == aetitles.end())
    {
        this->reject(RejectedPermanent, ULServiceUser,
                     CallingAETitleNotRecognized);
        this->drop();
        throw Exception("Bad AE Title");
    }

    // Check Application Context Name
    char buf[BUFSIZ];
    condition = ASC_getApplicationContextName(params, buf);
    if (condition.bad() || std::string(buf) != DICOM_STDAPPLICATIONCONTEXT)
    {
        // reject: application context name not supported
        this->reject(RejectedPermanent, ULServiceUser,
                     ApplicationContextNameNotSupported);
        this->drop();
        throw Exception("Bad Application context name");
    }

    if(accept_all)
    {
        unsigned int const pc_count = ASC_countPresentationContexts(params);
        for(unsigned int pc_index=0; pc_index<pc_count; ++pc_index)
        {
            T_ASC_PresentationContext pc;
            memset(&pc, 0, sizeof(pc));
            ASC_getPresentationContext(params, pc_index, &pc);

            for(unsigned int ts_index=0; ts_index<pc.transferSyntaxCount; ++ts_index)
            {
                std::string const abstract_syntax = pc.abstractSyntax;
                char const * abstract_syntax_data = abstract_syntax.c_str();

                condition = ASC_acceptContextsWithTransferSyntax(
                    this->_association->params,
                    pc.proposedTransferSyntaxes[ts_index],
                    1, &abstract_syntax_data);
                if(condition.bad())
                {
                    this->reject(RejectedPermanent, ULServiceUser, NoReasonGiven);
                    this->drop();
                    throw Exception(condition);
                }
            }
        }
    }
    else
    {
        for(auto const & context: this->_presentation_contexts)
        {
            for(std::size_t i = 0; i < context.transfer_syntaxes.size(); ++i)
            {
                char const * abstract_syntax = context.abstract_syntax.c_str();
                char const * transfer_syntax = context.transfer_syntaxes[i].c_str();
                condition = ASC_acceptContextsWithTransferSyntax(
                    this->_association->params, transfer_syntax,
                    1, &abstract_syntax);
                if(condition.bad())
                {
                    this->reject(RejectedPermanent, ULServiceUser, NoReasonGiven);
                    this->drop();
                    throw Exception(condition);
                }
            }
        }
    }

    // Get user identity information
    UserIdentityNegotiationSubItemRQ* identity =
            this->_association->params->DULparams.reqUserIdentNeg;

    this->_user_identity_primary_field = "";
    this->_user_identity_secondary_field = "";
    if (identity == NULL ||
        identity->getIdentityType() == ASC_USER_IDENTITY_NONE)
    {
        this->_user_identity_type = UserIdentityType::None;
    }
    else if (identity->getIdentityType() != ASC_USER_IDENTITY_UNKNOWN)
    {
        this->_user_identity_type =
                    (UserIdentityType)identity->getIdentityType();

        // Get primary field
        char * primary_field;
        Uint16 primary_field_length;
        identity->getPrimField(primary_field, primary_field_length);
        // user is not NULL-terminated
        this->_user_identity_primary_field = std::string(primary_field,
                                                         primary_field_length);

        if (identity->getIdentityType() == ASC_USER_IDENTITY_USER_PASSWORD)
        {
            // Get secondary field
            char * secondary_field;
            Uint16 secondary_field_length;
            identity->getSecField(secondary_field, secondary_field_length);
            // password is not NULL-terminated
            this->_user_identity_primary_field =
                    std::string(secondary_field, secondary_field_length);
        }
    }
    else
    {
        throw Exception("Unknown user identity type");
    }

    // Authentication
    if(authenticator(*this))
    {
        condition = ASC_acknowledgeAssociation(this->_association);
        if(condition.bad())
        {
            throw Exception(condition);
        }
    }
    else
    {
        this->reject(RejectedPermanent, ULServiceUser, NoReasonGiven);
        this->drop();
        throw Exception("Bad Authentication");
    }
}
예제 #9
0
/** Reads pixel data and corresponding attributes like rows etc. from image
*  file and inserts them into dataset.
*  @param dset - [out] The dataset to export the pixel data attributes to
*  @param outputTS - [out] The proposed transfex syntax of the dataset
*  @return EC_Normal, if successful, error otherwise
*/
OFCondition I2DImgSource::readAndInsertSpecificTags( DcmDataset* dset, E_TransferSyntax& outputTS)
{
        Uint16 samplesPerPixel, rows, cols, bitsAlloc, bitsStored, highBit, pixelRepr, planConf;
        Uint16 pixAspectH = 1;
        Uint16 pixAspectV = 1;
        OFString photoMetrInt;
        outputTS = EXS_Unknown;
        char* pixData = NULL;
        Uint32 length;

        OFCondition cond = readPixelData(rows, cols,
                                         samplesPerPixel, photoMetrInt, bitsAlloc, bitsStored, highBit, pixelRepr,
                                         planConf, pixAspectH, pixAspectV, pixData, length, outputTS);
        if (cond.bad())
                return cond;

        if (m_debug)
                printMessage(m_logStream, "Document2Dcm: Store imported pixel data to DICOM file");

        cond = dset->putAndInsertUint16(DCM_SamplesPerPixel, samplesPerPixel);
        if (cond.bad())
                return cond;

        cond = dset->putAndInsertOFStringArray(DCM_PhotometricInterpretation, photoMetrInt);
        if (cond.bad())
                return cond;

        cond = dset->putAndInsertOFStringArray(DCM_ConversionType, "WSD");
        if (cond.bad())
                return cond;
        /*
        cond = dset->putAndInsertOFStringArray(DCM_ImagerPixelSpacing, "1.000000\\1.000000");
        if (cond.bad())
        return cond;

        cond = dset->putAndInsertOFStringArray(DCM_PixelSpacing, "1.000000\\1.000000");
        if (cond.bad())
        return cond;
        */
        cond = dset->putAndInsertOFStringArray(DCM_ImagePositionPatient, "0.000000\\0.000000\\0.000000");
        if (cond.bad())
                return cond;

        cond = dset->putAndInsertOFStringArray(DCM_ImageOrientationPatient, "1.000000\\0.000000\\0.000000\\0.000000\\1.000000\\0.000000");
        if (cond.bad())
                return cond;


        // Should only be written if Samples per Pixel > 1
        if (samplesPerPixel > 1) {
                cond = dset->putAndInsertUint16(DCM_PlanarConfiguration, planConf);
                if (cond.bad())
                        return cond;
        }

        cond = dset->putAndInsertUint16(DCM_Rows, rows);
        if (cond.bad())
                return cond;

        cond = dset->putAndInsertUint16(DCM_Columns, cols);
        if (cond.bad())
                return cond;

        cond = dset->putAndInsertUint16(DCM_BitsAllocated, bitsAlloc);
        if (cond.bad())
                return cond;

        cond = dset->putAndInsertUint16(DCM_BitsStored, bitsStored);
        if (cond.bad())
                return cond;

        cond = dset->putAndInsertUint16(DCM_HighBit, highBit);
        if (cond.bad())
                return cond;

        cond = dset->putAndInsertUint16(DCM_PixelRepresentation, pixelRepr);
        if (cond.bad())
                return cond;


        if (Recompress()) {
                // create initial pixel sequence
                DcmElement* element = newDicomElement(DcmTag(DCM_PixelData, EVR_OW));
                element->putUint8Array((const Uint8*)pixData, length);
                cond = dset->insert(element);
                if (cond.bad()) {
                        delete element;
                        return cond;
                }

                //lo pasamos a jpeg lossless
                // create representation parameters for lossy and lossless
                OFCmdUnsignedInt opt_selection_value = 6;
                //este numero implica cierta perdida... si fuera 0 seria lossless real
                OFCmdUnsignedInt opt_point_transform = 3;

                E_TransferSyntax opt_oxfer;
                GNC::GCS::Permisos::EstadoPermiso codificacion = GNC::GCS::IControladorPermisos::Instance()->Get("core.importacion", "codec");
                switch (codificacion.ObtenerValor<int>()) {
                case 0: {
                        //baseline
                        opt_oxfer = EXS_JPEGProcess1;
                        DJ_RPLossy rp_lossy((int)90);
                        const DcmRepresentationParameter *rp = &rp_lossy;
                        dset->chooseRepresentation(opt_oxfer, rp);
                }
                break;
                case 1: {
                        //progresivo
                        opt_oxfer = EXS_JPEGProcess10_12;
                        DJ_RPLossy rp_lossy((int)90);
                        const DcmRepresentationParameter *rp = &rp_lossy;
                        dset->chooseRepresentation(opt_oxfer, rp);
                }
                break;
                case 2:
                default: {
                        //lossless
                        GNC::GCS::Permisos::EstadoPermiso estado = GNC::GCS::IControladorPermisos::Instance()->Get("core.importacion", "quality");
                        if (estado) {
                                opt_point_transform = std::min<int>(estado.ObtenerValor<int>(), 14);
                                opt_point_transform = std::max<int>(estado.ObtenerValor<int>(), 0);
                        }
                        opt_oxfer = EXS_JPEGProcess14SV1;
                        DJ_RPLossless rp_lossless((int)opt_selection_value, (int)opt_point_transform);
                        const DcmRepresentationParameter *rp = &rp_lossless;
                        dset->chooseRepresentation(opt_oxfer, rp);
                }
                break;
                }

                if(!dset->canWriteXfer(opt_oxfer))
                        return OFCondition(EC_UnsupportedEncoding);

                // force meta-header to refresh SOP Class/Instance UIDs.
                delete dset->remove(DCM_MediaStorageSOPClassUID);
                delete dset->remove(DCM_MediaStorageSOPInstanceUID);
                outputTS = opt_oxfer;

                return cond;
        } else {
                if (IsCompressed()) {
                        DcmPixelSequence *pixelSequence = NULL;

                        if (m_debug)
                                printMessage(m_logStream, "Document2Dcm: Store imported pixel data to DICOM file");
                        // create initial pixel sequence
                        pixelSequence = new DcmPixelSequence(DcmTag(DCM_PixelData, EVR_OB));
                        if (pixelSequence == NULL)
                                return EC_MemoryExhausted;
                        // insert empty offset table into sequence
                        DcmPixelItem *offsetTable = new DcmPixelItem(DcmTag(DCM_Item, EVR_OB));
                        if (offsetTable == NULL) {
                                delete pixelSequence;
                                pixelSequence = NULL;
                                return EC_MemoryExhausted;
                        }
                        cond = pixelSequence->insert(offsetTable);
                        if (cond.bad()) {
                                delete offsetTable;
                                offsetTable = NULL;
                                delete pixelSequence;
                                pixelSequence = NULL;
                                return cond;
                        }

                        // insert frame into pixel sequence
                        DcmOffsetList dummyList;
                        cond = pixelSequence->storeCompressedFrame(dummyList, (Uint8*) pixData, length, 0);
                        // storeCompressedFrame(..) does a deep copy, so the pixdata memory can be freed now
                        delete[] pixData;
                        if (cond.bad()) {
                                delete pixelSequence;
                                return cond;
                        }
                        cond = dset->insert(pixelSequence);
                        if (cond.bad())
                                delete pixelSequence;

                        if (m_debug)
                                printMessage(m_logStream, "Document2Dcm: Inserting Image Pixel module information");
                        return dset->putAndInsertUint16(DCM_PixelRepresentation, pixelRepr);
                } else {
                        //little endian to little endian...
                        // create initial pixel sequence
                        DcmElement* element = newDicomElement(DcmTag(DCM_PixelData, EVR_OW));
                        element->putUint8Array((const Uint8*)pixData, length);
                        cond = dset->insert(element);
                        if (cond.bad()) {
                                delete element;
                                return cond;
                        }
                        outputTS = EXS_LittleEndianExplicit;

                        return cond;
                }
        }
}
예제 #10
0
OFCondition GIL::DICOM::DCMTK::Network::ASC_ConnectAssociation(Association* assoc, const std::string& peerTitle, const std::string& peer, int port, const std::string& ouraet, int pdu)
{
    OFCondition cond;

    GTLSTransportLayer *tLayer = NULL;

    if (assoc->IsSecure()) {
        tLayer = new GTLSTransportLayer(DICOM_APPLICATION_REQUESTOR, NULL);
        if (tLayer == NULL) {
            return makeOFCondition(OFM_dcmtls, DULC_TLSERROR, OF_error, "TLS Error: Unable to create TLS transport layer");
        }
        tLayer->setCertificateFromString(assoc->GetCliCert());
        tLayer->setPrivateKeyFromString(assoc->GetCliKey());

        if (! tLayer->checkPrivateKeyMatchesCertificate()) {
            delete tLayer;
            return makeOFCondition(OFM_dcmtls, DULC_TLSERROR, OF_error, "TLS Error: Private key and certificate do not match");
        }

        tLayer->addSystemTrustedCertificates();

        if (assoc->GetValidate()) {
            tLayer->setCertificateVerification(DCV_requireCertificate);
        } else {
            tLayer->setCertificateVerification(DCV_ignoreCertificate);
        }
        /*
         if (opt_dhparam && ! (tLayer->setTempDHParameters(opt_dhparam)))
         {
         LOG_WARN(assoc->ambitolog, "unable to load temporary DH parameters. Ignoring");
         }
         */

        cond = ASC_setTransportLayer(m_pDCMTKNetwork, tLayer, 0);
        if (cond.bad()) {
            return cond;
        }
    }

    T_ASC_Parameters *params;

    std::string peerHost;
    char localHost[129];

    cond = ASC_createAssociationParameters(&params, pdu);
    if (!cond.good()) {
        return cond;
    }

    //user identity
    if (assoc->UseUserPass()) {
        cond = ASC_setIdentRQUserPassword(params, assoc->GetUser().c_str(), assoc->GetPass().c_str());
        if (!cond.good()) {
            return cond;
        }
    }

    ASC_setAPTitles(params, ouraet.c_str(), peerTitle.c_str(), NULL);

    cond = ASC_setTransportLayerType(params, assoc->IsSecure());
    if (cond.bad()) {
        return cond;
    }

    gethostname(localHost, sizeof (localHost) - 1);
    {
        std::ostringstream os;
        os << peer.c_str() << ":" << port;
        peerHost = os.str();
    }
    ASC_setPresentationAddresses(params, localHost, peerHost.c_str());

    assoc->OnAddPresentationContext(params);

    {
        OFString str;
        ASC_dumpParameters(str, params, ASC_ASSOC_RQ);
        LOG_DEBUG(assoc->ambitolog, "Requesting association" << std::endl << str.c_str());

    }

    /* create association */
    cond = ASC_requestAssociation(m_pDCMTKNetwork, params, &(assoc->assoc));
    if (cond != EC_Normal) {
        if (cond == DUL_ASSOCIATIONREJECTED) {
            T_ASC_RejectParameters rej;

            ASC_getRejectParameters(params, &rej);
            OFString str;
            ASC_printRejectParameters(str, &rej);
            return makeOFCondition(OFM_dcmnet, DULC_ASSOCIATIONREJECTED, OF_error, str.c_str());
        } else {
            return cond;
        }
    }

    {
        OFString str;
        ASC_dumpParameters(str, params, ASC_ASSOC_AC);
        LOG_DEBUG(assoc->ambitolog, "Association accepted" << std::endl << str.c_str());
    }

    /* what has been accepted/refused ? */

    if (ASC_countAcceptedPresentationContexts(params) == 0) {
        return cond;
    }

    return EC_Normal;
}
예제 #11
0
OFCondition Association::SendObject(DcmDataset *dataset)
{
        OFCondition cond = EC_Normal;
        DcmDataset *statusDetail = NULL;

        if (Stopped()) {
                return DUL_NETWORKCLOSED;
        }

        T_DIMSE_C_StoreRQ req;
        T_DIMSE_C_StoreRSP rsp;

        // check if we SOPClass and SOPInstance in dataset
        if (!DU_findSOPClassAndInstanceInDataSet(dataset, sopClass, sopInstance)) {
                return makeOFCondition(OFM_dcmnet, DIMSEC_BADDATA, OF_error, "No SOPClass or SOPInstanceUID found on dataset");
        }

        /* which presentation context should be used */
        presId = ASC_findAcceptedPresentationContextID(assoc, sopClass);
        if (presId == 0) {
                const char *modalityName = dcmSOPClassUIDToModality(sopClass);
                if (!modalityName) modalityName = dcmFindNameOfUID(sopClass);
                if (!modalityName) modalityName = "unknown SOP class";
                std::ostringstream os;
                os << "No valid presentation context found. SOPClass = " << sopClass << " Modality = " << modalityName;
                return makeOFCondition(OFM_dcmnet, DIMSEC_BADDATA, OF_error, os.str().c_str());
        }

        bzero((char*) & req, sizeof (req));
        req.MessageID = msgId;
        strncpy(req.AffectedSOPClassUID, sopClass, sizeof (req.AffectedSOPClassUID)-1);
        req.AffectedSOPClassUID[sizeof (req.AffectedSOPClassUID)-1] = 0;
        strncpy(req.AffectedSOPInstanceUID, sopInstance, sizeof (req.AffectedSOPInstanceUID)-1);
        req.AffectedSOPInstanceUID[sizeof(req.AffectedSOPInstanceUID)-1] = 0;

        req.DataSetType = DIMSE_DATASET_PRESENT;
        req.Priority = DIMSE_PRIORITY_LOW;

        // convert to accepted transfer syntax
        T_ASC_PresentationContext pc;
        cond = ASC_findAcceptedPresentationContext(assoc->params, presId, &pc);
        ASC_dumpPresentationContext(&pc, COUT);

        DcmXfer opt_oxferSyn(pc.acceptedTransferSyntax);
        E_TransferSyntax ori_oxferSyn = dataset->getOriginalXfer();

        DcmXfer original_xfer(dataset->getOriginalXfer());

        if (opt_oxferSyn.getXfer() != ori_oxferSyn) {
                LOG_DEBUG(ambitolog, "Converting object into accepted Transfer-Syntax: " << opt_oxferSyn.getXferName());

                OFCondition cond;
                // create RepresentationParameter
                DJ_RPLossless rp_lossless(6, 0);
                DJ_RPLossy rp_lossy(70);

                // NEW

                const DcmRepresentationParameter *rp = NULL;

                if (opt_oxferSyn.getXfer() == EXS_JPEGProcess14SV1 || opt_oxferSyn.getXfer() == EXS_JPEGProcess14) {
                        rp = &rp_lossless;
                } else if (opt_oxferSyn.getXfer() == EXS_JPEGProcess1 || opt_oxferSyn.getXfer() == EXS_JPEGProcess2_4) {
                        rp = &rp_lossy;
                }

                // recompress ?
                if (rp != NULL) {
                        if (original_xfer.isEncapsulated()) {
                                LOG_DEBUG(ambitolog, "The DICOM file is already compressed. It will previously converted to uncompressed Transfer Syntax");
                                if (EC_Normal != dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL)) {
                                        return makeOFCondition(OFM_dcmnet, DIMSEC_BADDATA, OF_error, "Unable to convert the original format to uncompressed Transfer Syntax");
                                }
                        }
                }

                cond = dataset->chooseRepresentation(opt_oxferSyn.getXfer(), rp);
                if (cond.bad()) {
                        LOG_ERROR(ambitolog, "Error choosing representation: " << cond.text());
                }

                if (dataset->canWriteXfer(opt_oxferSyn.getXfer())) {
                        LOG_DEBUG(ambitolog, "The output transfer syntax (" <<  opt_oxferSyn.getXferName() << " can be writen");
                } else {
                        std::ostringstream os;
                        os << "Unable to find any possible converson to output Transfer Syntax " <<  opt_oxferSyn.getXferName();
                        return makeOFCondition(OFM_dcmnet, DIMSEC_BADDATA, OF_error, os.str().c_str());
                }
        }

        // store it

        cond = DIMSE_storeUser(
                       assoc,
                       presId,
                       &req,
                       NULL,
                       dataset,
                       NULL,
                       NULL,
                       (m_timeout == 0) ? DIMSE_BLOCKING : DIMSE_NONBLOCKING,
                       m_timeout,
                       &rsp,
                       &statusDetail);

        // increase message id
        msgId++;

        // what happened

        if (rsp.DataSetType == DIMSE_DATASET_PRESENT) {
                LOG_DEBUG(ambitolog, "Response with dataset");
        }

        if (statusDetail != NULL) {
                LOG_TRACE(ambitolog, "Status: " << DumpDataset(statusDetail));
                delete statusDetail;
        }

        if (cond != EC_Normal) {
                return cond;
        }

        if (rsp.DimseStatus == STATUS_Success) {
                return EC_Normal;
        } else {
                LOG_ERROR(ambitolog, "DIMSE Status failed: " << rsp.DimseStatus);
                return DIMSE_BADDATA;
        }
}
void RetrieveDICOMFilesFromPACS::storeSCPCallback(void *callbackData, T_DIMSE_StoreProgress *progress, T_DIMSE_C_StoreRQ *storeRequest, char *imageFileName,
                                                  DcmDataset **imageDataSet, T_DIMSE_C_StoreRSP *storeResponse, DcmDataset **statusDetail)
{
    // Paràmetres d'entrada: callbackData, progress, storeRequest, imageFileName, imageDataSet
    // Paràmetres de sortida: storeResponse, statusDetail
    Q_UNUSED(imageFileName);

    // Si el paquest és de finalització d'una imatge hem de guardar-la
    if (progress->state == DIMSE_StoreEnd)
    {
        // No status detail
        *statusDetail = NULL;

        if ((imageDataSet) && (*imageDataSet))
        {
            DIC_UI sopClass, sopInstance;
            OFBool correctUIDPadding = OFFalse;
            StoreSCPCallbackData *storeSCPCallbackData = (StoreSCPCallbackData*)callbackData;
            RetrieveDICOMFilesFromPACS *retrieveDICOMFilesFromPACS = storeSCPCallbackData->retrieveDICOMFilesFromPACS;
            QString dicomFileAbsolutePath = retrieveDICOMFilesFromPACS->getAbsoluteFilePathCompositeInstance(*imageDataSet, storeSCPCallbackData->fileName);

            // Guardem la imatge
            OFCondition stateSaveImage = retrieveDICOMFilesFromPACS->save(storeSCPCallbackData->dcmFileFormat, dicomFileAbsolutePath);

            if (stateSaveImage.bad())
            {
                storeResponse->DimseStatus = STATUS_STORE_Refused_OutOfResources;
                DEBUG_LOG("No s'ha pogut guardar la imatge descarregada [" + dicomFileAbsolutePath + "], error: " + stateSaveImage.text());
                ERROR_LOG("No s'ha pogut guardar la imatge descarregada [" + dicomFileAbsolutePath + "], error: " + stateSaveImage.text());
                if (!QFile::remove(dicomFileAbsolutePath))
                {
                    DEBUG_LOG("Ha fallat el voler esborrar el fitxer " + dicomFileAbsolutePath + " que havia fallat prèviament al voler guardar-se.");
                    ERROR_LOG("Ha fallat el voler esborrar el fitxer " + dicomFileAbsolutePath + " que havia fallat prèviament al voler guardar-se.");
                }
            }
            else
            {
                // Should really check the image to make sure it is consistent, that its
                // sopClass and sopInstance correspond with those in the request.
                if (storeResponse->DimseStatus == STATUS_Success)
                {
                    // Which SOP class and SOP instance?
                    if (!DU_findSOPClassAndInstanceInDataSet(*imageDataSet, sopClass, sopInstance, correctUIDPadding))
                    {
                        storeResponse->DimseStatus = STATUS_STORE_Error_CannotUnderstand;
                        ERROR_LOG(QString("No s'ha trobat la sop class i la sop instance per la imatge %1").arg(storeSCPCallbackData->fileName));
                    }
                    else if (strcmp(sopClass, storeRequest->AffectedSOPClassUID) != 0)
                    {
                        storeResponse->DimseStatus = STATUS_STORE_Error_DataSetDoesNotMatchSOPClass;
                        ERROR_LOG(QString("No concorda la sop class rebuda amb la sol.licitada per la imatge %1").arg(storeSCPCallbackData->fileName));
                    }
                    else if (strcmp(sopInstance, storeRequest->AffectedSOPInstanceUID) != 0)
                    {
                        storeResponse->DimseStatus = STATUS_STORE_Error_DataSetDoesNotMatchSOPClass;
                        ERROR_LOG(QString("No concorda sop instance rebuda amb la sol.licitada per la imatge %1").arg(storeSCPCallbackData->fileName));
                    }
                }

                // TODO:Té processar el fitxer si ha fallat alguna de les anteriors comprovacions ?
                retrieveDICOMFilesFromPACS->m_numberOfImagesRetrieved++;
                DICOMTagReader *dicomTagReader = new DICOMTagReader(dicomFileAbsolutePath, storeSCPCallbackData->dcmFileFormat->getAndRemoveDataset());
                emit retrieveDICOMFilesFromPACS->DICOMFileRetrieved(dicomTagReader, retrieveDICOMFilesFromPACS->m_numberOfImagesRetrieved);
            }
        }
    }
}
예제 #13
0
bool echoscu(const QString &peerTitle, const QString &ourTitle,
             const QString &hostname, int port,
             QString &msg)
{
    T_ASC_Network *net;
    T_ASC_Parameters *params;
    T_ASC_Association *assoc;
    OFString temp_str;
    bool ret = false;

#ifdef HAVE_WINSOCK_H
    WSAData winSockData;
    /* we need at least version 1.1 */
    WORD winSockVersionNeeded = MAKEWORD( 1, 1 );
    WSAStartup(winSockVersionNeeded, &winSockData);
#endif

    /* initialize network, i.e. create an instance of T_ASC_Network*. */
    OFCondition cond = ASC_initializeNetwork(NET_REQUESTOR, 0, 6, &net);
    if (cond.bad()) {
        DimseCondition::dump(temp_str, cond);
        msg = QString::fromLatin1(temp_str.c_str());
        goto cleanup;
    }

    /* initialize asscociation parameters, i.e. create an instance of T_ASC_Parameters*. */
    cond = ASC_createAssociationParameters(&params, ASC_DEFAULTMAXPDU);
    if (cond.bad()) {
        DimseCondition::dump(temp_str, cond);
        msg = QString::fromLatin1(temp_str.c_str());
        goto cleanup;
    }

    ASC_setAPTitles(params, ourTitle.toLocal8Bit().data(), peerTitle.toLocal8Bit().data(), NULL);

    /* Set the transport layer type (type of network connection) in the params */
    /* strucutre. The default is an insecure connection; where OpenSSL is  */
    /* available the user is able to request an encrypted,secure connection. */
    cond = ASC_setTransportLayerType(params, OFFalse);
    if (cond.bad()) {
        DimseCondition::dump(temp_str, cond);
        msg = QString::fromLatin1(temp_str.c_str());
        goto cleanup;
    }

    /* Figure out the presentation addresses and copy the */
    /* corresponding values into the association parameters.*/
    DIC_NODENAME localHost;
    DIC_NODENAME peerHost;
    gethostname(localHost, sizeof(localHost) - 1);
    sprintf(peerHost, "%s:%d", hostname.toLocal8Bit().data(), port);

    ASC_setPresentationAddresses(params, localHost, peerHost);

    /* Set the presentation contexts which will be negotiated */
    /* when the network connection will be established */
    int presentationContextID = 1; /* odd byte value 1, 3, 5, .. 255 */
    for (unsigned long ii=0; ii<1; ii++)
    {
        cond = ASC_addPresentationContext(params, presentationContextID, UID_VerificationSOPClass,
                 transferSyntaxes, 3);
        presentationContextID += 2;
        if (cond.bad())
        {
            DimseCondition::dump(temp_str, cond);
            msg = QString::fromLatin1(temp_str.c_str());
            goto cleanup;
        }
    }

    /* create association, i.e. try to establish a network connection to another */
    /* DICOM application. This call creates an instance of T_ASC_Association*. */
    cond = ASC_requestAssociation(net, params, &assoc);
    if (cond.bad()) {
        if (cond == DUL_ASSOCIATIONREJECTED)
        {
            T_ASC_RejectParameters rej;

            ASC_getRejectParameters(params, &rej);
            ASC_printRejectParameters(temp_str, &rej);
            msg = QString("Association Rejected: %1").arg(temp_str.c_str());
            goto cleanup;
        } else {
            DimseCondition::dump(temp_str, cond);
            msg = QString("Association Request Failed: %1").arg(temp_str.c_str());
            goto cleanup;
        }
    }

    /* count the presentation contexts which have been accepted by the SCP */
    /* If there are none, finish the execution */
    if (ASC_countAcceptedPresentationContexts(params) == 0) {
        msg = QString("No Acceptable Presentation Contexts");
        goto cleanup;
    }

    /* do the real work, i.e. send a number of C-ECHO-RQ messages to the DICOM application */
    /* this application is connected with and handle corresponding C-ECHO-RSP messages. */
    DIC_US msgId = assoc->nextMsgID++;
    DIC_US status;
    DcmDataset *statusDetail = NULL;

    /* send C-ECHO-RQ and handle response */
    cond = DIMSE_echoUser(assoc, msgId, DIMSE_BLOCKING, 0, &status, &statusDetail);

    /* check for status detail information, there should never be any */
    if (statusDetail != NULL) {
        delete statusDetail;
    }

    /* tear down association, i.e. terminate network connection to SCP */
    if (cond == EC_Normal)
    {
        cond = ASC_releaseAssociation(assoc);
        ret = true;
    }
    else if (cond == DUL_PEERABORTEDASSOCIATION)
    {

    }
    else
    {
        DimseCondition::dump(temp_str, cond);
        msg = QString::fromLatin1(temp_str.c_str());
        cond = ASC_abortAssociation(assoc);
    }

cleanup:
    /* destroy the association, i.e. free memory of T_ASC_Association* structure. This */
    /* call is the counterpart of ASC_requestAssociation(...) which was called above. */
    cond = ASC_destroyAssociation(&assoc);

    /* drop the network, i.e. free memory of T_ASC_Network* structure. This call */
    /* is the counterpart of ASC_initializeNetwork(...) which was called above. */
    cond = ASC_dropNetwork(&net);

#ifdef HAVE_WINSOCK_H
    WSACleanup();
#endif

    return ret;
}