dcmtk 简单的C-FIND查询实现
利用DCMTK简单实现C-FIND
利用 Dcmtk封装的dcmscu即可实现C-FIND、C-GET、C-MOVE、C-STORE、等
具体的自己多研究DcmScu这个类
#include <iostream>
#include "dcmtk/dcmnet/scu.h"
#include "dcmtk/dcmdata/dcpath.h" /* for DcmPathProcessor */
static OFLogger getscuLogger = OFLog::getLogger("dcmtk.apps." "FINDSCU");
static void prepareTS(E_TransferSyntax ts, OFList<OFString>& syntaxes);
static void applyOverrideKeys(DcmDataset *dataset, const OFList<OFString> overrideKeys);
int main()
{
DcmSCU scu;
OFString temp_str;
OFList<OFString> overrideKeys;
overrideKeys.push_back("0008,0052=STUDY");
overrideKeys.push_back("0008,0050=202006010058");
overrideKeys.push_back("0020,000D=");
if (!dcmDataDict.isDictionaryLoaded())
{
OFLOG_WARN(getscuLogger, "no data dictionary loaded, check environment variable:");
}
/*设置 scu*/
OFList<OFString> syntaxes;
prepareTS(EXS_Unknown, syntaxes);
scu.setMaxReceivePDULength(ASC_DEFAULTMAXPDU);
scu.setACSETimeout(30);
scu.setDIMSEBlockingMode(DIMSE_BLOCKING);
scu.setDIMSETimeout(0);
scu.setAETitle("RADIANT");
scu.setPeerHostName("192.168.0.136");
scu.setPeerPort(OFstatic_cast(Uint16, 4242));
scu.setPeerAETitle("ORTHANC");
scu.setVerbosePCMode(OFFalse);
scu.setSelfPort(1112);
scu.addPresentationContext(UID_FINDStudyRootQueryRetrieveInformationModel, syntaxes);
auto cond = scu.initNetwork();
if (cond.bad())
{
OFLOG_FATAL(getscuLogger, "No Acceptable Presentation Contexts");
return -1;
}
cond = scu.negotiateAssociation();
if (cond.bad())
{
OFLOG_FATAL(getscuLogger, "No Acceptable Presentation Contexts");
exit(1);
}
cond = EC_Normal;
T_ASC_PresentationContextID pcid = scu.findPresentationContextID(UID_FINDStudyRootQueryRetrieveInformationModel,"");
if (pcid == 0)
{
OFLOG_FATAL(getscuLogger, "No adequate Presentation Contexts for sending C-FIND");
return -1;
}
DcmFileFormat dcmff;
DcmDataset *dset = dcmff.getDataset();
OFList<QRResponse*> responses;
//查询
applyOverrideKeys(dset, overrideKeys);
cond = scu.sendFINDRequest(pcid, dset, &responses);
if (!responses.empty())
{
/* output final status report */
OFLOG_INFO(getscuLogger, "Final status report from last C-FIND message:");
/* delete responses */
std::cout << responses.size() << std::endl;
for (auto &item:responses)
{
if (item->m_dataset)
{
OFString studyUID;
auto result = item->m_dataset->findAndGetOFString(DCM_StudyInstanceUID, studyUID);
std::cout << "studyUID:" << studyUID.c_str() << std::endl;
if (result.bad())
{
std::cout << result.text() << std::endl;
}
}
}
OFListIterator(QRResponse*) iter = responses.begin();
OFListConstIterator(QRResponse*) last = responses.end();
while (iter != last)
{
delete (*iter);
iter = responses.erase(iter);
}
}
if (cond.good())
{
}
if (cond == EC_Normal)
{
scu.releaseAssociation();
}
else
{
if (cond == DUL_PEERREQUESTEDRELEASE)
scu.closeAssociation(DCMSCU_PEER_REQUESTED_RELEASE);
else if (cond == DUL_PEERABORTEDASSOCIATION)
scu.closeAssociation(DCMSCU_PEER_ABORTED_ASSOCIATION);
else
{
OFLOG_ERROR(getscuLogger, "Find SCU Failed: " << DimseCondition::dump(temp_str, cond));
scu.abortAssociation();
}
/* TODO: need to find better exit codes */
}
return 0;
}
void applyOverrideKeys(DcmDataset *dataset, const OFList<OFString> overrideKeys)
{
/* replace specific keys by those in overrideKeys */
OFListConstIterator(OFString) path = overrideKeys.begin();
OFListConstIterator(OFString) endOfList = overrideKeys.end();
DcmPathProcessor proc;
proc.setItemWildcardSupport(OFFalse);
proc.checkPrivateReservations(OFFalse);
OFCondition cond;
while (path != endOfList)
{
cond = proc.applyPathWithValue(dataset, *path);
if (cond.bad())
{
OFLOG_ERROR(getscuLogger, "Bad override key/path: " << *path << ": " << cond.text());
}
path++;
}
}
void prepareTS(E_TransferSyntax ts, OFList<OFString>& syntaxes)
{
switch (ts)
{
case EXS_LittleEndianImplicit:
/* we only support Little Endian Implicit */
syntaxes.push_back(UID_LittleEndianExplicitTransferSyntax);
break;
case EXS_LittleEndianExplicit:
/* we prefer Little Endian Explicit */
syntaxes.push_back(UID_LittleEndianExplicitTransferSyntax);
syntaxes.push_back(UID_BigEndianExplicitTransferSyntax);
syntaxes.push_back(UID_LittleEndianImplicitTransferSyntax);
break;
case EXS_BigEndianExplicit:
/* we prefer Big Endian Explicit */
syntaxes.push_back(UID_BigEndianExplicitTransferSyntax);
syntaxes.push_back(UID_LittleEndianExplicitTransferSyntax);
syntaxes.push_back(UID_LittleEndianImplicitTransferSyntax);
break;
#ifdef WITH_ZLIB
case EXS_DeflatedLittleEndianExplicit:
/* we prefer Deflated Little Endian Explicit */
syntaxes.push_back(UID_DeflatedExplicitVRLittleEndianTransferSyntax);
syntaxes.push_back(UID_LittleEndianExplicitTransferSyntax);
syntaxes.push_back(UID_BigEndianExplicitTransferSyntax);
syntaxes.push_back(UID_LittleEndianImplicitTransferSyntax);
break;
#endif
default:
DcmXfer xfer(ts);
if (xfer.isEncapsulated())
{
syntaxes.push_back(xfer.getXferID());
}
/* We prefer explicit transfer syntaxes.
* If we are running on a Little Endian machine we prefer
* LittleEndianExplicitTransferSyntax to BigEndianTransferSyntax.
*/
if (gLocalByteOrder == EBO_LittleEndian) /* defined in dcxfer.h */
{
syntaxes.push_back(UID_LittleEndianExplicitTransferSyntax);
syntaxes.push_back(UID_BigEndianExplicitTransferSyntax);
}
else
{
syntaxes.push_back(UID_BigEndianExplicitTransferSyntax);
syntaxes.push_back(UID_LittleEndianExplicitTransferSyntax);
}
syntaxes.push_back(UID_LittleEndianImplicitTransferSyntax);
break;
}
}