changeset 3205:6c86d4d407da

new in plugin sdk: OrthancPluginEncodeDicomWebJson() and OrthancPluginEncodeDicomWebXml()
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 06 Feb 2019 18:01:43 +0100
parents 8792867b739a
children d9e3d3340918
files NEWS Plugins/Engine/OrthancPlugins.cpp Plugins/Include/orthanc/OrthancCPlugin.h Plugins/Samples/Basic/Plugin.c
diffstat 4 files changed, 243 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Wed Feb 06 16:46:08 2019 +0100
+++ b/NEWS	Wed Feb 06 18:01:43 2019 +0100
@@ -22,7 +22,12 @@
 Plugins
 -------
 
-* New primitives in the plugin SDK to set and refresh metrics
+* New functions in the SDK:
+  - OrthancPluginSetMetricsValue() to set the value of a metrics
+  - OrthancPluginRegisterRefreshMetricsCallback() to ask to refresh metrics
+  - OrthancPluginEncodeDicomWebJson() to convert DICOM to "application/dicom+json"
+  - OrthancPluginEncodeDicomWebXml() to convert DICOM to "application/dicom+xml"
+* New function: 
 * New extensions in the database SDK: LookupResourceAndParent and GetAllMetadata
 
 Maintenance
--- a/Plugins/Engine/OrthancPlugins.cpp	Wed Feb 06 16:46:08 2019 +0100
+++ b/Plugins/Engine/OrthancPlugins.cpp	Wed Feb 06 18:01:43 2019 +0100
@@ -47,6 +47,7 @@
 #include "../../Core/Compression/GzipCompressor.h"
 #include "../../Core/Compression/ZlibCompressor.h"
 #include "../../Core/DicomFormat/DicomArray.h"
+#include "../../Core/DicomParsing/DicomWebJsonVisitor.h"
 #include "../../Core/DicomParsing/FromDcmtkBridge.h"
 #include "../../Core/DicomParsing/Internals/DicomImageDecoder.h"
 #include "../../Core/DicomParsing/ToDcmtkBridge.h"
@@ -313,6 +314,94 @@
         return parameters_[i];
       }
     };
+
+
+    class DicomWebBinaryFormatter : public DicomWebJsonVisitor::IBinaryFormatter
+    {
+    private:
+      OrthancPluginDicomWebBinaryCallback  callback_;
+      DicomWebJsonVisitor::BinaryMode      currentMode_;
+      std::string                          currentBulkDataUri_;
+
+      static void Setter(OrthancPluginDicomWebNode*       node,
+                         OrthancPluginDicomWebBinaryMode  mode,
+                         const char*                      bulkDataUri)
+      {
+        DicomWebBinaryFormatter& that = *reinterpret_cast<DicomWebBinaryFormatter*>(node);
+
+        switch (mode)
+        {
+          case OrthancPluginDicomWebBinaryMode_Ignore:
+            that.currentMode_ = DicomWebJsonVisitor::BinaryMode_Ignore;
+            break;
+              
+          case OrthancPluginDicomWebBinaryMode_InlineBinary:
+            that.currentMode_ = DicomWebJsonVisitor::BinaryMode_InlineBinary;
+            break;
+              
+          case OrthancPluginDicomWebBinaryMode_BulkDataUri:
+            if (bulkDataUri == NULL)
+            {
+              throw OrthancException(ErrorCode_NullPointer);
+            }              
+            
+            that.currentBulkDataUri_ = bulkDataUri;
+            that.currentMode_ = DicomWebJsonVisitor::BinaryMode_BulkDataUri;
+            break;
+
+          default:
+            throw OrthancException(ErrorCode_ParameterOutOfRange);
+        }
+      }
+      
+    public:
+      DicomWebBinaryFormatter(const _OrthancPluginEncodeDicomWeb& parameters) :
+        callback_(parameters.callback)
+      {
+      }
+      
+      virtual DicomWebJsonVisitor::BinaryMode Format(std::string& bulkDataUri,
+                                                     const std::vector<DicomTag>& parentTags,
+                                                     const std::vector<size_t>& parentIndexes,
+                                                     const DicomTag& tag,
+                                                     ValueRepresentation vr)
+      {
+        if (callback_ == NULL)
+        {
+          return DicomWebJsonVisitor::BinaryMode_InlineBinary;
+        }
+        else
+        {
+          assert(parentTags.size() == parentIndexes.size());
+          std::vector<uint16_t> groups(parentTags.size());
+          std::vector<uint16_t> elements(parentTags.size());
+          std::vector<uint32_t> indexes(parentTags.size());
+
+          for (size_t i = 0; i < parentTags.size(); i++)
+          {
+            groups[i] = parentTags[i].GetGroup();
+            elements[i] = parentTags[i].GetElement();
+            indexes[i] = static_cast<uint32_t>(parentIndexes[i]);
+          }
+          bool empty = parentTags.empty();
+
+          currentMode_ = DicomWebJsonVisitor::BinaryMode_Ignore;
+
+          callback_(reinterpret_cast<OrthancPluginDicomWebNode*>(this),
+                    DicomWebBinaryFormatter::Setter,
+                    static_cast<uint32_t>(parentTags.size()),
+                    (empty ? NULL : &groups[0]),
+                    (empty ? NULL : &elements[0]),
+                    (empty ? NULL : &indexes[0]),
+                    tag.GetGroup(),
+                    tag.GetElement(),
+                    Plugins::Convert(vr));
+
+          bulkDataUri = currentBulkDataUri_;          
+          return currentMode_;
+        }
+      }
+    };
   }
 
 
@@ -3140,6 +3229,37 @@
         return true;
       }
 
+      case _OrthancPluginService_EncodeDicomWebJson:
+      case _OrthancPluginService_EncodeDicomWebXml:
+      {
+        const _OrthancPluginEncodeDicomWeb& p =
+          *reinterpret_cast<const _OrthancPluginEncodeDicomWeb*>(parameters);
+
+        DicomWebBinaryFormatter formatter(p);
+        
+        DicomWebJsonVisitor visitor;
+        visitor.SetFormatter(formatter);
+
+        {
+          ParsedDicomFile dicom(p.dicom, p.dicomSize);
+          dicom.Apply(visitor);
+        }
+
+        std::string s;
+
+        if (service == _OrthancPluginService_EncodeDicomWebJson)
+        {
+          s = visitor.GetResult().toStyledString();
+        }
+        else
+        {
+          visitor.FormatXml(s);
+        }
+        
+        *p.target = CopyString(s);
+        return true;
+      }
+
       default:
         return false;
     }
--- a/Plugins/Include/orthanc/OrthancCPlugin.h	Wed Feb 06 16:46:08 2019 +0100
+++ b/Plugins/Include/orthanc/OrthancCPlugin.h	Wed Feb 06 18:01:43 2019 +0100
@@ -426,6 +426,8 @@
     _OrthancPluginService_RegisterPrivateDictionaryTag = 29,
     _OrthancPluginService_AutodetectMimeType = 30,
     _OrthancPluginService_SetMetricsValue = 31,
+    _OrthancPluginService_EncodeDicomWebJson = 32,
+    _OrthancPluginService_EncodeDicomWebXml = 33,
     
     /* Registration of callbacks */
     _OrthancPluginService_RegisterRestCallback = 1000,
@@ -6625,6 +6627,94 @@
     context->InvokeService(context, _OrthancPluginService_RegisterRefreshMetricsCallback, &params);
   }
 
+
+
+
+  typedef enum
+  {
+    OrthancPluginDicomWebBinaryMode_Ignore,
+    OrthancPluginDicomWebBinaryMode_InlineBinary,
+    OrthancPluginDicomWebBinaryMode_BulkDataUri
+  } OrthancPluginDicomWebBinaryMode;
+
+  
+  typedef struct _OrthancPluginDicomWebNode_t OrthancPluginDicomWebNode;
+
+  typedef void (*OrthancPluginDicomWebSetBinaryNode) (
+    OrthancPluginDicomWebNode*       node,
+    OrthancPluginDicomWebBinaryMode  mode,
+    const char*                      bulkDataUri);
+    
+  typedef OrthancPluginErrorCode (*OrthancPluginDicomWebBinaryCallback) (
+    OrthancPluginDicomWebNode*          node,
+    OrthancPluginDicomWebSetBinaryNode  setter,
+    uint32_t                            levelDepth,
+    const uint16_t*                     levelTagGroup,
+    const uint16_t*                     levelTagElement,
+    const uint32_t*                     levelIndex,
+    uint16_t                            tagGroup,
+    uint16_t                            tagElement,
+    OrthancPluginValueRepresentation    vr);
+
+  typedef struct
+  {
+    char**                               target;
+    const void*                          dicom;
+    uint32_t                             dicomSize;
+    OrthancPluginDicomWebBinaryCallback  callback;
+  } _OrthancPluginEncodeDicomWeb;
+
+  ORTHANC_PLUGIN_INLINE char* OrthancPluginEncodeDicomWebJson(
+    OrthancPluginContext*                context,
+    const void*                          dicom,
+    uint32_t                             dicomSize,
+    OrthancPluginDicomWebBinaryCallback  callback)
+  {
+    char* target = NULL;
+    
+    _OrthancPluginEncodeDicomWeb params;
+    params.target = &target;
+    params.dicom = dicom;
+    params.dicomSize = dicomSize;
+    params.callback = callback;
+
+    if (context->InvokeService(context, _OrthancPluginService_EncodeDicomWebJson, &params) != OrthancPluginErrorCode_Success)
+    {
+      /* Error */
+      return NULL;
+    }
+    else
+    {
+      return target;
+    }
+  }
+
+  ORTHANC_PLUGIN_INLINE char* OrthancPluginEncodeDicomWebXml(
+    OrthancPluginContext*                context,
+    const void*                          dicom,
+    uint32_t                             dicomSize,
+    OrthancPluginDicomWebBinaryCallback  callback)
+  {
+    char* target = NULL;
+    
+    _OrthancPluginEncodeDicomWeb params;
+    params.target = &target;
+    params.dicom = dicom;
+    params.dicomSize = dicomSize;
+    params.callback = callback;
+
+    if (context->InvokeService(context, _OrthancPluginService_EncodeDicomWebXml, &params) != OrthancPluginErrorCode_Success)
+    {
+      /* Error */
+      return NULL;
+    }
+    else
+    {
+      return target;
+    }
+  }
+  
+
 #ifdef  __cplusplus
 }
 #endif
--- a/Plugins/Samples/Basic/Plugin.c	Wed Feb 06 16:46:08 2019 +0100
+++ b/Plugins/Samples/Basic/Plugin.c	Wed Feb 06 18:01:43 2019 +0100
@@ -263,6 +263,21 @@
 }
 
 
+ORTHANC_PLUGINS_API OrthancPluginErrorCode DicomWebBinaryCallback(
+  OrthancPluginDicomWebNode*          node,
+  OrthancPluginDicomWebSetBinaryNode  setter,
+  uint32_t                            levelDepth,
+  const uint16_t*                     levelTagGroup,
+  const uint16_t*                     levelTagElement,
+  const uint32_t*                     levelIndex,
+  uint16_t                            tagGroup,
+  uint16_t                            tagElement,
+  OrthancPluginValueRepresentation    vr)
+{
+  setter(node, OrthancPluginDicomWebBinaryMode_BulkDataUri, "HelloURI");
+}
+
+
 ORTHANC_PLUGINS_API OrthancPluginErrorCode OnStoredCallback(OrthancPluginDicomInstance* instance,
                                                             const char* instanceId)
 {
@@ -286,9 +301,7 @@
   json = OrthancPluginGetInstanceSimplifiedJson(context, instance);
   if (first)
   {
-    /* Only print the first DICOM instance */
     printf("[%s]\n", json);
-    first = 0;
   }
   OrthancPluginFreeString(context, json);
 
@@ -301,6 +314,18 @@
     OrthancPluginLogError(context, "Instance has no reception date, should never happen!");
   }
 
+  json = OrthancPluginEncodeDicomWebXml(context,
+                                         OrthancPluginGetInstanceData(context, instance),
+                                         OrthancPluginGetInstanceSize(context, instance),
+                                         DicomWebBinaryCallback);
+  if (first)
+  {
+    printf("[%s]\n", json);
+    first = 0;    /* Only print the first DICOM instance */
+  }
+  OrthancPluginFreeString(context, json);
+  
+
   return OrthancPluginErrorCode_Success;
 }