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; } }
OFCondition Association::SendObject(DcmDataset *dataset) { OFCondition cond; DcmDataset *statusDetail = NULL; 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 DIMSE_BADDATA; } /* 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"; return DIMSE_BADDATA; } // init store bzero((char*)&req, sizeof(req)); req.MessageID = msgId; strncpy(req.AffectedSOPClassUID, sopClass, sizeof(req.AffectedSOPClassUID)); strncpy(req.AffectedSOPInstanceUID, sopInstance, sizeof(req.AffectedSOPInstanceUID)); 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); DJEncoderRegistration::registerCodecs( ECC_lossyYCbCr, EUC_never, // UID generation (never create new UID's) OFFalse, // verbose OFTrue); // optimize huffman table DJDecoderRegistration::registerCodecs(); DcmXfer opt_oxferSyn(pc.acceptedTransferSyntax); E_TransferSyntax ori_oxferSyn = dataset->getOriginalXfer(); DcmXfer original_xfer(dataset->getOriginalXfer()); if(opt_oxferSyn.getXfer() != ori_oxferSyn) { std::cout << "Converting object to accepted transfer-syntax " << opt_oxferSyn.getXferName() << std::endl; OFCondition cond; // create RepresentationParameter DJ_RPLossless rp_lossless(6, 0); DJ_RPLossy rp_lossy(m_CompressionQuality); // 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()) { std::cout << "DICOM file is already compressed, convert to uncompressed xfer syntax first\n"; if(EC_Normal != dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL)) { std::cout << "No conversion from compressed original to uncompressed xfer syntax possible!\n"; } } } cond = dataset->chooseRepresentation(opt_oxferSyn.getXfer(), rp); if(cond.bad()) { DimseCondition::dump(cond); } if (dataset->canWriteXfer(opt_oxferSyn.getXfer())) { std::cout << "Output transfer syntax " << opt_oxferSyn.getXferName() << " can be written" << std::endl; } else { std::cout << "No conversion to transfer syntax " << opt_oxferSyn.getXferName() << " possible!" << std::endl; } } // 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) { printf("Response with dataset:\n"); } if (statusDetail != NULL) { printf("Status detail:\n"); statusDetail->print(COUT, false); delete statusDetail; } if (cond != EC_Normal) { return cond; } return (rsp.DimseStatus == STATUS_Success) ? EC_Normal : 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); } } } }