Mercurial > hg > orthanc-stone
diff Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp @ 1924:f4050908c6bc
display of overlays
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 23 Mar 2022 12:24:35 +0100 |
parents | bd527bbc34df |
children | a7a77488ddb1 |
line wrap: on
line diff
--- a/Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp Tue Mar 22 17:39:19 2022 +0100 +++ b/Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp Wed Mar 23 12:24:35 2022 +0100 @@ -1462,6 +1462,86 @@ +class OverlaysRegistry : public boost::noncopyable +{ +private: + typedef std::map<std::string, OrthancStone::LookupTableTextureSceneLayer*> Content; + + Content content_; + +public: + ~OverlaysRegistry() + { + for (Content::iterator it = content_.begin(); it != content_.end(); ++it) + { + assert(it->second != NULL); + delete it->second; + } + } + + static OverlaysRegistry& GetInstance() + { + static OverlaysRegistry singleton; + return singleton; + } + + void Register(const std::string& sopInstanceUid, + const OrthancStone::DicomInstanceParameters& parameters, + int overlayX, + int overlayY, + const Orthanc::ImageAccessor& overlay) + { + // Don't register twice the same overlay + Content::iterator found = content_.find(sopInstanceUid); + if (found == content_.end()) + { + content_[sopInstanceUid] = parameters.CreateOverlayTexture(overlayX, overlayY, overlay); + } + } + + class Accessor : public boost::noncopyable + { + private: + const OrthancStone::LookupTableTextureSceneLayer* texture_; + + public: + Accessor(const OverlaysRegistry& registry, + const std::string& sopInstanceUid) + { + Content::const_iterator found = registry.content_.find(sopInstanceUid); + if (found == registry.content_.end()) + { + texture_ = NULL; + } + else + { + assert(found->second != NULL); + texture_ = found->second; + } + } + + bool IsValid() const + { + return texture_ != NULL; + } + + OrthancStone::LookupTableTextureSceneLayer* CreateTexture() const + { + if (texture_ == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + else + { + return dynamic_cast<OrthancStone::LookupTableTextureSceneLayer*>(texture_->Clone()); + } + } + }; +}; + + + + class ViewerViewport : public OrthancStone::ObserverBase<ViewerViewport> { public: @@ -1505,9 +1585,10 @@ private: static const int LAYER_TEXTURE = 0; - static const int LAYER_REFERENCE_LINES = 1; - static const int LAYER_ANNOTATIONS_OSIRIX = 2; - static const int LAYER_ANNOTATIONS_STONE = 3; + static const int LAYER_OVERLAY = 1; + static const int LAYER_REFERENCE_LINES = 2; + static const int LAYER_ANNOTATIONS_OSIRIX = 3; + static const int LAYER_ANNOTATIONS_STONE = 4; class ICommand : public Orthanc::IDynamicObject @@ -1823,6 +1904,8 @@ Orthanc::DicomMap tags; dicom.ExtractDicomSummary(tags, ORTHANC_STONE_MAX_TAG_LENGTH); + OrthancStone::DicomInstanceParameters parameters(tags); + std::unique_ptr<Orthanc::ImageAccessor> converted; if (frameProtection->GetFormat() == Orthanc::PixelFormat_RGB24) @@ -1831,25 +1914,28 @@ } else { - double a = 1; - double b = 0; - - double doseScaling; - if (tags.ParseDouble(doseScaling, Orthanc::DICOM_TAG_DOSE_GRID_SCALING)) - { - a = doseScaling; - } - - double rescaleIntercept, rescaleSlope; - dicom.GetRescale(rescaleIntercept, rescaleSlope, frameNumber); - a *= rescaleSlope; - b = rescaleIntercept; - converted.reset(new Orthanc::Image(Orthanc::PixelFormat_Float32, frameProtection->GetWidth(), frameProtection->GetHeight(), false)); Orthanc::ImageProcessing::Convert(*converted, *frameProtection); - Orthanc::ImageProcessing::ShiftScale2(*converted, b, a, false); + parameters.ApplyRescaleAndDoseScaling(*converted, false /* don't use double */); } + try + { + int x, y; + std::unique_ptr<Orthanc::ImageAccessor> overlay(dicom.DecodeAllOverlays(x, y)); + + if (overlay.get() != NULL && + overlay->GetWidth() > 0 && + overlay->GetHeight() > 0) + { + OverlaysRegistry::GetInstance().Register(sopInstanceUid, parameters, x, y, *overlay); + } + } + catch (Orthanc::OrthancException& e) + { + LOG(ERROR) << "Cannot decode overlays from instance " << sopInstanceUid; + } + assert(converted.get() != NULL); viewport.RenderCurrentSceneFromCommand(*converted, sopInstanceUid, frameNumber, DisplayedFrameQuality_High); viewport.framesCache_->Acquire(sopInstanceUid, frameNumber, converted.release(), QUALITY_FULL); @@ -2107,6 +2193,18 @@ layer->SetPixelSpacing(pixelSpacingX, pixelSpacingY); } + std::unique_ptr<OrthancStone::LookupTableTextureSceneLayer> overlay; + + { + OverlaysRegistry::Accessor accessor(OverlaysRegistry::GetInstance(), instance.GetSopInstanceUid()); + if (accessor.IsValid()) + { + overlay.reset(accessor.CreateTexture()); + overlay->SetFlipX(flipX_); + overlay->SetFlipY(flipY_); + } + } + std::unique_ptr<OrthancStone::MacroSceneLayer> annotationsOsiriX; if (osiriXAnnotations_) @@ -2139,6 +2237,15 @@ scene.SetLayer(LAYER_TEXTURE, layer.release()); + if (overlay.get() != NULL) + { + scene.SetLayer(LAYER_OVERLAY, overlay.release()); + } + else + { + scene.DeleteLayer(LAYER_OVERLAY); + } + if (annotationsOsiriX.get() != NULL) { scene.SetLayer(LAYER_ANNOTATIONS_OSIRIX, annotationsOsiriX.release()); @@ -2339,6 +2446,15 @@ layer.SetFlipX(flipX_); layer.SetFlipY(flipY_); } + + { + OrthancStone::TextureBaseSceneLayer& layer = + dynamic_cast<OrthancStone::TextureBaseSceneLayer&>( + lock->GetController().GetScene().GetLayer(LAYER_OVERLAY)); + + layer.SetFlipX(flipX_); + layer.SetFlipY(flipY_); + } lock->Invalidate(); }