comparison Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp @ 1657:66e5fcdf5597

pdf viewer is working
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 18 Nov 2020 11:19:09 +0100
parents 39137da83b0b
children fc883105ee11
comparison
equal deleted inserted replaced
1656:4cdc297be5a6 1657:66e5fcdf5597
182 virtual void SignalSeriesThumbnailLoaded(const std::string& studyInstanceUid, 182 virtual void SignalSeriesThumbnailLoaded(const std::string& studyInstanceUid,
183 const std::string& seriesInstanceUid) = 0; 183 const std::string& seriesInstanceUid) = 0;
184 184
185 virtual void SignalSeriesMetadataLoaded(const std::string& studyInstanceUid, 185 virtual void SignalSeriesMetadataLoaded(const std::string& studyInstanceUid,
186 const std::string& seriesInstanceUid) = 0; 186 const std::string& seriesInstanceUid) = 0;
187
188 virtual void SignalSeriesPdfLoaded(const std::string& studyInstanceUid,
189 const std::string& seriesInstanceUid,
190 const std::string& pdf) = 0;
187 }; 191 };
188 192
189 private: 193 private:
194 OrthancStone::ILoadersContext& context_;
190 std::unique_ptr<IObserver> observer_; 195 std::unique_ptr<IObserver> observer_;
191 OrthancStone::DicomSource source_; 196 OrthancStone::DicomSource source_;
192 size_t pending_; 197 size_t pending_;
193 boost::shared_ptr<OrthancStone::LoadedDicomResources> studies_; 198 boost::shared_ptr<OrthancStone::LoadedDicomResources> studies_;
194 boost::shared_ptr<OrthancStone::LoadedDicomResources> series_; 199 boost::shared_ptr<OrthancStone::LoadedDicomResources> series_;
195 boost::shared_ptr<OrthancStone::DicomResourcesLoader> resourcesLoader_; 200 boost::shared_ptr<OrthancStone::DicomResourcesLoader> resourcesLoader_;
196 boost::shared_ptr<OrthancStone::SeriesThumbnailsLoader> thumbnailsLoader_; 201 boost::shared_ptr<OrthancStone::SeriesThumbnailsLoader> thumbnailsLoader_;
197 boost::shared_ptr<OrthancStone::SeriesMetadataLoader> metadataLoader_; 202 boost::shared_ptr<OrthancStone::SeriesMetadataLoader> metadataLoader_;
198 203
199 explicit ResourcesLoader(const OrthancStone::DicomSource& source) : 204 explicit ResourcesLoader(OrthancStone::ILoadersContext& context,
205 const OrthancStone::DicomSource& source) :
206 context_(context),
200 source_(source), 207 source_(source),
201 pending_(0), 208 pending_(0),
202 studies_(new OrthancStone::LoadedDicomResources(Orthanc::DICOM_TAG_STUDY_INSTANCE_UID)), 209 studies_(new OrthancStone::LoadedDicomResources(Orthanc::DICOM_TAG_STUDY_INSTANCE_UID)),
203 series_(new OrthancStone::LoadedDicomResources(Orthanc::DICOM_TAG_SERIES_INSTANCE_UID)) 210 series_(new OrthancStone::LoadedDicomResources(Orthanc::DICOM_TAG_SERIES_INSTANCE_UID))
204 { 211 {
290 new Orthanc::SingleValueObject<Orthanc::ResourceType>(Orthanc::ResourceType_Series)); 297 new Orthanc::SingleValueObject<Orthanc::ResourceType>(Orthanc::ResourceType_Series));
291 298
292 pending_ += 2; 299 pending_ += 2;
293 } 300 }
294 301
302
303 class PdfInfo : public Orthanc::IDynamicObject
304 {
305 private:
306 std::string studyInstanceUid_;
307 std::string seriesInstanceUid_;
308
309 public:
310 PdfInfo(const std::string& studyInstanceUid,
311 const std::string& seriesInstanceUid) :
312 studyInstanceUid_(studyInstanceUid),
313 seriesInstanceUid_(seriesInstanceUid)
314 {
315 }
316
317 const std::string& GetStudyInstanceUid() const
318 {
319 return studyInstanceUid_;
320 }
321
322 const std::string& GetSeriesInstanceUid() const
323 {
324 return seriesInstanceUid_;
325 }
326 };
327
328
329 void Handle(const OrthancStone::ParseDicomSuccessMessage& message)
330 {
331 const PdfInfo& info = dynamic_cast<const PdfInfo&>(message.GetOrigin().GetPayload());
332
333 if (observer_.get() != NULL)
334 {
335 std::string pdf;
336 if (message.GetDicom().ExtractPdf(pdf))
337 {
338 observer_->SignalSeriesPdfLoaded(info.GetStudyInstanceUid(), info.GetSeriesInstanceUid(), pdf);
339 }
340 else
341 {
342 LOG(ERROR) << "Unable to extract PDF from series: " << info.GetSeriesInstanceUid();
343 }
344 }
345 }
346
295 public: 347 public:
296 static boost::shared_ptr<ResourcesLoader> Create(OrthancStone::ILoadersContext::ILock& lock, 348 static boost::shared_ptr<ResourcesLoader> Create(OrthancStone::ILoadersContext::ILock& lock,
297 const OrthancStone::DicomSource& source) 349 const OrthancStone::DicomSource& source)
298 { 350 {
299 boost::shared_ptr<ResourcesLoader> loader(new ResourcesLoader(source)); 351 boost::shared_ptr<ResourcesLoader> loader(new ResourcesLoader(lock.GetContext(), source));
300 352
301 loader->resourcesLoader_ = OrthancStone::DicomResourcesLoader::Create(lock); 353 loader->resourcesLoader_ = OrthancStone::DicomResourcesLoader::Create(lock);
302 loader->thumbnailsLoader_ = OrthancStone::SeriesThumbnailsLoader::Create(lock, PRIORITY_LOW); 354 loader->thumbnailsLoader_ = OrthancStone::SeriesThumbnailsLoader::Create(lock, PRIORITY_LOW);
303 loader->metadataLoader_ = OrthancStone::SeriesMetadataLoader::Create(lock); 355 loader->metadataLoader_ = OrthancStone::SeriesMetadataLoader::Create(lock);
304 356
308 loader->Register<OrthancStone::SeriesThumbnailsLoader::SuccessMessage>( 360 loader->Register<OrthancStone::SeriesThumbnailsLoader::SuccessMessage>(
309 *loader->thumbnailsLoader_, &ResourcesLoader::Handle); 361 *loader->thumbnailsLoader_, &ResourcesLoader::Handle);
310 362
311 loader->Register<OrthancStone::SeriesMetadataLoader::SuccessMessage>( 363 loader->Register<OrthancStone::SeriesMetadataLoader::SuccessMessage>(
312 *loader->metadataLoader_, &ResourcesLoader::Handle); 364 *loader->metadataLoader_, &ResourcesLoader::Handle);
365
366 loader->Register<OrthancStone::ParseDicomSuccessMessage>(
367 lock.GetOracleObservable(), &ResourcesLoader::Handle);
313 368
314 return loader; 369 return loader;
315 } 370 }
316 371
317 void FetchAllStudies() 372 void FetchAllStudies()
405 } 460 }
406 461
407 void AcquireObserver(IObserver* observer) 462 void AcquireObserver(IObserver* observer)
408 { 463 {
409 observer_.reset(observer); 464 observer_.reset(observer);
465 }
466
467 void FetchPdf(const std::string& studyInstanceUid,
468 const std::string& seriesInstanceUid)
469 {
470 OrthancStone::SeriesMetadataLoader::Accessor accessor(*metadataLoader_, seriesInstanceUid);
471
472 if (accessor.IsComplete())
473 {
474 if (accessor.GetInstancesCount() > 1)
475 {
476 LOG(INFO) << "Series with more than one instance, will show the first PDF: "
477 << seriesInstanceUid;
478 }
479
480 for (size_t i = 0; i < accessor.GetInstancesCount(); i++)
481 {
482 std::string sopClassUid, sopInstanceUid;
483 if (accessor.GetInstance(i).LookupStringValue(sopClassUid, Orthanc::DICOM_TAG_SOP_CLASS_UID, false) &&
484 accessor.GetInstance(i).LookupStringValue(sopInstanceUid, Orthanc::DICOM_TAG_SOP_INSTANCE_UID, false) &&
485 sopClassUid == "1.2.840.10008.5.1.4.1.1.104.1")
486 {
487 std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(context_.Lock());
488 lock->Schedule(
489 GetSharedObserver(), PRIORITY_NORMAL, OrthancStone::ParseDicomFromWadoCommand::Create(
490 source_, studyInstanceUid, seriesInstanceUid, sopInstanceUid,
491 false /* no transcoding */, Orthanc::DicomTransferSyntax_LittleEndianExplicit /* dummy value */,
492 new PdfInfo(studyInstanceUid, seriesInstanceUid)));
493
494 return;
495 }
496 }
497
498 LOG(WARNING) << "Series without a PDF: " << seriesInstanceUid;
499 }
410 } 500 }
411 }; 501 };
412 502
413 503
414 504
2227 viewport.GetCanvasId().c_str(), 2317 viewport.GetCanvasId().c_str(),
2228 static_cast<int>(currentFrame), 2318 static_cast<int>(currentFrame),
2229 static_cast<int>(countFrames), 2319 static_cast<int>(countFrames),
2230 quality); 2320 quality);
2231 2321
2232
2233 UpdateReferenceLines(); 2322 UpdateReferenceLines();
2234 } 2323 }
2235 2324
2236 virtual void SignalCrosshair(const OrthancStone::Vector& click) ORTHANC_OVERRIDE 2325 virtual void SignalCrosshair(const OrthancStone::Vector& click) ORTHANC_OVERRIDE
2237 { 2326 {
2238 for (Viewports::const_iterator it = allViewports_.begin(); it != allViewports_.end(); ++it) 2327 for (Viewports::const_iterator it = allViewports_.begin(); it != allViewports_.end(); ++it)
2239 { 2328 {
2240 assert(it->second != NULL); 2329 assert(it->second != NULL);
2241 it->second->FocusOnPoint(click); 2330 it->second->FocusOnPoint(click);
2242 } 2331 }
2332 }
2333
2334 virtual void SignalSeriesPdfLoaded(const std::string& studyInstanceUid,
2335 const std::string& seriesInstanceUid,
2336 const std::string& pdf) ORTHANC_OVERRIDE
2337 {
2338 EM_ASM({
2339 const customEvent = document.createEvent("CustomEvent");
2340 customEvent.initCustomEvent("PdfLoaded", false, false,
2341 { "studyInstanceUid" : UTF8ToString($0),
2342 "seriesInstanceUid" : UTF8ToString($1),
2343 "pdfPointer" : $2,
2344 "pdfSize": $3});
2345 window.dispatchEvent(customEvent);
2346 },
2347 studyInstanceUid.c_str(),
2348 seriesInstanceUid.c_str(),
2349 pdf.empty() ? 0 : reinterpret_cast<intptr_t>(pdf.c_str()), // Explicit conversion to an integer
2350 pdf.size());
2243 } 2351 }
2244 }; 2352 };
2245 2353
2246 2354
2247 2355
2744 viewport->Redraw(); 2852 viewport->Redraw();
2745 } 2853 }
2746 } 2854 }
2747 EXTERN_CATCH_EXCEPTIONS; 2855 EXTERN_CATCH_EXCEPTIONS;
2748 } 2856 }
2857
2858
2859 EMSCRIPTEN_KEEPALIVE
2860 void FetchPdf(const char* studyInstanceUid,
2861 const char* seriesInstanceUid)
2862 {
2863 try
2864 {
2865 LOG(INFO) << "Fetching PDF series: " << seriesInstanceUid;
2866 GetResourcesLoader().FetchPdf(studyInstanceUid, seriesInstanceUid);
2867 }
2868 EXTERN_CATCH_EXCEPTIONS;
2869 }
2749 } 2870 }