comparison Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp @ 2102:9f7604d6b581 deep-learning

integration mainline->deep-learning
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 14 Nov 2023 11:45:17 +0100
parents fdb012c86a75 ec676dbe85ac
children de049fd88697
comparison
equal deleted inserted replaced
2082:a6d5373e471c 2102:9f7604d6b581
202 202
203 static const unsigned int DEFAULT_CINE_RATE = 30; 203 static const unsigned int DEFAULT_CINE_RATE = 30;
204 204
205 205
206 206
207 class IFramesCollection : public boost::noncopyable
208 {
209 public:
210 virtual ~IFramesCollection()
211 {
212 }
213
214 virtual size_t GetFramesCount() const = 0;
215
216 virtual const OrthancStone::DicomInstanceParameters& GetInstanceOfFrame(size_t frameIndex) const = 0;
217
218 virtual unsigned int GetFrameNumberInInstance(size_t frameIndex) const = 0;
219
220 virtual bool LookupFrame(size_t& frameIndex,
221 const std::string& sopInstanceUid,
222 unsigned int frameNumber) const = 0;
223
224 virtual bool FindClosestFrame(size_t& frameIndex,
225 const OrthancStone::Vector& point,
226 double maximumDistance) const = 0;
227
228 static OrthancStone::CoordinateSystem3D GetFrameGeometry(const IFramesCollection& frames,
229 size_t frameIndex)
230 {
231 return frames.GetInstanceOfFrame(frameIndex).GetFrameGeometry(frames.GetFrameNumberInInstance(frameIndex));
232 }
233 };
234
235
236 class SortedFramesCollection : public IFramesCollection
237 {
238 private:
239 std::unique_ptr<OrthancStone::SortedFrames> frames_;
240
241 public:
242 SortedFramesCollection(OrthancStone::SortedFrames* frames)
243 {
244 if (frames == NULL)
245 {
246 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
247 }
248 else
249 {
250 frames_.reset(frames);
251 }
252 }
253
254 virtual size_t GetFramesCount() const ORTHANC_OVERRIDE
255 {
256 return frames_->GetFramesCount();
257 }
258
259 const OrthancStone::DicomInstanceParameters& GetInstanceOfFrame(size_t frameIndex) const ORTHANC_OVERRIDE
260 {
261 return frames_->GetInstanceOfFrame(frameIndex);
262 }
263
264 virtual unsigned int GetFrameNumberInInstance(size_t frameIndex) const ORTHANC_OVERRIDE
265 {
266 return frames_->GetFrameNumberInInstance(frameIndex);
267 }
268
269 virtual bool LookupFrame(size_t& frameIndex,
270 const std::string& sopInstanceUid,
271 unsigned int frameNumber) const ORTHANC_OVERRIDE
272 {
273 return frames_->LookupFrame(frameIndex, sopInstanceUid, frameNumber);
274 }
275
276 virtual bool FindClosestFrame(size_t& frameIndex,
277 const OrthancStone::Vector& point,
278 double maximumDistance) const ORTHANC_OVERRIDE
279 {
280 return frames_->FindClosestFrame(frameIndex, point, maximumDistance);
281 };
282 };
283
284
207 class VirtualSeries : public boost::noncopyable 285 class VirtualSeries : public boost::noncopyable
208 { 286 {
209 private: 287 private:
210 class Item : public boost::noncopyable 288 class Item : public boost::noncopyable
211 { 289 {
739 { 817 {
740 return false; 818 return false;
741 } 819 }
742 } 820 }
743 821
744 bool SortSeriesFrames(OrthancStone::SortedFrames& target, 822 IFramesCollection* GetSeriesFrames(const std::string& seriesInstanceUid) const
745 const std::string& seriesInstanceUid) const
746 { 823 {
747 OrthancStone::SeriesMetadataLoader::Accessor accessor(*metadataLoader_, seriesInstanceUid); 824 OrthancStone::SeriesMetadataLoader::Accessor accessor(*metadataLoader_, seriesInstanceUid);
748 825
749 if (accessor.IsComplete()) 826 if (accessor.IsComplete())
750 { 827 {
751 target.Clear(); 828 std::unique_ptr<OrthancStone::SortedFrames> target(new OrthancStone::SortedFrames);
829 target->Clear();
752 830
753 for (size_t i = 0; i < accessor.GetInstancesCount(); i++) 831 for (size_t i = 0; i < accessor.GetInstancesCount(); i++)
754 { 832 {
755 target.AddInstance(accessor.GetInstance(i)); 833 target->AddInstance(accessor.GetInstance(i));
756 } 834 }
757 835
758 target.Sort(); 836 target->Sort();
759 837
760 return true; 838 return new SortedFramesCollection(target.release());
761 } 839 }
762 else 840 else
763 { 841 {
764 return false; 842 return NULL;
765 } 843 }
766 } 844 }
767 845
768 bool SortVirtualSeriesFrames(OrthancStone::SortedFrames& target, 846 IFramesCollection* GetVirtualSeriesFrames(const std::string& virtualSeriesId) const
769 const std::string& virtualSeriesId) const
770 { 847 {
771 const std::string& seriesInstanceUid = virtualSeries_.GetSeriesInstanceUid(virtualSeriesId); 848 const std::string& seriesInstanceUid = virtualSeries_.GetSeriesInstanceUid(virtualSeriesId);
772 849
773 OrthancStone::SeriesMetadataLoader::Accessor accessor(*metadataLoader_, seriesInstanceUid); 850 OrthancStone::SeriesMetadataLoader::Accessor accessor(*metadataLoader_, seriesInstanceUid);
774 851
775 if (accessor.IsComplete()) 852 if (accessor.IsComplete())
776 { 853 {
777 const std::list<std::string>& sopInstanceUids = virtualSeries_.GetSopInstanceUids(virtualSeriesId); 854 const std::list<std::string>& sopInstanceUids = virtualSeries_.GetSopInstanceUids(virtualSeriesId);
778 855
779 target.Clear(); 856 std::unique_ptr<OrthancStone::SortedFrames> target(new OrthancStone::SortedFrames);
857 target->Clear();
780 858
781 for (std::list<std::string>::const_iterator 859 for (std::list<std::string>::const_iterator
782 it = sopInstanceUids.begin(); it != sopInstanceUids.end(); ++it) 860 it = sopInstanceUids.begin(); it != sopInstanceUids.end(); ++it)
783 { 861 {
784 Orthanc::DicomMap instance; 862 Orthanc::DicomMap instance;
785 if (accessor.LookupInstance(instance, *it)) 863 if (accessor.LookupInstance(instance, *it))
786 { 864 {
787 target.AddInstance(instance); 865 target->AddInstance(instance);
788 } 866 }
789 else 867 else
790 { 868 {
791 LOG(ERROR) << "Missing instance: " << *it; 869 LOG(ERROR) << "Missing instance: " << *it;
792 } 870 }
793 } 871 }
794 872
795 target.Sort(); 873 target->Sort();
796 return true; 874
875 return new SortedFramesCollection(target.release());
797 } 876 }
798 else 877 else
799 { 878 {
800 return false; 879 return NULL;
801 } 880 }
802 } 881 }
803 882
804 size_t GetSeriesNumberOfFrames(const std::string& seriesInstanceUid) const 883 size_t GetSeriesNumberOfFrames(const std::string& seriesInstanceUid) const
805 { 884 {
1555 }; 1634 };
1556 }; 1635 };
1557 1636
1558 1637
1559 1638
1560
1561 class ViewerViewport : public OrthancStone::ObserverBase<ViewerViewport> 1639 class ViewerViewport : public OrthancStone::ObserverBase<ViewerViewport>
1562 { 1640 {
1563 public: 1641 public:
1564 class IObserver : public boost::noncopyable 1642 class IObserver : public boost::noncopyable
1565 { 1643 {
1838 1916
1839 1917
1840 class SetFullDicomFrame : public ICommand 1918 class SetFullDicomFrame : public ICommand
1841 { 1919 {
1842 private: 1920 private:
1921 std::string studyInstanceUid_;
1922 std::string seriesInstanceUid_;
1843 std::string sopInstanceUid_; 1923 std::string sopInstanceUid_;
1844 unsigned int frameNumber_; 1924 unsigned int frameNumber_;
1845 int priority_; 1925 int priority_;
1846 bool isPrefetch_; 1926 bool isPrefetch_;
1847 bool serverSideTranscoding_; 1927 bool serverSideTranscoding_;
1848 1928
1849 public: 1929 public:
1850 SetFullDicomFrame(boost::shared_ptr<ViewerViewport> viewport, 1930 SetFullDicomFrame(boost::shared_ptr<ViewerViewport> viewport,
1931 const std::string& studyInstanceUid,
1932 const std::string& seriesInstanceUid,
1851 const std::string& sopInstanceUid, 1933 const std::string& sopInstanceUid,
1852 unsigned int frameNumber, 1934 unsigned int frameNumber,
1853 int priority, 1935 int priority,
1854 bool isPrefetch, 1936 bool isPrefetch,
1855 bool serverSideTranscoding) : 1937 bool serverSideTranscoding) :
1856 ICommand(viewport), 1938 ICommand(viewport),
1939 studyInstanceUid_(studyInstanceUid),
1940 seriesInstanceUid_(seriesInstanceUid),
1857 sopInstanceUid_(sopInstanceUid), 1941 sopInstanceUid_(sopInstanceUid),
1858 frameNumber_(frameNumber), 1942 frameNumber_(frameNumber),
1859 priority_(priority), 1943 priority_(priority),
1860 isPrefetch_(isPrefetch), 1944 isPrefetch_(isPrefetch),
1861 serverSideTranscoding_(serverSideTranscoding) 1945 serverSideTranscoding_(serverSideTranscoding)
1877 if (!serverSideTranscoding_) 1961 if (!serverSideTranscoding_)
1878 { 1962 {
1879 // If we haven't tried server-side rendering yet, give it a try 1963 // If we haven't tried server-side rendering yet, give it a try
1880 LOG(INFO) << "Switching to server-side transcoding"; 1964 LOG(INFO) << "Switching to server-side transcoding";
1881 GetViewport().serverSideTranscoding_ = true; 1965 GetViewport().serverSideTranscoding_ = true;
1882 GetViewport().ScheduleLoadFullDicomFrame(sopInstanceUid_, frameNumber_, priority_, isPrefetch_); 1966 GetViewport().ScheduleLoadFullDicomFrame(studyInstanceUid_, seriesInstanceUid_, sopInstanceUid_, frameNumber_, priority_, isPrefetch_);
1883 } 1967 }
1884 return; 1968 return;
1885 } 1969 }
1886 else 1970 else
1887 { 1971 {
1995 OrthancStone::WebAssemblyLoadersContext& context_; 2079 OrthancStone::WebAssemblyLoadersContext& context_;
1996 boost::shared_ptr<OrthancStone::WebAssemblyViewport> viewport_; 2080 boost::shared_ptr<OrthancStone::WebAssemblyViewport> viewport_;
1997 boost::shared_ptr<OrthancStone::DicomResourcesLoader> loader_; 2081 boost::shared_ptr<OrthancStone::DicomResourcesLoader> loader_;
1998 OrthancStone::DicomSource source_; 2082 OrthancStone::DicomSource source_;
1999 boost::shared_ptr<FramesCache> framesCache_; 2083 boost::shared_ptr<FramesCache> framesCache_;
2000 std::unique_ptr<OrthancStone::SortedFrames> frames_; 2084 std::unique_ptr<IFramesCollection> frames_;
2001 std::unique_ptr<SeriesCursor> cursor_; 2085 std::unique_ptr<SeriesCursor> cursor_;
2002 float windowingCenter_; 2086 float windowingCenter_;
2003 float windowingWidth_; 2087 float windowingWidth_;
2004 std::vector<float> windowingPresetCenters_; 2088 std::vector<float> windowingPresetCenters_;
2005 std::vector<float> windowingPresetWidths_; 2089 std::vector<float> windowingPresetWidths_;
2385 2469
2386 // Only change the scene if the loaded frame still corresponds to the current cursor 2470 // Only change the scene if the loaded frame still corresponds to the current cursor
2387 if (instance.GetSopInstanceUid() == loadedSopInstanceUid && 2471 if (instance.GetSopInstanceUid() == loadedSopInstanceUid &&
2388 frameNumber == loadedFrameNumber) 2472 frameNumber == loadedFrameNumber)
2389 { 2473 {
2390 const OrthancStone::CoordinateSystem3D plane = frames_->GetFrameGeometry(cursorIndex); 2474 const OrthancStone::CoordinateSystem3D plane = IFramesCollection::GetFrameGeometry(*frames_, cursorIndex);
2391 2475
2392 if (quality == DisplayedFrameQuality_Low) 2476 if (quality == DisplayedFrameQuality_Low)
2393 { 2477 {
2394 FramesCache::Accessor accessor(*framesCache_, instance.GetSopInstanceUid(), frameNumber); 2478 FramesCache::Accessor accessor(*framesCache_, instance.GetSopInstanceUid(), frameNumber);
2395 if (accessor.IsValid() && 2479 if (accessor.IsValid() &&
2424 } 2508 }
2425 } 2509 }
2426 } 2510 }
2427 } 2511 }
2428 2512
2429 void ScheduleLoadFullDicomFrame(const std::string& sopInstanceUid, 2513 void ScheduleLoadFullDicomFrame(const std::string& studyInstanceUid,
2514 const std::string& seriesInstanceUid,
2515 const std::string& sopInstanceUid,
2430 unsigned int frameNumber, 2516 unsigned int frameNumber,
2431 int priority, 2517 int priority,
2432 bool isPrefetch) 2518 bool isPrefetch)
2433 { 2519 {
2434 if (frames_.get() != NULL) 2520 if (frames_.get() != NULL)
2435 { 2521 {
2436 std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(context_.Lock()); 2522 std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(context_.Lock());
2437 lock->Schedule( 2523 lock->Schedule(
2438 GetSharedObserver(), priority, OrthancStone::ParseDicomFromWadoCommand::Create( 2524 GetSharedObserver(), priority, OrthancStone::ParseDicomFromWadoCommand::Create(
2439 source_, frames_->GetStudyInstanceUid(), frames_->GetSeriesInstanceUid(), 2525 source_, studyInstanceUid, seriesInstanceUid, sopInstanceUid, serverSideTranscoding_,
2440 sopInstanceUid, serverSideTranscoding_,
2441 Orthanc::DicomTransferSyntax_LittleEndianExplicit, 2526 Orthanc::DicomTransferSyntax_LittleEndianExplicit,
2442 new SetFullDicomFrame(GetSharedObserver(), sopInstanceUid, frameNumber, priority, isPrefetch, serverSideTranscoding_))); 2527 new SetFullDicomFrame(GetSharedObserver(), studyInstanceUid, seriesInstanceUid,
2528 sopInstanceUid, frameNumber, priority, isPrefetch, serverSideTranscoding_)));
2443 } 2529 }
2444 } 2530 }
2445 2531
2446 void ScheduleLoadFullDicomFrame(size_t cursorIndex, 2532 void ScheduleLoadFullDicomFrame(size_t cursorIndex,
2447 int priority, 2533 int priority,
2448 bool isPrefetch) 2534 bool isPrefetch)
2449 { 2535 {
2450 if (frames_.get() != NULL) 2536 if (frames_.get() != NULL)
2451 { 2537 {
2538 std::string studyInstanceUid = frames_->GetInstanceOfFrame(cursorIndex).GetStudyInstanceUid();
2539 std::string seriesInstanceUid = frames_->GetInstanceOfFrame(cursorIndex).GetSeriesInstanceUid();
2452 std::string sopInstanceUid = frames_->GetInstanceOfFrame(cursorIndex).GetSopInstanceUid(); 2540 std::string sopInstanceUid = frames_->GetInstanceOfFrame(cursorIndex).GetSopInstanceUid();
2453 unsigned int frameNumber = frames_->GetFrameNumberInInstance(cursorIndex); 2541 unsigned int frameNumber = frames_->GetFrameNumberInInstance(cursorIndex);
2454 ScheduleLoadFullDicomFrame(sopInstanceUid, frameNumber, priority, isPrefetch); 2542 ScheduleLoadFullDicomFrame(studyInstanceUid, seriesInstanceUid, sopInstanceUid, frameNumber, priority, isPrefetch);
2455 } 2543 }
2456 } 2544 }
2457 2545
2458 void ScheduleLoadRenderedFrame(size_t cursorIndex, 2546 void ScheduleLoadRenderedFrame(size_t cursorIndex,
2459 int priority, 2547 int priority,
2498 } 2586 }
2499 2587
2500 bool isMonochrome1 = (instance.GetImageInformation().GetPhotometricInterpretation() == 2588 bool isMonochrome1 = (instance.GetImageInformation().GetPhotometricInterpretation() ==
2501 Orthanc::PhotometricInterpretation_Monochrome1); 2589 Orthanc::PhotometricInterpretation_Monochrome1);
2502 2590
2503 const std::string uri = ("studies/" + frames_->GetStudyInstanceUid() + 2591 const std::string uri = ("studies/" + instance.GetStudyInstanceUid() +
2504 "/series/" + frames_->GetSeriesInstanceUid() + 2592 "/series/" + instance.GetSeriesInstanceUid() +
2505 "/instances/" + instance.GetSopInstanceUid() + 2593 "/instances/" + instance.GetSopInstanceUid() +
2506 "/frames/" + boost::lexical_cast<std::string>(frameNumber + 1) + "/rendered"); 2594 "/frames/" + boost::lexical_cast<std::string>(frameNumber + 1) + "/rendered");
2507 2595
2508 std::map<std::string, std::string> headers, arguments; 2596 std::map<std::string, std::string> headers, arguments;
2509 // arguments["quality"] = "10"; // Low-level quality for test purpose 2597 // arguments["quality"] = "10"; // Low-level quality for test purpose
2540 2628
2541 lock->Invalidate(); 2629 lock->Invalidate();
2542 } 2630 }
2543 } 2631 }
2544 2632
2545
2546 ViewerViewport(OrthancStone::WebAssemblyLoadersContext& context, 2633 ViewerViewport(OrthancStone::WebAssemblyLoadersContext& context,
2547 const OrthancStone::DicomSource& source, 2634 const OrthancStone::DicomSource& source,
2548 const std::string& canvas, 2635 const std::string& canvas,
2549 boost::shared_ptr<FramesCache> cache, 2636 boost::shared_ptr<FramesCache> cache,
2550 bool softwareRendering, 2637 bool softwareRendering,
2635 2722
2636 if (that.synchronizationEnabled_) 2723 if (that.synchronizationEnabled_)
2637 { 2724 {
2638 const size_t currentCursorIndex = that.cursor_->GetCurrentIndex(); 2725 const size_t currentCursorIndex = that.cursor_->GetCurrentIndex();
2639 2726
2640 const OrthancStone::CoordinateSystem3D current = 2727 const OrthancStone::CoordinateSystem3D current = IFramesCollection::GetFrameGeometry(*that.frames_, currentCursorIndex);
2641 that.frames_->GetFrameGeometry(currentCursorIndex);
2642 2728
2643 if (isShift && 2729 if (isShift &&
2644 previousCursorIndex != currentCursorIndex) 2730 previousCursorIndex != currentCursorIndex)
2645 { 2731 {
2646 const OrthancStone::CoordinateSystem3D previous = 2732 const OrthancStone::CoordinateSystem3D previous = IFramesCollection::GetFrameGeometry(*that.frames_, previousCursorIndex);
2647 that.frames_->GetFrameGeometry(previousCursorIndex);
2648 that.synchronizationOffset_ += previous.GetOrigin() - current.GetOrigin(); 2733 that.synchronizationOffset_ += previous.GetOrigin() - current.GetOrigin();
2649 } 2734 }
2650 2735
2651 that.observer_->SignalSynchronizedBrowsing( 2736 that.observer_->SignalSynchronizedBrowsing(
2652 that, current.GetOrigin() + that.synchronizationOffset_, current.GetNormal()); 2737 that, current.GetOrigin() + that.synchronizationOffset_, current.GetNormal());
2789 } 2874 }
2790 2875
2791 return viewport; 2876 return viewport;
2792 } 2877 }
2793 2878
2794 void SetFrames(OrthancStone::SortedFrames* frames) 2879 void SetFrames(IFramesCollection* frames)
2795 { 2880 {
2796 if (frames == NULL) 2881 if (frames == NULL)
2797 { 2882 {
2798 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); 2883 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
2799 } 2884 }
2859 uid != OrthancStone::SopClassUid_RTPlan && 2944 uid != OrthancStone::SopClassUid_RTPlan &&
2860 uid != OrthancStone::SopClassUid_RTStruct && 2945 uid != OrthancStone::SopClassUid_RTStruct &&
2861 GetSeriesThumbnailType(uid) != OrthancStone::SeriesThumbnailType_Video) 2946 GetSeriesThumbnailType(uid) != OrthancStone::SeriesThumbnailType_Video)
2862 { 2947 {
2863 // Fetch the details of the series from the central instance 2948 // Fetch the details of the series from the central instance
2864 const std::string uri = ("studies/" + frames_->GetStudyInstanceUid() + 2949 const std::string uri = ("studies/" + centralInstance.GetStudyInstanceUid() +
2865 "/series/" + frames_->GetSeriesInstanceUid() + 2950 "/series/" + centralInstance.GetSeriesInstanceUid() +
2866 "/instances/" + centralInstance.GetSopInstanceUid() + "/metadata"); 2951 "/instances/" + centralInstance.GetSopInstanceUid() + "/metadata");
2867 2952
2868 loader_->ScheduleGetDicomWeb( 2953 loader_->ScheduleGetDicomWeb(
2869 boost::make_shared<OrthancStone::LoadedDicomResources>(Orthanc::DICOM_TAG_SOP_INSTANCE_UID), 2954 boost::make_shared<OrthancStone::LoadedDicomResources>(Orthanc::DICOM_TAG_SOP_INSTANCE_UID),
2870 0, source_, uri, new LoadSeriesDetailsFromInstance(GetSharedObserver())); 2955 0, source_, uri, new LoadSeriesDetailsFromInstance(GetSharedObserver()));
2916 const unsigned int frameNumber = frames_->GetFrameNumberInInstance(cursorIndex); 3001 const unsigned int frameNumber = frames_->GetFrameNumberInInstance(cursorIndex);
2917 3002
2918 FramesCache::Accessor accessor(*framesCache_, instance.GetSopInstanceUid(), frameNumber); 3003 FramesCache::Accessor accessor(*framesCache_, instance.GetSopInstanceUid(), frameNumber);
2919 if (accessor.IsValid()) 3004 if (accessor.IsValid())
2920 { 3005 {
2921 RenderCurrentScene(accessor.GetImage(), instance, frameNumber, frames_->GetFrameGeometry(cursorIndex)); 3006 RenderCurrentScene(accessor.GetImage(), instance, frameNumber, IFramesCollection::GetFrameGeometry(*frames_, cursorIndex));
2922 3007
2923 DisplayedFrameQuality quality; 3008 DisplayedFrameQuality quality;
2924 3009
2925 if (accessor.GetQuality() < QUALITY_FULL) 3010 if (accessor.GetQuality() < QUALITY_FULL)
2926 { 3011 {
3027 bool GetCurrentPlane(OrthancStone::CoordinateSystem3D& plane) const 3112 bool GetCurrentPlane(OrthancStone::CoordinateSystem3D& plane) const
3028 { 3113 {
3029 if (cursor_.get() != NULL && 3114 if (cursor_.get() != NULL &&
3030 frames_.get() != NULL) 3115 frames_.get() != NULL)
3031 { 3116 {
3032 plane = frames_->GetFrameGeometry(cursor_->GetCurrentIndex()); 3117 plane = IFramesCollection::GetFrameGeometry(*frames_, cursor_->GetCurrentIndex());
3033 return true; 3118 return true;
3034 } 3119 }
3035 else 3120 else
3036 { 3121 {
3037 return false; 3122 return false;
3101 3186
3102 3187
3103 void SetWindowingPreset() 3188 void SetWindowingPreset()
3104 { 3189 {
3105 assert(windowingPresetCenters_.size() == windowingPresetWidths_.size()); 3190 assert(windowingPresetCenters_.size() == windowingPresetWidths_.size());
3106 3191
3107 if (windowingPresetCenters_.empty()) 3192 if (windowingPresetCenters_.empty())
3108 { 3193 {
3109 SetWindowing(128, 256); 3194 SetWindowing(128, 256);
3110 } 3195 }
3111 else 3196 else
3566 frames_.get() != NULL && 3651 frames_.get() != NULL &&
3567 cursor_.get() != NULL) 3652 cursor_.get() != NULL)
3568 { 3653 {
3569 const size_t currentCursorIndex = cursor_->GetCurrentIndex(); 3654 const size_t currentCursorIndex = cursor_->GetCurrentIndex();
3570 3655
3571 const OrthancStone::CoordinateSystem3D current = 3656 const OrthancStone::CoordinateSystem3D current = IFramesCollection::GetFrameGeometry(*frames_, currentCursorIndex);
3572 frames_->GetFrameGeometry(currentCursorIndex);
3573 3657
3574 observer_->SignalSynchronizedBrowsing( 3658 observer_->SignalSynchronizedBrowsing(
3575 *this, current.GetOrigin() + synchronizationOffset_, current.GetNormal()); 3659 *this, current.GetOrigin() + synchronizationOffset_, current.GetNormal());
3576 } 3660 }
3577 } 3661 }
4474 int LoadSeriesInViewport(const char* canvas, 4558 int LoadSeriesInViewport(const char* canvas,
4475 const char* seriesInstanceUid) 4559 const char* seriesInstanceUid)
4476 { 4560 {
4477 try 4561 try
4478 { 4562 {
4479 std::unique_ptr<OrthancStone::SortedFrames> frames(new OrthancStone::SortedFrames); 4563 std::unique_ptr<IFramesCollection> frames(GetResourcesLoader().GetSeriesFrames(seriesInstanceUid));
4480 4564
4481 if (GetResourcesLoader().SortSeriesFrames(*frames, seriesInstanceUid)) 4565 if (frames.get() != NULL)
4482 { 4566 {
4483 GetViewport(canvas)->SetFrames(frames.release()); 4567 GetViewport(canvas)->SetFrames(frames.release());
4484 return 1; 4568 return 1;
4485 } 4569 }
4486 else 4570 else
4497 int LoadVirtualSeriesInViewport(const char* canvas, 4581 int LoadVirtualSeriesInViewport(const char* canvas,
4498 const char* virtualSeriesId) 4582 const char* virtualSeriesId)
4499 { 4583 {
4500 try 4584 try
4501 { 4585 {
4502 std::unique_ptr<OrthancStone::SortedFrames> frames(new OrthancStone::SortedFrames); 4586 std::unique_ptr<IFramesCollection> frames(GetResourcesLoader().GetVirtualSeriesFrames(virtualSeriesId));
4503 4587
4504 if (GetResourcesLoader().SortVirtualSeriesFrames(*frames, virtualSeriesId)) 4588 if (frames.get() != NULL)
4505 { 4589 {
4506 GetViewport(canvas)->SetFrames(frames.release()); 4590 GetViewport(canvas)->SetFrames(frames.release());
4507 return 1; 4591 return 1;
4508 } 4592 }
4509 else 4593 else