# HG changeset patch # User Benjamin Golinvaux # Date 1585143267 -3600 # Node ID 4f8db2d202c8cdfe0b75871b63ef3a66bf4c77bf # Parent 55166e57a77c8b2e5c1bcc546a67133bc0b1ab3d 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. diff -r 55166e57a77c -r 4f8db2d202c8 Framework/Deprecated/Loaders/LoaderCache.cpp --- 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 volumeImage(new OrthancStone::DicomVolumeImage); boost::shared_ptr 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; } diff -r 55166e57a77c -r 4f8db2d202c8 Framework/Deprecated/Loaders/OrthancSeriesVolumeProgressiveLoader.cpp --- 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 command; -#if USE_SINGLE_QUALITY -#else - if (quality == BEST_QUALITY) -#endif + if (!progressiveQuality_ || quality == QUALITY_02) { std::unique_ptr 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 tmp(new OrthancStone::GetOrthancWebViewerJpegCommand); + std::unique_ptr 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(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(slicesCount)), - SINGLE_QUALITY)); -#else - strategy_.reset(new OrthancStone::BasicFetchingStrategy( - sorter_->CreateSorter(static_cast(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(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& volume) + boost::shared_ptr 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::Create( OrthancStone::ILoadersContext& loadersContext, - const boost::shared_ptr& volume) + boost::shared_ptr volume, + bool progressiveQuality) { std::auto_ptr lock(loadersContext.Lock()); boost::shared_ptr obj( - new OrthancSeriesVolumeProgressiveLoader(loadersContext,volume)); + new OrthancSeriesVolumeProgressiveLoader( + loadersContext, volume, progressiveQuality)); obj->Register( lock->GetOracleObservable(), @@ -498,12 +509,10 @@ lock->GetOracleObservable(), &OrthancSeriesVolumeProgressiveLoader::LoadBestQualitySliceContent); -#if USE_SINGLE_QUALITY -#else obj->Register( 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); } diff -r 55166e57a77c -r 4f8db2d202c8 Framework/Deprecated/Loaders/OrthancSeriesVolumeProgressiveLoader.h --- 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 -#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 volume_; + boost::shared_ptr volume_; std::unique_ptr sorter_; - std::unique_ptr strategy_; - std::vector slicesQuality_; - bool volumeImageReadyInHighQuality_; - - + std::unique_ptr strategy_; + std::vector slicesQuality_; + bool volumeImageReadyInHighQuality_; + OrthancSeriesVolumeProgressiveLoader( OrthancStone::ILoadersContext& loadersContext, - const boost::shared_ptr& volume); + boost::shared_ptr volume, + bool progressiveQuality); public: ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, VolumeImageReadyInHighQuality, OrthancSeriesVolumeProgressiveLoader); + /** + See doc for the progressiveQuality_ field + */ static boost::shared_ptr Create( OrthancStone::ILoadersContext& context, - const boost::shared_ptr& volume); + boost::shared_ptr volume, + bool progressiveQuality = false); virtual ~OrthancSeriesVolumeProgressiveLoader(); diff -r 55166e57a77c -r 4f8db2d202c8 Framework/Scene2D/OpenGLCompositor.cpp --- 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 . **/ @@ -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! } } }