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; }
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; }
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; }
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; }
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; }
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; } }
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(¶ms, 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(¶ms); 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(¶ms); 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(¶ms); 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(¶ms); throw Exception("Unknown identity type"); } if(condition.bad()) { ASC_destroyAssociationParameters(¶ms); 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(¶ms); throw Exception(ASC_printRejectParameters(empty, &rej).c_str()); } else { ASC_destroyAssociationParameters(¶ms); throw Exception(DimseCondition::dump(empty, condition).c_str()); } } }
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"); } }
/** 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; } } }
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(¶ms, 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; }
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); } } } }
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(¶ms, 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; }