changeset 315:072968f00d26

support of transparency in OpenSlide
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 09 Sep 2024 20:12:14 +0200
parents 9dc7f1e8716d
children 51ef122c1882
files Applications/Dicomizer.cpp Framework/Inputs/OpenSlidePyramid.cpp Framework/Inputs/OpenSlidePyramid.h
diffstat 3 files changed, 66 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/Dicomizer.cpp	Wed Aug 14 15:52:13 2024 +0200
+++ b/Applications/Dicomizer.cpp	Mon Sep 09 20:12:14 2024 +0200
@@ -1109,6 +1109,10 @@
       new OrthancWSI::OpenSlidePyramid(path, parameters.GetTargetTileWidth(512),
                                        parameters.GetTargetTileHeight(512)));
 
+    openslide->SetBackgroundColor(parameters.GetBackgroundColorRed(),
+                                  parameters.GetBackgroundColorGreen(),
+                                  parameters.GetBackgroundColorBlue());
+
     float volumeWidth, volumeHeight;
     if (openslide->LookupImagedVolumeSize(volumeWidth, volumeHeight))
     {
--- a/Framework/Inputs/OpenSlidePyramid.cpp	Wed Aug 14 15:52:13 2024 +0200
+++ b/Framework/Inputs/OpenSlidePyramid.cpp	Mon Sep 09 20:12:14 2024 +0200
@@ -30,6 +30,7 @@
 #include <SerializationToolbox.h>
 #include <Logging.h>
 
+#include <boost/math/special_functions/round.hpp>
 #include <memory>
 
 namespace OrthancWSI
@@ -40,7 +41,49 @@
                                     unsigned int y)
   {
     std::unique_ptr<Orthanc::ImageAccessor> source(image_.ReadRegion(level, x, y, target.GetWidth(), target.GetHeight()));
-    Orthanc::ImageProcessing::Convert(target, *source);
+
+    if (target.GetWidth() != source->GetWidth() ||
+        target.GetHeight() != source->GetHeight())
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize);
+    }
+
+    const unsigned int width = source->GetWidth();
+    const unsigned int height = source->GetHeight();
+
+    if (target.GetFormat() == Orthanc::PixelFormat_RGB24 &&
+        source->GetFormat() == Orthanc::PixelFormat_BGRA32)
+    {
+      // Implements alpha blending: https://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending
+      for (unsigned int y = 0; y < height; y++)
+      {
+        const uint8_t* p = reinterpret_cast<const uint8_t*>(source->GetConstRow(y));
+        uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y));
+        for (unsigned int x = 0; x < width; x++)
+        {
+          /**
+             Alpha blending using integer arithmetics only (16 bits avoids overflows)
+
+             p = (1 - alpha) * background + alpha * value
+             <=> p = (1 - p[3] / 255) * background + p[3] / 255 * value
+             <=> p = ((255 - p[3]) * background + p[3] * value) / 255
+
+           **/
+
+          uint16_t alpha = p[3];
+          q[0] = static_cast<uint8_t>(((255 - alpha) * backgroundColor_[0] + alpha * p[2]) / 255);
+          q[1] = static_cast<uint8_t>(((255 - alpha) * backgroundColor_[1] + alpha * p[1]) / 255);
+          q[2] = static_cast<uint8_t>(((255 - alpha) * backgroundColor_[2] + alpha * p[0]) / 255);
+
+          p += 4;
+          q += 3;
+        }
+      }
+    }
+    else
+    {
+      Orthanc::ImageProcessing::Convert(target, *source);
+    }
   }
 
 
@@ -51,6 +94,9 @@
     tileWidth_(tileWidth),
     tileHeight_(tileHeight)
   {
+    backgroundColor_[0] = 255;
+    backgroundColor_[1] = 255;
+    backgroundColor_[2] = 255;
   }
 
 
@@ -76,4 +122,14 @@
       return false;
     }
   }
+
+
+  void OpenSlidePyramid::SetBackgroundColor(uint8_t red,
+                                            uint8_t green,
+                                            uint8_t blue)
+  {
+    backgroundColor_[0] = red;
+    backgroundColor_[1] = green;
+    backgroundColor_[2] = blue;
+  }
 }
--- a/Framework/Inputs/OpenSlidePyramid.h	Wed Aug 14 15:52:13 2024 +0200
+++ b/Framework/Inputs/OpenSlidePyramid.h	Mon Sep 09 20:12:14 2024 +0200
@@ -34,6 +34,7 @@
     OpenSlideLibrary::Image  image_;
     unsigned int             tileWidth_;
     unsigned int             tileHeight_;
+    uint8_t                  backgroundColor_[3];
 
   protected:
     virtual void ReadRegion(Orthanc::ImageAccessor& target,
@@ -83,5 +84,9 @@
 
     bool LookupImagedVolumeSize(float& width,
                                 float& height) const;
+
+    void SetBackgroundColor(uint8_t red,
+                            uint8_t green,
+                            uint8_t blue);
   };
 }