changeset 252:13b8e4c3c5bd

DicomWebFormatter::HttpWriter
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 26 Feb 2019 17:05:30 +0100
parents 768634772ad7
children 172ddccbbc1a
files Plugin/DicomWebFormatter.cpp Plugin/DicomWebFormatter.h Plugin/QidoRs.cpp Plugin/WadoRs.cpp
diffstat 4 files changed, 136 insertions(+), 61 deletions(-) [+]
line wrap: on
line diff
--- a/Plugin/DicomWebFormatter.cpp	Tue Feb 26 16:37:30 2019 +0100
+++ b/Plugin/DicomWebFormatter.cpp	Tue Feb 26 17:05:30 2019 +0100
@@ -45,24 +45,40 @@
                                    uint16_t tagElement,
                                    OrthancPluginValueRepresentation vr)
   {
-    std::string uri = GetSingleton().bulkRoot_;
+    const DicomWebFormatter& that = GetSingleton();
 
-    for (size_t i = 0; i < levelDepth; i++)
+    switch (that.mode_)
     {
-      uri += ("/" + FormatTag(levelTagGroup[i], levelTagElement[i]) + "/" +
-              boost::lexical_cast<std::string>(levelIndex[i] + 1));
-    }
+      case OrthancPluginDicomWebBinaryMode_Ignore:
+      case OrthancPluginDicomWebBinaryMode_InlineBinary:
+        setter(node, that.mode_, NULL);
+        break;
+
+      case OrthancPluginDicomWebBinaryMode_BulkDataUri:
+      {
+        std::string uri = GetSingleton().bulkRoot_;
+
+        for (size_t i = 0; i < levelDepth; i++)
+        {
+          uri += ("/" + FormatTag(levelTagGroup[i], levelTagElement[i]) + "/" +
+                  boost::lexical_cast<std::string>(levelIndex[i] + 1));
+        }
     
-    uri += "/" + FormatTag(tagGroup, tagElement);
+        uri += "/" + FormatTag(tagGroup, tagElement);
     
-    setter(node, OrthancPluginDicomWebBinaryMode_BulkDataUri, uri.c_str());
+        setter(node, that.mode_, uri.c_str());
+        break;
+      }
+    }
   }
 
 
-  DicomWebFormatter::Locker::Locker(const std::string& bulkRoot) :
+  DicomWebFormatter::Locker::Locker(OrthancPluginDicomWebBinaryMode mode,
+                                    const std::string& bulkRoot) :
     that_(GetSingleton()),
     lock_(that_.mutex_)
   {
+    that_.mode_ = mode;
     that_.bulkRoot_ = bulkRoot;
   }
 
@@ -86,4 +102,73 @@
 
     s.ToString(target);
   }
+
+
+  DicomWebFormatter::HttpWriter::HttpWriter(OrthancPluginRestOutput* output,
+                                            bool isXml) :
+    context_(OrthancPlugins::GetGlobalContext()),
+    output_(output),
+    isXml_(isXml),
+    first_(true)
+  {
+    if (context_ == NULL ||
+        output_ == NULL)
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
+    }
+
+    if (isXml_)
+    {
+      OrthancPluginStartMultipartAnswer(context_, output_, "related", "application/dicom+xml");
+    }
+    else
+    {
+      jsonBuffer_.AddChunk("[");
+    }
+  }
+
+
+  void DicomWebFormatter::HttpWriter::AddRawDicom(const void* dicom,
+                                                  size_t size,
+                                                  OrthancPluginDicomWebBinaryMode mode,
+                                                  const std::string& bulkRoot)
+  {
+    if (!first_ &&
+        !isXml_)
+    {
+      jsonBuffer_.AddChunk(",");      
+    }
+
+    first_ = false;
+
+    std::string item;
+
+    {
+      // TODO - Avoid a global mutex => Need to change Orthanc SDK
+      OrthancPlugins::DicomWebFormatter::Locker locker(mode, bulkRoot);
+      locker.Apply(item, context_, dicom, size, isXml_);
+    }
+   
+    if (isXml_)
+    {
+      OrthancPluginSendMultipartItem(context_, output_, item.c_str(), item.size());
+    }
+    else
+    {
+      jsonBuffer_.AddChunk(item);
+    }
+  }
+
+
+  void DicomWebFormatter::HttpWriter::Send()
+  {
+    if (!isXml_)
+    {
+      jsonBuffer_.AddChunk("]");
+      
+      std::string answer;
+      jsonBuffer_.Flatten(answer);
+      OrthancPluginAnswerBuffer(context_, output_, answer.c_str(), answer.size(), "application/dicom+json");
+    }
+  }
 }
--- a/Plugin/DicomWebFormatter.h	Tue Feb 26 16:37:30 2019 +0100
+++ b/Plugin/DicomWebFormatter.h	Tue Feb 26 17:05:30 2019 +0100
@@ -21,6 +21,8 @@
 
 #pragma once
 
+#include <Core/ChunkedBuffer.h>
+
 #include <orthanc/OrthancCPlugin.h>
 
 #include <boost/noncopyable.hpp>
@@ -32,8 +34,9 @@
   class DicomWebFormatter : public boost::noncopyable
   {
   private:
-    boost::mutex  mutex_;
-    std::string   bulkRoot_;
+    boost::mutex                     mutex_;
+    OrthancPluginDicomWebBinaryMode  mode_;
+    std::string                      bulkRoot_;
 
     static DicomWebFormatter& GetSingleton()
     {
@@ -59,7 +62,8 @@
       boost::mutex::scoped_lock  lock_;
 
     public:
-      Locker(const std::string& bulkRoot);
+      Locker(OrthancPluginDicomWebBinaryMode mode,
+             const std::string& bulkRoot);
 
       void Apply(std::string& target,
                  OrthancPluginContext* context,
@@ -67,5 +71,26 @@
                  size_t size,
                  bool xml);
     };
+
+    class HttpWriter : public boost::noncopyable
+    {
+    private:
+      OrthancPluginContext*     context_;
+      OrthancPluginRestOutput*  output_;
+      bool                      isXml_;
+      bool                      first_;
+      Orthanc::ChunkedBuffer    jsonBuffer_;
+
+    public:
+      HttpWriter(OrthancPluginRestOutput* output,
+                 bool isXml);
+
+      void AddRawDicom(const void* dicom,
+                       size_t size,
+                       OrthancPluginDicomWebBinaryMode mode,
+                       const std::string& bulkRoot);
+
+      void Send();
+    };
   };
 }
--- a/Plugin/QidoRs.cpp	Tue Feb 26 16:37:30 2019 +0100
+++ b/Plugin/QidoRs.cpp	Tue Feb 26 17:05:30 2019 +0100
@@ -302,11 +302,10 @@
           if (OrthancPlugins::RestApiGet(series, "/studies/" + resource + "/series?expand", false) &&
               OrthancPlugins::RestApiGet(instances, "/studies/" + resource + "/instances", false))
           {
-            // Number of Study Related Series
-            target[Orthanc::DicomTag(0x0020, 0x1206)] = boost::lexical_cast<std::string>(series.size());
-
-            // Number of Study Related Instances
-            target[Orthanc::DicomTag(0x0020, 0x1208)] = boost::lexical_cast<std::string>(instances.size());
+            target[Orthanc::DICOM_TAG_NUMBER_OF_STUDY_RELATED_SERIES] = 
+              boost::lexical_cast<std::string>(series.size());
+            target[Orthanc::DICOM_TAG_NUMBER_OF_STUDY_RELATED_INSTANCES] = 
+              boost::lexical_cast<std::string>(instances.size());
 
             // Collect the Modality of all the child series
             std::set<std::string> modalities;
@@ -331,13 +330,13 @@
               s += *it;
             }
 
-            target[Orthanc::DicomTag(0x0008, 0x0061)] = s;  // Modalities in Study
+            target[Orthanc::DICOM_TAG_MODALITIES_IN_STUDY] = s;
           }
           else
           {
-            target[Orthanc::DicomTag(0x0008, 0x0061)] = "";   // Modalities in Study
-            target[Orthanc::DicomTag(0x0020, 0x1206)] = "0";  // Number of Study Related Series
-            target[Orthanc::DicomTag(0x0020, 0x1208)] = "0";  // Number of Study Related Instances
+            target[Orthanc::DICOM_TAG_MODALITIES_IN_STUDY] = "";
+            target[Orthanc::DICOM_TAG_NUMBER_OF_STUDY_RELATED_SERIES] = "0";
+            target[Orthanc::DICOM_TAG_NUMBER_OF_STUDY_RELATED_INSTANCES] = "0"; 
           }
 
           break;
@@ -349,11 +348,12 @@
           if (OrthancPlugins::RestApiGet(instances, "/series/" + resource + "/instances", false))
           {
             // Number of Series Related Instances
-            target[Orthanc::DicomTag(0x0020, 0x1209)] = boost::lexical_cast<std::string>(instances.size());
+            target[Orthanc::DICOM_TAG_NUMBER_OF_SERIES_RELATED_INSTANCES] = 
+              boost::lexical_cast<std::string>(instances.size());
           }
           else
           {
-            target[Orthanc::DicomTag(0x0020, 0x1209)] = "0";  // Number of Series Related Instances
+            target[Orthanc::DICOM_TAG_NUMBER_OF_SERIES_RELATED_INSTANCES] = "0";
           }
 
           break;
--- a/Plugin/WadoRs.cpp	Tue Feb 26 16:37:30 2019 +0100
+++ b/Plugin/WadoRs.cpp	Tue Feb 26 17:05:30 2019 +0100
@@ -310,15 +310,7 @@
 
   const std::string wadoBase = OrthancPlugins::Configuration::GetBaseUrl(request);
 
-  // For JSON
-  Orthanc::ChunkedBuffer buffer;
-  buffer.AddChunk("[");
-  bool first = true;
-
-  if (isXml)
-  {
-    OrthancPluginStartMultipartAnswer(context, output, "related", "application/dicom+xml");
-  }
+  OrthancPlugins::DicomWebFormatter::HttpWriter writer(output, isXml);
 
   for (std::list<std::string>::const_iterator
          it = instances.begin(); it != instances.end(); ++it)
@@ -334,40 +326,13 @@
       OrthancPlugins::MemoryBuffer dicom;
       if (dicom.RestApiGet("/instances/" + *it + "/file", false))
       {
-        std::string item;
-        
-        {
-          // TODO - Avoid a global mutex
-          OrthancPlugins::DicomWebFormatter::Locker locker(bulkRoot);
-          locker.Apply(item, context, dicom.GetData(), dicom.GetSize(), isXml);
-        }
-
-        if (isXml)
-        {
-          OrthancPluginSendMultipartItem(context, output, item.c_str(), item.size());
-        }
-        else
-        {
-          if (!first)
-          {
-            buffer.AddChunk(",");
-            first = false;
-          }
-
-          buffer.AddChunk(item);
-        }
+        writer.AddRawDicom(dicom.GetData(), dicom.GetSize(), 
+                           OrthancPluginDicomWebBinaryMode_BulkDataUri, bulkRoot);
       }
     }
   }
 
-  if (!isXml)
-  {
-    buffer.AddChunk("]");
-
-    std::string answer;
-    buffer.Flatten(answer);
-    OrthancPluginAnswerBuffer(context, output, answer.c_str(), answer.size(), "application/dicom+json");
-  }
+  writer.Send();
 }