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;
        }
}