Mercurial > hg > orthanc-wsi
changeset 355:a307ec25a008
padding for on-the-fly pyramids
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 20 Dec 2024 13:48:34 +0100 |
parents | 5d3672320879 |
children | 03d33290cba1 |
files | ViewerPlugin/OrthancPyramidFrameFetcher.cpp ViewerPlugin/OrthancPyramidFrameFetcher.h ViewerPlugin/Plugin.cpp |
diffstat | 3 files changed, 137 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/ViewerPlugin/OrthancPyramidFrameFetcher.cpp Fri Dec 20 12:40:54 2024 +0100 +++ b/ViewerPlugin/OrthancPyramidFrameFetcher.cpp Fri Dec 20 13:48:34 2024 +0100 @@ -63,7 +63,14 @@ OrthancPyramidFrameFetcher::OrthancPyramidFrameFetcher(OrthancStone::IOrthancConnection* orthanc, bool smooth) : orthanc_(orthanc), - smooth_(smooth) + smooth_(smooth), + tileWidth_(512), + tileHeight_(512), + paddingX_(0), + paddingY_(0), + backgroundRed_(0), + backgroundGreen_(0), + backgroundBlue_(0) { if (orthanc == NULL) { @@ -72,6 +79,42 @@ } + void OrthancPyramidFrameFetcher::SetTileWidth(unsigned int tileWidth) + { + if (tileWidth <= 2) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + else + { + tileWidth_ = tileWidth; + } + } + + + void OrthancPyramidFrameFetcher::SetTileHeight(unsigned int tileHeight) + { + if (tileHeight <= 2) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + else + { + tileHeight_ = tileHeight; + } + } + + + void OrthancPyramidFrameFetcher::SetBackgroundColor(uint8_t red, + uint8_t green, + uint8_t blue) + { + backgroundRed_ = red; + backgroundGreen_ = green; + backgroundBlue_ = blue; + } + + DecodedTiledPyramid* OrthancPyramidFrameFetcher::Fetch(const std::string &instanceId, unsigned frameNumber) { @@ -104,26 +147,55 @@ Orthanc::ImageAccessor source; source.AssignReadOnly(format, frame->GetWidth(), frame->GetHeight(), frame->GetPitch(), frame->GetBuffer()); - std::unique_ptr<Orthanc::ImageAccessor> rendered(new Orthanc::Image(Orthanc::PixelFormat_RGB24, source.GetWidth(), source.GetHeight(), false)); + unsigned int paddedWidth, paddedHeight; + + if (paddingX_ >= 2) + { + paddedWidth = OrthancWSI::CeilingDivision(source.GetWidth(), paddingX_) * paddingX_; + } + else + { + paddedWidth = source.GetWidth(); + } + + if (paddingY_ >= 2) + { + paddedHeight = OrthancWSI::CeilingDivision(source.GetHeight(), paddingY_) * paddingY_; + } + else + { + paddedHeight = source.GetHeight(); + } + + std::unique_ptr<Orthanc::ImageAccessor> rendered(new Orthanc::Image(Orthanc::PixelFormat_RGB24, paddedWidth, paddedHeight, false)); + + if (paddedWidth != source.GetWidth() || + paddedHeight != source.GetHeight()) + { + Orthanc::ImageProcessing::Set(*rendered, backgroundRed_, backgroundGreen_, backgroundBlue_, 255 /* alpha */); + } + + Orthanc::ImageAccessor region; + rendered->GetRegion(region, 0, 0, source.GetWidth(), source.GetHeight()); switch (format) { case Orthanc::PixelFormat_RGB24: - Orthanc::ImageProcessing::Copy(*rendered, source); + Orthanc::ImageProcessing::Copy(region, source); break; case Orthanc::PixelFormat_Grayscale8: - Orthanc::ImageProcessing::Convert(*rendered, source); + Orthanc::ImageProcessing::Convert(region, source); break; case Orthanc::PixelFormat_Grayscale16: - RenderGrayscale(*rendered, source); + RenderGrayscale(region, source); break; default: throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); } - return new OnTheFlyPyramid(rendered.release(), 512, 512, smooth_); + return new OnTheFlyPyramid(rendered.release(), tileWidth_, tileHeight_, smooth_); } }
--- a/ViewerPlugin/OrthancPyramidFrameFetcher.h Fri Dec 20 12:40:54 2024 +0100 +++ b/ViewerPlugin/OrthancPyramidFrameFetcher.h Fri Dec 20 13:48:34 2024 +0100 @@ -34,6 +34,13 @@ private: std::unique_ptr<OrthancStone::IOrthancConnection> orthanc_; bool smooth_; + unsigned int tileWidth_; + unsigned int tileHeight_; + unsigned int paddingX_; + unsigned int paddingY_; + uint8_t backgroundRed_; + uint8_t backgroundGreen_; + uint8_t backgroundBlue_; static void RenderGrayscale(Orthanc::ImageAccessor& target, const Orthanc::ImageAccessor& source); @@ -42,6 +49,46 @@ OrthancPyramidFrameFetcher(OrthancStone::IOrthancConnection* orthanc, bool smooth); + unsigned int GetTileWidth() const + { + return tileWidth_; + } + + void SetTileWidth(unsigned int tileWidth); + + unsigned int GetTileHeight() const + { + return tileHeight_; + } + + void SetTileHeight(unsigned int tileHeight); + + unsigned int GetPaddingX() const + { + return paddingX_; + } + + // "0" or "1" implies no padding + void SetPaddingX(unsigned int paddingX) + { + paddingX_ = paddingX; + } + + unsigned int GetPaddingY() const + { + return paddingY_; + } + + // "0" or "1" implies no padding + void SetPaddingY(unsigned int paddingY) + { + paddingY_ = paddingY; + } + + void SetBackgroundColor(uint8_t red, + uint8_t green, + uint8_t blue); + DecodedTiledPyramid* Fetch(const std::string &instanceId, unsigned frameNumber) ORTHANC_OVERRIDE; };
--- a/ViewerPlugin/Plugin.cpp Fri Dec 20 12:40:54 2024 +0100 +++ b/ViewerPlugin/Plugin.cpp Fri Dec 20 13:48:34 2024 +0100 @@ -450,10 +450,18 @@ OrthancPlugins::SetDescription(ORTHANC_PLUGIN_NAME, "Provides a Web viewer of whole-slide microscopic images within Orthanc."); OrthancWSI::DicomPyramidCache::InitializeInstance(10 /* Number of pyramids to be cached - TODO parameter */); - OrthancWSI::DecodedPyramidCache::InitializeInstance( - new OrthancWSI::OrthancPyramidFrameFetcher(new OrthancWSI::OrthancPluginConnection(), false /* TODO PARAMETER */), - 10 /* TODO - PARAMETER */, - 256 * 1024 * 1024 /* TODO - PARAMETER */); + + { + std::unique_ptr<OrthancWSI::OrthancPyramidFrameFetcher> fetcher( + new OrthancWSI::OrthancPyramidFrameFetcher(new OrthancWSI::OrthancPluginConnection(), false /* TODO PARAMETER */)); + fetcher->SetPaddingX(64); // TODO PARAMETER + fetcher->SetPaddingY(64); // TODO PARAMETER + fetcher->SetBackgroundColor(255, 255, 255); // TODO PARAMETER + + OrthancWSI::DecodedPyramidCache::InitializeInstance(fetcher.release(), + 10 /* TODO - PARAMETER */, + 256 * 1024 * 1024 /* TODO - PARAMETER */); + } OrthancPluginRegisterOnChangeCallback(OrthancPlugins::GetGlobalContext(), OnChangeCallback);