# HG changeset patch # User Sebastien Jodogne # Date 1606151354 -3600 # Node ID 6fa05252b085cbdb7dee4025173807c528f7e31c # Parent 0621e523b6703ccc1c5ba551cde274446f3deefb don't load low-quality image if the parsed dicom file is cached by the oracle diff -r 0621e523b670 -r 6fa05252b085 Applications/Platforms/WebAssembly/WebAssemblyLoadersContext.h --- a/Applications/Platforms/WebAssembly/WebAssemblyLoadersContext.h Mon Nov 23 17:05:24 2020 +0100 +++ b/Applications/Platforms/WebAssembly/WebAssemblyLoadersContext.h Mon Nov 23 18:09:14 2020 +0100 @@ -58,6 +58,11 @@ oracle_.SetDicomCacheSize(size); } + WebAssemblyOracle::CachedInstanceAccessor* AccessCachedInstance(const std::string& sopInstanceUid) + { + return new WebAssemblyOracle::CachedInstanceAccessor(oracle_, sopInstanceUid); + } + virtual ILock* Lock() ORTHANC_OVERRIDE; }; } diff -r 0621e523b670 -r 6fa05252b085 Applications/Platforms/WebAssembly/WebAssemblyOracle.cpp --- a/Applications/Platforms/WebAssembly/WebAssemblyOracle.cpp Mon Nov 23 17:05:24 2020 +0100 +++ b/Applications/Platforms/WebAssembly/WebAssemblyOracle.cpp Mon Nov 23 18:09:14 2020 +0100 @@ -815,4 +815,71 @@ LOG(INFO) << "DCMTK support is disabled, the DICOM cache is disabled"; #endif } + + + WebAssemblyOracle::CachedInstanceAccessor::CachedInstanceAccessor(WebAssemblyOracle& oracle, + const std::string& sopInstanceUid) + { +#if ORTHANC_ENABLE_DCMTK == 1 + if (oracle.dicomCache_.get() != NULL) + { + reader_.reset(new ParsedDicomCache::Reader(*oracle.dicomCache_, BUCKET_SOP, sopInstanceUid)); + } +#endif + } + + bool WebAssemblyOracle::CachedInstanceAccessor::IsValid() const + { +#if ORTHANC_ENABLE_DCMTK == 1 + return (reader_.get() != NULL && + reader_->IsValid()); +#else + return false; +#endif + } + + const Orthanc::ParsedDicomFile& WebAssemblyOracle::CachedInstanceAccessor::GetDicom() const + { + if (IsValid()) + { +#if ORTHANC_ENABLE_DCMTK == 1 + assert(reader_.get() != NULL); + return reader_->GetDicom(); +#endif + } + else + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + } + + size_t WebAssemblyOracle::CachedInstanceAccessor::GetFileSize() const + { + if (IsValid()) + { +#if ORTHANC_ENABLE_DCMTK == 1 + assert(reader_.get() != NULL); + return reader_->GetFileSize(); +#endif + } + else + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + } + + bool WebAssemblyOracle::CachedInstanceAccessor::HasPixelData() const + { + if (IsValid()) + { +#if ORTHANC_ENABLE_DCMTK == 1 + assert(reader_.get() != NULL); + return reader_->HasPixelData(); +#endif + } + else + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + } } diff -r 0621e523b670 -r 6fa05252b085 Applications/Platforms/WebAssembly/WebAssemblyOracle.h --- a/Applications/Platforms/WebAssembly/WebAssemblyOracle.h Mon Nov 23 17:05:24 2020 +0100 +++ b/Applications/Platforms/WebAssembly/WebAssemblyOracle.h Mon Nov 23 18:09:14 2020 +0100 @@ -123,5 +123,26 @@ } void SetDicomCacheSize(size_t size); + + class CachedInstanceAccessor : public boost::noncopyable + { + private: +#if ORTHANC_ENABLE_DCMTK == 1 + std::unique_ptr reader_; +#endif + + public: + CachedInstanceAccessor(WebAssemblyOracle& oracle, + const std::string& sopInstanceUid); + + bool IsValid() const; + + const Orthanc::ParsedDicomFile& GetDicom() const; + + size_t GetFileSize() const; + + bool HasPixelData() const; + }; + }; } diff -r 0621e523b670 -r 6fa05252b085 Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp --- a/Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp Mon Nov 23 17:05:24 2020 +0100 +++ b/Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp Mon Nov 23 18:09:14 2020 +0100 @@ -584,6 +584,7 @@ FramesCache() { SetMaximumSize(100 * 1024 * 1024); // 100 MB + //SetMaximumSize(1); // DISABLE CACHE } size_t GetMaximumSize() @@ -1257,8 +1258,21 @@ virtual void Handle(const OrthancStone::ParseDicomSuccessMessage& message) const ORTHANC_OVERRIDE { + Apply(GetViewport(), message.GetDicom(), sopInstanceUid_, frameNumber_); + + if (isPrefetch_) + { + GetViewport().ScheduleNextPrefetch(); + } + } + + static void Apply(ViewerViewport& viewport, + const Orthanc::ParsedDicomFile& dicom, + const std::string& sopInstanceUid, + unsigned int frameNumber) + { Orthanc::DicomMap tags; - message.GetDicom().ExtractDicomSummary(tags, ORTHANC_STONE_MAX_TAG_LENGTH); + dicom.ExtractDicomSummary(tags, ORTHANC_STONE_MAX_TAG_LENGTH); std::string s; if (!tags.LookupStringValue(s, Orthanc::DICOM_TAG_SOP_INSTANCE_UID, false)) @@ -1267,7 +1281,7 @@ throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); } - std::unique_ptr frame(message.GetDicom().DecodeFrame(frameNumber_)); + std::unique_ptr frame(dicom.DecodeFrame(frameNumber)); if (frame.get() == NULL) { @@ -1305,13 +1319,8 @@ } assert(converted.get() != NULL); - GetViewport().RenderCurrentSceneFromCommand(*converted, sopInstanceUid_, frameNumber_, DisplayedFrameQuality_High); - GetViewport().cache_->Acquire(sopInstanceUid_, frameNumber_, converted.release(), QUALITY_FULL); - - if (isPrefetch_) - { - GetViewport().ScheduleNextPrefetch(); - } + viewport.RenderCurrentSceneFromCommand(*converted, sopInstanceUid, frameNumber, DisplayedFrameQuality_High); + viewport.cache_->Acquire(sopInstanceUid, frameNumber, converted.release(), QUALITY_FULL); } }; @@ -1343,7 +1352,7 @@ std::unique_ptr observer_; - OrthancStone::ILoadersContext& context_; + OrthancStone::WebAssemblyLoadersContext& context_; boost::shared_ptr viewport_; boost::shared_ptr loader_; OrthancStone::DicomSource source_; @@ -1653,6 +1662,27 @@ const OrthancStone::DicomInstanceParameters& instance = frames_->GetInstanceOfFrame(cursorIndex); unsigned int frameNumber = frames_->GetFrameNumberInInstance(cursorIndex); + /** + * If the full-resolution DICOM file is already available in the + * cache of the oracle, skip the loading of the "rendered". + **/ + std::unique_ptr accessor( + context_.AccessCachedInstance(instance.GetSopInstanceUid())); + + if (accessor.get() != NULL && + accessor->IsValid()) + { + try + { + SetFullDicomFrame::Apply(*this, accessor->GetDicom(), instance.GetSopInstanceUid(), frameNumber); + return; + } + catch (Orthanc::OrthancException&) + { + // This happens in the case of a JPEG2k image unsupported by DCMTK + } + } + bool isMonochrome1 = (instance.GetImageInformation().GetPhotometricInterpretation() == Orthanc::PhotometricInterpretation_Monochrome1); @@ -1707,7 +1737,7 @@ } - ViewerViewport(OrthancStone::ILoadersContext& context, + ViewerViewport(OrthancStone::WebAssemblyLoadersContext& context, const OrthancStone::DicomSource& source, const std::string& canvas, boost::shared_ptr cache, @@ -1814,24 +1844,28 @@ emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, this, false, NULL); } - static boost::shared_ptr Create(OrthancStone::ILoadersContext::ILock& lock, + static boost::shared_ptr Create(OrthancStone::WebAssemblyLoadersContext& context, const OrthancStone::DicomSource& source, const std::string& canvas, boost::shared_ptr cache, bool softwareRendering) { boost::shared_ptr viewport( - new ViewerViewport(lock.GetContext(), source, canvas, cache, softwareRendering)); - - viewport->loader_ = OrthancStone::DicomResourcesLoader::Create(lock); - viewport->Register( - *viewport->loader_, &ViewerViewport::Handle); - - viewport->Register( - lock.GetOracleObservable(), &ViewerViewport::Handle); - - viewport->Register( - lock.GetOracleObservable(), &ViewerViewport::Handle); + new ViewerViewport(context, source, canvas, cache, softwareRendering)); + + { + std::unique_ptr lock(context.Lock()); + + viewport->loader_ = OrthancStone::DicomResourcesLoader::Create(*lock); + viewport->Register( + *viewport->loader_, &ViewerViewport::Handle); + + viewport->Register( + lock->GetOracleObservable(), &ViewerViewport::Handle); + + viewport->Register( + lock->GetOracleObservable(), &ViewerViewport::Handle); + } return viewport; } @@ -2482,9 +2516,8 @@ Viewports::iterator found = allViewports_.find(canvas); if (found == allViewports_.end()) { - std::unique_ptr lock(context_->Lock()); boost::shared_ptr viewport( - ViewerViewport::Create(*lock, source_, canvas, cache_, softwareRendering_)); + ViewerViewport::Create(*context_, source_, canvas, cache_, softwareRendering_)); viewport->SetMouseButtonActions(leftButtonAction_, middleButtonAction_, rightButtonAction_); viewport->AcquireObserver(new WebAssemblyObserver); viewport->SetAnnotations(annotations_);