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)