diff OrthancStone/Sources/Toolbox/DicomInstanceParameters.cpp @ 2171:8e3c403cc643

Improved support of the (0028,9132) tag for Philips multiframe images
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 22 Oct 2024 15:40:40 +0200
parents fe5406abd43f
children 2410a171ebfb
line wrap: on
line diff
--- a/OrthancStone/Sources/Toolbox/DicomInstanceParameters.cpp	Mon Oct 21 16:02:28 2024 +0200
+++ b/OrthancStone/Sources/Toolbox/DicomInstanceParameters.cpp	Tue Oct 22 15:40:40 2024 +0200
@@ -32,6 +32,7 @@
 #include <Images/ImageProcessing.h>
 #include <Logging.h>
 #include <OrthancException.h>
+#include <SerializationToolbox.h>
 #include <Toolbox.h>
 
 
@@ -230,6 +231,65 @@
     {
       instanceNumber_ = 0;
     }
+
+
+    static const Orthanc::DicomTag DICOM_TAG_PER_FRAME_FUNCTIONAL_GROUPS_SEQUENCE(0x5200, 0x9230);
+    static const Orthanc::DicomTag DICOM_TAG_FRAME_VOI_LUT_SEQUENCE_ATTRIBUTE(0x0028, 0x9132);
+
+    const Orthanc::DicomValue* frames = dicom.TestAndGetValue(DICOM_TAG_PER_FRAME_FUNCTIONAL_GROUPS_SEQUENCE);
+    if (frames != NULL &&
+        hasNumberOfFrames_ &&
+        frames->IsSequence())
+    {
+      /**
+       * New in Stone Web viewer 2.2: Deal with Philips multiframe
+       * (cf. mail from Tomas Kenda on 2021-08-17). This cannot be done
+       * in LoadSeriesDetailsFromInstance, as the "Per Frame Functional Groups Sequence"
+       * is not available at that point.
+       **/
+
+      const Json::Value& sequence = frames->GetSequenceContent();
+
+      perFrameWindowing_.resize(numberOfFrames_);
+
+      // This corresponds to "ParsedDicomFile::GetDefaultWindowing()"
+      for (Json::ArrayIndex i = 0; i < sequence.size(); i++)
+      {
+        if (i < numberOfFrames_ &&
+            sequence[i].isMember(DICOM_TAG_FRAME_VOI_LUT_SEQUENCE_ATTRIBUTE.Format()))
+        {
+          const Json::Value& v = sequence[i][DICOM_TAG_FRAME_VOI_LUT_SEQUENCE_ATTRIBUTE.Format()];
+
+          static const char* KEY_VALUE = "Value";
+
+          if (v.isMember(KEY_VALUE) &&
+              v[KEY_VALUE].type() == Json::arrayValue &&
+              v[KEY_VALUE].size() >= 1 &&
+              v[KEY_VALUE][0].isMember(Orthanc::DICOM_TAG_WINDOW_CENTER.Format()) &&
+              v[KEY_VALUE][0].isMember(Orthanc::DICOM_TAG_WINDOW_WIDTH.Format()) &&
+              v[KEY_VALUE][0][Orthanc::DICOM_TAG_WINDOW_CENTER.Format()].isMember(KEY_VALUE) &&
+              v[KEY_VALUE][0][Orthanc::DICOM_TAG_WINDOW_WIDTH.Format()].isMember(KEY_VALUE))
+          {
+            const Json::Value& scenter = v[KEY_VALUE][0][Orthanc::DICOM_TAG_WINDOW_CENTER.Format()][KEY_VALUE];
+            const Json::Value& swidth = v[KEY_VALUE][0][Orthanc::DICOM_TAG_WINDOW_WIDTH.Format()][KEY_VALUE];
+
+            double center, width;
+            if (scenter.isString() &&
+                swidth.isString() &&
+                Orthanc::SerializationToolbox::ParseDouble(center, scenter.asString()) &&
+                Orthanc::SerializationToolbox::ParseDouble(width, swidth.asString()))
+            {
+              perFrameWindowing_[i] = Windowing(center, width);
+            }
+            else if (scenter.isNumeric() &&
+                     swidth.isNumeric())
+            {
+              perFrameWindowing_[i] = Windowing(scenter.asDouble(), swidth.asDouble());
+            }
+          }
+        }
+      }
+    }
   }
 
 
@@ -824,4 +884,19 @@
       return (data_.frameOffsets_[0] > data_.frameOffsets_[1]);
     }
   }
+
+
+  bool DicomInstanceParameters::LookupPerFrameWindowing(Windowing& windowing,
+                                                        unsigned int frame) const
+  {
+    if (frame < data_.perFrameWindowing_.size())
+    {
+      windowing = data_.perFrameWindowing_[frame];
+      return true;
+    }
+    else
+    {
+      return false;
+    }
+  }
 }