Mercurial > hg > orthanc-stone
comparison Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp @ 1669:d82a141e08d7
make the viewer work even if missing cache space
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 19 Nov 2020 19:16:37 +0100 |
parents | ab1bc8de1798 |
children | 24462a259d8d |
comparison
equal
deleted
inserted
replaced
1668:ab1bc8de1798 | 1669:d82a141e08d7 |
---|---|
1118 virtual void Handle(const OrthancStone::HttpCommand::SuccessMessage& message) const ORTHANC_OVERRIDE | 1118 virtual void Handle(const OrthancStone::HttpCommand::SuccessMessage& message) const ORTHANC_OVERRIDE |
1119 { | 1119 { |
1120 std::unique_ptr<Orthanc::JpegReader> jpeg(new Orthanc::JpegReader); | 1120 std::unique_ptr<Orthanc::JpegReader> jpeg(new Orthanc::JpegReader); |
1121 jpeg->ReadFromMemory(message.GetAnswer()); | 1121 jpeg->ReadFromMemory(message.GetAnswer()); |
1122 | 1122 |
1123 bool updatedCache; | 1123 std::unique_ptr<Orthanc::ImageAccessor> converted; |
1124 | 1124 |
1125 switch (jpeg->GetFormat()) | 1125 switch (jpeg->GetFormat()) |
1126 { | 1126 { |
1127 case Orthanc::PixelFormat_RGB24: | 1127 case Orthanc::PixelFormat_RGB24: |
1128 updatedCache = GetViewport().cache_->Acquire( | 1128 converted.reset(jpeg.release()); |
1129 sopInstanceUid_, frameNumber_, jpeg.release(), QUALITY_JPEG); | |
1130 break; | 1129 break; |
1131 | 1130 |
1132 case Orthanc::PixelFormat_Grayscale8: | 1131 case Orthanc::PixelFormat_Grayscale8: |
1133 { | 1132 { |
1134 if (isMonochrome1_) | 1133 if (isMonochrome1_) |
1135 { | 1134 { |
1136 Orthanc::ImageProcessing::Invert(*jpeg); | 1135 Orthanc::ImageProcessing::Invert(*jpeg); |
1137 } | 1136 } |
1138 | 1137 |
1139 std::unique_ptr<Orthanc::Image> converted( | 1138 converted.reset(new Orthanc::Image(Orthanc::PixelFormat_Float32, jpeg->GetWidth(), |
1140 new Orthanc::Image(Orthanc::PixelFormat_Float32, jpeg->GetWidth(), | 1139 jpeg->GetHeight(), false)); |
1141 jpeg->GetHeight(), false)); | |
1142 | 1140 |
1143 Orthanc::ImageProcessing::Convert(*converted, *jpeg); | 1141 Orthanc::ImageProcessing::Convert(*converted, *jpeg); |
1144 | 1142 |
1145 /** | 1143 /** |
1146 | 1144 |
1160 const float scaling = windowWidth_ / 255.0f; | 1158 const float scaling = windowWidth_ / 255.0f; |
1161 const float offset = (OrthancStone::LinearAlgebra::IsCloseToZero(scaling) ? 0 : | 1159 const float offset = (OrthancStone::LinearAlgebra::IsCloseToZero(scaling) ? 0 : |
1162 (windowCenter_ - windowWidth_ / 2.0f) / scaling); | 1160 (windowCenter_ - windowWidth_ / 2.0f) / scaling); |
1163 | 1161 |
1164 Orthanc::ImageProcessing::ShiftScale(*converted, offset, scaling, false); | 1162 Orthanc::ImageProcessing::ShiftScale(*converted, offset, scaling, false); |
1165 updatedCache = GetViewport().cache_->Acquire( | |
1166 sopInstanceUid_, frameNumber_, converted.release(), QUALITY_JPEG); | |
1167 break; | 1163 break; |
1168 } | 1164 } |
1169 | 1165 |
1170 default: | 1166 default: |
1171 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | 1167 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); |
1172 } | 1168 } |
1173 | 1169 |
1174 if (updatedCache) | 1170 assert(converted.get() != NULL); |
1175 { | 1171 GetViewport().RenderCurrentSceneFromCommand(*converted, sopInstanceUid_, frameNumber_, DisplayedFrameQuality_Low); |
1176 GetViewport().SignalUpdatedFrame(sopInstanceUid_, frameNumber_); | 1172 GetViewport().cache_->Acquire(sopInstanceUid_, frameNumber_, converted.release(), QUALITY_JPEG); |
1177 } | |
1178 | 1173 |
1179 if (isPrefetch_) | 1174 if (isPrefetch_) |
1180 { | 1175 { |
1181 GetViewport().ScheduleNextPrefetch(); | 1176 GetViewport().ScheduleNextPrefetch(); |
1182 } | 1177 } |
1220 if (frame.get() == NULL) | 1215 if (frame.get() == NULL) |
1221 { | 1216 { |
1222 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | 1217 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); |
1223 } | 1218 } |
1224 | 1219 |
1225 bool updatedCache; | 1220 std::unique_ptr<Orthanc::ImageAccessor> converted; |
1226 | 1221 |
1227 if (frame->GetFormat() == Orthanc::PixelFormat_RGB24) | 1222 if (frame->GetFormat() == Orthanc::PixelFormat_RGB24) |
1228 { | 1223 { |
1229 updatedCache = GetViewport().cache_->Acquire( | 1224 converted.reset(frame.release()); |
1230 sopInstanceUid_, frameNumber_, frame.release(), QUALITY_FULL); | |
1231 } | 1225 } |
1232 else | 1226 else |
1233 { | 1227 { |
1234 double a = 1; | 1228 double a = 1; |
1235 double b = 0; | 1229 double b = 0; |
1246 { | 1240 { |
1247 a *= rescaleSlope; | 1241 a *= rescaleSlope; |
1248 b = rescaleIntercept; | 1242 b = rescaleIntercept; |
1249 } | 1243 } |
1250 | 1244 |
1251 std::unique_ptr<Orthanc::ImageAccessor> converted( | 1245 converted.reset(new Orthanc::Image(Orthanc::PixelFormat_Float32, frame->GetWidth(), frame->GetHeight(), false)); |
1252 new Orthanc::Image(Orthanc::PixelFormat_Float32, frame->GetWidth(), frame->GetHeight(), false)); | |
1253 Orthanc::ImageProcessing::Convert(*converted, *frame); | 1246 Orthanc::ImageProcessing::Convert(*converted, *frame); |
1254 Orthanc::ImageProcessing::ShiftScale2(*converted, b, a, false); | 1247 Orthanc::ImageProcessing::ShiftScale2(*converted, b, a, false); |
1255 | 1248 } |
1256 updatedCache = GetViewport().cache_->Acquire( | 1249 |
1257 sopInstanceUid_, frameNumber_, converted.release(), QUALITY_FULL); | 1250 assert(converted.get() != NULL); |
1258 } | 1251 GetViewport().RenderCurrentSceneFromCommand(*converted, sopInstanceUid_, frameNumber_, DisplayedFrameQuality_High); |
1259 | 1252 GetViewport().cache_->Acquire(sopInstanceUid_, frameNumber_, converted.release(), QUALITY_FULL); |
1260 if (updatedCache) | |
1261 { | |
1262 GetViewport().SignalUpdatedFrame(sopInstanceUid_, frameNumber_); | |
1263 } | |
1264 | 1253 |
1265 if (isPrefetch_) | 1254 if (isPrefetch_) |
1266 { | 1255 { |
1267 GetViewport().ScheduleNextPrefetch(); | 1256 GetViewport().ScheduleNextPrefetch(); |
1268 } | 1257 } |
1362 windowingWidth_ = defaultWindowingWidth_; | 1351 windowingWidth_ = defaultWindowingWidth_; |
1363 | 1352 |
1364 inverted_ = false; | 1353 inverted_ = false; |
1365 } | 1354 } |
1366 | 1355 |
1367 void SignalUpdatedFrame(const std::string& sopInstanceUid, | |
1368 unsigned int frameNumber) | |
1369 { | |
1370 if (cursor_.get() != NULL && | |
1371 frames_.get() != NULL) | |
1372 { | |
1373 size_t cursorIndex = cursor_->GetCurrentIndex(); | |
1374 | |
1375 if (frames_->GetInstanceOfFrame(cursorIndex).GetSopInstanceUid() == sopInstanceUid && | |
1376 frames_->GetFrameNumberInInstance(cursorIndex) == frameNumber) | |
1377 { | |
1378 Redraw(); | |
1379 } | |
1380 } | |
1381 } | |
1382 | |
1383 | 1356 |
1384 void ClearViewport() | 1357 void ClearViewport() |
1385 { | 1358 { |
1386 { | 1359 { |
1387 std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_->Lock()); | 1360 std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_->Lock()); |
1410 layer.GetWindowing(windowingCenter_, windowingWidth_); | 1383 layer.GetWindowing(windowingCenter_, windowingWidth_); |
1411 } | 1384 } |
1412 } | 1385 } |
1413 | 1386 |
1414 | 1387 |
1388 void SetupPrefetchAfterRendering(DisplayedFrameQuality quality) | |
1389 { | |
1390 const size_t cursorIndex = cursor_->GetCurrentIndex(); | |
1391 | |
1392 // Prepare prefetching | |
1393 prefetchQueue_.clear(); | |
1394 for (size_t i = 0; i < cursor_->GetPrefetchSize() && i < 16; i++) | |
1395 { | |
1396 size_t a = cursor_->GetPrefetchIndex(i); | |
1397 if (a == cursorIndex) | |
1398 { | |
1399 if (quality == DisplayedFrameQuality_Low) | |
1400 { | |
1401 prefetchQueue_.push_back(PrefetchItem(a, true)); | |
1402 } | |
1403 } | |
1404 else | |
1405 { | |
1406 prefetchQueue_.push_back(PrefetchItem(a, i < 2)); | |
1407 } | |
1408 } | |
1409 | |
1410 ScheduleNextPrefetch(); | |
1411 | |
1412 if (observer_.get() != NULL) | |
1413 { | |
1414 observer_->SignalFrameUpdated(*this, cursor_->GetCurrentIndex(), | |
1415 frames_->GetFramesCount(), quality); | |
1416 } | |
1417 } | |
1418 | |
1419 | |
1415 void RenderCurrentScene(const Orthanc::ImageAccessor& frame, | 1420 void RenderCurrentScene(const Orthanc::ImageAccessor& frame, |
1416 const OrthancStone::DicomInstanceParameters& instance, | 1421 const OrthancStone::DicomInstanceParameters& instance, |
1417 const OrthancStone::CoordinateSystem3D& plane) | 1422 const OrthancStone::CoordinateSystem3D& plane) |
1418 { | 1423 { |
1419 SaveCurrentWindowing(); | 1424 SaveCurrentWindowing(); |
1508 assert(cursor_.get() != NULL); | 1513 assert(cursor_.get() != NULL); |
1509 assert(frames_.get() != NULL); | 1514 assert(frames_.get() != NULL); |
1510 | 1515 |
1511 const size_t cursorIndex = cursor_->GetCurrentIndex(); | 1516 const size_t cursorIndex = cursor_->GetCurrentIndex(); |
1512 const OrthancStone::DicomInstanceParameters& instance = frames_->GetInstanceOfFrame(cursorIndex); | 1517 const OrthancStone::DicomInstanceParameters& instance = frames_->GetInstanceOfFrame(cursorIndex); |
1513 const OrthancStone::CoordinateSystem3D plane = frames_->GetFrameGeometry(cursorIndex); | |
1514 | |
1515 const size_t frameNumber = frames_->GetFrameNumberInInstance(cursorIndex); | 1518 const size_t frameNumber = frames_->GetFrameNumberInInstance(cursorIndex); |
1516 | 1519 |
1517 FramesCache::Accessor accessor(*cache_, instance.GetSopInstanceUid(), frameNumber); | 1520 FramesCache::Accessor accessor(*cache_, instance.GetSopInstanceUid(), frameNumber); |
1518 if (accessor.IsValid()) | 1521 if (accessor.IsValid()) |
1519 { | 1522 { |
1520 quality = accessor.GetQuality(); | 1523 quality = accessor.GetQuality(); |
1521 RenderCurrentScene(accessor.GetImage(), instance, plane); | 1524 RenderCurrentScene(accessor.GetImage(), instance, frames_->GetFrameGeometry(cursorIndex)); |
1522 return true; | 1525 return true; |
1523 } | 1526 } |
1524 else | 1527 else |
1525 { | 1528 { |
1526 return false; | 1529 return false; |
1530 } | |
1531 } | |
1532 | |
1533 void RenderCurrentSceneFromCommand(const Orthanc::ImageAccessor& frame, | |
1534 const std::string& loadedSopInstanceUid, | |
1535 unsigned int loadedFrameNumber, | |
1536 DisplayedFrameQuality quality) | |
1537 { | |
1538 if (cursor_.get() != NULL && | |
1539 frames_.get() != NULL) | |
1540 { | |
1541 const size_t cursorIndex = cursor_->GetCurrentIndex(); | |
1542 const OrthancStone::DicomInstanceParameters& instance = frames_->GetInstanceOfFrame(cursorIndex); | |
1543 const size_t frameNumber = frames_->GetFrameNumberInInstance(cursorIndex); | |
1544 | |
1545 // Only change the same if the loaded frame still corresponds to the current cursor | |
1546 if (instance.GetSopInstanceUid() == loadedSopInstanceUid && | |
1547 frameNumber == loadedFrameNumber) | |
1548 { | |
1549 RenderCurrentScene(frame, instance, frames_->GetFrameGeometry(cursorIndex)); | |
1550 SetupPrefetchAfterRendering(quality); | |
1551 } | |
1527 } | 1552 } |
1528 } | 1553 } |
1529 | 1554 |
1530 void ScheduleLoadFullDicomFrame(size_t cursorIndex, | 1555 void ScheduleLoadFullDicomFrame(size_t cursorIndex, |
1531 int priority, | 1556 int priority, |
1826 { | 1851 { |
1827 assert(viewport_); | 1852 assert(viewport_); |
1828 return viewport_->GetCanvasId(); | 1853 return viewport_->GetCanvasId(); |
1829 } | 1854 } |
1830 | 1855 |
1831 | 1856 |
1832 void Redraw() | 1857 void Redraw() |
1833 { | 1858 { |
1834 DisplayedFrameQuality quality = DisplayedFrameQuality_None; | 1859 DisplayedFrameQuality quality = DisplayedFrameQuality_None; |
1835 | 1860 |
1836 if (cursor_.get() != NULL && | 1861 if (cursor_.get() != NULL && |
1860 else | 1885 else |
1861 { | 1886 { |
1862 quality = DisplayedFrameQuality_High; | 1887 quality = DisplayedFrameQuality_High; |
1863 } | 1888 } |
1864 | 1889 |
1865 { | 1890 SetupPrefetchAfterRendering(quality); |
1866 // Prepare prefetching | |
1867 prefetchQueue_.clear(); | |
1868 for (size_t i = 0; i < cursor_->GetPrefetchSize() && i < 16; i++) | |
1869 { | |
1870 size_t a = cursor_->GetPrefetchIndex(i); | |
1871 if (a != cursorIndex) | |
1872 { | |
1873 prefetchQueue_.push_back(PrefetchItem(a, i < 2)); | |
1874 } | |
1875 } | |
1876 | |
1877 ScheduleNextPrefetch(); | |
1878 } | |
1879 | |
1880 if (observer_.get() != NULL) | |
1881 { | |
1882 observer_->SignalFrameUpdated(*this, cursor_->GetCurrentIndex(), | |
1883 frames_->GetFramesCount(), quality); | |
1884 } | |
1885 } | 1891 } |
1886 } | 1892 } |
1887 | 1893 |
1888 | 1894 |
1889 void ChangeFrame(SeriesCursor::Action action) | 1895 void ChangeFrame(SeriesCursor::Action action) |