changeset 661:d233b5090105

accept more transfer syntaxes for C-Store SCP, write meta-header when receiving files
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 05 Nov 2013 17:41:25 +0100
parents f0232774b913
children 70161eb45b5c
files NEWS OrthancServer/FromDcmtkBridge.cpp OrthancServer/Internals/CommandDispatcher.cpp
diffstat 3 files changed, 75 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Mon Nov 04 15:07:58 2013 +0100
+++ b/NEWS	Tue Nov 05 17:41:25 2013 +0100
@@ -2,7 +2,9 @@
 ===============================
 
 
-* Fixes and improvements thanks to cppcheck
+* Accept more transfer syntaxes for C-Store SCP (including JPEG)
+* Create the meta-header when receiving files through C-Store SCP
+* Fixes and improvements thanks to the static analyzer cppcheck
 
 
 Version 0.7.1 (2013/10/30)
--- a/OrthancServer/FromDcmtkBridge.cpp	Mon Nov 04 15:07:58 2013 +0100
+++ b/OrthancServer/FromDcmtkBridge.cpp	Tue Nov 05 17:41:25 2013 +0100
@@ -98,6 +98,7 @@
 #include <dcmtk/dcmdata/dcfilefo.h>
 #include <dcmtk/dcmdata/dcistrmb.h>
 #include <dcmtk/dcmdata/dcuid.h>
+#include <dcmtk/dcmdata/dcmetinf.h>
 
 #include <dcmtk/dcmdata/dcvrae.h>
 #include <dcmtk/dcmdata/dcvras.h>
@@ -1554,25 +1555,41 @@
     // syntax, with explicit length.
 
     // http://support.dcmtk.org/docs/dcxfer_8h-source.html
-    E_TransferSyntax xfer = EXS_LittleEndianExplicit;
+
+
+    /**
+     * Note that up to Orthanc 0.7.1 (inclusive), the
+     * "EXS_LittleEndianExplicit" was always used to save the DICOM
+     * dataset into memory. We now keep the original transfer syntax
+     * (if available).
+     **/
+    E_TransferSyntax xfer = dataSet->getOriginalXfer();
+    if (xfer == EXS_Unknown)
+    {
+      // No information about the original transfer syntax: This is
+      // most probably a DICOM dataset that was read from memory.
+      xfer = EXS_LittleEndianExplicit;
+    }
+
     E_EncodingType encodingType = /*opt_sequenceType*/ EET_ExplicitLength;
 
-    uint32_t s = dataSet->getLength(xfer, encodingType);
+    // Create the meta-header information
+    DcmFileFormat ff(dataSet);
+    ff.validateMetaInfo(xfer);
 
+    // Create a memory buffer with the proper size
+    uint32_t s = ff.calcElementLength(xfer, encodingType);
     buffer.resize(s);
     DcmOutputBufferStream ob(&buffer[0], s);
 
-    dataSet->transferInit();
+    // Fill the memory buffer with the meta-header and the dataset
+    ff.transferInit();
+    OFCondition c = ff.write(ob, xfer, encodingType, NULL,
+                             /*opt_groupLength*/ EGL_recalcGL,
+                             /*opt_paddingType*/ EPD_withoutPadding);
+    ff.transferEnd();
 
-#if DCMTK_VERSION_NUMBER >= 360
-    OFCondition c = dataSet->write(ob, xfer, encodingType, NULL,
-                                   /*opt_groupLength*/ EGL_recalcGL,
-                                   /*opt_paddingType*/ EPD_withoutPadding);
-#else
-    OFCondition c = dataSet->write(ob, xfer, encodingType, NULL);
-#endif
-
-    dataSet->transferEnd();
+    // Handle errors
     if (c.good())
     {
       return true;
@@ -1582,15 +1599,5 @@
       buffer.clear();
       return false;
     }
-
-#if 0
-    OFCondition cond = cbdata->dcmff->saveFile(fileName.c_str(), xfer, 
-                                               encodingType, 
-                                               /*opt_groupLength*/ EGL_recalcGL,
-                                               /*opt_paddingType*/ EPD_withoutPadding,
-                                               OFstatic_cast(Uint32, /*opt_filepad*/ 0), 
-                                               OFstatic_cast(Uint32, /*opt_itempad*/ 0),
-                                               (opt_useMetaheader) ? EWM_fileformat : EWM_dataset);
-#endif
   }
 }
--- a/OrthancServer/Internals/CommandDispatcher.cpp	Mon Nov 04 15:07:58 2013 +0100
+++ b/OrthancServer/Internals/CommandDispatcher.cpp	Tue Nov 05 17:41:25 2013 +0100
@@ -240,9 +240,6 @@
         knownAbstractSyntaxes.push_back(UID_MOVEStudyRootQueryRetrieveInformationModel);
       }
 
-      const char* transferSyntaxes[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
-      int numTransferSyntaxes = 0;
-
       cond = ASC_receiveAssociation(net, &assoc, 
                                     /*opt_maxPDU*/ ASC_DEFAULTMAXPDU, 
                                     NULL, NULL,
@@ -267,13 +264,49 @@
 
       LOG(INFO) << "Association Received";
 
-      transferSyntaxes[0] = UID_LittleEndianExplicitTransferSyntax;
-      transferSyntaxes[1] = UID_BigEndianExplicitTransferSyntax;
-      transferSyntaxes[2] = UID_LittleEndianImplicitTransferSyntax;
-      numTransferSyntaxes = 3;
+      std::vector<const char*> transferSyntaxes;
+
+#if 0
+      // This is the list of the transfer syntaxes that were supported up to Orthanc 0.7.1
+      transferSyntaxes.push_back(UID_LittleEndianExplicitTransferSyntax);
+      transferSyntaxes.push_back(UID_BigEndianExplicitTransferSyntax);
+      transferSyntaxes.push_back(UID_LittleEndianImplicitTransferSyntax);
+#else
+      transferSyntaxes.push_back(UID_LittleEndianImplicitTransferSyntax); 
+      transferSyntaxes.push_back(UID_DeflatedExplicitVRLittleEndianTransferSyntax); 
+      transferSyntaxes.push_back(UID_JPEGProcess1TransferSyntax);
+      transferSyntaxes.push_back(UID_JPEGProcess2_4TransferSyntax);
+      transferSyntaxes.push_back(UID_JPEGProcess3_5TransferSyntax);
+      transferSyntaxes.push_back(UID_JPEGProcess6_8TransferSyntax);
+      transferSyntaxes.push_back(UID_JPEGProcess7_9TransferSyntax);
+      transferSyntaxes.push_back(UID_JPEGProcess10_12TransferSyntax);
+      transferSyntaxes.push_back(UID_JPEGProcess11_13TransferSyntax);
+      transferSyntaxes.push_back(UID_JPEGProcess14TransferSyntax);
+      transferSyntaxes.push_back(UID_JPEGProcess15TransferSyntax);
+      transferSyntaxes.push_back(UID_JPEGProcess16_18TransferSyntax);
+      transferSyntaxes.push_back(UID_JPEGProcess17_19TransferSyntax);
+      transferSyntaxes.push_back(UID_JPEGProcess20_22TransferSyntax);
+      transferSyntaxes.push_back(UID_JPEGProcess21_23TransferSyntax);
+      transferSyntaxes.push_back(UID_JPEGProcess24_26TransferSyntax);
+      transferSyntaxes.push_back(UID_JPEGProcess25_27TransferSyntax);
+      transferSyntaxes.push_back(UID_JPEGProcess28TransferSyntax);
+      transferSyntaxes.push_back(UID_JPEGProcess29TransferSyntax);
+      transferSyntaxes.push_back(UID_JPEGProcess14SV1TransferSyntax);
+      transferSyntaxes.push_back(UID_JPEGLSLosslessTransferSyntax);
+      transferSyntaxes.push_back(UID_JPEGLSLossyTransferSyntax);
+      transferSyntaxes.push_back(UID_JPEG2000LosslessOnlyTransferSyntax);
+      transferSyntaxes.push_back(UID_JPEG2000TransferSyntax);
+      transferSyntaxes.push_back(UID_JPEG2000Part2MulticomponentImageCompressionLosslessOnlyTransferSyntax);
+      transferSyntaxes.push_back(UID_JPEG2000Part2MulticomponentImageCompressionTransferSyntax);
+      transferSyntaxes.push_back(UID_JPIPReferencedTransferSyntax);
+      transferSyntaxes.push_back(UID_JPIPReferencedDeflateTransferSyntax);
+      transferSyntaxes.push_back(UID_MPEG2MainProfileAtMainLevelTransferSyntax);
+      transferSyntaxes.push_back(UID_MPEG2MainProfileAtHighLevelTransferSyntax);
+      transferSyntaxes.push_back(UID_RLELosslessTransferSyntax);
+#endif
 
       /* accept the Verification SOP Class if presented */
-      cond = ASC_acceptContextsWithPreferredTransferSyntaxes( assoc->params, &knownAbstractSyntaxes[0], knownAbstractSyntaxes.size(), transferSyntaxes, numTransferSyntaxes);
+      cond = ASC_acceptContextsWithPreferredTransferSyntaxes( assoc->params, &knownAbstractSyntaxes[0], knownAbstractSyntaxes.size(), &transferSyntaxes[0], transferSyntaxes.size());
       if (cond.bad())
       {
         LOG(INFO) << cond.text();
@@ -282,7 +315,7 @@
       }
 
       /* the array of Storage SOP Class UIDs comes from dcuid.h */
-      cond = ASC_acceptContextsWithPreferredTransferSyntaxes( assoc->params, dcmAllStorageSOPClassUIDs, numberOfAllDcmStorageSOPClassUIDs, transferSyntaxes, numTransferSyntaxes);
+      cond = ASC_acceptContextsWithPreferredTransferSyntaxes( assoc->params, dcmAllStorageSOPClassUIDs, numberOfAllDcmStorageSOPClassUIDs, &transferSyntaxes[0], transferSyntaxes.size());
       if (cond.bad())
       {
         LOG(INFO) << cond.text();
@@ -293,7 +326,7 @@
 #if ORTHANC_PROMISCUOUS == 1
       /* accept everything not known not to be a storage SOP class */
       cond = acceptUnknownContextsWithPreferredTransferSyntaxes(
-        assoc->params, transferSyntaxes, numTransferSyntaxes);
+        assoc->params, &transferSyntaxes[0], transferSyntaxes.size());
       if (cond.bad())
       {
         LOG(INFO) << cond.text();