Ejemplo n.º 1
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;
        }
}
Ejemplo n.º 2
0
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);
            }
        }
    }
}