changeset 1665:f62f685e0eb2

avoid loading instance metadata on RTSTRUCT to avoid JSON parsing that freezes the browser
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 19 Nov 2020 15:39:30 +0100
parents 32e765ca7193
children 1e6d3289b1ad
files Applications/StoneWebViewer/WebApplication/app.js Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp OrthancStone/Sources/Loaders/SeriesThumbnailsLoader.cpp OrthancStone/Sources/Loaders/SeriesThumbnailsLoader.h OrthancStone/Sources/StoneEnumerations.cpp OrthancStone/Sources/StoneEnumerations.h UnitTestsSources/UnitTestsMain.cpp
diffstat 7 files changed, 103 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/StoneWebViewer/WebApplication/app.js	Thu Nov 19 12:15:21 2020 +0100
+++ b/Applications/StoneWebViewer/WebApplication/app.js	Thu Nov 19 15:39:30 2020 +0100
@@ -611,7 +611,7 @@
   stone.Setup(Module);
   stone.SetOrthancRoot('..', true);
   stone.SetSoftwareRendering(localStorage.settingSoftwareRendering == '1');
-  console.warn('Native Stone properly intialized');
+  console.warn('Stone properly initialized');
 
   var study = getParameterFromUrl('study');
   var series = getParameterFromUrl('series');
--- a/Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp	Thu Nov 19 12:15:21 2020 +0100
+++ b/Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp	Thu Nov 19 15:39:30 2020 +0100
@@ -1857,16 +1857,28 @@
       observer_->SignalFrameUpdated(*this, cursor_->GetCurrentIndex(),
                                     frames_->GetFramesCount(), DisplayedFrameQuality_None);
     }
-    
+
     if (frames_->GetFramesCount() != 0)
     {
-      const std::string& sopInstanceUid = frames_->GetInstanceOfFrame(cursor_->GetCurrentIndex()).GetSopInstanceUid();
-
+      const OrthancStone::DicomInstanceParameters& centralInstance = frames_->GetInstanceOfFrame(cursor_->GetCurrentIndex());
+
+      /**
+       * Avoid loading metadata if we know that this cannot be a
+       * "true" image with pixel data. Retrieving instance metadata on
+       * RTSTRUCT can lead to very large JSON whose parsing will
+       * freeze the browser for several seconds.
+       **/
+      const OrthancStone::SopClassUid uid = centralInstance.GetSopClassUid();
+      if (uid != OrthancStone::SopClassUid_EncapsulatedPdf &&
+          uid != OrthancStone::SopClassUid_RTDose &&
+          uid != OrthancStone::SopClassUid_RTPlan &&
+          uid != OrthancStone::SopClassUid_RTStruct &&
+          GetSeriesThumbnailType(uid) != OrthancStone::SeriesThumbnailType_Video)
       {
         // Fetch the default windowing for the central instance
         const std::string uri = ("studies/" + frames_->GetStudyInstanceUid() +
                                  "/series/" + frames_->GetSeriesInstanceUid() +
-                                 "/instances/" + sopInstanceUid + "/metadata");
+                                 "/instances/" + centralInstance.GetSopInstanceUid() + "/metadata");
         
         loader_->ScheduleGetDicomWeb(
           boost::make_shared<OrthancStone::LoadedDicomResources>(Orthanc::DICOM_TAG_SOP_INSTANCE_UID),
@@ -2423,7 +2435,7 @@
 {
   int main(int argc, char const *argv[]) 
   {
-    printf("OK\n");
+    printf("Initializing Stone\n");
     Orthanc::InitializeFramework("", true);
     Orthanc::Logging::EnableInfoLevel(true);
     //Orthanc::Logging::EnableTraceLevel(true);
--- a/OrthancStone/Sources/Loaders/SeriesThumbnailsLoader.cpp	Thu Nov 19 12:15:21 2020 +0100
+++ b/OrthancStone/Sources/Loaders/SeriesThumbnailsLoader.cpp	Thu Nov 19 15:39:30 2020 +0100
@@ -45,25 +45,6 @@
 
 namespace OrthancStone
 {
-  static SeriesThumbnailType ExtractSopClassUid(const std::string& sopClassUid)
-  {
-    if (sopClassUid == "1.2.840.10008.5.1.4.1.1.104.1")  // Encapsulated PDF Storage
-    {
-      return SeriesThumbnailType_Pdf;
-    }
-    else if (sopClassUid == "1.2.840.10008.5.1.4.1.1.77.1.1.1" ||  // Video Endoscopic Image Storage
-             sopClassUid == "1.2.840.10008.5.1.4.1.1.77.1.2.1" ||  // Video Microscopic Image Storage
-             sopClassUid == "1.2.840.10008.5.1.4.1.1.77.1.4.1")    // Video Photographic Image Storage
-    {
-      return SeriesThumbnailType_Video;
-    }
-    else
-    {
-      return SeriesThumbnailType_Unsupported;
-    }
-  }
-
-
   SeriesThumbnailsLoader::Thumbnail::Thumbnail(const std::string& image,
                                                const std::string& mime) :
     type_(SeriesThumbnailType_Image),
@@ -259,7 +240,7 @@
 
           if (ok)
           {
-            type = ExtractSopClassUid(sopClassUid);
+            type = GetSeriesThumbnailType(StringToSopClassUid(sopClassUid));
           }
         }
 
@@ -370,7 +351,7 @@
     virtual void HandleSuccess(const std::string& body,
                                const std::map<std::string, std::string>& headers) ORTHANC_OVERRIDE
     {
-      SeriesThumbnailType type = ExtractSopClassUid(body);
+      SeriesThumbnailType type = GetSeriesThumbnailType(StringToSopClassUid(body));
 
       if (type == SeriesThumbnailType_Pdf ||
           type == SeriesThumbnailType_Video)
--- a/OrthancStone/Sources/Loaders/SeriesThumbnailsLoader.h	Thu Nov 19 12:15:21 2020 +0100
+++ b/OrthancStone/Sources/Loaders/SeriesThumbnailsLoader.h	Thu Nov 19 15:39:30 2020 +0100
@@ -40,16 +40,6 @@
 
 namespace OrthancStone
 {
-  enum SeriesThumbnailType
-  {
-    SeriesThumbnailType_NotLoaded = 1,  // The remote server cannot decode this image
-    SeriesThumbnailType_Unsupported = 2,  // The remote server cannot decode this image
-    SeriesThumbnailType_Pdf = 3,
-    SeriesThumbnailType_Video = 4,
-    SeriesThumbnailType_Image = 5
-  };
-  
-
   class SeriesThumbnailsLoader :
     public IObservable,
     public ObserverBase<SeriesThumbnailsLoader>
--- a/OrthancStone/Sources/StoneEnumerations.cpp	Thu Nov 19 12:15:21 2020 +0100
+++ b/OrthancStone/Sources/StoneEnumerations.cpp	Thu Nov 19 15:39:30 2020 +0100
@@ -36,6 +36,30 @@
     {
       return SopClassUid_RTDose;
     }
+    else if (s == "1.2.840.10008.5.1.4.1.1.481.5")
+    {
+      return SopClassUid_RTPlan;
+    }
+    else if (s == "1.2.840.10008.5.1.4.1.1.481.3")
+    {
+      return SopClassUid_RTStruct;
+    }
+    else if (s == "1.2.840.10008.5.1.4.1.1.104.1")
+    {
+      return SopClassUid_EncapsulatedPdf;
+    }
+    else if (s == "1.2.840.10008.5.1.4.1.1.77.1.1.1")
+    {
+      return SopClassUid_VideoEndoscopicImageStorage;
+    }      
+    else if (s == "1.2.840.10008.5.1.4.1.1.77.1.2.1")
+    {
+      return SopClassUid_VideoMicroscopicImageStorage;
+    }      
+    else if (s == "1.2.840.10008.5.1.4.1.1.77.1.4.1")
+    {
+      return SopClassUid_VideoPhotographicImageStorage;
+    }      
     else
     {
       //LOG(INFO) << "Other SOP class UID: " << source;
@@ -175,4 +199,22 @@
       }
     }
   }
+
+
+  SeriesThumbnailType GetSeriesThumbnailType(SopClassUid sopClassUid)
+  {
+    switch (sopClassUid)
+    {
+      case SopClassUid_EncapsulatedPdf:
+        return SeriesThumbnailType_Pdf;
+        
+      case SopClassUid_VideoEndoscopicImageStorage:
+      case SopClassUid_VideoMicroscopicImageStorage:
+      case SopClassUid_VideoPhotographicImageStorage:
+        return SeriesThumbnailType_Video;
+
+      default:
+        return SeriesThumbnailType_Unsupported;
+    }
+  }
 }
--- a/OrthancStone/Sources/StoneEnumerations.h	Thu Nov 19 12:15:21 2020 +0100
+++ b/OrthancStone/Sources/StoneEnumerations.h	Thu Nov 19 15:39:30 2020 +0100
@@ -108,7 +108,22 @@
   enum SopClassUid
   {
     SopClassUid_Other,
-    SopClassUid_RTDose
+    SopClassUid_RTDose,
+    SopClassUid_RTStruct,
+    SopClassUid_RTPlan,
+    SopClassUid_EncapsulatedPdf,
+    SopClassUid_VideoEndoscopicImageStorage,
+    SopClassUid_VideoMicroscopicImageStorage,
+    SopClassUid_VideoPhotographicImageStorage
+  };
+
+  enum SeriesThumbnailType
+  {
+    SeriesThumbnailType_NotLoaded = 1,  // The remote server cannot decode this image
+    SeriesThumbnailType_Unsupported = 2,  // The remote server cannot decode this image
+    SeriesThumbnailType_Pdf = 3,
+    SeriesThumbnailType_Video = 4,
+    SeriesThumbnailType_Image = 5
   };
 
   enum BitmapAnchor
@@ -156,4 +171,6 @@
                                 unsigned int bitmapWidth,
                                 unsigned int bitmapHeight,
                                 unsigned int border = 0);
+
+  SeriesThumbnailType GetSeriesThumbnailType(SopClassUid sopClassUid);
 }
--- a/UnitTestsSources/UnitTestsMain.cpp	Thu Nov 19 12:15:21 2020 +0100
+++ b/UnitTestsSources/UnitTestsMain.cpp	Thu Nov 19 15:39:30 2020 +0100
@@ -940,6 +940,29 @@
 }
 
 
+TEST(Enumerations, Basic)
+{
+  using namespace OrthancStone;
+  ASSERT_EQ(SopClassUid_EncapsulatedPdf, StringToSopClassUid("1.2.840.10008.5.1.4.1.1.104.1"));
+  ASSERT_EQ(SopClassUid_RTStruct, StringToSopClassUid("1.2.840.10008.5.1.4.1.1.481.3"));
+  ASSERT_EQ(SopClassUid_RTDose, StringToSopClassUid("1.2.840.10008.5.1.4.1.1.481.2"));
+  ASSERT_EQ(SopClassUid_RTPlan, StringToSopClassUid("1.2.840.10008.5.1.4.1.1.481.5"));
+  ASSERT_EQ(SopClassUid_VideoEndoscopicImageStorage, StringToSopClassUid("1.2.840.10008.5.1.4.1.1.77.1.1.1"));
+  ASSERT_EQ(SopClassUid_VideoMicroscopicImageStorage, StringToSopClassUid("1.2.840.10008.5.1.4.1.1.77.1.2.1"));
+  ASSERT_EQ(SopClassUid_VideoPhotographicImageStorage, StringToSopClassUid("1.2.840.10008.5.1.4.1.1.77.1.4.1"));
+  ASSERT_EQ(SopClassUid_Other, StringToSopClassUid("nope"));
+
+  ASSERT_EQ(SeriesThumbnailType_Pdf, GetSeriesThumbnailType(SopClassUid_EncapsulatedPdf));
+  ASSERT_EQ(SeriesThumbnailType_Video, GetSeriesThumbnailType(SopClassUid_VideoEndoscopicImageStorage));
+  ASSERT_EQ(SeriesThumbnailType_Video, GetSeriesThumbnailType(SopClassUid_VideoMicroscopicImageStorage));
+  ASSERT_EQ(SeriesThumbnailType_Video, GetSeriesThumbnailType(SopClassUid_VideoPhotographicImageStorage));
+  ASSERT_EQ(SeriesThumbnailType_Unsupported, GetSeriesThumbnailType(SopClassUid_Other));
+  ASSERT_EQ(SeriesThumbnailType_Unsupported, GetSeriesThumbnailType(SopClassUid_RTDose));
+  ASSERT_EQ(SeriesThumbnailType_Unsupported, GetSeriesThumbnailType(SopClassUid_RTStruct));
+  ASSERT_EQ(SeriesThumbnailType_Unsupported, GetSeriesThumbnailType(SopClassUid_RTPlan));
+}
+
+
 int main(int argc, char **argv)
 {
   Orthanc::Logging::Initialize();