Mercurial > hg > orthanc-stone
comparison 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 |
comparison
equal
deleted
inserted
replaced
1923:f4cdcba8c32a | 1924:f4050908c6bc |
---|---|
1460 } | 1460 } |
1461 }; | 1461 }; |
1462 | 1462 |
1463 | 1463 |
1464 | 1464 |
1465 class OverlaysRegistry : public boost::noncopyable | |
1466 { | |
1467 private: | |
1468 typedef std::map<std::string, OrthancStone::LookupTableTextureSceneLayer*> Content; | |
1469 | |
1470 Content content_; | |
1471 | |
1472 public: | |
1473 ~OverlaysRegistry() | |
1474 { | |
1475 for (Content::iterator it = content_.begin(); it != content_.end(); ++it) | |
1476 { | |
1477 assert(it->second != NULL); | |
1478 delete it->second; | |
1479 } | |
1480 } | |
1481 | |
1482 static OverlaysRegistry& GetInstance() | |
1483 { | |
1484 static OverlaysRegistry singleton; | |
1485 return singleton; | |
1486 } | |
1487 | |
1488 void Register(const std::string& sopInstanceUid, | |
1489 const OrthancStone::DicomInstanceParameters& parameters, | |
1490 int overlayX, | |
1491 int overlayY, | |
1492 const Orthanc::ImageAccessor& overlay) | |
1493 { | |
1494 // Don't register twice the same overlay | |
1495 Content::iterator found = content_.find(sopInstanceUid); | |
1496 if (found == content_.end()) | |
1497 { | |
1498 content_[sopInstanceUid] = parameters.CreateOverlayTexture(overlayX, overlayY, overlay); | |
1499 } | |
1500 } | |
1501 | |
1502 class Accessor : public boost::noncopyable | |
1503 { | |
1504 private: | |
1505 const OrthancStone::LookupTableTextureSceneLayer* texture_; | |
1506 | |
1507 public: | |
1508 Accessor(const OverlaysRegistry& registry, | |
1509 const std::string& sopInstanceUid) | |
1510 { | |
1511 Content::const_iterator found = registry.content_.find(sopInstanceUid); | |
1512 if (found == registry.content_.end()) | |
1513 { | |
1514 texture_ = NULL; | |
1515 } | |
1516 else | |
1517 { | |
1518 assert(found->second != NULL); | |
1519 texture_ = found->second; | |
1520 } | |
1521 } | |
1522 | |
1523 bool IsValid() const | |
1524 { | |
1525 return texture_ != NULL; | |
1526 } | |
1527 | |
1528 OrthancStone::LookupTableTextureSceneLayer* CreateTexture() const | |
1529 { | |
1530 if (texture_ == NULL) | |
1531 { | |
1532 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
1533 } | |
1534 else | |
1535 { | |
1536 return dynamic_cast<OrthancStone::LookupTableTextureSceneLayer*>(texture_->Clone()); | |
1537 } | |
1538 } | |
1539 }; | |
1540 }; | |
1541 | |
1542 | |
1543 | |
1544 | |
1465 class ViewerViewport : public OrthancStone::ObserverBase<ViewerViewport> | 1545 class ViewerViewport : public OrthancStone::ObserverBase<ViewerViewport> |
1466 { | 1546 { |
1467 public: | 1547 public: |
1468 class IObserver : public boost::noncopyable | 1548 class IObserver : public boost::noncopyable |
1469 { | 1549 { |
1503 virtual void SignalStoneAnnotationRemoved(const ViewerViewport& viewport) = 0; | 1583 virtual void SignalStoneAnnotationRemoved(const ViewerViewport& viewport) = 0; |
1504 }; | 1584 }; |
1505 | 1585 |
1506 private: | 1586 private: |
1507 static const int LAYER_TEXTURE = 0; | 1587 static const int LAYER_TEXTURE = 0; |
1508 static const int LAYER_REFERENCE_LINES = 1; | 1588 static const int LAYER_OVERLAY = 1; |
1509 static const int LAYER_ANNOTATIONS_OSIRIX = 2; | 1589 static const int LAYER_REFERENCE_LINES = 2; |
1510 static const int LAYER_ANNOTATIONS_STONE = 3; | 1590 static const int LAYER_ANNOTATIONS_OSIRIX = 3; |
1591 static const int LAYER_ANNOTATIONS_STONE = 4; | |
1511 | 1592 |
1512 | 1593 |
1513 class ICommand : public Orthanc::IDynamicObject | 1594 class ICommand : public Orthanc::IDynamicObject |
1514 { | 1595 { |
1515 private: | 1596 private: |
1821 std::unique_ptr<Orthanc::ImageAccessor> frameProtection(f); | 1902 std::unique_ptr<Orthanc::ImageAccessor> frameProtection(f); |
1822 | 1903 |
1823 Orthanc::DicomMap tags; | 1904 Orthanc::DicomMap tags; |
1824 dicom.ExtractDicomSummary(tags, ORTHANC_STONE_MAX_TAG_LENGTH); | 1905 dicom.ExtractDicomSummary(tags, ORTHANC_STONE_MAX_TAG_LENGTH); |
1825 | 1906 |
1907 OrthancStone::DicomInstanceParameters parameters(tags); | |
1908 | |
1826 std::unique_ptr<Orthanc::ImageAccessor> converted; | 1909 std::unique_ptr<Orthanc::ImageAccessor> converted; |
1827 | 1910 |
1828 if (frameProtection->GetFormat() == Orthanc::PixelFormat_RGB24) | 1911 if (frameProtection->GetFormat() == Orthanc::PixelFormat_RGB24) |
1829 { | 1912 { |
1830 converted.reset(frameProtection.release()); | 1913 converted.reset(frameProtection.release()); |
1831 } | 1914 } |
1832 else | 1915 else |
1833 { | 1916 { |
1834 double a = 1; | |
1835 double b = 0; | |
1836 | |
1837 double doseScaling; | |
1838 if (tags.ParseDouble(doseScaling, Orthanc::DICOM_TAG_DOSE_GRID_SCALING)) | |
1839 { | |
1840 a = doseScaling; | |
1841 } | |
1842 | |
1843 double rescaleIntercept, rescaleSlope; | |
1844 dicom.GetRescale(rescaleIntercept, rescaleSlope, frameNumber); | |
1845 a *= rescaleSlope; | |
1846 b = rescaleIntercept; | |
1847 | |
1848 converted.reset(new Orthanc::Image(Orthanc::PixelFormat_Float32, frameProtection->GetWidth(), frameProtection->GetHeight(), false)); | 1917 converted.reset(new Orthanc::Image(Orthanc::PixelFormat_Float32, frameProtection->GetWidth(), frameProtection->GetHeight(), false)); |
1849 Orthanc::ImageProcessing::Convert(*converted, *frameProtection); | 1918 Orthanc::ImageProcessing::Convert(*converted, *frameProtection); |
1850 Orthanc::ImageProcessing::ShiftScale2(*converted, b, a, false); | 1919 parameters.ApplyRescaleAndDoseScaling(*converted, false /* don't use double */); |
1851 } | 1920 } |
1852 | 1921 |
1922 try | |
1923 { | |
1924 int x, y; | |
1925 std::unique_ptr<Orthanc::ImageAccessor> overlay(dicom.DecodeAllOverlays(x, y)); | |
1926 | |
1927 if (overlay.get() != NULL && | |
1928 overlay->GetWidth() > 0 && | |
1929 overlay->GetHeight() > 0) | |
1930 { | |
1931 OverlaysRegistry::GetInstance().Register(sopInstanceUid, parameters, x, y, *overlay); | |
1932 } | |
1933 } | |
1934 catch (Orthanc::OrthancException& e) | |
1935 { | |
1936 LOG(ERROR) << "Cannot decode overlays from instance " << sopInstanceUid; | |
1937 } | |
1938 | |
1853 assert(converted.get() != NULL); | 1939 assert(converted.get() != NULL); |
1854 viewport.RenderCurrentSceneFromCommand(*converted, sopInstanceUid, frameNumber, DisplayedFrameQuality_High); | 1940 viewport.RenderCurrentSceneFromCommand(*converted, sopInstanceUid, frameNumber, DisplayedFrameQuality_High); |
1855 viewport.framesCache_->Acquire(sopInstanceUid, frameNumber, converted.release(), QUALITY_FULL); | 1941 viewport.framesCache_->Acquire(sopInstanceUid, frameNumber, converted.release(), QUALITY_FULL); |
1856 } | 1942 } |
1857 }; | 1943 }; |
2105 else | 2191 else |
2106 { | 2192 { |
2107 layer->SetPixelSpacing(pixelSpacingX, pixelSpacingY); | 2193 layer->SetPixelSpacing(pixelSpacingX, pixelSpacingY); |
2108 } | 2194 } |
2109 | 2195 |
2196 std::unique_ptr<OrthancStone::LookupTableTextureSceneLayer> overlay; | |
2197 | |
2198 { | |
2199 OverlaysRegistry::Accessor accessor(OverlaysRegistry::GetInstance(), instance.GetSopInstanceUid()); | |
2200 if (accessor.IsValid()) | |
2201 { | |
2202 overlay.reset(accessor.CreateTexture()); | |
2203 overlay->SetFlipX(flipX_); | |
2204 overlay->SetFlipY(flipY_); | |
2205 } | |
2206 } | |
2207 | |
2110 std::unique_ptr<OrthancStone::MacroSceneLayer> annotationsOsiriX; | 2208 std::unique_ptr<OrthancStone::MacroSceneLayer> annotationsOsiriX; |
2111 | 2209 |
2112 if (osiriXAnnotations_) | 2210 if (osiriXAnnotations_) |
2113 { | 2211 { |
2114 std::set<size_t> a; | 2212 std::set<size_t> a; |
2136 std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_->Lock()); | 2234 std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_->Lock()); |
2137 | 2235 |
2138 OrthancStone::Scene2D& scene = lock->GetController().GetScene(); | 2236 OrthancStone::Scene2D& scene = lock->GetController().GetScene(); |
2139 | 2237 |
2140 scene.SetLayer(LAYER_TEXTURE, layer.release()); | 2238 scene.SetLayer(LAYER_TEXTURE, layer.release()); |
2239 | |
2240 if (overlay.get() != NULL) | |
2241 { | |
2242 scene.SetLayer(LAYER_OVERLAY, overlay.release()); | |
2243 } | |
2244 else | |
2245 { | |
2246 scene.DeleteLayer(LAYER_OVERLAY); | |
2247 } | |
2141 | 2248 |
2142 if (annotationsOsiriX.get() != NULL) | 2249 if (annotationsOsiriX.get() != NULL) |
2143 { | 2250 { |
2144 scene.SetLayer(LAYER_ANNOTATIONS_OSIRIX, annotationsOsiriX.release()); | 2251 scene.SetLayer(LAYER_ANNOTATIONS_OSIRIX, annotationsOsiriX.release()); |
2145 } | 2252 } |
2333 | 2440 |
2334 { | 2441 { |
2335 OrthancStone::TextureBaseSceneLayer& layer = | 2442 OrthancStone::TextureBaseSceneLayer& layer = |
2336 dynamic_cast<OrthancStone::TextureBaseSceneLayer&>( | 2443 dynamic_cast<OrthancStone::TextureBaseSceneLayer&>( |
2337 lock->GetController().GetScene().GetLayer(LAYER_TEXTURE)); | 2444 lock->GetController().GetScene().GetLayer(LAYER_TEXTURE)); |
2445 | |
2446 layer.SetFlipX(flipX_); | |
2447 layer.SetFlipY(flipY_); | |
2448 } | |
2449 | |
2450 { | |
2451 OrthancStone::TextureBaseSceneLayer& layer = | |
2452 dynamic_cast<OrthancStone::TextureBaseSceneLayer&>( | |
2453 lock->GetController().GetScene().GetLayer(LAYER_OVERLAY)); | |
2338 | 2454 |
2339 layer.SetFlipX(flipX_); | 2455 layer.SetFlipX(flipX_); |
2340 layer.SetFlipY(flipY_); | 2456 layer.SetFlipY(flipY_); |
2341 } | 2457 } |
2342 | 2458 |