# HG changeset patch # User Sebastien Jodogne # Date 1725905534 -7200 # Node ID 072968f00d26b562f09b68e7ceff2146c3bbf407 # Parent 9dc7f1e8716d2d7eab531cc105582c75ca17bd73 support of transparency in OpenSlide diff -r 9dc7f1e8716d -r 072968f00d26 Applications/Dicomizer.cpp --- 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)) { diff -r 9dc7f1e8716d -r 072968f00d26 Framework/Inputs/OpenSlidePyramid.cpp --- 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 #include +#include #include namespace OrthancWSI @@ -40,7 +41,49 @@ unsigned int y) { std::unique_ptr 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(source->GetConstRow(y)); + uint8_t* q = reinterpret_cast(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(((255 - alpha) * backgroundColor_[0] + alpha * p[2]) / 255); + q[1] = static_cast(((255 - alpha) * backgroundColor_[1] + alpha * p[1]) / 255); + q[2] = static_cast(((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; + } } diff -r 9dc7f1e8716d -r 072968f00d26 Framework/Inputs/OpenSlidePyramid.h --- 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); }; }