changeset 1110:b82b74d13830 broker

ParseDicomFileCommand
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 31 Oct 2019 15:05:46 +0100
parents 79b1b541fe15
children 3730956f41a5
files Framework/Oracle/GenericOracleRunner.cpp Framework/Oracle/IOracleCommand.h Framework/Oracle/ParseDicomFileCommand.cpp Framework/Oracle/ParseDicomFileCommand.h Resources/CMake/OrthancStoneConfiguration.cmake
diffstat 5 files changed, 212 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/Oracle/GenericOracleRunner.cpp	Wed Oct 30 11:56:10 2019 +0100
+++ b/Framework/Oracle/GenericOracleRunner.cpp	Thu Oct 31 15:05:46 2019 +0100
@@ -21,6 +21,10 @@
 
 #include "GenericOracleRunner.h"
 
+#if !defined(ORTHANC_ENABLE_DCMTK)
+#  error The macro ORTHANC_ENABLE_DCMTK must be defined
+#endif
+
 #include "CustomOracleCommand.h"
 #include "GetOrthancImageCommand.h"
 #include "GetOrthancWebViewerJpegCommand.h"
@@ -29,6 +33,11 @@
 #include "OrthancRestApiCommand.h"
 #include "ReadFileCommand.h"
 
+#if ORTHANC_ENABLE_DCMTK == 1
+#  include "ParseDicomFileCommand.h"
+#  include <dcmtk/dcmdata/dcdeftag.h>
+#endif
+
 #include <Core/Compression/GzipCompressor.h>
 #include <Core/HttpClient.h>
 #include <Core/OrthancException.h>
@@ -37,6 +46,7 @@
 
 #include <boost/filesystem.hpp>
 
+
 namespace OrthancStone
 {
   static void CopyHttpHeaders(Orthanc::HttpClient& client,
@@ -182,27 +192,80 @@
   }
 
 
+  static std::string GetPath(const std::string& root,
+                             const std::string& file)
+  {
+    boost::filesystem::path a(root);
+    boost::filesystem::path b(file);
+
+    boost::filesystem::path c;
+    if (b.is_absolute())
+    {
+      c = b;
+    }
+    else
+    {
+      c = a / b;
+    }
+
+    LOG(INFO) << "Oracle reading file: " << c.string();
+    return c.string();
+  }
+
+
   static IMessage* Execute(const std::string& root,
                            const ReadFileCommand& command)
   {
-    boost::filesystem::path a(root);
-    boost::filesystem::path b(command.GetPath());
+    std::string path = GetPath(root, command.GetPath());
+
+    std::string content;
+    Orthanc::SystemToolbox::ReadFile(content, path, true /* log */);
+
+    return new ReadFileCommand::SuccessMessage(command, content);
+  }
+
 
-    boost::filesystem::path path;
-    if (b.is_absolute())
+#if ORTHANC_ENABLE_DCMTK == 1
+  static IMessage* Execute(const std::string& root,
+                           const ParseDicomFileCommand& command)
+  {
+    std::string path = GetPath(root, command.GetPath());
+
+    DcmFileFormat f;
+    bool ok;
+
+    if (command.IsPixelDataIncluded())
     {
-      path = b;
+      ok = f.loadFile(path.c_str()).good();
     }
     else
     {
-      path = a / b;
+#if DCMTK_VERSION_NUMBER >= 362
+      // NB : We could stop at (0x3007, 0x0000) instead of
+      // DCM_PixelData, cf. the Orthanc::DICOM_TAG_* constants
+
+      static const DcmTagKey STOP = DCM_PixelData;
+      //static const DcmTagKey STOP(0x3007, 0x0000);
+
+      ok = f.loadFileUntilTag(path.c_str(), EXS_Unknown, EGL_noChange,
+                              DCM_MaxReadLength, ERM_autoDetect, STOP).good();
+#else
+      // The primitive "loadFileUntilTag" was introduced in DCMTK 3.6.2
+      ok = f.loadFile(path.c_str()).good();
+#endif
     }
 
-    std::string content;
-    Orthanc::SystemToolbox::ReadFile(content, path.string(), true /* log */);
-
-    return new ReadFileCommand::SuccessMessage(command, content);
+    if (ok)
+    {
+      return new ParseDicomFileCommand::SuccessMessage(command, f);
+    }
+    else
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat,
+                                      "Cannot parse file: " + path);
+    }
   }
+#endif
 
 
   IMessage* GenericOracleRunner::Run(IOracleCommand& command)
@@ -233,6 +296,14 @@
         case IOracleCommand::Type_ReadFile:
           return Execute(rootDirectory_, dynamic_cast<const ReadFileCommand&>(command));
 
+        case IOracleCommand::Type_ParseDicomFile:
+#if ORTHANC_ENABLE_DCMTK == 1
+          return Execute(rootDirectory_, dynamic_cast<const ParseDicomFileCommand&>(command));
+#else
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented,
+                                          "DCMTK must be enabled to parse DICOM files");
+#endif
+
         default:
           throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
       }
--- a/Framework/Oracle/IOracleCommand.h	Wed Oct 30 11:56:10 2019 +0100
+++ b/Framework/Oracle/IOracleCommand.h	Thu Oct 31 15:05:46 2019 +0100
@@ -35,6 +35,7 @@
       Type_GetOrthancWebViewerJpeg,
       Type_Http,
       Type_OrthancRestApi,
+      Type_ParseDicomFile,
       Type_ReadFile,
       Type_Sleep
     };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Framework/Oracle/ParseDicomFileCommand.cpp	Thu Oct 31 15:05:46 2019 +0100
@@ -0,0 +1,32 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2019 Osimis S.A., Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Affero General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "ParseDicomFileCommand.h"
+
+namespace OrthancStone
+{
+  ParseDicomFileCommand::SuccessMessage::SuccessMessage(const ParseDicomFileCommand& command,
+                                                        DcmFileFormat& content) :
+    OriginMessage(command)
+  {
+    dicom_.reset(new Orthanc::ParsedDicomFile(content));
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Framework/Oracle/ParseDicomFileCommand.h	Thu Oct 31 15:05:46 2019 +0100
@@ -0,0 +1,92 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2019 Osimis S.A., Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Affero General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#if !defined(ORTHANC_ENABLE_DCMTK)
+#  error The macro ORTHANC_ENABLE_DCMTK must be defined
+#endif
+
+#if ORTHANC_ENABLE_DCMTK != 1
+#  error Support for DCMTK must be enabled to use ParseDicomFileCommand
+#endif
+
+#include "../Messages/IMessage.h"
+#include "OracleCommandWithPayload.h"
+
+#include <Core/DicomParsing/ParsedDicomFile.h>
+
+#include <dcmtk/dcmdata/dcfilefo.h>
+
+namespace OrthancStone
+{
+  class ParseDicomFileCommand : public OracleCommandWithPayload
+  {
+  public:
+    class SuccessMessage : public OriginMessage<ParseDicomFileCommand>
+    {
+      ORTHANC_STONE_MESSAGE(__FILE__, __LINE__);
+
+    private:
+      std::auto_ptr<Orthanc::ParsedDicomFile>  dicom_;
+
+    public:
+      SuccessMessage(const ParseDicomFileCommand& command,
+                     DcmFileFormat& content);
+
+      const Orthanc::ParsedDicomFile& GetDicom() const
+      {
+        return *dicom_;
+      }
+    };
+
+  private:
+    std::string  path_;
+    bool         pixelDataIncluded_;
+
+  public:
+    ParseDicomFileCommand(const std::string& path) :
+      path_(path),
+      pixelDataIncluded_(true)
+    {
+    }
+
+    virtual Type GetType() const
+    {
+      return Type_ParseDicomFile;
+    }
+
+    const std::string& GetPath() const
+    {
+      return path_;
+    }
+
+    bool IsPixelDataIncluded() const
+    {
+      return pixelDataIncluded_;
+    }
+
+    void SetPixelDataIncluded(bool included)
+    {
+      pixelDataIncluded_ = included;
+    }
+  };
+}
--- a/Resources/CMake/OrthancStoneConfiguration.cmake	Wed Oct 30 11:56:10 2019 +0100
+++ b/Resources/CMake/OrthancStoneConfiguration.cmake	Thu Oct 31 15:05:46 2019 +0100
@@ -399,6 +399,12 @@
 endif()
 
 
+if (ENABLE_DCMTK)
+  list(APPEND ORTHANC_STONE_SOURCES
+    ${ORTHANC_STONE_ROOT}/Framework/Oracle/ParseDicomFileCommand.cpp
+    )
+endif()
+
 if (ENABLE_THREADS)
   list(APPEND ORTHANC_STONE_SOURCES
     ${ORTHANC_STONE_ROOT}/Framework/Messages/LockingEmitter.cpp