`
qimo601
  • 浏览: 3418499 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

DCMTK: Set output directory to DcmSCP

阅读更多

 

Author Message
 Post subject: Set output directory to DcmSCP
PostPosted: Thu, 2011-09-22, 13:26 
Offline

Joined: Thu, 2011-09-22, 12:54
Posts: 4
Location: France
Hello, 

I am a student working on a project (Skuld) which uses dcmtk on Android. 

Dcmtk runs perfectly on Android! I can send echo requests, find requests and initiate move requests. I followed the example of DcmSCU

The problem is, I need a SCP that will allow to store the dicom images. 

I already successfully used movescu as a binary file in Android. The problem is that we cannot ship this binary with our Android application (Actually we can put it in the installation bundle, but 

1) for security reasons it is not possible to execute it in its folder : 
either the user has to manipulate Android tools, not very user friendly, and some devices simply don't allow access to the internal filesystem. 

2) Ship a binary file increase installation bundle size, which is not very good for a mobile application. 

I wish to use DcmSCP for receiving incoming DICOM files, but I am not sure this tool would be able to satisfy what I want to do, so my questions are : 

1) Should I launch DcmSCP as a separate process running indefinitely? 

2) How to set the output folder for DcmSCP? I didn't see any method to handle this, is it taking a default folder? 

Thanks by advance,

_________________
Nicolas Zerr
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu, 2011-09-22, 14:17 
Offline
OFFIS DICOM Team
OFFIS DICOM Team

Joined: Fri, 2004-11-05, 14:47
Posts: 1153
Location: Oldenburg, Germany
Hi Nicolas, 

Quote:
Dcmtk runs perfectly on Android!

Great! That's good to know :-) If you have patches that were necessary we are happy to incorporate/offer them to other users. This might also help you to keep your Android DCMTK copy up-to-date with the latest DCMTK since you do not have to patch your changes into the latest version.

Quote:
1) Should I launch DcmSCP as a separate process running indefinitely?


If this is possible for you, you can do it like that. Note that also DcmSCP has a function to stop after the current request. If stopAfterCurrentAssociation() return OFTrue, then DcmSCP returns after the current association is ended by the SCU. Thus, you have to derive your own class from DcmSCP and overwrite this virtual function, making it returning OFTrue when the SCP should stop return the association.

There is no other method to stop listening, by now.

Quote:
2) How to set the output folder for DcmSCP? I didn't see any method to handle this, is it taking a default folder?


Note that there is currently no functionality for any DICOM service besides ECHO. So you have to add Storage Service Class functionality yourself, i.e. overwrite the function handleIncomingCommand() and switch for C-STORE to your own code within. 

Surprisingly (maybe) I implemented that already for DmSCU -- it is needed for C-GET functionality to receive and store DICOM objects. So you might have a look into the current DcmSCU implementation (see DCMTK's public git repository) and implement it similarly. 

Best regards, 
Michael


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu, 2011-09-22, 15:37 
Offline

Joined: Thu, 2011-09-22, 12:54
Posts: 4
Location: France
Hello Michael, 

Thank you for you quick answer. 

The C-GET functionnality in DcmSCU would be very useful and easy to use in my project, however it is said few software support C-GET command and implement rather C-MOVE that fires a C-STORE request, and I wish to be compatible with most of the PACS servers. Since I am not really in a medical environment, could you confirm this fact to me? 

I found maybe another solution, which consists in compiling storescp as a shared library, and pass the arguments from Java through JNI. 

I saw that you can set the output file in the DicomSCU class, however I think for me it would be easier to generate the filenames in the right folders. 

I will post a tutorial to compile and use it for Android (already in French here ). 

I will open a new topic, post the tutorial translated in English in a few days. 

For compiling purposes I only had to edit one line, like this : 

File : dcmdata/libsrc/dcuid.cc 
Line : 1484 

Code:
diff dcmtk-original/dcmdata/libsrc/dcuid.cc  dcmtk/dcmdata/libsrc/dcuid.cc


Code:
1484c1484
< #if defined(_REENTRANT) && !defined(_WIN32) && !defined(__CYGWIN__)
---
> #if defined(_REENTRANT) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(ANDROID)

_________________
Nicolas Zerr
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu, 2011-09-22, 15:43 
Offline
OFFIS DICOM Team
OFFIS DICOM Team

Joined: Fri, 2004-11-05, 14:47
Posts: 1153
Location: Oldenburg, Germany
Hi Nicolas, 

thanks for the tutorial link! If you ever do an English translation we will be happy to host it or at least link to it from our HOWTO page in the wiki

Ah, only one line? When I tried it some time ago, there was more to do. But that is good news! Did you compile the complete public toolkit or "only" ofstd, oflog, dcmdata and dcmnet? [Edit: Ah, just read it in your tutorial] 

I recommend you deriving your own class from DcmSCP and add the storage functionality yourself -- it works very similarly compared to what is already inDcmSCU

Hope to see your DCMTK application on the Android Market soon :-) 

Michael 

[Edit: Linked your tutorial in the wiki]


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu, 2011-09-22, 17:07 
Offline

Joined: Thu, 2011-09-22, 12:54
Posts: 4
Location: France
Hello, 

I compiled all the dcmtk toolkit, including apps. I tried movescu, it worked fine, I don't know about the other tools but they should work too. 

I used android-cmake to build the application, and you may tried without this tool, that's why you had much work to do. This script makes the build process very easy (once the script installed, it only requires 4 or 5 steps!) 

I will write a cleaned Android makefile for all DCMTK modules, easy to include in other applications. 

For your information : 

Dicom images libraries are also working, I can display a dicom bitmap I generated with dcmimage. In fact, I first use DicomImage->writeBmp() 
then load the generated file with Android Bitmap API. 

The pictures are a little dark, we should process the bitmap pixels to make them brighter. 

I did not yet succeed in putting the pixels directly from DCMTK, because there's a problem with UInt8 that needs to be converted to java bytes (which are unsigned). However, it should be possible to convert with bits operations. 

I will come back later to ask questions about it, for the moment I just need to retrieve Dicom Images ;) 

Thanks again for your answers speed and clearness.

_________________
Nicolas Zerr
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu, 2011-09-22, 17:28 
Offline
DCMTK Developer

Joined: Tue, 2011-05-03, 15:38
Posts: 706
Quote:
The pictures are a little dark, we should process the bitmap pixels to make them brighter.

Did you specify an appropriate VOI window (for monochrome images)?

Quote:
I did not yet succeed in putting the pixels directly from DCMTK, because there's a problem with UInt8 that needs to be converted to java bytes (which are unsigned). However, it should be possible to convert with bits operations.

This is something we already did for DICOMscope about 13 years ago. Have a look at the JNI code of DICOMscope.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon, 2011-09-26, 15:18 
Offline

Joined: Thu, 2011-09-22, 12:54
Posts: 4
Location: France
Hello, 

I did not yet try to set a VOI window, but i'll try as soon as I finished the Query/Retrieve part. 

I have two questions : 

The first is related to storescp and SCP in general. 

I built storescp as a shared library for Android, and used the dcmscu example to send move requests. It works, but the problem is that I cannot stop the server once I retrieved the study. It results in a background thread that I cannot stop properly. 

I would like to start the server each time I want to retrieve a study, but with different parameters (port, output directory). 

Is it possible to stop the storeSCP after retrieving a study, for instance using option --exec-on-eostudy ? 



I also wanted to implement a c-get request. However it does not work. Here is my code : 

-------------- 
Get.cpp 
-------------- 
Code:
//init scu and JNI stuff...

scu.setACSETimeout(5);
   scu.setPacs(jHost, jPort, jPeerAeTitle, jCallingAeTitle);

   OFList<OFString> ts;
   ts.push_back(UID_LittleEndianExplicitTransferSyntax);
   ts.push_back(UID_BigEndianExplicitTransferSyntax);
   ts.push_back(UID_LittleEndianImplicitTransferSyntax);

scu.addPresentationContext(UID_GETStudyRootQueryRetrieveInformationModel, ts);
   scu.addPresentationContext(UID_VerificationSOPClass, ts);

   OFCondition result = scu.initNetwork();
   if (result.bad())
   {
      scu.setLastError(result.text());
      scu.closeAssociation(DCMSCU_RELEASE_ASSOCIATION);
      return 1;
   }

   result = scu.negotiateAssociation();
   if (result.bad())
   {
      OFString s("Unable to negotiate association: ");
      scu.setLastError(s + result.text());
      scu.closeAssociation(DCMSCU_RELEASE_ASSOCIATION);
      return 2;
   }

   T_ASC_PresentationContextID presID = scu.findUncompressedPC(UID_GETStudyRootQueryRetrieveInformationModel);
   if (presID == 0)
   {
      scu.setLastError("There is no uncompressed presentation context for Study Root FIND");
      return 3;
   }

   OFString storageDir = env->GetStringUTFChars(jStorageDir, NULL);
   scu.setStorageDir(storageDir);

   OFString uid = env->GetStringUTFChars(jUid, NULL);
   DcmDataset *req = new DcmDataset;
   req->putAndInsertOFStringArray(DCM_QueryRetrieveLevel, "SERIES");
   LOGI("%s", uid.c_str());
   req->putAndInsertOFStringArray(DCM_SeriesInstanceUID, uid, true);

   OFList<RetrieveResponse *> responses;
   result = scu.sendCGETRequest(presID, req, &responses);
   if (result.bad())
   {
      scu.setLastError("C-GET request failed");
      return 4;
   }
   scu.closeAssociation(DCMSCU_RELEASE_ASSOCIATION);
   return 0;
}



-------
DicomSCU.cpp
The DicomSCU class inherits DcmSCU
-------

Code:
OFCondition DicomSCU::handleCGETResponse(const T_ASC_PresentationContextID presID,
      RetrieveResponse *response,
      OFBool &continueCGETSession)
{
   
   LOGI("%s", response->m_affectedSOPClassUID.c_str());
   LOGI("Failed : %d", response->m_numberOfFailedSubops);
   LOGI("Completed : %d", response->m_numberOfCompletedSubops);
   LOGI("Remaining : %d", response->m_numberOfRemainingSubops);
   return DcmSCU::handleCGETResponse(presID, response, continueCGETSession);
}


LOGI refers to Android Log. 
The output is : 

Failed : 22 
Completed : 0 
Remaining : 0 

The study I want to retrieve has effectively 22 elements, however the single C-GET response tell me it failed. 

How to solve it ? Is it due to a bad presentation context? 
Could you provide a C-GET example? 

Thanks by Advance

_________________
Nicolas Zerr
 

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon, 2011-09-26, 16:33 
Offline
OFFIS DICOM Team
OFFIS DICOM Team

Joined: Fri, 2004-11-05, 14:47
Posts: 1153
Location: Oldenburg, Germany
Hi, 

no there is no way to stop storescp. You woudl have to program that yourself (i.e. stop after association was received and terminated). Only bad hacks are possible with --exec...options, e.g. let the process exec a kill script to kill itself or the like ;) I would advice adding that in the source code yourself, as you need. 

For your DcmSCU sample application: You also have to add the storage SOP classes to the proposed presentation contexts since the same connection/association will be used for retrieval. Thus, you have to propose each Storage SOP Class from your code with the role "SCP" which is not the default. You can look into getscu.cc how it must be done -- don't worry, it's really easy, I promise 8) 

Best regards, 
Michael


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri, 2011-09-30, 11:14 
Offline
DCMTK Developer

Joined: Thu, 2009-11-26, 09:15
Posts: 88
Hi, 

DCMTK should now correctly detect that gethostbyname_r() is not available on android. Thanks for the hint. 

http://git.dcmtk.org/web?p=dcmtk.git;a= ... e17aa79feb 

Uli


Report this post
Top
 Profile  
Reply with quote  
 Post subject: Re: Set output directory to DcmSCP
PostPosted: Mon, 2012-03-19, 08:05 
Offline

Joined: Fri, 2012-02-24, 05:13
Posts: 1
Hi Nicolas, 

Can you release the DCMTK on Android tutorial? 

Your reply is really appriciated.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu, 2012-04-12, 12:07 
Offline

Joined: Wed, 2012-04-11, 18:02
Posts: 1
Anyone else can explain how to build DCMTK with Android NDK? 
Thanks in advance.


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous: All posts 1 day 7 days 2 weeks 1 month 3 months 6 months 1 year Sort by Author Post time Subject Ascending Descending 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics