diff OrthancStone/Sources/Toolbox/DicomInstanceParameters.cpp @ 2169:fe5406abd43f

added separate class Windowing
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 21 Oct 2024 15:40:34 +0200
parents 16c01cc201e7
children 8e3c403cc643
line wrap: on
line diff
--- a/OrthancStone/Sources/Toolbox/DicomInstanceParameters.cpp	Wed Oct 09 12:50:10 2024 +0200
+++ b/OrthancStone/Sources/Toolbox/DicomInstanceParameters.cpp	Mon Oct 21 15:40:34 2024 +0200
@@ -190,29 +190,29 @@
       }
     }
 
-    bool ok = false;
+
+    windowingPresets_.clear();
+
+    Vector centers, widths;
     
-    if (LinearAlgebra::ParseVector(windowingPresetCenters_, dicom, Orthanc::DICOM_TAG_WINDOW_CENTER) &&
-        LinearAlgebra::ParseVector(windowingPresetWidths_, dicom, Orthanc::DICOM_TAG_WINDOW_WIDTH))
+    if (LinearAlgebra::ParseVector(centers, dicom, Orthanc::DICOM_TAG_WINDOW_CENTER) &&
+        LinearAlgebra::ParseVector(widths, dicom, Orthanc::DICOM_TAG_WINDOW_WIDTH))
     {
-      if (windowingPresetCenters_.size() == windowingPresetWidths_.size())
+      if (centers.size() == widths.size())
       {
-        ok = true;
+        windowingPresets_.resize(centers.size());
+
+        for (size_t i = 0; i < centers.size(); i++)
+        {
+          windowingPresets_[i] = Windowing(centers[i], widths[i]);
+        }
       }
       else
       {
         LOG(ERROR) << "Mismatch in the number of preset windowing widths/centers, ignoring this";
-        ok = false;
       }
     }
 
-    if (!ok)
-    {
-      // Don't use "Vector::clear()", as it has not the same meaning as "std::vector::clear()"
-      windowingPresetCenters_.resize(0);
-      windowingPresetWidths_.resize(0);
-    }      
-
     // This computes the "IndexInSeries" metadata from Orthanc (check
     // out "Orthanc::ServerIndex::Store()")
     hasIndexInSeries_ = (
@@ -399,18 +399,45 @@
   }
 
 
+  Windowing DicomInstanceParameters::GetFallbackWindowing() const
+  {
+    double a, b;
+    if (tags_->ParseDouble(a, Orthanc::DICOM_TAG_SMALLEST_IMAGE_PIXEL_VALUE) &&
+        tags_->ParseDouble(b, Orthanc::DICOM_TAG_LARGEST_IMAGE_PIXEL_VALUE))
+    {
+      const double center = (a + b) / 2.0f;
+      const double width = (b - a);
+      return Windowing(center, width);
+    }
+
+    // Added in Stone Web viewer > 2.5
+    uint32_t bitsStored, pixelRepresentation;
+    if (tags_->ParseUnsignedInteger32(bitsStored, Orthanc::DICOM_TAG_BITS_STORED) &&
+        tags_->ParseUnsignedInteger32(pixelRepresentation, Orthanc::DICOM_TAG_PIXEL_REPRESENTATION))
+    {
+      const bool isSigned = (pixelRepresentation != 0);
+      const float maximum = powf(2.0, bitsStored);
+      return Windowing(isSigned ? 0.0f : maximum / 2.0f, maximum);
+    }
+    else
+    {
+      // Cannot infer a suitable windowing from the available tags
+      return Windowing();
+    }
+  }
+
+
   size_t DicomInstanceParameters::GetWindowingPresetsCount() const
   {
-    assert(data_.windowingPresetCenters_.size() == data_.windowingPresetWidths_.size());
-    return data_.windowingPresetCenters_.size();
+    return data_.windowingPresets_.size();
   }
   
 
-  float DicomInstanceParameters::GetWindowingPresetCenter(size_t i) const
+  Windowing DicomInstanceParameters::GetWindowingPreset(size_t i) const
   {
     if (i < GetWindowingPresetsCount())
     {
-      return static_cast<float>(data_.windowingPresetCenters_[i]);
+      return data_.windowingPresets_[i];
     }
     else
     {
@@ -418,32 +445,8 @@
     }
   }
 
-
-  float DicomInstanceParameters::GetWindowingPresetWidth(size_t i) const
-  {
-    if (i < GetWindowingPresetsCount())
-    {
-      return static_cast<float>(data_.windowingPresetWidths_[i]);
-    }
-    else
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  static void GetWindowingBounds(float& low,
-                                 float& high,
-                                 double center,  // in
-                                 double width)   // in
-  {
-    low = static_cast<float>(center - width / 2.0);
-    high = static_cast<float>(center + width / 2.0);
-  }
-
   
-  void DicomInstanceParameters::GetWindowingPresetsUnion(float& center,
-                                                         float& width) const
+  Windowing DicomInstanceParameters::GetWindowingPresetsUnion() const
   {
     assert(tags_.get() != NULL);
     size_t s = GetWindowingPresetsCount();
@@ -452,48 +455,29 @@
     {
       // Use the largest windowing given all the preset windowings
       // that are available in the DICOM tags
-      float low, high;
-      GetWindowingBounds(low, high, GetWindowingPresetCenter(0), GetWindowingPresetWidth(0));
+      double low, high;
+      GetWindowingPreset(0).GetBounds(low, high);
 
       for (size_t i = 1; i < s; i++)
       {
-        float a, b;
-        GetWindowingBounds(a, b, GetWindowingPresetCenter(i), GetWindowingPresetWidth(i));
+        double a, b;
+        GetWindowingPreset(i).GetBounds(a, b);
         low = std::min(low, a);
         high = std::max(high, b);
       }
 
       assert(low <= high);
 
-      if (LinearAlgebra::IsNear(low, high))
+      if (!LinearAlgebra::IsNear(low, high))
       {
-        // Cannot infer a suitable windowing from the available tags
-        center = 128.0f;
-        width = 256.0f;
-      }
-      else
-      {
-        center = (low + high) / 2.0f;
-        width = (high - low);
+        const double center = (low + high) / 2.0f;
+        const double width = (high - low);
+        return Windowing(center, width);
       }
     }
-    else
-    {
-      float a, b;
-      if (tags_->ParseFloat(a, Orthanc::DICOM_TAG_SMALLEST_IMAGE_PIXEL_VALUE) &&
-          tags_->ParseFloat(b, Orthanc::DICOM_TAG_LARGEST_IMAGE_PIXEL_VALUE) &&
-          a < b)
-      {
-        center = (a + b) / 2.0f;
-        width = (b - a);
-      }
-      else
-      {
-        // Cannot infer a suitable windowing from the available tags
-        center = 128.0f;
-        width = 256.0f;
-      }
-    }
+
+    // No preset, or presets with an empty range
+    return GetFallbackWindowing();
   }
 
 
@@ -565,7 +549,8 @@
 
       if (GetWindowingPresetsCount() > 0)
       {
-        floatTexture.SetCustomWindowing(GetWindowingPresetCenter(0), GetWindowingPresetWidth(0));
+        Windowing preset = GetWindowingPreset(0);
+        floatTexture.SetCustomWindowing(preset.GetCenter(), preset.GetWidth());
       }
       
       switch (GetImageInformation().GetPhotometricInterpretation())