changeset 56:83cd735c885d

speedup the loading of DICOM sources
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 24 Nov 2016 15:41:21 +0100
parents b6432a00b103
children 91fc9583b2de
files Framework/Inputs/DicomPyramid.cpp Framework/Inputs/DicomPyramidInstance.cpp Framework/Inputs/DicomPyramidInstance.h Framework/Inputs/DicomPyramidLevel.cpp Framework/Inputs/DicomPyramidLevel.h
diffstat 5 files changed, 41 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/Inputs/DicomPyramid.cpp	Thu Nov 24 14:44:11 2016 +0100
+++ b/Framework/Inputs/DicomPyramid.cpp	Thu Nov 24 15:41:21 2016 +0100
@@ -108,8 +108,7 @@
     {
       const DicomPyramidInstance& b = *instances_[i];
 
-      if (a.GetImageCompression() != b.GetImageCompression() ||
-          a.GetPixelFormat() != b.GetPixelFormat() ||
+      if (a.GetPixelFormat() != b.GetPixelFormat() ||
           a.GetTileWidth() != b.GetTileWidth() ||
           a.GetTileHeight() != b.GetTileHeight() ||
           a.GetTotalWidth() < b.GetTotalWidth() ||
@@ -226,7 +225,7 @@
   ImageCompression DicomPyramid::GetImageCompression() const
   {
     assert(!instances_.empty() && instances_[0] != NULL);
-    return instances_[0]->GetImageCompression();
+    return instances_[0]->GetImageCompression(orthanc_);
   }
 
 
--- a/Framework/Inputs/DicomPyramidInstance.cpp	Thu Nov 24 14:44:11 2016 +0100
+++ b/Framework/Inputs/DicomPyramidInstance.cpp	Thu Nov 24 15:41:21 2016 +0100
@@ -91,14 +91,38 @@
     }
   }
 
+
+  ImageCompression  DicomPyramidInstance::GetImageCompression(IOrthancConnection& orthanc)
+  {
+    /**
+     * Lazy detection of the image compression using the transfer
+     * syntax stored inside the DICOM header. Given the fact that
+     * reading the header is a time-consuming operation (it implies
+     * the decoding of the DICOM image by Orthanc, whereas the "/tags"
+     * endpoint only reads the "DICOM-as-JSON" attachment), the
+     * "/header" REST call is delayed until it is really required.
+     **/
+
+    if (!hasCompression_)
+    {
+      Json::Value header;
+      IOrthancConnection::RestApiGet(header, orthanc, "/instances/" + instanceId_ + "/header?simplify");
+
+      hasCompression_ = true;
+      compression_ = DetectImageCompression(header);
+    }
+
+    return compression_;
+  }
+
   
   DicomPyramidInstance::DicomPyramidInstance(IOrthancConnection&  orthanc,
                                              const std::string& instanceId) :
-    instanceId_(instanceId)
+    instanceId_(instanceId),
+    hasCompression_(false)
   {
-    Json::Value dicom, header;
+    Json::Value dicom;
     IOrthancConnection::RestApiGet(dicom, orthanc, "/instances/" + instanceId + "/tags?simplify");
-    IOrthancConnection::RestApiGet(header, orthanc, "/instances/" + instanceId + "/header?simplify");
 
     if (DicomToolbox::GetMandatoryStringTag(dicom, "SOPClassUID") != "1.2.840.10008.5.1.4.1.1.77.1.6" ||
         DicomToolbox::GetMandatoryStringTag(dicom, "Modality") != "SM")
@@ -106,7 +130,6 @@
       throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
     }
 
-    compression_ = DetectImageCompression(header);
     format_ = DetectPixelFormat(dicom);
     tileWidth_ = DicomToolbox::GetUnsignedIntegerTag(dicom, "Columns");
     tileHeight_ = DicomToolbox::GetUnsignedIntegerTag(dicom, "Rows");
--- a/Framework/Inputs/DicomPyramidInstance.h	Thu Nov 24 14:44:11 2016 +0100
+++ b/Framework/Inputs/DicomPyramidInstance.h	Thu Nov 24 15:41:21 2016 +0100
@@ -34,6 +34,7 @@
     typedef std::pair<unsigned int, unsigned int>  FrameLocation;
 
     std::string                 instanceId_;
+    bool                        hasCompression_;
     ImageCompression            compression_;
     Orthanc::PixelFormat        format_;
     unsigned int                tileWidth_;
@@ -51,10 +52,7 @@
       return instanceId_;
     }
 
-    ImageCompression GetImageCompression() const
-    {
-      return compression_;
-    }
+    ImageCompression GetImageCompression(IOrthancConnection& orthanc);
 
     Orthanc::PixelFormat GetPixelFormat() const
     {
--- a/Framework/Inputs/DicomPyramidLevel.cpp	Thu Nov 24 14:44:11 2016 +0100
+++ b/Framework/Inputs/DicomPyramidLevel.cpp	Thu Nov 24 15:41:21 2016 +0100
@@ -41,7 +41,7 @@
     return tiles_[tileY * countTilesX_ + tileX];
   }
 
-  void DicomPyramidLevel::RegisterFrame(const DicomPyramidInstance& instance,
+  void DicomPyramidLevel::RegisterFrame(DicomPyramidInstance& instance,
                                         unsigned int frame)
   {
     unsigned int tileX = instance.GetFrameLocationX(frame);
@@ -79,7 +79,7 @@
   }
 
 
-  DicomPyramidLevel::DicomPyramidLevel(const DicomPyramidInstance& instance) :
+  DicomPyramidLevel::DicomPyramidLevel(DicomPyramidInstance& instance) :
     totalWidth_(instance.GetTotalWidth()),
     totalHeight_(instance.GetTotalHeight()),
     tileWidth_(instance.GetTileWidth()),
@@ -99,7 +99,7 @@
   }
 
 
-  void DicomPyramidLevel::AddInstance(const DicomPyramidInstance& instance)
+  void DicomPyramidLevel::AddInstance(DicomPyramidInstance& instance)
   {
     if (instance.GetTotalWidth() != totalWidth_ ||
         instance.GetTotalHeight() != totalHeight_ ||
@@ -127,14 +127,14 @@
     if (LookupTile(tile, tileX, tileY))
     {
       assert(tile.instance_ != NULL);
-      const DicomPyramidInstance& instance = *tile.instance_;
+      DicomPyramidInstance& instance = *tile.instance_;
 
       std::string uri = ("/instances/" + instance.GetInstanceId() + 
                          "/frames/" + boost::lexical_cast<std::string>(tile.frame_) + "/raw");
 
       orthanc.RestApiGet(raw, uri);
 
-      compression = instance.GetImageCompression();
+      compression = instance.GetImageCompression(orthanc);
       format = instance.GetPixelFormat();
 
       return true;
--- a/Framework/Inputs/DicomPyramidLevel.h	Thu Nov 24 14:44:11 2016 +0100
+++ b/Framework/Inputs/DicomPyramidLevel.h	Thu Nov 24 15:41:21 2016 +0100
@@ -31,8 +31,8 @@
   private:
     struct TileContent
     {
-      const DicomPyramidInstance*  instance_;
-      unsigned int                 frame_;
+      DicomPyramidInstance*  instance_;
+      unsigned int           frame_;
 
       TileContent() : 
         instance_(NULL),
@@ -52,7 +52,7 @@
     TileContent& GetTileContent(unsigned int tileX,
                                 unsigned int tileY);
 
-    void RegisterFrame(const DicomPyramidInstance& instance,
+    void RegisterFrame(DicomPyramidInstance& instance,
                        unsigned int frame);
 
     bool LookupTile(TileContent& tile,
@@ -60,9 +60,9 @@
                     unsigned int tileY) const;
 
   public:
-    DicomPyramidLevel(const DicomPyramidInstance& instance);
+    DicomPyramidLevel(DicomPyramidInstance& instance);
 
-    void AddInstance(const DicomPyramidInstance& instance);
+    void AddInstance(DicomPyramidInstance& instance);
 
     unsigned int GetTotalWidth() const
     {