Mercurial > hg > orthanc-stone
changeset 1327:4f8db2d202c8 broker
OrthancSeriesProgressiveLoader now has two modes that
can be selected at object creation :
- progressive (will first load jpeg50, then jpeg90 then PAM)
- non-progressive (will directly load PAM (uncompressed))
Please note that the slice loading order remains dynamic
and depending upon the slice that the client code wishes
to extract from the volume.
author | Benjamin Golinvaux <bgo@osimis.io> |
---|---|
date | Wed, 25 Mar 2020 14:34:27 +0100 |
parents | 55166e57a77c |
children | fd616c4a5904 |
files | Framework/Deprecated/Loaders/LoaderCache.cpp Framework/Deprecated/Loaders/OrthancSeriesVolumeProgressiveLoader.cpp Framework/Deprecated/Loaders/OrthancSeriesVolumeProgressiveLoader.h Framework/Scene2D/OpenGLCompositor.cpp |
diffstat | 4 files changed, 106 insertions(+), 80 deletions(-) [+] |
line wrap: on
line diff
--- a/Framework/Deprecated/Loaders/LoaderCache.cpp Tue Mar 24 21:32:35 2020 +0100 +++ b/Framework/Deprecated/Loaders/LoaderCache.cpp Wed Mar 25 14:34:27 2020 +0100 @@ -83,7 +83,9 @@ boost::shared_ptr<OrthancStone::DicomVolumeImage> volumeImage(new OrthancStone::DicomVolumeImage); boost::shared_ptr<OrthancSeriesVolumeProgressiveLoader> loader; - loader = OrthancSeriesVolumeProgressiveLoader::Create(loadersContext_, volumeImage); + // true means "use progressive quality" + // false means "load high quality slices only" + loader = OrthancSeriesVolumeProgressiveLoader::Create(loadersContext_, volumeImage, false); loader->LoadSeries(seriesUuid); seriesVolumeProgressiveLoaders_[seriesUuid] = loader; }
--- a/Framework/Deprecated/Loaders/OrthancSeriesVolumeProgressiveLoader.cpp Tue Mar 24 21:32:35 2020 +0100 +++ b/Framework/Deprecated/Loaders/OrthancSeriesVolumeProgressiveLoader.cpp Wed Mar 25 14:34:27 2020 +0100 @@ -21,6 +21,7 @@ #include "OrthancSeriesVolumeProgressiveLoader.h" +#include "../../StoneException.h" #include "../../Loaders/ILoadersContext.h" #include "../../Loaders/BasicFetchingItemsSorter.h" #include "../../Loaders/BasicFetchingStrategy.h" @@ -64,11 +65,9 @@ } } }; - - - void OrthancSeriesVolumeProgressiveLoader::SeriesGeometry::CheckSlice(size_t index, - const OrthancStone::DicomInstanceParameters& reference) const + void OrthancSeriesVolumeProgressiveLoader::SeriesGeometry::CheckSlice( + size_t index, const OrthancStone::DicomInstanceParameters& reference) const { const OrthancStone::DicomInstanceParameters& slice = *slices_[index]; @@ -260,16 +259,15 @@ { assert(strategy_.get() != NULL); - unsigned int sliceIndex, quality; + unsigned int sliceIndex = 0, quality = 0; if (strategy_->GetNext(sliceIndex, quality)) { - -#if USE_SINGLE_QUALITY - assert(quality == SINGLE_QUALITY); -#else - assert(quality <= BEST_QUALITY); -#endif + if (!progressiveQuality_) + { + ORTHANC_ASSERT(quality == QUALITY_00, "INTERNAL ERROR. quality != QUALITY_00 in " + << "OrthancSeriesVolumeProgressiveLoader::ScheduleNextSliceDownload"); + } const OrthancStone::DicomInstanceParameters& slice = seriesGeometry_.GetSliceParameters(sliceIndex); @@ -281,10 +279,7 @@ std::unique_ptr<OrthancStone::OracleCommandBase> command; -#if USE_SINGLE_QUALITY -#else - if (quality == BEST_QUALITY) -#endif + if (!progressiveQuality_ || quality == QUALITY_02) { std::unique_ptr<OrthancStone::GetOrthancImageCommand> tmp(new OrthancStone::GetOrthancImageCommand); // TODO: review the following comment. @@ -304,23 +299,22 @@ // << " URI = " << tmp->GetUri(); command.reset(tmp.release()); } -#if USE_SINGLE_QUALITY -#else - else + else // progressive mode is true AND quality is not final (different from QUALITY_02 { - std::unique_ptr<OrthancStone::GetOrthancWebViewerJpegCommand> tmp(new OrthancStone::GetOrthancWebViewerJpegCommand); + std::unique_ptr<OrthancStone::GetOrthancWebViewerJpegCommand> tmp( + new OrthancStone::GetOrthancWebViewerJpegCommand); + // TODO: review the following comment. Commented out by bgo on 2019-07-19 // (gzip for jpeg seems overkill) //tmp->SetHttpHeader("Accept-Encoding", "gzip"); tmp->SetInstance(instance); - tmp->SetQuality((quality == 0 ? 50 : 90)); + tmp->SetQuality((quality == 0 ? 50 : 90)); // QUALITY_00 is Jpeg50 while QUALITY_01 is Jpeg90 tmp->SetExpectedPixelFormat(slice.GetExpectedPixelFormat()); LOG(TRACE) << "OrthancSeriesVolumeProgressiveLoader.ScheduleNextSliceDownload()" << " sliceIndex = " << sliceIndex << " slice quality = " << quality; command.reset(tmp.release()); } -#endif command->AcquirePayload(new Orthanc::SingleValueObject<unsigned int>(sliceIndex)); @@ -386,15 +380,15 @@ volume_->SetDicomParameters(parameters); volume_->GetPixelData().Clear(); -#if USE_SINGLE_QUALITY + // If we are in progressive mode, the Fetching strategy will first request QUALITY_00, then QUALITY_01, then + // QUALITY_02... Otherwise, it's only QUALITY_00 + unsigned int maxQuality = QUALITY_00; + if (progressiveQuality_) + maxQuality = QUALITY_02; + strategy_.reset(new OrthancStone::BasicFetchingStrategy( sorter_->CreateSorter(static_cast<unsigned int>(slicesCount)), - SINGLE_QUALITY)); -#else - strategy_.reset(new OrthancStone::BasicFetchingStrategy( - sorter_->CreateSorter(static_cast<unsigned int>(slicesCount)), - BEST_QUALITY)); -#endif + maxQuality)); assert(simultaneousDownloads_ != 0); for (unsigned int i = 0; i < simultaneousDownloads_; i++) @@ -413,13 +407,22 @@ const Orthanc::ImageAccessor& image, unsigned int quality) { - assert(sliceIndex < slicesQuality_.size() && + ORTHANC_ASSERT(sliceIndex < slicesQuality_.size() && slicesQuality_.size() == volume_->GetPixelData().GetDepth()); + if (!progressiveQuality_) + { + ORTHANC_ASSERT(quality == QUALITY_00); + ORTHANC_ASSERT(slicesQuality_[sliceIndex] == QUALITY_00); + } + if (quality >= slicesQuality_[sliceIndex]) { { - OrthancStone::ImageBuffer3D::SliceWriter writer(volume_->GetPixelData(), OrthancStone::VolumeProjection_Axial, sliceIndex); + OrthancStone::ImageBuffer3D::SliceWriter writer(volume_->GetPixelData(), + OrthancStone::VolumeProjection_Axial, + sliceIndex); + Orthanc::ImageProcessing::Copy(writer.GetAccessor(), image); } @@ -434,30 +437,35 @@ ScheduleNextSliceDownload(); } - void OrthancSeriesVolumeProgressiveLoader::LoadBestQualitySliceContent(const OrthancStone::GetOrthancImageCommand::SuccessMessage& message) + void OrthancSeriesVolumeProgressiveLoader::LoadBestQualitySliceContent( + const OrthancStone::GetOrthancImageCommand::SuccessMessage& message) { -#if USE_SINGLE_QUALITY - SetSliceContent(GetSliceIndexPayload(message.GetOrigin()), message.GetImage(), SINGLE_QUALITY); -#else - SetSliceContent(GetSliceIndexPayload(message.GetOrigin()), message.GetImage(), BEST_QUALITY); -#endif + unsigned int quality = QUALITY_00; + if (progressiveQuality_) + quality = QUALITY_02; + + SetSliceContent(GetSliceIndexPayload(message.GetOrigin()), + message.GetImage(), + quality); } -#if USE_SINGLE_QUALITY -#else - void OrthancSeriesVolumeProgressiveLoader::LoadJpegSliceContent(const OrthancStone::GetOrthancWebViewerJpegCommand::SuccessMessage& message) + void OrthancSeriesVolumeProgressiveLoader::LoadJpegSliceContent( + const OrthancStone::GetOrthancWebViewerJpegCommand::SuccessMessage& message) { + ORTHANC_ASSERT(progressiveQuality_, "INTERNAL ERROR: OrthancSeriesVolumeProgressiveLoader::LoadJpegSliceContent" + << " called while progressiveQuality_ is false!"); + LOG(TRACE) << "OrthancSeriesVolumeProgressiveLoader::LoadJpegSliceContent"; unsigned int quality; switch (dynamic_cast<const OrthancStone::GetOrthancWebViewerJpegCommand&>(message.GetOrigin()).GetQuality()) { case 50: - quality = LOW_QUALITY; + quality = QUALITY_00; break; case 90: - quality = MIDDLE_QUALITY; + quality = QUALITY_01; break; default: @@ -466,13 +474,14 @@ SetSliceContent(GetSliceIndexPayload(message.GetOrigin()), message.GetImage(), quality); } -#endif OrthancSeriesVolumeProgressiveLoader::OrthancSeriesVolumeProgressiveLoader( OrthancStone::ILoadersContext& loadersContext, - const boost::shared_ptr<OrthancStone::DicomVolumeImage>& volume) + boost::shared_ptr<OrthancStone::DicomVolumeImage> volume, + bool progressiveQuality) : loadersContext_(loadersContext) , active_(false) + , progressiveQuality_(progressiveQuality) , simultaneousDownloads_(4) , volume_(volume) , sorter_(new OrthancStone::BasicFetchingItemsSorter::Factory) @@ -483,12 +492,14 @@ boost::shared_ptr<OrthancSeriesVolumeProgressiveLoader> OrthancSeriesVolumeProgressiveLoader::Create( OrthancStone::ILoadersContext& loadersContext, - const boost::shared_ptr<OrthancStone::DicomVolumeImage>& volume) + boost::shared_ptr<OrthancStone::DicomVolumeImage> volume, + bool progressiveQuality) { std::auto_ptr<OrthancStone::ILoadersContext::ILock> lock(loadersContext.Lock()); boost::shared_ptr<OrthancSeriesVolumeProgressiveLoader> obj( - new OrthancSeriesVolumeProgressiveLoader(loadersContext,volume)); + new OrthancSeriesVolumeProgressiveLoader( + loadersContext, volume, progressiveQuality)); obj->Register<OrthancStone::OrthancRestApiCommand::SuccessMessage>( lock->GetOracleObservable(), @@ -498,12 +509,10 @@ lock->GetOracleObservable(), &OrthancSeriesVolumeProgressiveLoader::LoadBestQualitySliceContent); -#if USE_SINGLE_QUALITY -#else obj->Register<OrthancStone::GetOrthancWebViewerJpegCommand::SuccessMessage>( lock->GetOracleObservable(), &OrthancSeriesVolumeProgressiveLoader::LoadJpegSliceContent); -#endif + return obj; } @@ -533,10 +542,8 @@ void OrthancSeriesVolumeProgressiveLoader::LoadSeries(const std::string& seriesId) { -// LOG(TRACE) << "OrthancSeriesVolumeProgressiveLoader::LoadSeries seriesId=" << seriesId; if (active_) { -// LOG(TRACE) << "OrthancSeriesVolumeProgressiveLoader::LoadSeries NOT ACTIVE! --> ERROR"; LOG(ERROR) << "OrthancSeriesVolumeProgressiveLoader::LoadSeries(const std::string& seriesId): (active_)"; throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); }
--- a/Framework/Deprecated/Loaders/OrthancSeriesVolumeProgressiveLoader.h Tue Mar 24 21:32:35 2020 +0100 +++ b/Framework/Deprecated/Loaders/OrthancSeriesVolumeProgressiveLoader.h Wed Mar 25 14:34:27 2020 +0100 @@ -38,9 +38,6 @@ #include <boost/shared_ptr.hpp> -#define USE_SINGLE_QUALITY 1 - - namespace OrthancStone { class ILoadersContext; @@ -59,15 +56,10 @@ public IGeometryProvider { private: -#if USE_SINGLE_QUALITY - static const unsigned int SINGLE_QUALITY = 0; -#else - static const unsigned int LOW_QUALITY = 0; - static const unsigned int MIDDLE_QUALITY = 1; - static const unsigned int BEST_QUALITY = 2; -#endif - - + static const unsigned int QUALITY_00 = 0; + static const unsigned int QUALITY_01 = 1; + static const unsigned int QUALITY_02 = 2; + class ExtractedSlice; /** Helper class internal to OrthancSeriesVolumeProgressiveLoader */ @@ -119,32 +111,34 @@ void LoadBestQualitySliceContent(const OrthancStone::GetOrthancImageCommand::SuccessMessage& message); -#if USE_SINGLE_QUALITY -#else void LoadJpegSliceContent(const OrthancStone::GetOrthancWebViewerJpegCommand::SuccessMessage& message); -#endif - OrthancStone::ILoadersContext& loadersContext_; + OrthancStone::ILoadersContext& loadersContext_; bool active_; + bool progressiveQuality_; unsigned int simultaneousDownloads_; SeriesGeometry seriesGeometry_; - boost::shared_ptr<OrthancStone::DicomVolumeImage> volume_; + boost::shared_ptr<OrthancStone::DicomVolumeImage> volume_; std::unique_ptr<OrthancStone::IFetchingItemsSorter::IFactory> sorter_; - std::unique_ptr<OrthancStone::IFetchingStrategy> strategy_; - std::vector<unsigned int> slicesQuality_; - bool volumeImageReadyInHighQuality_; - - + std::unique_ptr<OrthancStone::IFetchingStrategy> strategy_; + std::vector<unsigned int> slicesQuality_; + bool volumeImageReadyInHighQuality_; + OrthancSeriesVolumeProgressiveLoader( OrthancStone::ILoadersContext& loadersContext, - const boost::shared_ptr<OrthancStone::DicomVolumeImage>& volume); + boost::shared_ptr<OrthancStone::DicomVolumeImage> volume, + bool progressiveQuality); public: ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, VolumeImageReadyInHighQuality, OrthancSeriesVolumeProgressiveLoader); + /** + See doc for the progressiveQuality_ field + */ static boost::shared_ptr<OrthancSeriesVolumeProgressiveLoader> Create( OrthancStone::ILoadersContext& context, - const boost::shared_ptr<OrthancStone::DicomVolumeImage>& volume); + boost::shared_ptr<OrthancStone::DicomVolumeImage> volume, + bool progressiveQuality = false); virtual ~OrthancSeriesVolumeProgressiveLoader();
--- a/Framework/Scene2D/OpenGLCompositor.cpp Tue Mar 24 21:32:35 2020 +0100 +++ b/Framework/Scene2D/OpenGLCompositor.cpp Wed Mar 25 14:34:27 2020 +0100 @@ -13,7 +13,7 @@ * 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/>. **/ @@ -150,11 +150,34 @@ { if (!context_.IsContextLost()) { - context_.MakeCurrent(); // this can throw if context lost! - for (Fonts::iterator it = fonts_.begin(); it != fonts_.end(); ++it) + try { - assert(it->second != NULL); - delete it->second; + try + { + context_.MakeCurrent(); // this can throw if context lost! + } + catch (...) + { + LOG(ERROR) << "context_.MakeCurrent() failed in OpenGLCompositor::~OpenGLCompositor()!"; + } + + for (Fonts::iterator it = fonts_.begin(); it != fonts_.end(); ++it) + { + try + { + + assert(it->second != NULL); + delete it->second; + } + catch (...) + { + LOG(ERROR) << "Exception thrown while deleting OpenGL-based font!"; + } + } + } + catch (...) + { + // logging threw an exception! } } }