comparison Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp @ 1600:b253b79906fa

clarifying variable names: frameIndex vs numberIndex
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 28 Oct 2020 15:23:26 +0100
parents 4fb8fdf03314
children 595c0952ef7e
comparison
equal deleted inserted replaced
1599:73cd85d7da6a 1600:b253b79906fa
439 } 439 }
440 }; 440 };
441 441
442 442
443 static std::string GetKey(const std::string& sopInstanceUid, 443 static std::string GetKey(const std::string& sopInstanceUid,
444 size_t frameIndex) 444 size_t frameNumber)
445 { 445 {
446 return sopInstanceUid + "|" + boost::lexical_cast<std::string>(frameIndex); 446 return sopInstanceUid + "|" + boost::lexical_cast<std::string>(frameNumber);
447 } 447 }
448 448
449 449
450 Orthanc::MemoryObjectCache cache_; 450 Orthanc::MemoryObjectCache cache_;
451 451
468 /** 468 /**
469 * Returns "true" iff the provided image has better quality than the 469 * Returns "true" iff the provided image has better quality than the
470 * previously cached one, or if no cache was previously available. 470 * previously cached one, or if no cache was previously available.
471 **/ 471 **/
472 bool Acquire(const std::string& sopInstanceUid, 472 bool Acquire(const std::string& sopInstanceUid,
473 size_t frameIndex, 473 size_t frameNumber,
474 Orthanc::ImageAccessor* image /* transfer ownership */, 474 Orthanc::ImageAccessor* image /* transfer ownership */,
475 unsigned int quality) 475 unsigned int quality)
476 { 476 {
477 std::unique_ptr<Orthanc::ImageAccessor> protection(image); 477 std::unique_ptr<Orthanc::ImageAccessor> protection(image);
478 478
484 image->GetFormat() != Orthanc::PixelFormat_RGB24) 484 image->GetFormat() != Orthanc::PixelFormat_RGB24)
485 { 485 {
486 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); 486 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat);
487 } 487 }
488 488
489 const std::string& key = GetKey(sopInstanceUid, frameIndex); 489 const std::string& key = GetKey(sopInstanceUid, frameNumber);
490 490
491 bool invalidate = false; 491 bool invalidate = false;
492 492
493 { 493 {
494 /** 494 /**
546 } 546 }
547 547
548 public: 548 public:
549 Accessor(FramesCache& that, 549 Accessor(FramesCache& that,
550 const std::string& sopInstanceUid, 550 const std::string& sopInstanceUid,
551 size_t frameIndex) : 551 size_t frameNumber) :
552 accessor_(that.cache_, GetKey(sopInstanceUid, frameIndex), false /* shared lock */) 552 accessor_(that.cache_, GetKey(sopInstanceUid, frameNumber), false /* shared lock */)
553 { 553 {
554 } 554 }
555 555
556 bool IsValid() const 556 bool IsValid() const
557 { 557 {
1080 1080
1081 class SetLowQualityFrame : public ICommand 1081 class SetLowQualityFrame : public ICommand
1082 { 1082 {
1083 private: 1083 private:
1084 std::string sopInstanceUid_; 1084 std::string sopInstanceUid_;
1085 unsigned int frameIndex_; 1085 unsigned int frameNumber_;
1086 float windowCenter_; 1086 float windowCenter_;
1087 float windowWidth_; 1087 float windowWidth_;
1088 bool isMonochrome1_; 1088 bool isMonochrome1_;
1089 bool isPrefetch_; 1089 bool isPrefetch_;
1090 1090
1091 public: 1091 public:
1092 SetLowQualityFrame(boost::shared_ptr<ViewerViewport> viewport, 1092 SetLowQualityFrame(boost::shared_ptr<ViewerViewport> viewport,
1093 const std::string& sopInstanceUid, 1093 const std::string& sopInstanceUid,
1094 unsigned int frameIndex, 1094 unsigned int frameNumber,
1095 float windowCenter, 1095 float windowCenter,
1096 float windowWidth, 1096 float windowWidth,
1097 bool isMonochrome1, 1097 bool isMonochrome1,
1098 bool isPrefetch) : 1098 bool isPrefetch) :
1099 ICommand(viewport), 1099 ICommand(viewport),
1100 sopInstanceUid_(sopInstanceUid), 1100 sopInstanceUid_(sopInstanceUid),
1101 frameIndex_(frameIndex), 1101 frameNumber_(frameNumber),
1102 windowCenter_(windowCenter), 1102 windowCenter_(windowCenter),
1103 windowWidth_(windowWidth), 1103 windowWidth_(windowWidth),
1104 isMonochrome1_(isMonochrome1), 1104 isMonochrome1_(isMonochrome1),
1105 isPrefetch_(isPrefetch) 1105 isPrefetch_(isPrefetch)
1106 { 1106 {
1115 1115
1116 switch (jpeg->GetFormat()) 1116 switch (jpeg->GetFormat())
1117 { 1117 {
1118 case Orthanc::PixelFormat_RGB24: 1118 case Orthanc::PixelFormat_RGB24:
1119 updatedCache = GetViewport().cache_->Acquire( 1119 updatedCache = GetViewport().cache_->Acquire(
1120 sopInstanceUid_, frameIndex_, jpeg.release(), QUALITY_JPEG); 1120 sopInstanceUid_, frameNumber_, jpeg.release(), QUALITY_JPEG);
1121 break; 1121 break;
1122 1122
1123 case Orthanc::PixelFormat_Grayscale8: 1123 case Orthanc::PixelFormat_Grayscale8:
1124 { 1124 {
1125 if (isMonochrome1_) 1125 if (isMonochrome1_)
1152 const float offset = (OrthancStone::LinearAlgebra::IsCloseToZero(scaling) ? 0 : 1152 const float offset = (OrthancStone::LinearAlgebra::IsCloseToZero(scaling) ? 0 :
1153 (windowCenter_ - windowWidth_ / 2.0f) / scaling); 1153 (windowCenter_ - windowWidth_ / 2.0f) / scaling);
1154 1154
1155 Orthanc::ImageProcessing::ShiftScale(*converted, offset, scaling, false); 1155 Orthanc::ImageProcessing::ShiftScale(*converted, offset, scaling, false);
1156 updatedCache = GetViewport().cache_->Acquire( 1156 updatedCache = GetViewport().cache_->Acquire(
1157 sopInstanceUid_, frameIndex_, converted.release(), QUALITY_JPEG); 1157 sopInstanceUid_, frameNumber_, converted.release(), QUALITY_JPEG);
1158 break; 1158 break;
1159 } 1159 }
1160 1160
1161 default: 1161 default:
1162 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); 1162 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
1163 } 1163 }
1164 1164
1165 if (updatedCache) 1165 if (updatedCache)
1166 { 1166 {
1167 GetViewport().SignalUpdatedFrame(sopInstanceUid_, frameIndex_); 1167 GetViewport().SignalUpdatedFrame(sopInstanceUid_, frameNumber_);
1168 } 1168 }
1169 1169
1170 if (isPrefetch_) 1170 if (isPrefetch_)
1171 { 1171 {
1172 GetViewport().ScheduleNextPrefetch(); 1172 GetViewport().ScheduleNextPrefetch();
1177 1177
1178 class SetFullDicomFrame : public ICommand 1178 class SetFullDicomFrame : public ICommand
1179 { 1179 {
1180 private: 1180 private:
1181 std::string sopInstanceUid_; 1181 std::string sopInstanceUid_;
1182 unsigned int frameIndex_; 1182 unsigned int frameNumber_;
1183 bool isPrefetch_; 1183 bool isPrefetch_;
1184 1184
1185 public: 1185 public:
1186 SetFullDicomFrame(boost::shared_ptr<ViewerViewport> viewport, 1186 SetFullDicomFrame(boost::shared_ptr<ViewerViewport> viewport,
1187 const std::string& sopInstanceUid, 1187 const std::string& sopInstanceUid,
1188 unsigned int frameIndex, 1188 unsigned int frameNumber,
1189 bool isPrefetch) : 1189 bool isPrefetch) :
1190 ICommand(viewport), 1190 ICommand(viewport),
1191 sopInstanceUid_(sopInstanceUid), 1191 sopInstanceUid_(sopInstanceUid),
1192 frameIndex_(frameIndex), 1192 frameNumber_(frameNumber),
1193 isPrefetch_(isPrefetch) 1193 isPrefetch_(isPrefetch)
1194 { 1194 {
1195 } 1195 }
1196 1196
1197 virtual void Handle(const OrthancStone::ParseDicomSuccessMessage& message) const ORTHANC_OVERRIDE 1197 virtual void Handle(const OrthancStone::ParseDicomSuccessMessage& message) const ORTHANC_OVERRIDE
1204 { 1204 {
1205 // Safety check 1205 // Safety check
1206 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); 1206 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
1207 } 1207 }
1208 1208
1209 std::unique_ptr<Orthanc::ImageAccessor> frame(message.GetDicom().DecodeFrame(frameIndex_)); 1209 std::unique_ptr<Orthanc::ImageAccessor> frame(message.GetDicom().DecodeFrame(frameNumber_));
1210 1210
1211 if (frame.get() == NULL) 1211 if (frame.get() == NULL)
1212 { 1212 {
1213 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); 1213 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
1214 } 1214 }
1216 bool updatedCache; 1216 bool updatedCache;
1217 1217
1218 if (frame->GetFormat() == Orthanc::PixelFormat_RGB24) 1218 if (frame->GetFormat() == Orthanc::PixelFormat_RGB24)
1219 { 1219 {
1220 updatedCache = GetViewport().cache_->Acquire( 1220 updatedCache = GetViewport().cache_->Acquire(
1221 sopInstanceUid_, frameIndex_, frame.release(), QUALITY_FULL); 1221 sopInstanceUid_, frameNumber_, frame.release(), QUALITY_FULL);
1222 } 1222 }
1223 else 1223 else
1224 { 1224 {
1225 double a = 1; 1225 double a = 1;
1226 double b = 0; 1226 double b = 0;
1243 new Orthanc::Image(Orthanc::PixelFormat_Float32, frame->GetWidth(), frame->GetHeight(), false)); 1243 new Orthanc::Image(Orthanc::PixelFormat_Float32, frame->GetWidth(), frame->GetHeight(), false));
1244 Orthanc::ImageProcessing::Convert(*converted, *frame); 1244 Orthanc::ImageProcessing::Convert(*converted, *frame);
1245 Orthanc::ImageProcessing::ShiftScale2(*converted, b, a, false); 1245 Orthanc::ImageProcessing::ShiftScale2(*converted, b, a, false);
1246 1246
1247 updatedCache = GetViewport().cache_->Acquire( 1247 updatedCache = GetViewport().cache_->Acquire(
1248 sopInstanceUid_, frameIndex_, converted.release(), QUALITY_FULL); 1248 sopInstanceUid_, frameNumber_, converted.release(), QUALITY_FULL);
1249 } 1249 }
1250 1250
1251 if (updatedCache) 1251 if (updatedCache)
1252 { 1252 {
1253 GetViewport().SignalUpdatedFrame(sopInstanceUid_, frameIndex_); 1253 GetViewport().SignalUpdatedFrame(sopInstanceUid_, frameNumber_);
1254 } 1254 }
1255 1255
1256 if (isPrefetch_) 1256 if (isPrefetch_)
1257 { 1257 {
1258 GetViewport().ScheduleNextPrefetch(); 1258 GetViewport().ScheduleNextPrefetch();
1285 return isFull_; 1285 return isFull_;
1286 } 1286 }
1287 }; 1287 };
1288 1288
1289 1289
1290 std::unique_ptr<IObserver> observer_; 1290 std::unique_ptr<IObserver> observer_;
1291 OrthancStone::ILoadersContext& context_; 1291 OrthancStone::ILoadersContext& context_;
1292 boost::shared_ptr<OrthancStone::WebAssemblyViewport> viewport_; 1292 boost::shared_ptr<OrthancStone::WebAssemblyViewport> viewport_;
1293 boost::shared_ptr<OrthancStone::DicomResourcesLoader> loader_; 1293 boost::shared_ptr<OrthancStone::DicomResourcesLoader> loader_;
1294 OrthancStone::DicomSource source_; 1294 OrthancStone::DicomSource source_;
1295 boost::shared_ptr<FramesCache> cache_; 1295 boost::shared_ptr<FramesCache> cache_;
1305 bool fitNextContent_; 1305 bool fitNextContent_;
1306 bool isCtrlDown_; 1306 bool isCtrlDown_;
1307 FrameGeometry currentFrameGeometry_; 1307 FrameGeometry currentFrameGeometry_;
1308 std::list<PrefetchItem> prefetchQueue_; 1308 std::list<PrefetchItem> prefetchQueue_;
1309 1309
1310 boost::shared_ptr<OrthancStone::OsiriX::CollectionOfAnnotations> annotations_; 1310
1311 bool hasFocusOnInstance_;
1312 std::string focusSopInstanceUid_;
1313
1314 boost::shared_ptr<OrthancStone::OsiriX::CollectionOfAnnotations> annotations_;
1311 1315
1312 void ScheduleNextPrefetch() 1316 void ScheduleNextPrefetch()
1313 { 1317 {
1314 while (!prefetchQueue_.empty()) 1318 while (!prefetchQueue_.empty())
1315 { 1319 {
1316 size_t index = prefetchQueue_.front().GetFrameIndex(); 1320 size_t index = prefetchQueue_.front().GetFrameIndex();
1317 bool isFull = prefetchQueue_.front().IsFull(); 1321 bool isFull = prefetchQueue_.front().IsFull();
1318 prefetchQueue_.pop_front(); 1322 prefetchQueue_.pop_front();
1319 1323
1320 const std::string sopInstanceUid = frames_->GetFrameSopInstanceUid(index); 1324 const std::string sopInstanceUid = frames_->GetFrameSopInstanceUid(index);
1321 unsigned int frame = frames_->GetFrameIndex(index); 1325 unsigned int frameNumber = frames_->GetFrameNumberInInstance(index);
1322 1326
1323 { 1327 {
1324 FramesCache::Accessor accessor(*cache_, sopInstanceUid, frame); 1328 FramesCache::Accessor accessor(*cache_, sopInstanceUid, frameNumber);
1325 if (!accessor.IsValid() || 1329 if (!accessor.IsValid() ||
1326 (isFull && accessor.GetQuality() == 0)) 1330 (isFull && accessor.GetQuality() == 0))
1327 { 1331 {
1328 if (isFull) 1332 if (isFull)
1329 { 1333 {
1350 1354
1351 inverted_ = false; 1355 inverted_ = false;
1352 } 1356 }
1353 1357
1354 void SignalUpdatedFrame(const std::string& sopInstanceUid, 1358 void SignalUpdatedFrame(const std::string& sopInstanceUid,
1355 unsigned int frameIndex) 1359 unsigned int frameNumber)
1356 { 1360 {
1357 if (cursor_.get() != NULL && 1361 if (cursor_.get() != NULL &&
1358 frames_.get() != NULL) 1362 frames_.get() != NULL)
1359 { 1363 {
1360 size_t index = cursor_->GetCurrentIndex(); 1364 size_t index = cursor_->GetCurrentIndex();
1361 1365
1362 if (frames_->GetFrameSopInstanceUid(index) == sopInstanceUid && 1366 if (frames_->GetFrameSopInstanceUid(index) == sopInstanceUid &&
1363 frames_->GetFrameIndex(index) == frameIndex) 1367 frames_->GetFrameNumberInInstance(index) == frameNumber)
1364 { 1368 {
1365 DisplayCurrentFrame(); 1369 DisplayCurrentFrame();
1366 } 1370 }
1367 } 1371 }
1368 } 1372 }
1469 { 1473 {
1470 return false; 1474 return false;
1471 } 1475 }
1472 1476
1473 const std::string sopInstanceUid = frames_->GetFrameSopInstanceUid(index); 1477 const std::string sopInstanceUid = frames_->GetFrameSopInstanceUid(index);
1474 unsigned int frame = frames_->GetFrameIndex(index); 1478 size_t frameNumber = frames_->GetFrameNumberInInstance(index);
1475 1479
1476 FramesCache::Accessor accessor(*cache_, sopInstanceUid, frame); 1480 FramesCache::Accessor accessor(*cache_, sopInstanceUid, frameNumber);
1477 if (accessor.IsValid()) 1481 if (accessor.IsValid())
1478 { 1482 {
1479 SaveCurrentWindowing(); 1483 SaveCurrentWindowing();
1480 1484
1481 quality = accessor.GetQuality(); 1485 quality = accessor.GetQuality();
1654 bool isPrefetch) 1658 bool isPrefetch)
1655 { 1659 {
1656 if (frames_.get() != NULL) 1660 if (frames_.get() != NULL)
1657 { 1661 {
1658 std::string sopInstanceUid = frames_->GetFrameSopInstanceUid(index); 1662 std::string sopInstanceUid = frames_->GetFrameSopInstanceUid(index);
1659 unsigned int frame = frames_->GetFrameIndex(index); 1663 unsigned int frameNumber = frames_->GetFrameNumberInInstance(index);
1660 1664
1661 { 1665 {
1662 std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(context_.Lock()); 1666 std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(context_.Lock());
1663 lock->Schedule( 1667 lock->Schedule(
1664 GetSharedObserver(), priority, OrthancStone::ParseDicomFromWadoCommand::Create( 1668 GetSharedObserver(), priority, OrthancStone::ParseDicomFromWadoCommand::Create(
1665 source_, frames_->GetStudyInstanceUid(), frames_->GetSeriesInstanceUid(), 1669 source_, frames_->GetStudyInstanceUid(), frames_->GetSeriesInstanceUid(),
1666 sopInstanceUid, false /* transcoding (TODO) */, 1670 sopInstanceUid, false /* transcoding (TODO) */,
1667 Orthanc::DicomTransferSyntax_LittleEndianExplicit /* TODO */, 1671 Orthanc::DicomTransferSyntax_LittleEndianExplicit /* TODO */,
1668 new SetFullDicomFrame(GetSharedObserver(), sopInstanceUid, frame, isPrefetch))); 1672 new SetFullDicomFrame(GetSharedObserver(), sopInstanceUid, frameNumber, isPrefetch)));
1669 } 1673 }
1670 } 1674 }
1671 } 1675 }
1672 1676
1673 void ScheduleLoadRenderedFrame(size_t index, 1677 void ScheduleLoadRenderedFrame(size_t index,
1679 ScheduleLoadFullDicomFrame(index, priority, isPrefetch); 1683 ScheduleLoadFullDicomFrame(index, priority, isPrefetch);
1680 } 1684 }
1681 else if (frames_.get() != NULL) 1685 else if (frames_.get() != NULL)
1682 { 1686 {
1683 std::string sopInstanceUid = frames_->GetFrameSopInstanceUid(index); 1687 std::string sopInstanceUid = frames_->GetFrameSopInstanceUid(index);
1684 unsigned int frame = frames_->GetFrameIndex(index); 1688 unsigned int frameNumber = frames_->GetFrameNumberInInstance(index);
1685 bool isMonochrome1 = frames_->IsFrameMonochrome1(index); 1689 bool isMonochrome1 = frames_->IsFrameMonochrome1(index);
1686 1690
1687 const std::string uri = ("studies/" + frames_->GetStudyInstanceUid() + 1691 const std::string uri = ("studies/" + frames_->GetStudyInstanceUid() +
1688 "/series/" + frames_->GetSeriesInstanceUid() + 1692 "/series/" + frames_->GetSeriesInstanceUid() +
1689 "/instances/" + sopInstanceUid + 1693 "/instances/" + sopInstanceUid +
1690 "/frames/" + boost::lexical_cast<std::string>(frame + 1) + "/rendered"); 1694 "/frames/" + boost::lexical_cast<std::string>(frameNumber + 1) + "/rendered");
1691 1695
1692 std::map<std::string, std::string> headers, arguments; 1696 std::map<std::string, std::string> headers, arguments;
1693 arguments["window"] = ( 1697 arguments["window"] = (
1694 boost::lexical_cast<std::string>(windowingCenter_) + "," + 1698 boost::lexical_cast<std::string>(windowingCenter_) + "," +
1695 boost::lexical_cast<std::string>(windowingWidth_) + ",linear"); 1699 boost::lexical_cast<std::string>(windowingWidth_) + ",linear");
1696 1700
1697 std::unique_ptr<OrthancStone::IOracleCommand> command( 1701 std::unique_ptr<OrthancStone::IOracleCommand> command(
1698 source_.CreateDicomWebCommand( 1702 source_.CreateDicomWebCommand(
1699 uri, arguments, headers, new SetLowQualityFrame( 1703 uri, arguments, headers, new SetLowQualityFrame(
1700 GetSharedObserver(), sopInstanceUid, frame, 1704 GetSharedObserver(), sopInstanceUid, frameNumber,
1701 windowingCenter_, windowingWidth_, isMonochrome1, isPrefetch))); 1705 windowingCenter_, windowingWidth_, isMonochrome1, isPrefetch)));
1702 1706
1703 { 1707 {
1704 std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(context_.Lock()); 1708 std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(context_.Lock());
1705 lock->Schedule(GetSharedObserver(), priority, command.release()); 1709 lock->Schedule(GetSharedObserver(), priority, command.release());
1744 source_(source), 1748 source_(source),
1745 cache_(cache), 1749 cache_(cache),
1746 fitNextContent_(true), 1750 fitNextContent_(true),
1747 isCtrlDown_(false), 1751 isCtrlDown_(false),
1748 flipX_(false), 1752 flipX_(false),
1749 flipY_(false) 1753 flipY_(false),
1754 hasFocusOnInstance_(false)
1750 { 1755 {
1751 if (!cache_) 1756 if (!cache_)
1752 { 1757 {
1753 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); 1758 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
1754 } 1759 }
1849 1854
1850 void Handle(const OrthancStone::ParseDicomSuccessMessage& message) 1855 void Handle(const OrthancStone::ParseDicomSuccessMessage& message)
1851 { 1856 {
1852 dynamic_cast<const ICommand&>(message.GetOrigin().GetPayload()).Handle(message); 1857 dynamic_cast<const ICommand&>(message.GetOrigin().GetPayload()).Handle(message);
1853 } 1858 }
1859
1860 void ApplyScheduledFocus()
1861 {
1862 size_t instanceIndex;
1863
1864 if (hasFocusOnInstance_ &&
1865 frames_.get() != NULL &&
1866 frames_->LookupSopInstanceUid(instanceIndex, focusSopInstanceUid_))
1867 {
1868 // TODO
1869
1870 hasFocusOnInstance_ = false;
1871 }
1872 }
1854 1873
1855 public: 1874 public:
1856 static boost::shared_ptr<ViewerViewport> Create(OrthancStone::ILoadersContext::ILock& lock, 1875 static boost::shared_ptr<ViewerViewport> Create(OrthancStone::ILoadersContext::ILock& lock,
1857 const OrthancStone::DicomSource& source, 1876 const OrthancStone::DicomSource& source,
1858 const std::string& canvas, 1877 const std::string& canvas,