diff Framework/Radiography/RadiographyWidget.cpp @ 432:4eb96c6b4e96 am-vsol-upgrade

improved handling of MONOCHROME1, background and invertion
author am@osimis.io
date Mon, 03 Dec 2018 13:53:29 +0100
parents 751fb354149e
children a750f11892ec
line wrap: on
line diff
--- a/Framework/Radiography/RadiographyWidget.cpp	Thu Nov 29 19:25:15 2018 +0100
+++ b/Framework/Radiography/RadiographyWidget.cpp	Mon Dec 03 13:53:29 2018 +0100
@@ -21,18 +21,53 @@
 
 #include "RadiographyWidget.h"
 
+#include <Core/OrthancException.h>
 #include <Core/Images/Image.h>
+#include <Core/Images/ImageProcessing.h>
 
 
 namespace OrthancStone
 {
+
+  bool RadiographyWidget::IsInvertedInternal() const
+  {
+    return (scene_->GetPreferredPhotomotricDisplayMode() == PhotometricDisplayMode_Monochrome1) ^ invert_; // MONOCHROME1 images must be inverted and the user can invert the image too -> XOR the two
+  }
+
+  void RadiographyWidget::RenderBackground(Orthanc::ImageAccessor& image, float minValue, float maxValue)
+  {
+    // wipe background before rendering
+    float backgroundValue = minValue;
+
+    switch (scene_->GetPreferredPhotomotricDisplayMode())
+    {
+    case PhotometricDisplayMode_Monochrome1:
+    case PhotometricDisplayMode_Default:
+      if (IsInvertedInternal())
+        backgroundValue = maxValue;
+      else
+        backgroundValue = minValue;
+      break;
+    case PhotometricDisplayMode_Monochrome2:
+      if (IsInvertedInternal())
+        backgroundValue = minValue;
+      else
+        backgroundValue = maxValue;
+      break;
+    default:
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
+    }
+
+    Orthanc::ImageProcessing::Set(image, backgroundValue);
+  }
+
   bool RadiographyWidget::RenderInternal(unsigned int width,
                                          unsigned int height,
                                          ImageInterpolation interpolation)
   {
     float windowCenter, windowWidth;
     scene_->GetWindowingWithDefault(windowCenter, windowWidth);
-      
+
     float x0 = windowCenter - windowWidth / 2.0f;
     float x1 = windowCenter + windowWidth / 2.0f;
 
@@ -56,8 +91,10 @@
         cairoBuffer_.reset(new CairoSurface(width, height));
       }
 
+      RenderBackground(*floatBuffer_, x0, x1);
+
       scene_->Render(*floatBuffer_, GetView().GetMatrix(), interpolation);
-        
+
       // Conversion from Float32 to BGRA32 (cairo). Very similar to
       // GrayscaleFrameRenderer => TODO MERGE?
 
@@ -65,7 +102,9 @@
       cairoBuffer_->GetWriteableAccessor(target);
 
       float scaling = 255.0f / (x1 - x0);
-        
+
+      bool invert = IsInvertedInternal();
+
       for (unsigned int y = 0; y < height; y++)
       {
         const float* p = reinterpret_cast<const float*>(floatBuffer_->GetConstRow(y));
@@ -88,7 +127,7 @@
             v = static_cast<uint8_t>(scaling * (*p - x0));  // (*)
           }
 
-          if (invert_)
+          if (invert)
           {
             v = 255 - v;
           }
@@ -172,14 +211,15 @@
   
   void RadiographyWidget::OnGeometryChanged(const RadiographyScene::GeometryChangedMessage& message)
   {
-    LOG(INFO) << "Geometry has changed";
+    LOG(INFO) << "Scene geometry has changed";
+
     FitContent();
   }
 
   
   void RadiographyWidget::OnContentChanged(const RadiographyScene::ContentChangedMessage& message)
   {
-    LOG(INFO) << "Content has changed";
+    LOG(INFO) << "Scene content has changed";
     NotifyContentChanged();
   }
 
@@ -220,12 +260,14 @@
     scene_ = scene;
 
     scene_->RegisterObserverCallback(
-      new Callable<RadiographyWidget, RadiographyScene::GeometryChangedMessage>
-      (*this, &RadiographyWidget::OnGeometryChanged));
+          new Callable<RadiographyWidget, RadiographyScene::GeometryChangedMessage>
+          (*this, &RadiographyWidget::OnGeometryChanged));
 
     scene_->RegisterObserverCallback(
-      new Callable<RadiographyWidget, RadiographyScene::ContentChangedMessage>
-      (*this, &RadiographyWidget::OnContentChanged));
+          new Callable<RadiographyWidget, RadiographyScene::ContentChangedMessage>
+          (*this, &RadiographyWidget::OnContentChanged));
+
+    NotifyContentChanged();
 
     // force redraw
     FitContent();