comparison Samples/Sdl/Loader.cpp @ 711:70d1c28560b3

simplification
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 20 May 2019 13:40:23 +0200
parents 3046a603eebf
children f334b098b243
comparison
equal deleted inserted replaced
710:3046a603eebf 711:70d1c28560b3
1403 1403
1404 1404
1405 class VolumeSeriesOrthancLoader : public OrthancStone::IObserver 1405 class VolumeSeriesOrthancLoader : public OrthancStone::IObserver
1406 { 1406 {
1407 private: 1407 private:
1408 class MessageHandler : public Orthanc::IDynamicObject 1408 static const unsigned int LOW_QUALITY = 0;
1409 { 1409 static const unsigned int MIDDLE_QUALITY = 1;
1410 public: 1410 static const unsigned int BEST_QUALITY = 2;
1411 virtual void Handle(const Json::Value& body) const 1411
1412 { 1412
1413 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); 1413 static unsigned int GetSliceIndexPayload(const OracleCommandWithPayload& command)
1414 } 1414 {
1415 1415 return dynamic_cast< const Orthanc::SingleValueObject<unsigned int>& >(command.GetPayload()).GetValue();
1416 virtual void Handle(const Orthanc::ImageAccessor& image,
1417 unsigned int quality) const
1418 {
1419 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
1420 }
1421 };
1422
1423 void Handle(const OrthancRestApiCommand::SuccessMessage& message)
1424 {
1425 Json::Value body;
1426 message.ParseJsonBody(body);
1427
1428 if (body.type() != Json::objectValue)
1429 {
1430 throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol);
1431 }
1432
1433 dynamic_cast<const MessageHandler&>(message.GetOrigin().GetPayload()).Handle(body);
1434 }
1435
1436 void Handle(const Refactoring::GetOrthancImageCommand::SuccessMessage& message)
1437 {
1438 dynamic_cast<const MessageHandler&>(message.GetOrigin().GetPayload()).Handle(message.GetImage(), 2 /* best quality */);
1439 }
1440
1441 void Handle(const Refactoring::GetOrthancWebViewerJpegCommand::SuccessMessage& message)
1442 {
1443 unsigned int quality;
1444
1445 switch (message.GetOrigin().GetQuality())
1446 {
1447 case 50:
1448 quality = 0;
1449 break;
1450
1451 case 95:
1452 quality = 1;
1453 break;
1454
1455 default:
1456 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
1457 }
1458
1459 dynamic_cast<const MessageHandler&>(message.GetOrigin().GetPayload()).Handle(message.GetImage(), quality);
1460 }
1461
1462
1463 class LoadSliceImage : public MessageHandler
1464 {
1465 private:
1466 VolumeSeriesOrthancLoader& that_;
1467 size_t slice_;
1468
1469 public:
1470 LoadSliceImage(VolumeSeriesOrthancLoader& that,
1471 size_t slice) :
1472 that_(that),
1473 slice_(slice)
1474 {
1475 }
1476
1477 virtual void Handle(const Orthanc::ImageAccessor& image,
1478 unsigned int quality) const
1479 {
1480 that_.SetSliceContent(slice_, image, quality);
1481 }
1482 };
1483
1484
1485 class LoadSeriesGeometryHandler : public MessageHandler
1486 {
1487 private:
1488 VolumeSeriesOrthancLoader& that_;
1489
1490 public:
1491 LoadSeriesGeometryHandler(VolumeSeriesOrthancLoader& that) :
1492 that_(that)
1493 {
1494 }
1495
1496 virtual void Handle(const Json::Value& body) const
1497 {
1498 that_.SetGeometry(body);
1499 }
1500 };
1501
1502
1503 void SetGeometry(const Json::Value& body)
1504 {
1505 {
1506 Json::Value::Members instances = body.getMemberNames();
1507
1508 OrthancStone::SlicesSorter slices;
1509
1510 for (size_t i = 0; i < instances.size(); i++)
1511 {
1512 Orthanc::DicomMap dicom;
1513 dicom.FromDicomAsJson(body[instances[i]]);
1514
1515 std::auto_ptr<DicomInstanceParameters> instance(new DicomInstanceParameters(dicom));
1516 instance->SetOrthancInstanceIdentifier(instances[i]);
1517
1518 OrthancStone::CoordinateSystem3D geometry = instance->GetGeometry();
1519 slices.AddSlice(geometry, instance.release());
1520 }
1521
1522 volume_.SetGeometry(slices);
1523 }
1524
1525 if (volume_.GetSlicesCount() != 0)
1526 {
1527 strategy_.reset(new OrthancStone::BasicFetchingStrategy(
1528 new OrthancStone::BasicFetchingItemsSorter(volume_.GetSlicesCount()), 2));
1529
1530 for (unsigned int i = 0; i < 4; i++) // Schedule up to 4 simultaneous downloads (TODO - parameter)
1531 {
1532 ScheduleNextSliceDownload();
1533 }
1534 }
1535 } 1416 }
1536 1417
1537 1418
1538 void ScheduleNextSliceDownload() 1419 void ScheduleNextSliceDownload()
1539 { 1420 {
1541 1422
1542 unsigned int sliceIndex, quality; 1423 unsigned int sliceIndex, quality;
1543 1424
1544 if (strategy_->GetNext(sliceIndex, quality)) 1425 if (strategy_->GetNext(sliceIndex, quality))
1545 { 1426 {
1546 assert(quality <= 2); 1427 assert(quality <= BEST_QUALITY);
1547 1428
1548 const DicomInstanceParameters& slice = volume_.GetSliceParameters(sliceIndex); 1429 const DicomInstanceParameters& slice = volume_.GetSliceParameters(sliceIndex);
1549 1430
1550 const std::string& instance = slice.GetOrthancInstanceIdentifier(); 1431 const std::string& instance = slice.GetOrthancInstanceIdentifier();
1551 if (instance.empty()) 1432 if (instance.empty())
1552 { 1433 {
1553 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); 1434 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
1554 } 1435 }
1555 1436
1556 std::auto_ptr<Refactoring::IOracleCommand> command; 1437 std::auto_ptr<Refactoring::OracleCommandWithPayload> command;
1557 1438
1558 if (quality == 2) // Best quality 1439 if (quality == BEST_QUALITY)
1559 { 1440 {
1560 std::auto_ptr<Refactoring::GetOrthancImageCommand> tmp( 1441 std::auto_ptr<Refactoring::GetOrthancImageCommand> tmp(
1561 new Refactoring::GetOrthancImageCommand); 1442 new Refactoring::GetOrthancImageCommand);
1562 tmp->SetHttpHeader("Accept-Encoding", "gzip"); 1443 tmp->SetHttpHeader("Accept-Encoding", "gzip");
1563 tmp->SetHttpHeader("Accept", std::string(Orthanc::EnumerationToString(Orthanc::MimeType_Pam))); 1444 tmp->SetHttpHeader("Accept", std::string(Orthanc::EnumerationToString(Orthanc::MimeType_Pam)));
1564 tmp->SetInstanceUri(instance, slice.GetExpectedPixelFormat()); 1445 tmp->SetInstanceUri(instance, slice.GetExpectedPixelFormat());
1565 tmp->SetExpectedPixelFormat(slice.GetExpectedPixelFormat()); 1446 tmp->SetExpectedPixelFormat(slice.GetExpectedPixelFormat());
1566 tmp->SetPayload(new LoadSliceImage(*this, sliceIndex));
1567 command.reset(tmp.release()); 1447 command.reset(tmp.release());
1568 } 1448 }
1569 else 1449 else
1570 { 1450 {
1571 std::auto_ptr<Refactoring::GetOrthancWebViewerJpegCommand> tmp( 1451 std::auto_ptr<Refactoring::GetOrthancWebViewerJpegCommand> tmp(
1572 new Refactoring::GetOrthancWebViewerJpegCommand); 1452 new Refactoring::GetOrthancWebViewerJpegCommand);
1573 tmp->SetHttpHeader("Accept-Encoding", "gzip"); 1453 tmp->SetHttpHeader("Accept-Encoding", "gzip");
1574 tmp->SetInstance(instance); 1454 tmp->SetInstance(instance);
1575 tmp->SetQuality((quality == 0 ? 50 : 95)); 1455 tmp->SetQuality((quality == 0 ? 50 : 95));
1576 tmp->SetExpectedPixelFormat(slice.GetExpectedPixelFormat()); 1456 tmp->SetExpectedPixelFormat(slice.GetExpectedPixelFormat());
1577 tmp->SetPayload(new LoadSliceImage(*this, sliceIndex));
1578 command.reset(tmp.release()); 1457 command.reset(tmp.release());
1579 } 1458 }
1580 1459
1460 command->SetPayload(new Orthanc::SingleValueObject<unsigned int>(sliceIndex));
1581 oracle_.Schedule(*this, command.release()); 1461 oracle_.Schedule(*this, command.release());
1582 } 1462 }
1583 } 1463 }
1584 1464
1585 1465
1586 void SetSliceContent(unsigned int sliceIndex, 1466 void LoadGeometry(const OrthancRestApiCommand::SuccessMessage& message)
1587 const Orthanc::ImageAccessor& image, 1467 {
1588 unsigned int quality) 1468 Json::Value body;
1589 { 1469 message.ParseJsonBody(body);
1590 assert(quality <= 2);
1591 1470
1592 volume_.SetSliceContent(sliceIndex, image, quality); 1471 if (body.type() != Json::objectValue)
1472 {
1473 throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol);
1474 }
1475
1476 {
1477 Json::Value::Members instances = body.getMemberNames();
1478
1479 OrthancStone::SlicesSorter slices;
1480
1481 for (size_t i = 0; i < instances.size(); i++)
1482 {
1483 Orthanc::DicomMap dicom;
1484 dicom.FromDicomAsJson(body[instances[i]]);
1485
1486 std::auto_ptr<DicomInstanceParameters> instance(new DicomInstanceParameters(dicom));
1487 instance->SetOrthancInstanceIdentifier(instances[i]);
1488
1489 OrthancStone::CoordinateSystem3D geometry = instance->GetGeometry();
1490 slices.AddSlice(geometry, instance.release());
1491 }
1492
1493 volume_.SetGeometry(slices);
1494 }
1495
1496 if (volume_.GetSlicesCount() != 0)
1497 {
1498 strategy_.reset(new OrthancStone::BasicFetchingStrategy(
1499 new OrthancStone::BasicFetchingItemsSorter(volume_.GetSlicesCount()), BEST_QUALITY));
1500
1501 for (unsigned int i = 0; i < 4; i++) // Schedule up to 4 simultaneous downloads (TODO - parameter)
1502 {
1503 ScheduleNextSliceDownload();
1504 }
1505 }
1506 }
1507
1508
1509 void LoadBestQualitySliceContent(const Refactoring::GetOrthancImageCommand::SuccessMessage& message)
1510 {
1511 volume_.SetSliceContent(GetSliceIndexPayload(message.GetOrigin()),
1512 message.GetImage(), BEST_QUALITY);
1513
1593 ScheduleNextSliceDownload(); 1514 ScheduleNextSliceDownload();
1594 } 1515 }
1595 1516
1517
1518 void LoadJpegSliceContent(const Refactoring::GetOrthancWebViewerJpegCommand::SuccessMessage& message)
1519 {
1520 unsigned int quality;
1521
1522 switch (message.GetOrigin().GetQuality())
1523 {
1524 case 50:
1525 quality = LOW_QUALITY;
1526 break;
1527
1528 case 90:
1529 quality = MIDDLE_QUALITY;
1530 break;
1531
1532 default:
1533 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
1534 }
1535
1536 volume_.SetSliceContent(GetSliceIndexPayload(message.GetOrigin()), message.GetImage(), quality);
1537
1538 ScheduleNextSliceDownload();
1539 }
1540
1596 1541
1597 IOracle& oracle_; 1542 IOracle& oracle_;
1598 bool active_; 1543 bool active_;
1599 DicomVolumeImage volume_; 1544 DicomVolumeImage volume_;
1600 1545
1607 oracle_(oracle), 1552 oracle_(oracle),
1608 active_(false) 1553 active_(false)
1609 { 1554 {
1610 oracleObservable.RegisterObserverCallback( 1555 oracleObservable.RegisterObserverCallback(
1611 new OrthancStone::Callable<VolumeSeriesOrthancLoader, OrthancRestApiCommand::SuccessMessage> 1556 new OrthancStone::Callable<VolumeSeriesOrthancLoader, OrthancRestApiCommand::SuccessMessage>
1612 (*this, &VolumeSeriesOrthancLoader::Handle)); 1557 (*this, &VolumeSeriesOrthancLoader::LoadGeometry));
1613 1558
1614 oracleObservable.RegisterObserverCallback( 1559 oracleObservable.RegisterObserverCallback(
1615 new OrthancStone::Callable<VolumeSeriesOrthancLoader, GetOrthancImageCommand::SuccessMessage> 1560 new OrthancStone::Callable<VolumeSeriesOrthancLoader, GetOrthancImageCommand::SuccessMessage>
1616 (*this, &VolumeSeriesOrthancLoader::Handle)); 1561 (*this, &VolumeSeriesOrthancLoader::LoadBestQualitySliceContent));
1617 1562
1618 oracleObservable.RegisterObserverCallback( 1563 oracleObservable.RegisterObserverCallback(
1619 new OrthancStone::Callable<VolumeSeriesOrthancLoader, GetOrthancWebViewerJpegCommand::SuccessMessage> 1564 new OrthancStone::Callable<VolumeSeriesOrthancLoader, GetOrthancWebViewerJpegCommand::SuccessMessage>
1620 (*this, &VolumeSeriesOrthancLoader::Handle)); 1565 (*this, &VolumeSeriesOrthancLoader::LoadJpegSliceContent));
1621 } 1566 }
1622 1567
1623 void LoadSeries(const std::string& seriesId) 1568 void LoadSeries(const std::string& seriesId)
1624 { 1569 {
1625 if (active_) 1570 if (active_)
1629 1574
1630 active_ = true; 1575 active_ = true;
1631 1576
1632 std::auto_ptr<Refactoring::OrthancRestApiCommand> command(new Refactoring::OrthancRestApiCommand); 1577 std::auto_ptr<Refactoring::OrthancRestApiCommand> command(new Refactoring::OrthancRestApiCommand);
1633 command->SetUri("/series/" + seriesId + "/instances-tags"); 1578 command->SetUri("/series/" + seriesId + "/instances-tags");
1634 command->SetPayload(new LoadSeriesGeometryHandler(*this));
1635 1579
1636 oracle_.Schedule(*this, command.release()); 1580 oracle_.Schedule(*this, command.release());
1637 } 1581 }
1638 }; 1582 };
1639 1583
1662 } 1606 }
1663 #endif 1607 #endif
1664 1608
1665 1609
1666 /* class VolumeSlicerBase : public IVolumeSlicer 1610 /* class VolumeSlicerBase : public IVolumeSlicer
1667 { 1611 {
1668 private: 1612 private:
1669 OrthancStone::Scene2D& scene_; 1613 OrthancStone::Scene2D& scene_;
1670 int layerDepth_; 1614 int layerDepth_;
1671 bool first_; 1615 bool first_;
1672 OrthancStone::CoordinateSystem3D lastPlane_; 1616 OrthancStone::CoordinateSystem3D lastPlane_;
1673 1617
1674 protected: 1618 protected:
1675 bool HasViewportPlaneChanged(const OrthancStone::CoordinateSystem3D& plane) const 1619 bool HasViewportPlaneChanged(const OrthancStone::CoordinateSystem3D& plane) const
1676 { 1620 {
1677 if (first_ || 1621 if (first_ ||
1678 !OrthancStone::LinearAlgebra::IsCloseToZero( 1622 !OrthancStone::LinearAlgebra::IsCloseToZero(
1679 boost::numeric::ublas::norm_2(lastPlane_.GetNormal() - plane.GetNormal()))) 1623 boost::numeric::ublas::norm_2(lastPlane_.GetNormal() - plane.GetNormal())))
1680 { 1624 {
1681 // This is the first rendering, or the plane has not the same orientation 1625 // This is the first rendering, or the plane has not the same orientation
1682 return false; 1626 return false;
1683 } 1627 }
1684 else 1628 else
1685 { 1629 {
1686 double offset1 = lastPlane_.ProjectAlongNormal(plane.GetOrigin()); 1630 double offset1 = lastPlane_.ProjectAlongNormal(plane.GetOrigin());
1687 double offset2 = lastPlane_.ProjectAlongNormal(lastPlane_.GetOrigin()); 1631 double offset2 = lastPlane_.ProjectAlongNormal(lastPlane_.GetOrigin());
1688 return OrthancStone::LinearAlgebra::IsCloseToZero(offset2 - offset1); 1632 return OrthancStone::LinearAlgebra::IsCloseToZero(offset2 - offset1);
1689 } 1633 }
1690 } 1634 }
1691 1635
1692 void SetLastViewportPlane(const OrthancStone::CoordinateSystem3D& plane) 1636 void SetLastViewportPlane(const OrthancStone::CoordinateSystem3D& plane)
1693 { 1637 {
1694 first_ = false; 1638 first_ = false;
1695 lastPlane_ = plane; 1639 lastPlane_ = plane;
1696 } 1640 }
1697 1641
1698 void SetLayer(OrthancStone::ISceneLayer* layer) 1642 void SetLayer(OrthancStone::ISceneLayer* layer)
1699 { 1643 {
1700 scene_.SetLayer(layerDepth_, layer); 1644 scene_.SetLayer(layerDepth_, layer);
1701 } 1645 }
1702 1646
1703 void DeleteLayer() 1647 void DeleteLayer()
1704 { 1648 {
1705 scene_.DeleteLayer(layerDepth_); 1649 scene_.DeleteLayer(layerDepth_);
1706 } 1650 }
1707 1651
1708 public: 1652 public:
1709 VolumeSlicerBase(OrthancStone::Scene2D& scene, 1653 VolumeSlicerBase(OrthancStone::Scene2D& scene,
1710 int layerDepth) : 1654 int layerDepth) :
1711 scene_(scene), 1655 scene_(scene),
1712 layerDepth_(layerDepth), 1656 layerDepth_(layerDepth),
1713 first_(true) 1657 first_(true)
1714 { 1658 {
1715 } 1659 }
1716 };*/ 1660 };*/
1717 1661
1718 1662
1719 1663
1720 class DicomVolumeSlicer : public IVolumeSlicer 1664 class DicomVolumeSlicer : public IVolumeSlicer
1721 { 1665 {
2053 } 1997 }
2054 1998
2055 1999
2056 public: 2000 public:
2057 NativeOracle(IMessageEmitter& emitter) : 2001 NativeOracle(IMessageEmitter& emitter) :
2058 emitter_(emitter), 2002 emitter_(emitter),
2059 state_(State_Setup), 2003 state_(State_Setup),
2060 workers_(4) 2004 workers_(4)
2061 { 2005 {
2062 } 2006 }
2063 2007
2165 NativeApplicationContext& that_; 2109 NativeApplicationContext& that_;
2166 boost::shared_lock<boost::shared_mutex> lock_; 2110 boost::shared_lock<boost::shared_mutex> lock_;
2167 2111
2168 public: 2112 public:
2169 ReaderLock(NativeApplicationContext& that) : 2113 ReaderLock(NativeApplicationContext& that) :
2170 that_(that), 2114 that_(that),
2171 lock_(that.mutex_) 2115 lock_(that.mutex_)
2172 { 2116 {
2173 } 2117 }
2174 }; 2118 };
2175 2119
2176 2120
2180 NativeApplicationContext& that_; 2124 NativeApplicationContext& that_;
2181 boost::unique_lock<boost::shared_mutex> lock_; 2125 boost::unique_lock<boost::shared_mutex> lock_;
2182 2126
2183 public: 2127 public:
2184 WriterLock(NativeApplicationContext& that) : 2128 WriterLock(NativeApplicationContext& that) :
2185 that_(that), 2129 that_(that),
2186 lock_(that.mutex_) 2130 lock_(that.mutex_)
2187 { 2131 {
2188 } 2132 }
2189 2133
2190 OrthancStone::MessageBroker& GetBroker() 2134 OrthancStone::MessageBroker& GetBroker()
2191 { 2135 {
2251 (new OrthancStone::Callable 2195 (new OrthancStone::Callable
2252 <Toto, Refactoring::GetOrthancImageCommand::SuccessMessage>(*this, &Toto::Handle)); 2196 <Toto, Refactoring::GetOrthancImageCommand::SuccessMessage>(*this, &Toto::Handle));
2253 2197
2254 oracle.RegisterObserverCallback 2198 oracle.RegisterObserverCallback
2255 (new OrthancStone::Callable 2199 (new OrthancStone::Callable
2256 <Toto, Refactoring::GetOrthancWebViewerJpegCommand::SuccessMessage>(*this, &Toto::Handle)); 2200 <Toto, Refactoring::GetOrthancWebViewerJpegCommand::SuccessMessage>(*this, &Toto::Handle));
2257 2201
2258 oracle.RegisterObserverCallback 2202 oracle.RegisterObserverCallback
2259 (new OrthancStone::Callable 2203 (new OrthancStone::Callable
2260 <Toto, Refactoring::OracleCommandExceptionMessage>(*this, &Toto::Handle)); 2204 <Toto, Refactoring::OracleCommandExceptionMessage>(*this, &Toto::Handle));
2261 } 2205 }