Mercurial > hg > orthanc-wsi
changeset 335:62dd571a40af
created OnTheFlyPyramid class
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 04 Dec 2024 22:37:58 +0100 |
parents | f011fc199b6a |
children | dfd9ecf38091 |
files | .clang-format Applications/CMakeLists.txt Framework/Inputs/OnTheFlyPyramid.cpp Framework/Inputs/OnTheFlyPyramid.h ViewerPlugin/CMakeLists.txt |
diffstat | 5 files changed, 276 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.clang-format Wed Dec 04 22:37:58 2024 +0100 @@ -0,0 +1,57 @@ +--- +Language: Cpp +BasedOnStyle: LLVM +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignOperands: true +AlignTrailingComments: false +AlwaysBreakTemplateDeclarations: Yes +BraceWrapping: + AfterCaseLabel: true + AfterClass: true + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: true + BeforeElse: true + BeforeLambdaBody: true + BeforeWhile: true + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBraces: Custom +BreakBeforeTernaryOperators: false +BreakConstructorInitializers: AfterColon +BreakConstructorInitializersBeforeComma: false +ColumnLimit: 200 +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ContinuationIndentWidth: 2 +IncludeCategories: + - Regex: '^<.*' + Priority: 1 + - Regex: '^".*' + Priority: 2 + - Regex: '.*' + Priority: 3 +IncludeIsMainRegex: '([-_](test|unittest))?$' +IndentCaseLabels: true +InsertNewlineAtEOF: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: All +SpaceAfterCStyleCast: true +SpaceAfterTemplateKeyword: false +SpaceBeforeRangeBasedForLoopColon: false +SpaceInEmptyParentheses: false +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +TabWidth: 2 +...
--- a/Applications/CMakeLists.txt Fri Oct 18 15:44:18 2024 +0200 +++ b/Applications/CMakeLists.txt Wed Dec 04 22:37:58 2024 +0100 @@ -119,6 +119,7 @@ ${ORTHANC_WSI_DIR}/Framework/Inputs/DicomPyramidInstance.cpp ${ORTHANC_WSI_DIR}/Framework/Inputs/DicomPyramidLevel.cpp ${ORTHANC_WSI_DIR}/Framework/Inputs/HierarchicalTiff.cpp + ${ORTHANC_WSI_DIR}/Framework/Inputs/OnTheFlyPyramid.cpp ${ORTHANC_WSI_DIR}/Framework/Inputs/OpenSlideLibrary.cpp ${ORTHANC_WSI_DIR}/Framework/Inputs/OpenSlidePyramid.cpp ${ORTHANC_WSI_DIR}/Framework/Inputs/PlainTiff.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Inputs/OnTheFlyPyramid.cpp Wed Dec 04 22:37:58 2024 +0100 @@ -0,0 +1,122 @@ +/** +* Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "../PrecompiledHeadersWSI.h" +#include "OnTheFlyPyramid.h" + +#include <OrthancException.h> + +#include <cassert> +#include <Images/Image.h> +#include <Images/ImageProcessing.h> + +#include "../../Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h" + +namespace OrthancWSI +{ + void OnTheFlyPyramid::ReadRegion(Orthanc::ImageAccessor &target, + bool &isEmpty, + unsigned level, + unsigned x, + unsigned y) + { + isEmpty = false; + GetLevel(level).GetRegion(target, x, y, tileWidth_, tileHeight_); + } + + + OnTheFlyPyramid::OnTheFlyPyramid(Orthanc::ImageAccessor *baseLevel, + unsigned int tileWidth, + unsigned int tileHeight, + bool smooth) : + tileWidth_(tileWidth), + tileHeight_(tileHeight) + { + if (baseLevel == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); + } + + std::unique_ptr<Orthanc::ImageAccessor> protection(baseLevel); + + if (protection->GetFormat() == Orthanc::PixelFormat_RGB24) + { + baseLevel_.reset(protection.release()); + } + else + { + baseLevel_.reset(new Orthanc::Image(Orthanc::PixelFormat_RGB24, protection->GetWidth(), protection->GetHeight(), false)); + Orthanc::ImageProcessing::Convert(*baseLevel_, *protection); + } + + Orthanc::ImageAccessor* current = baseLevel_.get(); + while (current->GetWidth() > tileWidth_ || + current->GetHeight() > tileHeight_) + { + std::unique_ptr<Orthanc::ImageAccessor> next; + + if (smooth) + { + std::unique_ptr<Orthanc::ImageAccessor> smoothed(Orthanc::Image::Clone(*current)); + Orthanc::ImageProcessing::SmoothGaussian5x5(*smoothed, false); + next.reset(Orthanc::ImageProcessing::Halve(*smoothed, false)); + } + else + { + next.reset(Orthanc::ImageProcessing::Halve(*current, false)); + } + + higherLevels_.push_back(next.release()); + current = higherLevels_.back(); + } + } + + + OnTheFlyPyramid::~OnTheFlyPyramid() + { + for (size_t i = 0; i < higherLevels_.size(); i++) + { + assert(higherLevels_[i] != NULL); + delete higherLevels_[i]; + } + } + + + const Orthanc::ImageAccessor & OnTheFlyPyramid::GetLevel(unsigned int level) const + { + if (level >= GetLevelCount()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + else if (level == 0) + { + assert(baseLevel_.get() != NULL); + return *baseLevel_; + } + else + { + assert(higherLevels_[level - 1] != NULL); + return *higherLevels_[level - 1]; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Inputs/OnTheFlyPyramid.h Wed Dec 04 22:37:58 2024 +0100 @@ -0,0 +1,94 @@ +/** +* Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "DecodedTiledPyramid.h" + +#include <Compatibility.h> + +#include <vector> + +namespace OrthancWSI +{ + class OnTheFlyPyramid : public DecodedTiledPyramid + { + private: + std::unique_ptr<Orthanc::ImageAccessor> baseLevel_; + std::vector<Orthanc::ImageAccessor*> higherLevels_; + unsigned int tileWidth_; + unsigned int tileHeight_; + + protected: + void ReadRegion(Orthanc::ImageAccessor &target, + bool &isEmpty, + unsigned level, + unsigned x, + unsigned y) ORTHANC_OVERRIDE; + + public: + OnTheFlyPyramid(Orthanc::ImageAccessor* baseLevel /* takes ownership */, + unsigned int tileWidth, + unsigned int tileHeight, + bool smooth); + + virtual ~OnTheFlyPyramid(); + + const Orthanc::ImageAccessor& GetLevel(unsigned int level) const; + + unsigned GetLevelCount() const ORTHANC_OVERRIDE + { + return higherLevels_.size() + 1 /* base level */; + } + + unsigned GetLevelWidth(unsigned int level) const ORTHANC_OVERRIDE + { + return GetLevel(level).GetWidth(); + } + + unsigned GetLevelHeight(unsigned int level) const ORTHANC_OVERRIDE + { + return GetLevel(level).GetHeight(); + } + + unsigned GetTileWidth(unsigned int level) const ORTHANC_OVERRIDE + { + return tileWidth_; + } + + unsigned GetTileHeight(unsigned level) const ORTHANC_OVERRIDE + { + return tileHeight_; + } + + Orthanc::PixelFormat GetPixelFormat() const ORTHANC_OVERRIDE + { + return baseLevel_->GetFormat(); + } + + Orthanc::PhotometricInterpretation GetPhotometricInterpretation() const ORTHANC_OVERRIDE + { + return Orthanc::PhotometricInterpretation_RGB; + } + }; +}
--- a/ViewerPlugin/CMakeLists.txt Fri Oct 18 15:44:18 2024 +0200 +++ b/ViewerPlugin/CMakeLists.txt Wed Dec 04 22:37:58 2024 +0100 @@ -195,9 +195,11 @@ ${ORTHANC_WSI_DIR}/Framework/DicomToolbox.cpp ${ORTHANC_WSI_DIR}/Framework/Enumerations.cpp ${ORTHANC_WSI_DIR}/Framework/ImageToolbox.cpp + ${ORTHANC_WSI_DIR}/Framework/Inputs/DecodedTiledPyramid.cpp ${ORTHANC_WSI_DIR}/Framework/Inputs/DicomPyramid.cpp ${ORTHANC_WSI_DIR}/Framework/Inputs/DicomPyramidInstance.cpp ${ORTHANC_WSI_DIR}/Framework/Inputs/DicomPyramidLevel.cpp + ${ORTHANC_WSI_DIR}/Framework/Inputs/OnTheFlyPyramid.cpp ${ORTHANC_WSI_DIR}/Framework/Inputs/PyramidWithRawTiles.cpp ${ORTHANC_WSI_DIR}/Framework/Jpeg2000Reader.cpp ${ORTHANC_WSI_DIR}/Framework/Jpeg2000Writer.cpp