Mercurial > hg > orthanc-stone
comparison Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp @ 1722:802cb1272f3a
fix for the WRIX dataset
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 01 Dec 2020 14:47:11 +0100 |
parents | d4a8e2b19a65 |
children | 9ac2a65d4172 |
comparison
equal
deleted
inserted
replaced
1721:d4a8e2b19a65 | 1722:802cb1272f3a |
---|---|
1403 private: | 1403 private: |
1404 std::string sopInstanceUid_; | 1404 std::string sopInstanceUid_; |
1405 unsigned int frameNumber_; | 1405 unsigned int frameNumber_; |
1406 int priority_; | 1406 int priority_; |
1407 bool isPrefetch_; | 1407 bool isPrefetch_; |
1408 bool serverSideTranscoding_; | |
1408 | 1409 |
1409 public: | 1410 public: |
1410 SetFullDicomFrame(boost::shared_ptr<ViewerViewport> viewport, | 1411 SetFullDicomFrame(boost::shared_ptr<ViewerViewport> viewport, |
1411 const std::string& sopInstanceUid, | 1412 const std::string& sopInstanceUid, |
1412 unsigned int frameNumber, | 1413 unsigned int frameNumber, |
1413 int priority, | 1414 int priority, |
1414 bool isPrefetch) : | 1415 bool isPrefetch, |
1416 bool serverSideTranscoding) : | |
1415 ICommand(viewport), | 1417 ICommand(viewport), |
1416 sopInstanceUid_(sopInstanceUid), | 1418 sopInstanceUid_(sopInstanceUid), |
1417 frameNumber_(frameNumber), | 1419 frameNumber_(frameNumber), |
1418 priority_(priority), | 1420 priority_(priority), |
1419 isPrefetch_(isPrefetch) | 1421 isPrefetch_(isPrefetch), |
1422 serverSideTranscoding_(serverSideTranscoding) | |
1420 { | 1423 { |
1421 } | 1424 } |
1422 | 1425 |
1423 virtual void Handle(const OrthancStone::ParseDicomSuccessMessage& message) const ORTHANC_OVERRIDE | 1426 virtual void Handle(const OrthancStone::ParseDicomSuccessMessage& message) const ORTHANC_OVERRIDE |
1424 { | 1427 { |
1425 Apply(GetViewport(), message.GetDicom(), sopInstanceUid_, frameNumber_, priority_, isPrefetch_); | |
1426 | |
1427 if (isPrefetch_) | |
1428 { | |
1429 GetViewport().ScheduleNextPrefetch(); | |
1430 } | |
1431 } | |
1432 | |
1433 static void Apply(ViewerViewport& viewport, | |
1434 const Orthanc::ParsedDicomFile& dicom, | |
1435 const std::string& sopInstanceUid, | |
1436 unsigned int frameNumber, | |
1437 int priority, | |
1438 bool isPrefetch) | |
1439 { | |
1440 Orthanc::DicomMap tags; | |
1441 dicom.ExtractDicomSummary(tags, ORTHANC_STONE_MAX_TAG_LENGTH); | |
1442 | |
1443 std::string s; | |
1444 if (!tags.LookupStringValue(s, Orthanc::DICOM_TAG_SOP_INSTANCE_UID, false)) | |
1445 { | |
1446 // Safety check | |
1447 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
1448 } | |
1449 | |
1450 std::unique_ptr<Orthanc::ImageAccessor> frame; | 1428 std::unique_ptr<Orthanc::ImageAccessor> frame; |
1451 | 1429 |
1452 try | 1430 try |
1453 { | 1431 { |
1454 frame.reset(dicom.DecodeFrame(frameNumber)); | 1432 frame.reset(message.GetDicom().DecodeFrame(frameNumber_)); |
1455 } | 1433 } |
1456 catch (Orthanc::OrthancException& e) | 1434 catch (Orthanc::OrthancException& e) |
1457 { | 1435 { |
1458 if (e.GetErrorCode() == Orthanc::ErrorCode_NotImplemented) | 1436 if (e.GetErrorCode() == Orthanc::ErrorCode_NotImplemented) |
1459 { | 1437 { |
1460 viewport.serverSideTranscoding_ = true; | 1438 if (!serverSideTranscoding_) |
1461 LOG(INFO) << "Switching to server-side transcoding"; | 1439 { |
1462 viewport.ScheduleLoadFullDicomFrame(sopInstanceUid, frameNumber, priority, isPrefetch); | 1440 // If we haven't tried server-side rendering yet, give it a try |
1441 LOG(INFO) << "Switching to server-side transcoding"; | |
1442 GetViewport().serverSideTranscoding_ = true; | |
1443 GetViewport().ScheduleLoadFullDicomFrame(sopInstanceUid_, frameNumber_, priority_, isPrefetch_); | |
1444 } | |
1463 return; | 1445 return; |
1464 } | 1446 } |
1465 else | 1447 else |
1466 { | 1448 { |
1467 throw; | 1449 throw; |
1470 | 1452 |
1471 if (frame.get() == NULL) | 1453 if (frame.get() == NULL) |
1472 { | 1454 { |
1473 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | 1455 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); |
1474 } | 1456 } |
1457 else | |
1458 { | |
1459 Apply(GetViewport(), message.GetDicom(), frame.release(), sopInstanceUid_, frameNumber_); | |
1460 | |
1461 if (isPrefetch_) | |
1462 { | |
1463 GetViewport().ScheduleNextPrefetch(); | |
1464 } | |
1465 } | |
1466 } | |
1467 | |
1468 static void Apply(ViewerViewport& viewport, | |
1469 const Orthanc::ParsedDicomFile& dicom, | |
1470 Orthanc::ImageAccessor* f, | |
1471 const std::string& sopInstanceUid, | |
1472 unsigned int frameNumber) | |
1473 { | |
1474 std::unique_ptr<Orthanc::ImageAccessor> frameProtection(f); | |
1475 | |
1476 Orthanc::DicomMap tags; | |
1477 dicom.ExtractDicomSummary(tags, ORTHANC_STONE_MAX_TAG_LENGTH); | |
1475 | 1478 |
1476 std::unique_ptr<Orthanc::ImageAccessor> converted; | 1479 std::unique_ptr<Orthanc::ImageAccessor> converted; |
1477 | 1480 |
1478 if (frame->GetFormat() == Orthanc::PixelFormat_RGB24) | 1481 if (frameProtection->GetFormat() == Orthanc::PixelFormat_RGB24) |
1479 { | 1482 { |
1480 converted.reset(frame.release()); | 1483 converted.reset(frameProtection.release()); |
1481 } | 1484 } |
1482 else | 1485 else |
1483 { | 1486 { |
1484 double a = 1; | 1487 double a = 1; |
1485 double b = 0; | 1488 double b = 0; |
1496 { | 1499 { |
1497 a *= rescaleSlope; | 1500 a *= rescaleSlope; |
1498 b = rescaleIntercept; | 1501 b = rescaleIntercept; |
1499 } | 1502 } |
1500 | 1503 |
1501 converted.reset(new Orthanc::Image(Orthanc::PixelFormat_Float32, frame->GetWidth(), frame->GetHeight(), false)); | 1504 converted.reset(new Orthanc::Image(Orthanc::PixelFormat_Float32, frameProtection->GetWidth(), frameProtection->GetHeight(), false)); |
1502 Orthanc::ImageProcessing::Convert(*converted, *frame); | 1505 Orthanc::ImageProcessing::Convert(*converted, *frameProtection); |
1503 Orthanc::ImageProcessing::ShiftScale2(*converted, b, a, false); | 1506 Orthanc::ImageProcessing::ShiftScale2(*converted, b, a, false); |
1504 } | 1507 } |
1505 | 1508 |
1506 assert(converted.get() != NULL); | 1509 assert(converted.get() != NULL); |
1507 viewport.RenderCurrentSceneFromCommand(*converted, sopInstanceUid, frameNumber, DisplayedFrameQuality_High); | 1510 viewport.RenderCurrentSceneFromCommand(*converted, sopInstanceUid, frameNumber, DisplayedFrameQuality_High); |
1854 lock->Schedule( | 1857 lock->Schedule( |
1855 GetSharedObserver(), priority, OrthancStone::ParseDicomFromWadoCommand::Create( | 1858 GetSharedObserver(), priority, OrthancStone::ParseDicomFromWadoCommand::Create( |
1856 source_, frames_->GetStudyInstanceUid(), frames_->GetSeriesInstanceUid(), | 1859 source_, frames_->GetStudyInstanceUid(), frames_->GetSeriesInstanceUid(), |
1857 sopInstanceUid, serverSideTranscoding_, | 1860 sopInstanceUid, serverSideTranscoding_, |
1858 Orthanc::DicomTransferSyntax_LittleEndianExplicit, | 1861 Orthanc::DicomTransferSyntax_LittleEndianExplicit, |
1859 new SetFullDicomFrame(GetSharedObserver(), sopInstanceUid, frameNumber, priority, isPrefetch))); | 1862 new SetFullDicomFrame(GetSharedObserver(), sopInstanceUid, frameNumber, priority, isPrefetch, serverSideTranscoding_))); |
1860 } | 1863 } |
1861 } | 1864 } |
1862 | 1865 |
1863 void ScheduleLoadFullDicomFrame(size_t cursorIndex, | 1866 void ScheduleLoadFullDicomFrame(size_t cursorIndex, |
1864 int priority, | 1867 int priority, |
1885 const OrthancStone::DicomInstanceParameters& instance = frames_->GetInstanceOfFrame(cursorIndex); | 1888 const OrthancStone::DicomInstanceParameters& instance = frames_->GetInstanceOfFrame(cursorIndex); |
1886 unsigned int frameNumber = frames_->GetFrameNumberInInstance(cursorIndex); | 1889 unsigned int frameNumber = frames_->GetFrameNumberInInstance(cursorIndex); |
1887 | 1890 |
1888 /** | 1891 /** |
1889 * If the full-resolution DICOM file is already available in the | 1892 * If the full-resolution DICOM file is already available in the |
1890 * cache of the oracle, skip the loading of the "rendered". | 1893 * cache of the oracle, bypass the loading of the "rendered" and |
1894 * use the cached DICOM file. | |
1891 **/ | 1895 **/ |
1892 std::unique_ptr<OrthancStone::WebAssemblyOracle::CachedInstanceAccessor> accessor( | 1896 std::unique_ptr<OrthancStone::WebAssemblyOracle::CachedInstanceAccessor> accessor( |
1893 context_.AccessCachedInstance(instance.GetSopInstanceUid())); | 1897 context_.AccessCachedInstance(instance.GetSopInstanceUid())); |
1894 | 1898 |
1895 if (accessor.get() != NULL && | 1899 if (accessor.get() != NULL && |
1896 accessor->IsValid()) | 1900 accessor->IsValid()) |
1897 { | 1901 { |
1898 try | 1902 try |
1899 { | 1903 { |
1900 SetFullDicomFrame::Apply(*this, accessor->GetDicom(), instance.GetSopInstanceUid(), | 1904 std::unique_ptr<Orthanc::ImageAccessor> frame(accessor->GetDicom().DecodeFrame(frameNumber)); |
1901 frameNumber, priority, isPrefetch); | 1905 SetFullDicomFrame::Apply(*this, accessor->GetDicom(), frame.release(), instance.GetSopInstanceUid(), frameNumber); |
1902 return; | 1906 return; // Success |
1903 } | 1907 } |
1904 catch (Orthanc::OrthancException&) | 1908 catch (Orthanc::OrthancException&) |
1905 { | 1909 { |
1906 // This happens in the case of a JPEG2k image unsupported by DCMTK | 1910 /** |
1911 * This happens if the cached DICOM file uses a transfer | |
1912 * syntax that is not supported by DCMTK (such as | |
1913 * JPEG2k). Fallback to "/rendered" in order to re-download | |
1914 * the DICOM file using server-side transcoding. This | |
1915 * happens on WRIX dataset. | |
1916 **/ | |
1907 } | 1917 } |
1908 } | 1918 } |
1909 | 1919 |
1910 bool isMonochrome1 = (instance.GetImageInformation().GetPhotometricInterpretation() == | 1920 bool isMonochrome1 = (instance.GetImageInformation().GetPhotometricInterpretation() == |
1911 Orthanc::PhotometricInterpretation_Monochrome1); | 1921 Orthanc::PhotometricInterpretation_Monochrome1); |