Status ConvertDicomToLittleEndian::convert(QString inputFile, QString outputFile) { DcmFileFormat fileformat; DcmDataset *dataset = fileformat.getDataset(); OFCondition error; Status state; // Transfer Syntax del fitxer d'entrada E_TransferSyntax opt_ixfer = EXS_Unknown; E_FileReadMode opt_readMode = ERM_autoDetect; E_TransferSyntax opt_oxfer = EXS_LittleEndianExplicit; QString descriptionError; E_EncodingType opt_oenctype = EET_ExplicitLength; E_GrpLenEncoding opt_oglenc = EGL_recalcGL; E_PaddingEncoding opt_opadenc = EPD_noChange; OFCmdUnsignedInt opt_filepad = 0; OFCmdUnsignedInt opt_itempad = 0; E_FileWriteMode writeMode = EWM_fileformat; error = fileformat.loadFile(qPrintable(QDir::toNativeSeparators(inputFile)), opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode); if (error.bad()) { ERROR_LOG(QString("No s'ha pogut obrir el fitxer a convertir LittleEndian %1, descripcio error: %2").arg(inputFile, error.text())); return state.setStatus(error); } dataset->loadAllDataIntoMemory(); DcmXfer opt_oxferSyn(opt_oxfer); dataset->chooseRepresentation(opt_oxfer, NULL); if (!dataset->canWriteXfer(opt_oxfer)) { descriptionError = "Error: no conversion to transfer syntax " + QString(opt_oxferSyn.getXferName()) + " possible"; state.setStatus(qPrintable(descriptionError), false, 1300); ERROR_LOG(descriptionError); return state; } error = fileformat.saveFile(qPrintable(QDir::toNativeSeparators(outputFile)), opt_oxfer, opt_oenctype, opt_oglenc, opt_opadenc, OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad), writeMode); if (!error.good()) { ERROR_LOG(QString("S'ha produit un error al intentar gravar la imatge %1 convertida a LittleEndian al path %2, descripcio error: %3") .arg(inputFile, outputFile, error.text())); } return state.setStatus(error); }
//------------------------------------------------------------------------------ bool ctkDICOMRetrievePrivate::retrieve ( QString UID, RetrieveType retriveType ) { if ( !this->RetrieveDatabase ) { logger.error ( "Must have RetrieveDatabase for retrieve transaction" ); return false; } // Register the JPEG libraries in case we need them // (registration only happens once, so it's okay to call repeatedly) // register global JPEG decompression codecs DJDecoderRegistration::registerCodecs(); // register global JPEG compression codecs DJEncoderRegistration::registerCodecs(); // register RLE compression codec DcmRLEEncoderRegistration::registerCodecs(); // register RLE decompression codec DcmRLEDecoderRegistration::registerCodecs(); // Set the DCMTK log level log4cplus::Logger rootLogger = log4cplus::Logger::getRoot(); rootLogger.setLogLevel(log4cplus::DEBUG_LOG_LEVEL); // TODO: use this->SCU instead ? DcmSCU scu; scu.setAETitle ( OFString(this->CallingAETitle.toStdString().c_str()) ); scu.setPort ( this->CallingPort ); scu.setPeerAETitle ( OFString(this->CalledAETitle.toStdString().c_str()) ); scu.setPeerHostName ( OFString(this->Host.toStdString().c_str()) ); scu.setPeerPort ( this->CalledPort ); scu.setMoveDestinationAETitle ( OFString(this->MoveDestinationAETitle.toStdString().c_str()) ); logger.info ( "Setting Transfer Syntaxes" ); OFList<OFString> transferSyntaxes; transferSyntaxes.push_back ( UID_LittleEndianExplicitTransferSyntax ); transferSyntaxes.push_back ( UID_BigEndianExplicitTransferSyntax ); transferSyntaxes.push_back ( UID_LittleEndianImplicitTransferSyntax ); scu.addPresentationContext ( UID_FINDStudyRootQueryRetrieveInformationModel, transferSyntaxes ); scu.addPresentationContext ( UID_MOVEStudyRootQueryRetrieveInformationModel, transferSyntaxes ); if ( !scu.initNetwork().good() ) { logger.error ( "Error initializing the network" ); return false; } logger.debug ( "Negotiating Association" ); if ( !scu.negotiateAssociation().good() ) { logger.error ( "Error negotiating association" ); return false;; } logger.debug ( "Setting Parameters" ); // Clear the query unsigned long elements = this->parameters->card(); // Clean it out for ( unsigned long i = 0; i < elements; i++ ) { this->parameters->remove ( 0ul ); } if ( retriveType == RetrieveSeries ) { this->parameters->putAndInsertString ( DCM_QueryRetrieveLevel, "SERIES" ); this->parameters->putAndInsertString ( DCM_SeriesInstanceUID, UID.toStdString().c_str() ); } else { this->parameters->putAndInsertString ( DCM_QueryRetrieveLevel, "STUDY" ); this->parameters->putAndInsertString ( DCM_StudyInstanceUID, UID.toStdString().c_str() ); } logger.debug ( "Sending Move Request" ); MOVEResponses *responses = new MOVEResponses(); OFCondition status = scu.sendMOVERequest ( 0, this->parameters, responses ); if (!status.good()) { logger.error ( "MOVE Request failed: " + QString ( status.text() ) ); return false; } logger.debug ( "Find succeded" ); logger.debug ( "Making Output Directory" ); QDir directory = QDir( RetrieveDatabase->databaseDirectory() ); if ( responses->begin() == responses->end() ) { logger.error ( "No responses!" ); throw std::runtime_error( std::string("No responses!") ); } // Write the responses out to disk for ( OFListIterator(FINDResponse*) it = responses->begin(); it != responses->end(); it++ ) { DcmDataset *dataset = (*it)->m_dataset; if ( dataset != NULL ) { logger.debug ( "Got a valid dataset" ); // Save in correct directory E_TransferSyntax output_transfersyntax = dataset->getOriginalXfer(); dataset->chooseRepresentation( output_transfersyntax, NULL ); if ( !dataset->canWriteXfer( output_transfersyntax ) ) { // Pick EXS_LittleEndianExplicit as our default output_transfersyntax = EXS_LittleEndianExplicit; } DcmXfer opt_oxferSyn( output_transfersyntax ); if ( !dataset->chooseRepresentation( opt_oxferSyn.getXfer(), NULL ).bad() ) { DcmFileFormat* fileformat = new DcmFileFormat ( dataset ); // Follow dcmdjpeg example fileformat->loadAllDataIntoMemory(); OFString SOPInstanceUID; dataset->findAndGetOFString ( DCM_SOPInstanceUID, SOPInstanceUID ); QFileInfo fi ( directory, QString ( SOPInstanceUID.c_str() ) ); logger.debug ( "Saving file: " + fi.absoluteFilePath() ); status = fileformat->saveFile ( fi.absoluteFilePath().toStdString().c_str(), opt_oxferSyn.getXfer() ); if ( !status.good() ) { logger.error ( "Error saving file: " + fi.absoluteFilePath() + " Error is " + status.text() ); } RetrieveDatabase->insert( dataset, true ); delete fileformat; } } } delete responses; //if ( !scu.dropNetwork().good() ) //{ //logger.error ( "Error dropping the network" ); //return false; //} return true; }
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; }
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; } }