diff Plugin/Plugin.cpp @ 133:3251ec958a29

Option "RestrictTransferSyntaxes" saying which transfer syntaxes should be decoded with GDCM
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 09 Jun 2016 17:04:58 +0200
parents 5754d39b011d
children 16f8471e3872
line wrap: on
line diff
--- a/Plugin/Plugin.cpp	Tue May 31 12:12:59 2016 +0200
+++ b/Plugin/Plugin.cpp	Thu Jun 09 17:04:58 2016 +0200
@@ -24,6 +24,7 @@
 #include <boost/filesystem.hpp>
 
 #include "../Orthanc/Core/OrthancException.h"
+#include "../Orthanc/Core/DicomFormat/DicomMap.h"
 #include "ViewerToolbox.h"
 #include "ViewerPrefetchPolicy.h"
 #include "DecodedImageAdapter.h"
@@ -33,7 +34,8 @@
 
 
 static OrthancPluginContext* context_ = NULL;
-
+static bool restrictTransferSyntaxes_ = false;
+static std::set<std::string> enabledTransferSyntaxes_;
 
 
 class CacheContext
@@ -323,6 +325,80 @@
 }
 
 
+
+static bool ExtractTransferSyntax(std::string& transferSyntax,
+                                  const void* dicom,
+                                  const uint32_t size)
+{
+  Orthanc::DicomMap header;
+  if (!Orthanc::DicomMap::ParseDicomMetaInformation(header, reinterpret_cast<const char*>(dicom), size))
+  {
+    return false;
+  }
+
+  const Orthanc::DicomValue* tag = header.TestAndGetValue(0x0002, 0x0010);
+  if (tag == NULL ||
+      tag->IsNull() ||
+      tag->IsBinary())
+  {
+    return false;
+  }
+  else
+  {
+    // Stripping spaces should not be required, as this is a UI value
+    // representation whose stripping is supported by the Orthanc
+    // core, but let's be careful...
+    transferSyntax = Orthanc::Toolbox::StripSpaces(tag->GetContent());
+    return true;
+  }
+}
+
+
+static bool IsTransferSyntaxEnabled(const void* dicom,
+                                    const uint32_t size)
+{
+  std::string formattedSize;
+
+  {
+    char tmp[16];
+    sprintf(tmp, "%0.1fMB", static_cast<float>(size) / (1024.0f * 1024.0f));
+    formattedSize.assign(tmp);
+  }
+
+  if (!restrictTransferSyntaxes_)
+  {
+    std::string s = "Decoding one DICOM instance of " + formattedSize + " using GDCM";
+    OrthancPluginLogInfo(context_, s.c_str());
+    return true;
+  }
+
+  std::string transferSyntax;
+  if (!ExtractTransferSyntax(transferSyntax, dicom, size))
+  {
+    std::string s = ("Cannot extract the transfer syntax of this instance of " + 
+                     formattedSize + ", will use GDCM to decode it");
+    OrthancPluginLogInfo(context_, s.c_str());
+    return true;
+  }
+
+  if (enabledTransferSyntaxes_.find(transferSyntax) != enabledTransferSyntaxes_.end())
+  {
+    // Decoding for this transfer syntax is enabled
+    std::string s = ("Using GDCM to decode this instance of " + 
+                     formattedSize + " with transfer syntax " + transferSyntax);
+    OrthancPluginLogInfo(context_, s.c_str());
+    return true;
+  }
+  else
+  {
+    std::string s = ("Won't use GDCM to decode this instance of " + 
+                     formattedSize + ", as its transfer syntax " + transferSyntax + " is disabled");
+    OrthancPluginLogInfo(context_, s.c_str());
+    return false;
+  }
+}
+
+
 static OrthancPluginErrorCode DecodeImageCallback(OrthancPluginImage** target,
                                                   const void* dicom,
                                                   const uint32_t size,
@@ -330,6 +406,12 @@
 {
   try
   {
+    if (!IsTransferSyntaxEnabled(dicom, size))
+    {
+      *target = NULL;
+      return OrthancPluginErrorCode_Success;
+    }
+
     std::auto_ptr<OrthancPlugins::OrthancImageWrapper> image;
 
 #if 0
@@ -364,6 +446,91 @@
 }
 
 
+void ParseConfiguration(bool& enableGdcm,
+                        int& decodingThreads,
+                        boost::filesystem::path& cachePath,
+                        int& cacheSize)
+{
+  /* Read the configuration of the Web viewer */
+  Json::Value configuration;
+  if (!OrthancPlugins::ReadConfiguration(configuration, context_))
+  {
+    throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);    
+  }
+
+  // By default, the cache of the Web viewer is located inside the
+  // "StorageDirectory" of Orthanc
+  cachePath = OrthancPlugins::GetStringValue(configuration, "StorageDirectory", ".");
+  cachePath /= "WebViewerCache";
+
+  static const char* CONFIG_WEB_VIEWER = "WebViewer";
+  if (configuration.isMember(CONFIG_WEB_VIEWER))
+  {
+
+    std::string key = "CachePath";
+    if (!configuration[CONFIG_WEB_VIEWER].isMember(key))
+    {
+      // For backward compatibility with the initial release of the Web viewer
+      key = "Cache";
+    }
+
+    cachePath = OrthancPlugins::GetStringValue(configuration[CONFIG_WEB_VIEWER], key, cachePath.string());
+    cacheSize = OrthancPlugins::GetIntegerValue(configuration[CONFIG_WEB_VIEWER], "CacheSize", cacheSize);
+    decodingThreads = OrthancPlugins::GetIntegerValue(configuration[CONFIG_WEB_VIEWER], "Threads", decodingThreads);
+
+    static const char* CONFIG_ENABLE_GDCM = "EnableGdcm";
+    if (configuration[CONFIG_WEB_VIEWER].isMember(CONFIG_ENABLE_GDCM))
+    {
+      if (configuration[CONFIG_WEB_VIEWER][CONFIG_ENABLE_GDCM].type() != Json::booleanValue)
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
+      }
+      else
+      {
+        enableGdcm = configuration[CONFIG_WEB_VIEWER][CONFIG_ENABLE_GDCM].asBool();
+      }
+    }
+
+    static const char* CONFIG_RESTRICT_TRANSFER_SYNTAXES = "RestrictTransferSyntaxes";
+    if (enableGdcm)
+    {
+      if (configuration[CONFIG_WEB_VIEWER].isMember(CONFIG_RESTRICT_TRANSFER_SYNTAXES))
+      {
+        const Json::Value& config = configuration[CONFIG_WEB_VIEWER][CONFIG_RESTRICT_TRANSFER_SYNTAXES];
+
+        if (config.type() != Json::arrayValue)
+        {
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
+        }
+
+        restrictTransferSyntaxes_ = true;
+        for (Json::Value::ArrayIndex i = 0; i < config.size(); i++)
+        {
+          if (config[i].type() != Json::stringValue)
+          {
+            throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
+          }
+          else
+          {
+            std::string s = "Web viewer will use GDCM to decode transfer syntax " + config[i].asString();
+            enabledTransferSyntaxes_.insert(config[i].asString());
+            OrthancPluginLogWarning(context_, s.c_str());
+          }
+        }
+      }
+    }
+  }
+
+  if (decodingThreads <= 0 ||
+      cacheSize <= 0)
+  {
+    throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+  }
+
+}
+
+
+
 extern "C"
 {
   ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* context)
@@ -400,53 +567,18 @@
     /* By default, use GDCM */
     bool enableGdcm = true;
 
+    /* By default, a cache of 100 MB is used */
+    int cacheSize = 100; 
 
     try
     {
-      /* Read the configuration of the Web viewer */
-      Json::Value configuration;
-      if (!ReadConfiguration(configuration, context))
-      {
-        OrthancPluginLogError(context_, "Unable to read the configuration file of Orthanc");
-        return -1;
-      }
-
-      // By default, the cache of the Web viewer is located inside the
-      // "StorageDirectory" of Orthanc
-      boost::filesystem::path cachePath = GetStringValue(configuration, "StorageDirectory", ".");
-      cachePath /= "WebViewerCache";
-      int cacheSize = 100;  // By default, a cache of 100 MB is used
-
-      if (configuration.isMember("WebViewer"))
-      {
-        std::string key = "CachePath";
-        if (!configuration["WebViewer"].isMember(key))
-        {
-          // For backward compatibility with the initial release of the Web viewer
-          key = "Cache";
-        }
-
-        cachePath = GetStringValue(configuration["WebViewer"], key, cachePath.string());
-        cacheSize = GetIntegerValue(configuration["WebViewer"], "CacheSize", cacheSize);
-        decodingThreads = GetIntegerValue(configuration["WebViewer"], "Threads", decodingThreads);
-
-        if (configuration["WebViewer"].isMember("EnableGdcm") &&
-            configuration["WebViewer"]["EnableGdcm"].type() == Json::booleanValue)
-        {
-          enableGdcm = configuration["WebViewer"]["EnableGdcm"].asBool();
-        }
-      }
+      boost::filesystem::path cachePath;
+      ParseConfiguration(enableGdcm, decodingThreads, cachePath, cacheSize);
 
       std::string message = ("Web viewer using " + boost::lexical_cast<std::string>(decodingThreads) + 
                              " threads for the decoding of the DICOM images");
       OrthancPluginLogWarning(context_, message.c_str());
 
-      if (decodingThreads <= 0 ||
-          cacheSize <= 0)
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
-      }
-
       message = "Storing the cache of the Web viewer in folder: " + cachePath.string();
       OrthancPluginLogWarning(context_, message.c_str());
 
@@ -515,7 +647,14 @@
     }
     catch (Orthanc::OrthancException& e)
     {
-      OrthancPluginLogError(context_, e.What());
+      if (e.GetErrorCode() == Orthanc::ErrorCode_BadFileFormat)
+      {
+        OrthancPluginLogError(context_, "Unable to read the configuration of the Web viewer plugin");
+      }
+      else
+      {
+        OrthancPluginLogError(context_, e.What());
+      }
       return -1;
     }