changeset 570:524f2543d23f

Speeded up instance metadata retrieval using OrthancPluginLoadDicomInstance() from SDK 1.12.1
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 26 Jun 2023 14:10:18 +0200 (2023-06-26)
parents 22f1c41518eb
children c56c1037f1d1
files NEWS Plugin/DicomWebFormatter.cpp Plugin/DicomWebFormatter.h Plugin/WadoRs.cpp
diffstat 4 files changed, 95 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Mon Jun 26 14:06:23 2023 +0200
+++ b/NEWS	Mon Jun 26 14:10:18 2023 +0200
@@ -1,9 +1,10 @@
 Pending changes in the mainline
 ===============================
 
+* Speeded up instance metadata retrieval using OrthancPluginLoadDicomInstance() from SDK 1.12.1
 * Support "X-Forwarded-Host" and "X-Forwarded-Proto" headers to compute BulkDataURI.
-* small speed-up the studies/../series/../metadata route when in "MainDicomTags" mode.
-* new "Experimental" mode for "SeriesMetadata" that is fetching tags from the DB or
+* Small speed-up the studies/../series/../metadata route when in "MainDicomTags" mode.
+* New "Experimental" mode for "SeriesMetadata" that is fetching tags from the DB or
   from the storage if they are missing (useful if you recently changed the "ExtraMainDicomTags"
   configuration)
 
@@ -11,14 +12,14 @@
 Version 1.13 (2023-02-03)
 =========================
 
-* Use Orthanc SDK 1.11.3 to avoid a crash in Stow-RS jobs.
+* Use Orthanc SDK 1.11.3 to avoid a crash in STOW-RS jobs.
 
 
 Version 1.12 (2022-10-27)
 =========================
 
-* Stow-RS now calls to the plugin flavored /instances route and now also forwards
-  the HTTP headers from the Incoming Stow-RS request.
+* STOW-RS now calls to the plugin flavored /instances route and now also forwards
+  the HTTP headers from the Incoming STOW-RS request.
 
 
 Version 1.11 (2022-10-13)
@@ -32,7 +33,7 @@
 
 * speed-up the /metadata routes by a factor of 2 when in "MainDicomTags" or "Extrapolate"
   mode.
-* improved HTTP status code for Stow-RS (now returning 202 instead of 200 if some instances 
+* improved HTTP status code for STOW-RS (now returning 202 instead of 200 if some instances 
   could not be ingested).  Also reporting a Failure Reason "out of resources 0xA700"  if
   new instances can not be ingested because storage is full.
 
--- a/Plugin/DicomWebFormatter.cpp	Mon Jun 26 14:06:23 2023 +0200
+++ b/Plugin/DicomWebFormatter.cpp	Mon Jun 26 14:10:18 2023 +0200
@@ -87,7 +87,7 @@
                                 const std::string& bulkRoot)
   {
     DicomWebFormatter payload(mode, bulkRoot);
-    
+
     OrthancString s;
 
     if (xml)
@@ -124,6 +124,38 @@
   }
 
 
+  void DicomWebFormatter::Apply(std::string& target,
+                                OrthancPluginContext* context,
+                                const DicomInstance& instance,
+                                bool xml,
+                                OrthancPluginDicomWebBinaryMode mode,
+                                const std::string& bulkRoot)
+  {
+    DicomWebFormatter payload(mode, bulkRoot);
+
+    OrthancString s;
+
+    if (xml)
+    {
+      s.Assign(OrthancPluginGetInstanceDicomWebXml(context, instance.GetObject(), Callback, &payload));
+    }
+    else
+    {
+      s.Assign(OrthancPluginGetInstanceDicomWebJson(context, instance.GetObject(), Callback, &payload));
+    }
+
+    if (s.GetContent() == NULL)
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError,
+                                      "Cannot convert DICOM to DICOMweb");
+    }
+    else
+    {
+      s.ToString(target);
+    }
+  }
+
+
   DicomWebFormatter::HttpWriter::HttpWriter(OrthancPluginRestOutput* output,
                                             bool isXml) :
     context_(GetGlobalContext()),
@@ -297,4 +329,30 @@
       OrthancPluginAnswerBuffer(context_, output_, answer.c_str(), answer.size(), "application/dicom+json");
     }
   }
+
+
+  void DicomWebFormatter::HttpWriter::AddInstance(const DicomInstance& instance,
+                                                  const std::string& bulkRoot)
+  {
+    if (!first_ &&
+        !isXml_)
+    {
+      jsonBuffer_.AddChunk(",");
+    }
+
+    first_ = false;
+
+    std::string item;
+
+    DicomWebFormatter::Apply(item, context_, instance, isXml_, OrthancPluginDicomWebBinaryMode_BulkDataUri, bulkRoot);
+   
+    if (isXml_)
+    {
+      OrthancPluginSendMultipartItem(context_, output_, item.c_str(), item.size());
+    }
+    else
+    {
+      jsonBuffer_.AddChunk(item);
+    }
+  }
 }
--- a/Plugin/DicomWebFormatter.h	Mon Jun 26 14:06:23 2023 +0200
+++ b/Plugin/DicomWebFormatter.h	Mon Jun 26 14:10:18 2023 +0200
@@ -24,7 +24,7 @@
 #include <ChunkedBuffer.h>
 #include <DicomFormat/DicomMap.h>
 
-#include <orthanc/OrthancCPlugin.h>
+#include "../Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h"
 
 #include <json/value.h>
 
@@ -73,6 +73,13 @@
                       OrthancPluginDicomWebBinaryMode mode,
                       const std::string& bulkRoot);
 
+    static void Apply(std::string& target,
+                      OrthancPluginContext* context,
+                      const DicomInstance& instance,
+                      bool xml,
+                      OrthancPluginDicomWebBinaryMode mode,
+                      const std::string& bulkRoot);
+
     class HttpWriter : public boost::noncopyable
     {
     private:
@@ -111,6 +118,9 @@
                                      size_t size);
 
       void Send();
+
+      void AddInstance(const DicomInstance& instance,
+                       const std::string& bulkRoot);
     };
   };
 }
--- a/Plugin/WadoRs.cpp	Mon Jun 26 14:06:23 2023 +0200
+++ b/Plugin/WadoRs.cpp	Mon Jun 26 14:10:18 2023 +0200
@@ -822,14 +822,31 @@
                                     "/series/" + seriesInstanceUid + 
                                     "/instances/" + dicom.GetStringValue(Orthanc::DICOM_TAG_SOP_INSTANCE_UID, "", false) + "/bulk");
 
+#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 1)
+      std::unique_ptr<OrthancPlugins::DicomInstance> instance;
+
+      try
+      {
+        instance.reset(OrthancPlugins::DicomInstance::Load(orthancId, OrthancPluginLoadDicomInstanceMode_EmptyPixelData));
+      }
+      catch (Orthanc::OrthancException& e)
+      {
+      }
+
+      if (instance.get() != NULL)
+      {
+        writer.AddInstance(*instance, bulkRoot);
+      }
+#else
       // On a SSD drive, this version is twice slower than if using
       // cache (see below)
-    
+
       OrthancPlugins::MemoryBuffer dicomFile;
       if (dicomFile.RestApiGet("/instances/" + orthancId + "/file", false))
       {
         writer.AddDicom(dicomFile.GetData(), dicomFile.GetSize(), bulkRoot);
       }
+#endif
 
       break;
     }