changeset 91:2bd3bf4d95bb

Content-Location header
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 09 Dec 2015 17:12:24 +0100
parents cb86c0518d74
children 85609146eb16
files NEWS Plugin/Dicom.cpp Plugin/Dicom.h Plugin/WadoRs.cpp Status.txt UnitTestsSources/UnitTestsMain.cpp
diffstat 6 files changed, 90 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Wed Dec 09 16:29:31 2015 +0100
+++ b/NEWS	Wed Dec 09 17:12:24 2015 +0100
@@ -4,11 +4,11 @@
 
 => Minimum SDK version: 0.9.5 <=
 
+* Support of WADO-RS - RetrieveFrames
 * QIDO-RS now takes advantage of "/tools/find"
 * Upgrade to GDCM 2.6.0 for static and Windows builds
 
 
-
 Version 0.1 (2015/08/03)
 ========================
 
--- a/Plugin/Dicom.cpp	Wed Dec 09 16:29:31 2015 +0100
+++ b/Plugin/Dicom.cpp	Wed Dec 09 17:12:24 2015 +0100
@@ -20,16 +20,17 @@
 
 #include "Dicom.h"
 
+#include "Plugin.h"
 #include "ChunkedBuffer.h"
 
+#include "../Orthanc/Core/OrthancException.h"
+#include "../Orthanc/Core/Toolbox.h"
+
 #include <gdcmDictEntry.h>
 #include <gdcmStringFilter.h>
 #include <boost/lexical_cast.hpp>
 #include <json/writer.h>
 
-#include "../Orthanc/Core/OrthancException.h"
-#include "../Orthanc/Core/Toolbox.h"
-
 namespace OrthancPlugins
 {
   namespace
@@ -56,6 +57,35 @@
   }
 
 
+  static std::string MyStripSpaces(const std::string& source)
+  {
+    size_t first = 0;
+
+    while (first < source.length() &&
+           (isspace(source[first]) || 
+            source[first] == '\0'))
+    {
+      first++;
+    }
+
+    if (first == source.length())
+    {
+      // String containing only spaces
+      return "";
+    }
+
+    size_t last = source.length();
+    while (last > first &&
+           (isspace(source[last - 1]) ||
+            source[last - 1] == '\0'))
+    {
+      last--;
+    }          
+    
+    assert(first <= last);
+    return source.substr(first, last - first);
+  }
+
 
   static const char* GetVRName(bool& isSequence,
                                const gdcm::Dict& dictionary,
@@ -138,7 +168,7 @@
       result = Orthanc::Toolbox::ConvertToUtf8(tmp, sourceEncoding);
     }
 
-    result = Orthanc::Toolbox::StripSpaces(result);
+    result = MyStripSpaces(result);
     return true;
   }
 
@@ -181,7 +211,7 @@
 
         if (stripSpaces)
         {
-          result = Orthanc::Toolbox::StripSpaces(result);
+          result = MyStripSpaces(result);
         }
 
         return true;
@@ -235,7 +265,7 @@
 
     if (stripSpaces)
     {
-      result = Orthanc::Toolbox::StripSpaces(result);
+      result = MyStripSpaces(result);
     }
 
     return true;
@@ -320,8 +350,8 @@
   }
 
 
-  static std::string GetBulkUriRoot(const std::string& wadoBase,
-                                    const gdcm::DataSet& dicom)
+  static std::string GetWadoUrl(const std::string& wadoBase,
+                                const gdcm::DataSet& dicom)
   {
     std::string study, series, instance;
 
@@ -333,7 +363,7 @@
     }
     else
     {
-      return wadoBase + "studies/" + study + "/series/" + series + "/instances/" + instance + "/bulk/";
+      return wadoBase + "studies/" + study + "/series/" + series + "/instances/" + instance + "/";
     }
   }
 
@@ -356,7 +386,7 @@
     }
 
     std::string tmp(data->GetPointer(), data->GetLength());
-    tmp = Orthanc::Toolbox::StripSpaces(tmp);
+    tmp = MyStripSpaces(tmp);
 
     Orthanc::Encoding encoding;
     if (Orthanc::GetDicomEncoding(encoding, tmp.c_str()))
@@ -583,7 +613,7 @@
     std::string bulkUriRoot;
     if (isBulkAccessible)
     {
-      bulkUriRoot = GetBulkUriRoot(wadoBase, dicom);
+      bulkUriRoot = GetWadoUrl(wadoBase, dicom) + "bulk/";
     }
 
     if (isXml)
@@ -620,4 +650,11 @@
     OrthancPluginAnswerBuffer(context, output, answer.c_str(), answer.size(), 
                               isXml ? "application/dicom+xml" : "application/json");
   }
+
+
+  std::string ParsedDicomFile::GetWadoUrl(const OrthancPluginHttpRequest* request) const
+  {
+    const std::string base = OrthancPlugins::Configuration::GetBaseUrl(configuration_, request);
+    return OrthancPlugins::GetWadoUrl(base, GetDataSet());
+  }
 }
--- a/Plugin/Dicom.h	Wed Dec 09 16:29:31 2015 +0100
+++ b/Plugin/Dicom.h	Wed Dec 09 17:12:24 2015 +0100
@@ -94,6 +94,8 @@
                        const gdcm::Tag& tag) const;
 
     Orthanc::Encoding  GetEncoding() const;
+
+    std::string GetWadoUrl(const OrthancPluginHttpRequest* request) const;
   };
 
 
--- a/Plugin/WadoRs.cpp	Wed Dec 09 16:29:31 2015 +0100
+++ b/Plugin/WadoRs.cpp	Wed Dec 09 17:12:24 2015 +0100
@@ -857,7 +857,35 @@
 }
 
 
+
+static void AnswerSingleFrame(OrthancPluginRestOutput* output,
+                              const OrthancPluginHttpRequest* request,
+                              const OrthancPlugins::ParsedDicomFile& dicom,
+                              const char* frame,
+                              size_t size,
+                              unsigned int frameIndex)
+{
+  OrthancPluginErrorCode error;
+
+#if HAS_SEND_MULTIPART_ITEM_2 == 1
+  std::string location = dicom.GetWadoUrl(request) + "frames/" + boost::lexical_cast<std::string>(frameIndex + 1);
+  const char *keys[] = { "Content-Location" };
+  const char *values[] = { location.c_str() };
+  error = OrthancPluginSendMultipartItem2(context_, output, frame, size, 1, keys, values);
+#else
+  error = OrthancPluginSendMultipartItem(context_, output, frame, size);
+#endif
+
+  if (error != OrthancPluginErrorCode_Success)
+  {
+    throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol);      
+  }
+}
+
+
+
 static bool AnswerFrames(OrthancPluginRestOutput* output,
+                         const OrthancPluginHttpRequest* request,
                          const OrthancPlugins::ParsedDicomFile& dicom,
                          const gdcm::TransferSyntax& syntax,
                          const std::list<unsigned int>& frames)
@@ -918,12 +946,7 @@
       else
       {
         const char* p = buffer + (*frame) * frameSize;
-
-        // TODO SET Content-Location
-        if (OrthancPluginSendMultipartItem(context_, output, p, frameSize) != OrthancPluginErrorCode_Success)
-        {
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol);      
-        }
+        AnswerSingleFrame(output, request, dicom, p, frameSize, *frame);
       }
     }
   }
@@ -943,13 +966,9 @@
       }
       else
       {
-        // TODO SET Content-Location
-        if (OrthancPluginSendMultipartItem(context_, output,
-                                           fragments->GetFragment(*frame).GetByteValue()->GetPointer(),
-                                           fragments->GetFragment(*frame).GetByteValue()->GetLength()) != OrthancPluginErrorCode_Success)
-        {
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol);      
-        }
+        AnswerSingleFrame(output, request, dicom,
+                          fragments->GetFragment(*frame).GetByteValue()->GetPointer(),
+                          fragments->GetFragment(*frame).GetByteValue()->GetLength(), *frame);
       }
     }
   }
@@ -958,6 +977,7 @@
 }
 
 
+
 OrthancPluginErrorCode RetrieveFrames(OrthancPluginRestOutput* output,
                                       const char* url,
                                       const OrthancPluginHttpRequest* request)
@@ -1017,7 +1037,7 @@
         source.reset(new OrthancPlugins::ParsedDicomFile(content));
       }
 
-      AnswerFrames(output, *source, targetSyntax, frames);
+      AnswerFrames(output, request, *source, targetSyntax, frames);
     }
     else
     {
@@ -1061,7 +1081,7 @@
       }
 
       OrthancPlugins::ParsedDicomFile transcoded(ss.str());
-      AnswerFrames(output, transcoded, targetSyntax, frames);
+      AnswerFrames(output, request, transcoded, targetSyntax, frames);
     }
   }    
 
--- a/Status.txt	Wed Dec 09 16:29:31 2015 +0100
+++ b/Status.txt	Wed Dec 09 17:12:24 2015 +0100
@@ -50,7 +50,9 @@
 6.5.4 WADO-RS / RetrieveFrames
 ================================
 
-Not supported.
+Almost entirely supported.
+
+The only missing feature is returning multi-frame media types (cf. Table 6.5-1).
 
 
 
--- a/UnitTestsSources/UnitTestsMain.cpp	Wed Dec 09 16:29:31 2015 +0100
+++ b/UnitTestsSources/UnitTestsMain.cpp	Wed Dec 09 17:12:24 2015 +0100
@@ -26,6 +26,7 @@
 
 using namespace OrthancPlugins;
 
+Json::Value configuration_ = Json::objectValue;
 
 
 TEST(ContentType, Parse)