DCMTK:howto:dcmscu-example 网络客户端

 

DcmSCU example program

This is example code how to program an actual DICOM client with the DcmSCU class. In particular, it demonstrates

  1. how to send an ECHO to the server (usually a PACS),
  2. receive a list of studies the PACS has (Query)
  3. and downloads them (Retrieve). For this last step, a separate Storage  SCP like storescp is needed which actually receives the study images.

The code uses the public DICOM server at www.dicomserver.co.uk which is offered by Dave Harvey (MedicalObjects). :-)There are also logs you can check at the server in order to debug your application.

 

/* 
 * 
 *  Copyright (C) 2011-2012, OFFIS e.V. 
 *  All rights reserved.  See COPYRIGHT file for details. 
 * 
 *  This software and supporting documentation were developed by 
 * 
 *    OFFIS e.V. 
 *    R&D Division Health 
 *    Escherweg 2 
 *    D-26121 Oldenburg, Germany 
 * 
 * 
 *  Module:  dcmnet 
 * 
 *  Author:  Michael Onken 
 * 
 *  Purpose: Test for move feature of the DcmSCU class 
 */ 
 
#include "dcmtk/config/osconfig.h"    /* make sure OS specific configuration is included first */ 
#include "dcmtk/dcmnet/testscu.h" 
#include "dcmtk/dcmnet/diutil.h" 
 
#define OFFIS_CONSOLE_APPLICATION "testscu" 
 
static OFLogger echoscuLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); 
 
static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" 
  OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; 
 
// our application entity title used for calling the peer machine 
#define APPLICATIONTITLE     "TEST-SCU" 
 
// host name of the peer machine 
#define PEERHOSTNAME         "www.dicomserver.co.uk" 
 
// TCP/IP port to connect to the peer machine 
#define PEERPORT 11112 
 
// application entity title of the peer machine 
#define PEERAPPLICATIONTITLE "MOVESCP" 
 
// MOVE destination AE Title 
#define MOVEAPPLICATIONTITLE "TEST-SCU" 
 
static Uint8 findUncompressedPC(const OFString& sopClass, 
                                DcmSCU& scu) 
{ 
  Uint8 pc; 
  pc = scu.findPresentationContextID(sopClass, UID_LittleEndianExplicitTransferSyntax); 
  if (pc == 0) 
    pc = scu.findPresentationContextID(sopClass, UID_BigEndianExplicitTransferSyntax); 
  if (pc == 0) 
    pc = scu.findPresentationContextID(sopClass, UID_LittleEndianImplicitTransferSyntax); 
  return pc; 
} 
 
// ******************************************** 
 
int main(int argc, char *argv[]) 
{ 
  /* Setup DICOM connection parameters */ 
  OFLog::configure(OFLogger::DEBUG_LOG_LEVEL); 
  DcmTestSCU scu; 
  // set AE titles 
  scu.setAETitle(APPLICATIONTITLE); 
  scu.setPeerHostName(PEERHOSTNAME); 
  scu.setPeerPort(PEERPORT); 
  scu.setPeerAETitle(PEERAPPLICATIONTITLE); 
  // Use presentation context for FIND/MOVE in study root, propose all uncompressed transfer syntaxes 
  OFList<OFString> ts; 
  ts.push_back(UID_LittleEndianExplicitTransferSyntax); 
  ts.push_back(UID_BigEndianExplicitTransferSyntax); 
  ts.push_back(UID_LittleEndianImplicitTransferSyntax); 
  scu.addPresentationContext(UID_FINDStudyRootQueryRetrieveInformationModel, ts); 
  scu.addPresentationContext(UID_MOVEStudyRootQueryRetrieveInformationModel, ts); 
  scu.addPresentationContext(UID_VerificationSOPClass, ts); 
 
  /* Initialize network */ 
  OFCondition result = scu.initNetwork(); 
  if (result.bad()) 
  { 
    DCMNET_ERROR("Unable to set up the network: " << result.text()); 
    return 1; 
  } 
 
  /* Negotiate Association */ 
  result = scu.negotiateAssociation(); 
  if (result.bad()) 
  { 
    DCMNET_ERROR("Unable to negotiate association: " << result.text()); 
    return 1; 
  } 
 
  /* Let's look whether the server is listening: 
     Assemble and send C-ECHO request 
   */ 
  result = scu.sendECHORequest(0); 
  if (result.bad()) 
  { 
    DCMNET_ERROR("Could not process C-ECHO with the server: " << result.text()); 
    return 1; 
  } 
 
  /* Assemble and send C-FIND request */ 
  OFList<QRResponse*> findResponses; 
  DcmDataset req; 
  req.putAndInsertOFStringArray(DCM_QueryRetrieveLevel, "STUDY"); 
  req.putAndInsertOFStringArray(DCM_StudyInstanceUID, ""); 
  T_ASC_PresentationContextID presID = findUncompressedPC(UID_FINDStudyRootQueryRetrieveInformationModel, scu);
  if (presID == 0) 
  { 
    DCMNET_ERROR("There is no uncompressed presentation context for Study Root FIND"); 
    return 1; 
  } 
  result = scu.sendFINDRequest(presID, &req, &findResponses); 
  if (result.bad()) 
    return 1; 
  else 
    DCMNET_INFO("There are " << findResponses.size() << " studies available"); 
 
  /* Assemble and send C-MOVE request, for each study identified above*/ 
  presID = findUncompressedPC(UID_MOVEStudyRootQueryRetrieveInformationModel, scu); 
  if (presID == 0) 
  { 
    DCMNET_ERROR("There is no uncompressed presentation context for Study Root MOVE"); 
    return 1; 
  } 
  OFListIterator(QRResponse*) study = findResponses.begin(); 
  Uint32 studyCount = 1; 
  OFBool failed = OFFalse; 
  // Every while loop run will get all image for a specific study 
  while (study != findResponses.end() && result.good())
  { 
    // be sure we are not in the last response which does not have a dataset 
    if ( (*study)->m_dataset != NULL) 
    { 
      OFString studyInstanceUID; 
      result = (*study)->m_dataset->findAndGetOFStringArray(DCM_StudyInstanceUID, studyInstanceUID); 
      // only try to get study if we actually have study instance uid, otherwise skip it 
      if (result.good()) 
      { 
        req.putAndInsertOFStringArray(DCM_StudyInstanceUID, studyInstanceUID); 
        // fetches all images of this particular study 
        result = scu.sendMOVERequest(presID, MOVEAPPLICATIONTITLE, &req, NULL /* we are not interested into responses*/); 
        if (result.good()) 
        { 
          DCMNET_INFO("Received study #" << std::setw(7) << studyCount << ": " << studyInstanceUID); 
          studyCount++; 
        } 
      }
    } 
    study++;
  } 
  if (result.bad()) 
  { 
    DCMNET_ERROR("Unable to retrieve all studies: " << result.text()); 
  }
  while (!findResponses.empty())
  {
    delete findResponses.front();
    findResponses.pop_front();
  }
  /* Release association */ 
  scu.closeAssociation(DCMSCU_RELEASE_ASSOCIATION);
  return 0; 
}
 

P.S: The header file would be trivial:

 

#ifndef TESTSCU_H 
#define TESTSCU_H 
 
#include "dcmtk/config/osconfig.h"  /* make sure OS specific configuration is included first */ 
 
#include "dcmtk/dcmnet/scu.h"     /* Covers most common dcmdata classes */ 
 
 
class DcmTestSCU : public DcmSCU 
{ 
 
public: 
 
  DcmTestSCU()  {} 
  ~DcmTestSCU() {} 
 
}; 
 
#endif // TESTSCU_H
  Note

sendMOVERequest() and corresponding code was added after the 3.6.0 release. You need to use a current snapshot version in order to compile and run the code.

------------------------------------------------------------------

柳北风儿

http://qimo601.iteye.com

转载:http://support.dcmtk.org/wiki/dcmtk/howto/dcmscu-example

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值