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