使用dctmtk实现DICOM文件的发送(StoreSCU)
2012-12-26 10:34
253 查看
//===================================================================== // SendDICOM.cpp : Defines the entry point for the DLL application. // // Created by HGB 2011 Nanjing ChunRen L.T.D //===================================================================== #include "stdafx.h" #include "SendDICOM.h" #include "osconfig.h" /* make sure OS specific configuration is included first */ #define INCLUDE_CSTDLIB #define INCLUDE_CSTDIO #define INCLUDE_CSTRING #define INCLUDE_CERRNO #define INCLUDE_CSTDARG #define INCLUDE_CCTYPE #include "ofstdinc.h" BEGIN_EXTERN_C #ifdef HAVE_SYS_FILE_H #include <sys/file.h> #endif END_EXTERN_C #ifdef HAVE_GUSI_H #include <GUSI.h> #endif #include "ofstring.h" #include "dimse.h" #include "diutil.h" #include "dcdatset.h" #include "dcmetinf.h" #include "dcfilefo.h" #include "dcdebug.h" #include "dcuid.h" #include "dcdict.h" #include "dcdeftag.h" #include "cmdlnarg.h" #include "ofconapp.h" #include "dcuid.h" /* for dcmtk version name */ #include "dicom.h" /* for DICOM_APPLICATION_REQUESTOR */ #include "dcostrmz.h" /* for dcmZlibCompressionLevel */ #include "dcasccfg.h" /* for class DcmAssociationConfiguration */ #include "dcasccff.h" /* for class DcmAssociationConfigurationFile */ #ifdef ON_THE_FLY_COMPRESSION #include "djdecode.h" /* for dcmjpeg decoders */ #include "djencode.h" /* for dcmjpeg encoders */ #include "dcrledrg.h" /* for DcmRLEDecoderRegistration */ #include "dcrleerg.h" /* for DcmRLEEncoderRegistration */ #endif #ifdef WITH_OPENSSL #include "tlstrans.h" #include "tlslayer.h" #endif #include "WINSOCK.H" #ifdef WITH_ZLIB #include <zlib.h> /* for zlibVersion() */ #endif static E_TransferSyntax opt_networkTransferSyntax = EXS_Unknown; static OFBool opt_proposeOnlyRequiredPresentationContexts = OFFalse; static OFBool opt_combineProposedTransferSyntaxes = OFFalse; static OFCmdUnsignedInt opt_repeatCount = 1; static OFBool opt_haltOnUnsuccessfulStore = OFTrue; static OFCmdUnsignedInt opt_inventPatientCount = 25; static OFCmdUnsignedInt opt_inventStudyCount = 50; static OFCmdUnsignedInt opt_inventSeriesCount = 100; static OFBool opt_inventSOPInstanceInformation = OFFalse; static OFBool opt_correctUIDPadding = OFFalse; static OFBool unsuccessfulStoreEncountered = OFFalse; static OFBool opt_verbose = OFFalse; static OFBool opt_showPresentationContexts = OFFalse; static OFBool opt_debug = OFFalse; static OFBool opt_abortAssociation = OFFalse; static OFCmdUnsignedInt opt_maxReceivePDULength = ASC_DEFAULTMAXPDU; static OFCmdUnsignedInt opt_maxSendPDULength = 0; T_DIMSE_BlockingMode opt_blockMode = DIMSE_BLOCKING; int opt_dimse_timeout = 0; int opt_acse_timeout = 30; static int lastStatusCode = STATUS_Success; static OFString studyIDPrefix("SID_"); // StudyID is SH (maximum 16 chars) static OFString accessionNumberPrefix; // AccessionNumber is SH (maximum 16 chars) static OFString patientIDPrefix("PID_"); // PatientID is LO (maximum 64 chars) static OFString patientNamePrefix("OFFIS^TEST_PN_"); // PatientName is PN (maximum 16 chars) static OFCondition addStoragePresentationContexts(T_ASC_Parameters *params, OFList<OFString>& sopClasses); static OFCondition cstore(T_ASC_Association * assoc, const OFString& fname); static OFBool isaListMember(OFList<OFString>& lst, OFString& s); static OFCondition addPresentationContext(T_ASC_Parameters *params, int presentationContextId, const OFString& abstractSyntax, const OFList<OFString>& transferSyntaxList, T_ASC_SC_ROLE proposedRole = ASC_SC_ROLE_DEFAULT); static OFCondition addPresentationContext(T_ASC_Parameters *params, int presentationContextId, const OFString& abstractSyntax, const OFString& transferSyntax, T_ASC_SC_ROLE proposedRole = ASC_SC_ROLE_DEFAULT); static OFCondition storeSCU(T_ASC_Association * assoc, const char *fname); static void replaceSOPInstanceInformation(DcmDataset* dataset); static void progressCallback(void * /*callbackData*/, T_DIMSE_StoreProgress *progress, T_DIMSE_C_StoreRQ * /*req*/); static OFString makeUID(OFString basePrefix, int counter); static int secondsSince1970(); static OFString intToString(int i); static OFBool updateStringAttributeValue(DcmItem* dataset, const DcmTagKey& key, OFString& value); BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { return TRUE; } int IncInt(int params) { return params+1; } //int IniNet /*==========================================================*/ //Created by hgb 20061229 //result value: //0: success //-1: not foud file //-2: //-3: //-4: //-5: /*==========================================================*/ int __stdcall SendDCM(LPSTR ourTitle, LPSTR peerTitle, LPSTR scpIP, LPSTR scpPort, LPSTR FileName) { char sopClassUID[128]; char sopInstanceUID[128]; OFList<OFString> fileNameList; OFList<OFString> sopClassUIDList; OFList<OFString> sopInstanceUIDList; T_ASC_Network *net; T_ASC_Parameters *params; DIC_NODENAME localHost; DIC_NODENAME peerHost; T_ASC_Association *assoc; //TCHAR tcsModulePath[_MAX_PATH]; //::GetModuleFileName(NULL, tcsModulePath, _MAX_PATH); //CString strCurDir = tcsModulePath; //strCurDir = strCurDir.Left(strCurDir.ReverseFind(TEXT('\\'))+1); //char currentFilename[strCurDir.GetLength()+1]; //strcpy(currentFilename, strCurDir.GetBuffer()); //char *currentFilename = strCurDir; #ifdef HAVE_GUSI_H GUSISetup(GUSIwithSIOUXSockets); GUSISetup(GUSIwithInternetSockets); #endif #ifdef HAVE_WINSOCK_H WSAData winSockData; /* we need at least version 1.1 */ WORD winSockVersionNeeded = MAKEWORD( 1, 1 ); WSAStartup(winSockVersionNeeded, &winSockData); #endif /* CFileFind find; if(find.FindFile(FileName)) { return -1; // not found the file } */ if (access(FileName, R_OK)!=0) return -2; // did't access file if (!DU_findSOPClassAndInstanceInFile(FileName, sopClassUID, sopInstanceUID)) return -101; if (!dcmIsaStorageSOPClassUID(sopClassUID)) return -102; else { //fileNameList.push_back(FileName); sopClassUIDList.push_back(sopClassUID); sopInstanceUIDList.push_back(sopInstanceUID); OFCondition cond = ASC_initializeNetwork(NET_REQUESTOR, 0, 30, &net); if (cond.bad()) return -103; cond = ASC_createAssociationParameters(¶ms, ASC_DEFAULTMAXPDU); if (cond.bad()) return -104; ASC_setAPTitles(params, ourTitle, peerTitle, NULL); gethostname(localHost, sizeof(localHost) - 1); sprintf(peerHost, "%s:%s", scpIP, scpPort);//////// ASC_setPresentationAddresses(params, localHost, peerHost); cond = addStoragePresentationContexts(params, sopClassUIDList); if (cond.bad()) { return -105; } cond = ASC_requestAssociation(net, params, &assoc); if (cond.bad()) { if (cond == DUL_ASSOCIATIONREJECTED) { return -106; } else { //Association Request Failed return -107; } } //发送文件 cond = EC_Normal; //OFListIterator(OFString) iter = fileNameList.begin(); //OFListIterator(OFString) enditer = fileNameList.end();//// //cond = cstore(assoc, *iter); //OFString cond = cstore(assoc, OFString(FileName)); if (cond != EC_Normal) { //ASC_releaseAssociation(assoc); //ASC_destroyAssociation(&assoc); //DimseCondition::dump(cond); //#ifdef HAVE_WINSOCK_H //WSACleanup(); //#endif return -108;//send faid; } cond = ASC_releaseAssociation(assoc); if (cond.bad()) return -109; cond = ASC_destroyAssociation(&assoc); if (cond.bad()) return -120; } #ifdef HAVE_WINSOCK_H WSACleanup(); #endif return 0; } static OFCondition addStoragePresentationContexts(T_ASC_Parameters *params, OFList<OFString>& sopClasses) { /* * Each SOP Class will be proposed in two presentation contexts (unless * the opt_combineProposedTransferSyntaxes global variable is true). * The command line specified a preferred transfer syntax to use. * This prefered transfer syntax will be proposed in one * presentation context and a set of alternative (fallback) transfer * syntaxes will be proposed in a different presentation context. * * Generally, we prefer to use Explicitly encoded transfer syntaxes * and if running on a Little Endian machine we prefer * LittleEndianExplicitTransferSyntax to BigEndianTransferSyntax. * Some SCP implementations will just select the first transfer * syntax they support (this is not part of the standard) so * organise the proposed transfer syntaxes to take advantage * of such behaviour. */ // Which transfer syntax was preferred on the command line OFString preferredTransferSyntax; if (opt_networkTransferSyntax == EXS_Unknown) { /* gLocalByteOrder is defined in dcxfer.h */ if (gLocalByteOrder == EBO_LittleEndian) { /* we are on a little endian machine */ preferredTransferSyntax = UID_LittleEndianExplicitTransferSyntax; } else { /* we are on a big endian machine */ preferredTransferSyntax = UID_BigEndianExplicitTransferSyntax; } } else { DcmXfer xfer(opt_networkTransferSyntax); preferredTransferSyntax = xfer.getXferID(); } OFListIterator(OFString) s_cur; OFListIterator(OFString) s_end; OFList<OFString> fallbackSyntaxes; fallbackSyntaxes.push_back(UID_LittleEndianExplicitTransferSyntax); fallbackSyntaxes.push_back(UID_BigEndianExplicitTransferSyntax); fallbackSyntaxes.push_back(UID_LittleEndianImplicitTransferSyntax); // Remove the preferred syntax from the fallback list fallbackSyntaxes.remove(preferredTransferSyntax); // If little endian implicit is preferred then we don't need any fallback syntaxes // because it is the default transfer syntax and all applications must support it. if (opt_networkTransferSyntax == EXS_LittleEndianImplicit) { fallbackSyntaxes.clear(); } // created a list of transfer syntaxes combined from the preferred and fallback syntaxes OFList<OFString> combinedSyntaxes; s_cur = fallbackSyntaxes.begin(); s_end = fallbackSyntaxes.end(); combinedSyntaxes.push_back(preferredTransferSyntax); while (s_cur != s_end) { if (!isaListMember(combinedSyntaxes, *s_cur)) combinedSyntaxes.push_back(*s_cur); ++s_cur; } if (!opt_proposeOnlyRequiredPresentationContexts) { // add the (short list of) known storage sop classes to the list // the array of Storage SOP Class UIDs comes from dcuid.h for (int i=0; i<numberOfDcmShortSCUStorageSOPClassUIDs; i++) { sopClasses.push_back(dcmShortSCUStorageSOPClassUIDs[i]); } } // thin out the sop classes to remove any duplicates. OFList<OFString> sops; s_cur = sopClasses.begin(); s_end = sopClasses.end(); while (s_cur != s_end) { if (!isaListMember(sops, *s_cur)) { sops.push_back(*s_cur); } ++s_cur; } // add a presentations context for each sop class / transfer syntax pair OFCondition cond = EC_Normal; int pid = 1; // presentation context id s_cur = sops.begin(); s_end = sops.end(); while (s_cur != s_end && cond.good()) { if (pid > 255) { ///errmsg("Too many presentation contexts"); return ASC_BADPRESENTATIONCONTEXTID; } if (opt_combineProposedTransferSyntaxes) { cond = addPresentationContext(params, pid, *s_cur, combinedSyntaxes); pid += 2; /* only odd presentation context id's */ } else { // sop class with preferred transfer syntax cond = addPresentationContext(params, pid, *s_cur, preferredTransferSyntax); pid += 2; /* only odd presentation context id's */ if (fallbackSyntaxes.size() > 0) { if (pid > 255) { //errmsg("Too many presentation contexts"); return ASC_BADPRESENTATIONCONTEXTID; } // sop class with fallback transfer syntax cond = addPresentationContext(params, pid, *s_cur, fallbackSyntaxes); pid += 2; /* only odd presentation context id's */ } } ++s_cur; } return cond; } static OFCondition cstore(T_ASC_Association * assoc, const OFString& fname) /* * This function will process the given file as often as is specified by opt_repeatCount. * "Process" in this case means "read file, send C-STORE-RQ, receive C-STORE-RSP". * * Parameters: * assoc - [in] The association (network connection to another DICOM application). * fname - [in] Name of the file which shall be processed. */ { OFCondition cond = EC_Normal; /* opt_repeatCount specifies how many times a certain file shall be processed */ int n = (int)opt_repeatCount; /* as long as no error occured and the counter does not equal 0 */ while ((cond.good()) && n-- && !(opt_haltOnUnsuccessfulStore && unsuccessfulStoreEncountered)) { /* process file (read file, send C-STORE-RQ, receive C-STORE-RSP) */ cond = storeSCU(assoc, fname.c_str()); } // we don't want to return an error code if --no-halt was specified. if (! opt_haltOnUnsuccessfulStore) { cond = EC_Normal; } /* return result value */ return cond; } static OFBool isaListMember(OFList<OFString>& lst, OFString& s) { OFListIterator(OFString) cur = lst.begin(); OFListIterator(OFString) end = lst.end(); OFBool found = OFFalse; while (cur != end && !found) { found = (s == *cur); ++cur; } return found; } static OFCondition addPresentationContext(T_ASC_Parameters *params, int presentationContextId, const OFString& abstractSyntax, const OFString& transferSyntax, T_ASC_SC_ROLE proposedRole) { const char* c_p = transferSyntax.c_str(); OFCondition cond = ASC_addPresentationContext(params, presentationContextId, abstractSyntax.c_str(), &c_p, 1, proposedRole); return cond; } static OFCondition addPresentationContext(T_ASC_Parameters *params, int presentationContextId, const OFString& abstractSyntax, const OFList<OFString>& transferSyntaxList, T_ASC_SC_ROLE proposedRole) { // create an array of supported/possible transfer syntaxes const char** transferSyntaxes = new const char*[transferSyntaxList.size()]; int transferSyntaxCount = 0; OFListConstIterator(OFString) s_cur = transferSyntaxList.begin(); OFListConstIterator(OFString) s_end = transferSyntaxList.end(); while (s_cur != s_end) { transferSyntaxes[transferSyntaxCount++] = (*s_cur).c_str(); ++s_cur; } OFCondition cond = ASC_addPresentationContext(params, presentationContextId, abstractSyntax.c_str(), transferSyntaxes, transferSyntaxCount, proposedRole); delete[] transferSyntaxes; return cond; } static OFCondition storeSCU(T_ASC_Association * assoc, const char *fname) /* * This function will read all the information from the given file, * figure out a corresponding presentation context which will be used * to transmit the information over the network to the SCP, and it * will finally initiate the transmission of all data to the SCP. * * Parameters: * assoc - [in] The association (network connection to another DICOM application). * fname - [in] Name of the file which shall be processed. */ { DIC_US msgId = assoc->nextMsgID++; T_ASC_PresentationContextID presId; T_DIMSE_C_StoreRQ req; T_DIMSE_C_StoreRSP rsp; DIC_UI sopClass; DIC_UI sopInstance; DcmDataset *statusDetail = NULL; unsuccessfulStoreEncountered = OFTrue; // assumption if (opt_verbose) { printf("--------------------------\n"); printf("Sending file: %s\n", fname); } /* read information from file. After the call to DcmFileFormat::loadFile(...) the information */ /* which is encapsulated in the file will be available through the DcmFileFormat object. */ /* In detail, it will be available through calls to DcmFileFormat::getMetaInfo() (for */ /* meta header information) and DcmFileFormat::getDataset() (for data set information). */ DcmFileFormat dcmff; OFCondition cond = dcmff.loadFile(fname); /* figure out if an error occured while the file was read*/ if (cond.bad()) { //errmsg("Bad DICOM file: %s: %s", fname, cond.text()); return cond; } /* if required, invent new SOP instance information for the current data set (user option) */ if (opt_inventSOPInstanceInformation) { replaceSOPInstanceInformation(dcmff.getDataset()); } /* figure out which SOP class and SOP instance is encapsulated in the file */ if (!DU_findSOPClassAndInstanceInDataSet(dcmff.getDataset(), sopClass, sopInstance, opt_correctUIDPadding)) { //errmsg("No SOP Class & Instance UIDs in file: %s", fname); return DIMSE_BADDATA; } /* figure out which of the accepted presentation contexts should be used */ DcmXfer filexfer(dcmff.getDataset()->getOriginalXfer());//??????? added by HGB /* special case: if the file uses an unencapsulated transfer syntax (uncompressed * or deflated explicit VR) and we prefer deflated explicit VR, then try * to find a presentation context for deflated explicit VR first. */ if (filexfer.isNotEncapsulated() && opt_networkTransferSyntax == EXS_DeflatedLittleEndianExplicit) { filexfer = EXS_DeflatedLittleEndianExplicit; } if (filexfer.getXfer() != EXS_Unknown) presId = ASC_findAcceptedPresentationContextID(assoc, sopClass, filexfer.getXferID()); else presId = ASC_findAcceptedPresentationContextID(assoc, sopClass); if (presId == 0) { const char *modalityName = dcmSOPClassUIDToModality(sopClass); if (!modalityName) modalityName = dcmFindNameOfUID(sopClass); if (!modalityName) modalityName = "unknown SOP class"; // errmsg("No presentation context for: (%s) %s", modalityName, sopClass); return DIMSE_NOVALIDPRESENTATIONCONTEXTID; } /* if required, dump general information concerning transfer syntaxes */ if (opt_verbose) { DcmXfer fileTransfer(dcmff.getDataset()->getOriginalXfer()); T_ASC_PresentationContext pc; ASC_findAcceptedPresentationContext(assoc->params, presId, &pc); DcmXfer netTransfer(pc.acceptedTransferSyntax); printf("Transfer: %s -> %s\n", dcmFindNameOfUID(fileTransfer.getXferID()), dcmFindNameOfUID(netTransfer.getXferID())); } /* prepare the transmission of data */ bzero((char*)&req, sizeof(req)); req.MessageID = msgId; strcpy(req.AffectedSOPClassUID, sopClass); strcpy(req.AffectedSOPInstanceUID, sopInstance); req.DataSetType = DIMSE_DATASET_PRESENT; req.Priority = DIMSE_PRIORITY_LOW; /* if required, dump some more general information */ if (opt_verbose) { printf("Store SCU RQ: MsgID %d, (%s)\n", msgId, dcmSOPClassUIDToModality(sopClass)); } /* finally conduct transmission of data */ cond = DIMSE_storeUser(assoc, presId, &req, NULL, dcmff.getDataset(), progressCallback, NULL, opt_blockMode, opt_dimse_timeout, &rsp, &statusDetail, NULL, DU_fileSize(fname)); /* * If store command completed normally, with a status * of success or some warning then the image was accepted. */ if (cond == EC_Normal && (rsp.DimseStatus == STATUS_Success || DICOM_WARNING_STATUS(rsp.DimseStatus))) { unsuccessfulStoreEncountered = OFFalse; } /* remember the response's status for later transmissions of data */ lastStatusCode = rsp.DimseStatus; /* dump some more general information */ if (cond == EC_Normal) { if (opt_verbose) { DIMSE_printCStoreRSP(stdout, &rsp); } } else { //errmsg("Store Failed, file: %s:", fname); DimseCondition::dump(cond); } /* dump status detail information if there is some */ if (statusDetail != NULL) { printf(" Status Detail:\n"); statusDetail->print(COUT); delete statusDetail; } /* return */ return cond; } static void replaceSOPInstanceInformation(DcmDataset* dataset) { static OFCmdUnsignedInt patientCounter = 0; static OFCmdUnsignedInt studyCounter = 0; static OFCmdUnsignedInt seriesCounter = 0; static OFCmdUnsignedInt imageCounter = 0; static OFString seriesInstanceUID; static OFString seriesNumber; static OFString studyInstanceUID; static OFString studyID; static OFString accessionNumber; static OFString patientID; static OFString patientName; if (seriesInstanceUID.length() == 0) seriesInstanceUID=makeUID(SITE_SERIES_UID_ROOT, (int)seriesCounter); if (seriesNumber.length() == 0) seriesNumber = intToString((int)seriesCounter); if (studyInstanceUID.length() == 0) studyInstanceUID = makeUID(SITE_STUDY_UID_ROOT, (int)studyCounter); if (studyID.length() == 0) studyID = studyIDPrefix + intToString((int)secondsSince1970()) + intToString((int)studyCounter); if (accessionNumber.length() == 0) accessionNumber = accessionNumberPrefix + intToString(secondsSince1970()) + intToString((int)studyCounter); if (patientID.length() == 0) patientID = patientIDPrefix + intToString(secondsSince1970()) + intToString((int)patientCounter); if (patientName.length() == 0) patientName = patientNamePrefix + intToString(secondsSince1970()) + intToString((int)patientCounter); if (imageCounter >= opt_inventSeriesCount) { imageCounter = 0; seriesCounter++; seriesInstanceUID = makeUID(SITE_SERIES_UID_ROOT, (int)seriesCounter); seriesNumber = intToString((int)seriesCounter); } if (seriesCounter >= opt_inventStudyCount) { seriesCounter = 0; studyCounter++; studyInstanceUID = makeUID(SITE_STUDY_UID_ROOT, (int)studyCounter); studyID = studyIDPrefix + intToString(secondsSince1970()) + intToString((int)studyCounter); accessionNumber = accessionNumberPrefix + intToString(secondsSince1970()) + intToString((int)studyCounter); } if (studyCounter >= opt_inventPatientCount) { // we create as many patients as necessary */ studyCounter = 0; patientCounter++; patientID = patientIDPrefix + intToString(secondsSince1970()) + intToString((int)patientCounter); patientName = patientNamePrefix + intToString(secondsSince1970()) + intToString((int)patientCounter); } OFString sopInstanceUID = makeUID(SITE_INSTANCE_UID_ROOT, (int)imageCounter); OFString imageNumber = intToString((int)imageCounter); if (opt_verbose) { COUT << "Inventing Identifying Information (" << "pa" << patientCounter << ", st" << studyCounter << ", se" << seriesCounter << ", im" << imageCounter << "): " << endl; COUT << " PatientName=" << patientName << endl; COUT << " PatientID=" << patientID << endl; COUT << " StudyInstanceUID=" << studyInstanceUID << endl; COUT << " StudyID=" << studyID << endl; COUT << " SeriesInstanceUID=" << seriesInstanceUID << endl; COUT << " SeriesNumber=" << seriesNumber << endl; COUT << " SOPInstanceUID=" << sopInstanceUID << endl; COUT << " ImageNumber=" << imageNumber << endl; } updateStringAttributeValue(dataset, DCM_PatientsName, patientName); updateStringAttributeValue(dataset, DCM_PatientID, patientID); updateStringAttributeValue(dataset, DCM_StudyInstanceUID, studyInstanceUID); updateStringAttributeValue(dataset, DCM_StudyID, studyID); updateStringAttributeValue(dataset, DCM_SeriesInstanceUID, seriesInstanceUID); updateStringAttributeValue(dataset, DCM_SeriesNumber, seriesNumber); updateStringAttributeValue(dataset, DCM_SOPInstanceUID, sopInstanceUID); updateStringAttributeValue(dataset, DCM_InstanceNumber, imageNumber); imageCounter++; } static void progressCallback(void * /*callbackData*/, T_DIMSE_StoreProgress *progress, T_DIMSE_C_StoreRQ * /*req*/) { if (opt_verbose) { switch (progress->state) { case DIMSE_StoreBegin: printf("XMIT:"); break; case DIMSE_StoreEnd: printf("\n"); break; default: putchar('.'); break; } fflush(stdout); } } static OFString makeUID(OFString basePrefix, int counter) { OFString prefix = basePrefix + "." + intToString(counter); char uidbuf[65]; OFString uid = dcmGenerateUniqueIdentifier(uidbuf, prefix.c_str()); return uid; } static int secondsSince1970() { time_t t = time(NULL); return (int)t; } static OFString intToString(int i) { char numbuf[32]; sprintf(numbuf, "%d", i); return numbuf; } static OFBool updateStringAttributeValue(DcmItem* dataset, const DcmTagKey& key, OFString& value) { DcmStack stack; DcmTag tag(key); OFCondition cond = EC_Normal; cond = dataset->search(key, stack, ESM_fromHere, OFFalse); if (cond != EC_Normal) { CERR << "error: updateStringAttributeValue: cannot find: " << tag.getTagName() << " " << key << ": " << cond.text() << endl; return OFFalse; } DcmElement* elem = (DcmElement*) stack.top(); DcmVR vr(elem->ident()); if (elem->getLength() > vr.getMaxValueLength()) { CERR << "error: updateStringAttributeValue: INTERNAL ERROR: " << tag.getTagName() << " " << key << ": value too large (max " << vr.getMaxValueLength() << ") for " << vr.getVRName() << " value: " << value << endl; return OFFalse; } cond = elem->putOFStringArray(value); if (cond != EC_Normal) { CERR << "error: updateStringAttributeValue: cannot put string in attribute: " << tag.getTagName() << " " << key << ": " << cond.text() << endl; return OFFalse; } return OFTrue; }
相关文章推荐
- 使用dctmtk实现DICOM文件的发送(StoreSCU)
- 使用dctmtk实现DICOM文件的发送(StoreSCU)
- 使用HttpClient4实现文件上传请求的发送,服务器端以MultipartFile形式接收(附依赖jar包地址)
- 在Android中使用 asmack 实现文件的接收和发送
- 使用leadtools的WCF接口功能实现从web端上传Dicom影像文件
- 使用splice实现零拷贝复制文件
- windows下发送文件到邮箱,使用VBS发送邮件
- unity使用屏幕后处理实现闪烁特效,创建新的shader文件过程
- Hadoop使用CombineFileInputFormat处理大量小文件接口实现(Hadoop-1.0.4)
- Linux下使用extundelete实现文件/文件夹数据恢复
- 使用nginx搭建集群tomcat8,redis实现session共享,文件共享问题
- 使用变量实现的一个简单windwos批处理包括copy、del、rename一个文件
- 使用inotify实现实时文件同步的shell脚本
- 使用common-fileUpload和 Spring中MultipartHttpServletRequest实现文件上传
- 使用IO流实现对特殊文件及文件夹中文件拷贝到指定文件中
- 如何实现app文件,第一次使用时的启动画面
- 如何使用C\C++实现文件的检索&nbsp;?
- 使用cwRsync实现windows下文件定时同步【转】
- 使用common-fileUpload实现文件上传
- 使用rsync实现文件同步