diff Framework/Toolbox/DicomFrameConverter.cpp @ 119:ba83e38cf3ff wasm

rendering of rt-dose
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 02 Oct 2017 22:01:41 +0200
parents a4d0b6c82b29
children 063f7f3d9f14
line wrap: on
line diff
--- a/Framework/Toolbox/DicomFrameConverter.cpp	Mon Oct 02 14:31:26 2017 +0200
+++ b/Framework/Toolbox/DicomFrameConverter.cpp	Mon Oct 02 22:01:41 2017 +0200
@@ -39,26 +39,7 @@
     rescaleSlope_ = 1;
     defaultWindowCenter_ = 128;
     defaultWindowWidth_ = 256;
-  }
-
-
-  Orthanc::PixelFormat DicomFrameConverter::GetExpectedPixelFormat() const
-  {
-    // TODO Add more checks, e.g. on the number of bytes per value
-    // (cf. DicomImageInformation.h in Orthanc)
-
-    if (isColor_)
-    {
-      return Orthanc::PixelFormat_RGB24;
-    }
-    else if (isSigned_)
-    {
-      return Orthanc::PixelFormat_SignedGrayscale16;
-    }
-    else
-    {
-      return Orthanc::PixelFormat_Grayscale16;
-    }
+    expectedPixelFormat_ = Orthanc::PixelFormat_Grayscale16;
   }
 
 
@@ -85,11 +66,22 @@
 
     isSigned_ = (tmp == 1);
 
-    if (dicom.ParseFloat(rescaleIntercept_, Orthanc::DICOM_TAG_RESCALE_INTERCEPT) &&
-        dicom.ParseFloat(rescaleSlope_, Orthanc::DICOM_TAG_RESCALE_SLOPE))
+    double doseGridScaling;
+    bool isRTDose = false;
+    
+    if (dicom.ParseDouble(rescaleIntercept_, Orthanc::DICOM_TAG_RESCALE_INTERCEPT) &&
+        dicom.ParseDouble(rescaleSlope_, Orthanc::DICOM_TAG_RESCALE_SLOPE))
     {
       hasRescale_ = true;
     }
+    else if (dicom.ParseDouble(doseGridScaling, Orthanc::DICOM_TAG_DOSE_GRID_SCALING))
+    {
+      // This is for RT-DOSE
+      hasRescale_ = true;
+      isRTDose = true;
+      rescaleIntercept_ = 0;
+      rescaleSlope_ = doseGridScaling;
+    }
 
     std::string photometric;
     if (dicom.CopyToString(photometric, Orthanc::DICOM_TAG_PHOTOMETRIC_INTERPRETATION, false))
@@ -104,6 +96,26 @@
     
     isColor_ = (photometric != "MONOCHROME1" &&
                 photometric != "MONOCHROME2");
+
+    // TODO Add more checks, e.g. on the number of bytes per value
+    // (cf. DicomImageInformation.h in Orthanc)
+
+    if (isRTDose)
+    {
+      expectedPixelFormat_ = Orthanc::PixelFormat_Grayscale32;
+    }
+    else if (isColor_)
+    {
+      expectedPixelFormat_ = Orthanc::PixelFormat_RGB24;
+    }
+    else if (isSigned_)
+    {
+      expectedPixelFormat_ = Orthanc::PixelFormat_SignedGrayscale16;
+    }
+    else
+    {
+      expectedPixelFormat_ = Orthanc::PixelFormat_Grayscale16;
+    }
   }
 
 
@@ -130,6 +142,7 @@
     }
 
     assert(sourceFormat == Orthanc::PixelFormat_Grayscale16 ||
+           sourceFormat == Orthanc::PixelFormat_Grayscale32 ||
            sourceFormat == Orthanc::PixelFormat_SignedGrayscale16);
 
     // This is the case of a grayscale frame. Convert it to Float32.
@@ -142,25 +155,51 @@
     source.reset(NULL);  // We don't need the source frame anymore
 
     // Correct rescale slope/intercept if need be
+    ApplyRescale(*converted, sourceFormat != Orthanc::PixelFormat_Grayscale32);
+      
+    source = converted;
+  }
+
+
+  void DicomFrameConverter::ApplyRescale(Orthanc::ImageAccessor& image,
+                                         bool useDouble) const
+  {
+    if (image.GetFormat() != Orthanc::PixelFormat_Float32)
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat);
+    }
+    
     if (hasRescale_)
     {
-      for (unsigned int y = 0; y < converted->GetHeight(); y++)
+      for (unsigned int y = 0; y < image.GetHeight(); y++)
       {
-        float* p = reinterpret_cast<float*>(converted->GetRow(y));
-        for (unsigned int x = 0; x < converted->GetWidth(); x++, p++)
-        {
-          float value = *p;
+        float* p = reinterpret_cast<float*>(image.GetRow(y));
 
-          if (hasRescale_)
+        if (useDouble)
+        {
+          // Slower, accurate implementation using double
+          for (unsigned int x = 0; x < image.GetWidth(); x++, p++)
           {
-            value = value * rescaleSlope_ + rescaleIntercept_;
+            double value = static_cast<double>(*p);
+            *p = static_cast<float>(value * rescaleSlope_ + rescaleIntercept_);
           }
-            
-          *p = value;
+        }
+        else
+        {
+          // Fast, approximate implementation using float
+          for (unsigned int x = 0; x < image.GetWidth(); x++, p++)
+          {
+            *p = (*p) * static_cast<float>(rescaleSlope_) + static_cast<float>(rescaleIntercept_);
+          }
         }
       }
     }
-      
-    source = converted;
   }
+
+  
+  double DicomFrameConverter::Apply(double x) const
+  {
+    return x * rescaleSlope_ + rescaleIntercept_;
+  }
+
 }