Mercurial > hg > orthanc-stone
diff Samples/Common/RtViewer.cpp @ 1386:dfb48f0794b1
Ongoing splitting SDL vs WASM (preparing RtViewer WASM)
author | Benjamin Golinvaux <bgo@osimis.io> |
---|---|
date | Mon, 27 Apr 2020 16:48:19 +0200 |
parents | ab871499ed30 |
children | 5c83be3a6be5 |
line wrap: on
line diff
--- a/Samples/Common/RtViewer.cpp Mon Apr 27 16:47:46 2020 +0200 +++ b/Samples/Common/RtViewer.cpp Mon Apr 27 16:48:19 2020 +0200 @@ -18,23 +18,12 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. **/ +// Sample app #include "RtViewer.h" -#include <stdio.h> - -#include <boost/shared_ptr.hpp> -#include <boost/weak_ptr.hpp> -#include <boost/make_shared.hpp> - -#include <Core/Images/Image.h> -#include <Core/Images/ImageProcessing.h> -#include <Core/Images/PngWriter.h> -#include <Core/Logging.h> -#include <Core/OrthancException.h> - +// Stone of Orthanc #include <Framework/OpenGL/SdlOpenGLContext.h> #include <Framework/StoneInitialization.h> - #include <Framework/Scene2D/CairoCompositor.h> #include <Framework/Scene2D/ColorTextureSceneLayer.h> #include <Framework/Scene2D/OpenGLCompositor.h> @@ -57,6 +46,21 @@ #include <Framework/Volumes/DicomVolumeImageMPRSlicer.h> #include <Framework/StoneException.h> +// Orthanc +#include <Core/Images/Image.h> +#include <Core/Images/ImageProcessing.h> +#include <Core/Images/PngWriter.h> +#include <Core/Logging.h> +#include <Core/OrthancException.h> + +// System +#include <boost/shared_ptr.hpp> +#include <boost/weak_ptr.hpp> +#include <boost/make_shared.hpp> + +#include <stdio.h> + + namespace OrthancStone { const char* RtViewerGuiToolToString(size_t i) @@ -263,6 +267,18 @@ } break; + case SDLK_r: + UpdateLayers(); + { + std::unique_ptr<IViewport::ILock> lock(viewport_->Lock()); + lock->Invalidate(); + } + break; + + case SDLK_s: + compositor.FitContent(scene); + break; + case SDLK_t: if (!activeTracker_) SelectNextTool(); @@ -272,9 +288,6 @@ " is taking place"; } break; - case SDLK_s: - compositor.FitContent(scene); - break; case SDLK_z: LOG(TRACE) << "SDLK_z has been pressed. event.key.keysym.mod == " << event.key.keysym.mod; @@ -466,15 +479,11 @@ RtViewerApp::RtViewerApp() - : oracle_(*this) - , currentTool_(RtViewerGuiTool_Rotate) + : currentTool_(RtViewerGuiTool_Rotate) , undoStack_(new UndoStack) , currentPlane_(0) , projection_(VolumeProjection_Coronal) { - loadersContext_.reset(new GenericLoadersContext(1, 4, 1)); - loadersContext_->StartOracle(); - // False means we do NOT let Windows treat this as a legacy application that needs to be scaled viewport_ = SdlOpenGLViewport::Create("CT RTDOSE RTSTRUCT viewer", 1024, 1024, false); @@ -482,18 +491,9 @@ ViewportController& controller = lock->GetController(); Scene2D& scene = controller.GetScene(); - //oracleObservable.RegisterObserverCallback - //(new Callable - // <RtViewerApp, SleepOracleCommand::TimeoutMessage>(*this, &RtViewerApp::Handle)); - - //oracleObservable.RegisterObserverCallback - //(new Callable - // <Toto, GetOrthancImageCommand::SuccessMessage>(*this, &RtViewerApp::Handle)); - - //oracleObservable.RegisterObserverCallback - //(new Callable - // <RtViewerApp, GetOrthancWebViewerJpegCommand::SuccessMessage>(*this, &ToRtViewerAppto::Handle)); - + // Create the volumes that will be filled later on + ctVolume_ = boost::make_shared<DicomVolumeImage>(); + doseVolume_ = boost::make_shared<DicomVolumeImage>(); TEXTURE_2x2_1_ZINDEX = 1; TEXTURE_1x1_ZINDEX = 2; @@ -509,7 +509,6 @@ std::unique_ptr<IViewport::ILock> lock(viewport_->Lock()); ViewportController& controller = lock->GetController(); Scene2D& scene = controller.GetScene(); - Register<OracleCommandExceptionMessage>(oracleObservable_, &RtViewerApp::Handle); Register<ViewportController::SceneTransformChanged>(controller, &RtViewerApp::OnSceneTransformChanged); } @@ -520,6 +519,7 @@ return thisOne; } +#if 0 void RtViewerApp::PrepareScene() { std::unique_ptr<IViewport::ILock> lock(viewport_->Lock()); @@ -551,6 +551,7 @@ scene.SetLayer(TEXTURE_2x2_1_ZINDEX, new ColorTextureSceneLayer(i)); } } +#endif void RtViewerApp::DisableTracker() { @@ -588,33 +589,107 @@ // std::vector<boost::shared_ptr<MeasureTool>> measureTools_; return boost::shared_ptr<IFlexiblePointerTracker>(); } + + void RtViewerApp::PrepareLoadersAndSlicers() + { - static void GLAPIENTRY - OpenGLMessageCallback(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar* message, - const void* userParam) - { - if (severity != GL_DEBUG_SEVERITY_NOTIFICATION) + //{ + // Orthanc::WebServiceParameters p; + // //p.SetUrl("http://localhost:8043/"); + // p.SetCredentials("orthanc", "orthanc"); + // oracle_.SetOrthancParameters(p); + //} + { - fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", - (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), - type, severity, message); + // "true" means use progressive quality (jpeg 50 --> jpeg 90 --> 16-bit raw) + // "false" means only using hi quality + // TODO: add flag for quality + ctLoader_ = OrthancSeriesVolumeProgressiveLoader::Create(*loadersContext_, ctVolume_, false); + + // we need to store the CT loader to ask from geometry details later on when geometry is loaded + geometryProvider_ = ctLoader_; + + doseLoader_ = OrthancMultiframeVolumeLoader::Create(*loadersContext_, doseVolume_); + rtstructLoader_ = DicomStructureSetLoader::Create(*loadersContext_); } + + /** + Register for notifications issued by the loaders + */ + + Register<DicomVolumeImage::GeometryReadyMessage> + (*ctLoader_, &RtViewerApp::HandleGeometryReady); + + Register<OrthancSeriesVolumeProgressiveLoader::VolumeImageReadyInHighQuality> + (*ctLoader_, &RtViewerApp::HandleCTLoaded); + + Register<DicomVolumeImage::ContentUpdatedMessage> + (*ctLoader_, &RtViewerApp::HandleCTContentUpdated); + + Register<DicomVolumeImage::ContentUpdatedMessage> + (*doseLoader_, &RtViewerApp::HandleDoseLoaded); + + Register<DicomStructureSetLoader::StructuresReady> + (*rtstructLoader_, &RtViewerApp::HandleStructuresReady); + + Register<DicomStructureSetLoader::StructuresUpdated> + (*rtstructLoader_, &RtViewerApp::HandleStructuresUpdated); + + /** + Configure the CT + */ + + + std::auto_ptr<GrayscaleStyleConfigurator> style(new GrayscaleStyleConfigurator); + style->SetLinearInterpolation(true); + + this->SetCtVolumeSlicer(LAYER_POSITION + 0, ctLoader_, style.release()); + + { + std::unique_ptr<LookupTableStyleConfigurator> config(new LookupTableStyleConfigurator); + config->SetLookupTable(Orthanc::EmbeddedResources::COLORMAP_HOT); + + boost::shared_ptr<DicomVolumeImageMPRSlicer> tmp(new DicomVolumeImageMPRSlicer(doseVolume_)); + this->SetDoseVolumeSlicer(LAYER_POSITION + 1, tmp, config.release()); + } + + this->SetStructureSet(LAYER_POSITION + 2, rtstructLoader_); + +#if 1 + LOG(INFO) << "About to load:"; + LOG(INFO) << " CT : " << ctSeriesId_;; + LOG(INFO) << " RTDOSE : " << doseInstanceId_; + LOG(INFO) << " RTSTRUCT : " << rtStructInstanceId_; + ctLoader_->LoadSeries(ctSeriesId_); + doseLoader_->LoadInstance(doseInstanceId_); + rtstructLoader_->LoadInstanceFullVisibility(rtStructInstanceId_); + +#elif 0 + /* + BGO data + http://localhost:8042/twiga-orthanc-viewer-demo/twiga-orthanc-viewer-demo.html?ct-series=a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa + & + dose-instance=830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb + & + struct-instance=54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9 + */ + ctLoader_->LoadSeries("a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa"); // CT + doseLoader_->LoadInstance("830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb"); // RT-DOSE + rtstructLoader_->LoadInstanceFullVisibility("54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9"); // RT-STRUCT +#else + //SJO data + //ctLoader->LoadSeries("cb3ea4d1-d08f3856-ad7b6314-74d88d77-60b05618"); // CT + //doseLoader->LoadInstance("41029085-71718346-811efac4-420e2c15-d39f99b6"); // RT-DOSE + //rtstructLoader->LoadInstanceFullVisibility("83d9c0c3-913a7fee-610097d7-cbf0522d-fd75bee6"); // RT-STRUCT + + // 2017-05-16 + ctLoader_->LoadSeries("a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa"); // CT + doseLoader_->LoadInstance("eac822ef-a395f94e-e8121fe0-8411fef8-1f7bffad"); // RT-DOSE + rtstructLoader_->LoadInstanceFullVisibility("54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9"); // RT-STRUCT +#endif } - static bool g_stopApplication = false; - - - void RtViewerApp::Handle(const DicomVolumeImage::GeometryReadyMessage& message) - { - RetrieveGeometry(); - } - - +#if 0 void RtViewerApp::Handle(const OracleCommandExceptionMessage& message) { const OracleCommandBase& command = dynamic_cast<const OracleCommandBase&>(message.GetOrigin()); @@ -631,8 +706,14 @@ break; } } +#endif + void RtViewerApp::HandleGeometryReady(const DicomVolumeImage::GeometryReadyMessage& message) + { + RetrieveGeometry(); + } + void RtViewerApp::HandleCTLoaded(const OrthancSeriesVolumeProgressiveLoader::VolumeImageReadyInHighQuality& message) { UpdateLayers(); @@ -659,7 +740,7 @@ UpdateLayers(); } - void RtViewerApp::SetCtVolume(int depth, + void RtViewerApp::SetCtVolumeSlicer(int depth, const boost::shared_ptr<OrthancStone::IVolumeSlicer>& volume, OrthancStone::ILayerStyleConfigurator* style) { @@ -675,7 +756,7 @@ } } - void RtViewerApp::SetDoseVolume(int depth, + void RtViewerApp::SetDoseVolumeSlicer(int depth, const boost::shared_ptr<OrthancStone::IVolumeSlicer>& volume, OrthancStone::ILayerStyleConfigurator* style) { @@ -701,170 +782,6 @@ structLayerSource_.reset(new OrthancStone::VolumeSceneLayerSource(scene, depth, volume)); } - void RtViewerApp::Run() - { - { - std::unique_ptr<IViewport::ILock> lock(viewport_->Lock()); - ViewportController& controller = lock->GetController(); - Scene2D& scene = controller.GetScene(); - ICompositor& compositor = lock->GetCompositor(); - - // False means we do NOT let Windows treat this as a legacy application - // that needs to be scaled - controller.FitContent(compositor.GetCanvasWidth(), compositor.GetCanvasHeight()); - - glEnable(GL_DEBUG_OUTPUT); - glDebugMessageCallback(OpenGLMessageCallback, 0); - - compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, - FONT_SIZE_0, Orthanc::Encoding_Latin1); - compositor.SetFont(1, Orthanc::EmbeddedResources::UBUNTU_FONT, - FONT_SIZE_1, Orthanc::Encoding_Latin1); - } - //////// from loader - { - Orthanc::WebServiceParameters p; - //p.SetUrl("http://localhost:8043/"); - p.SetCredentials("orthanc", "orthanc"); - oracle_.SetOrthancParameters(p); - } - - //////// from Run - - boost::shared_ptr<DicomVolumeImage> ctVolume(new DicomVolumeImage); - boost::shared_ptr<DicomVolumeImage> doseVolume(new DicomVolumeImage); - - - boost::shared_ptr<OrthancSeriesVolumeProgressiveLoader> ctLoader; - boost::shared_ptr<OrthancMultiframeVolumeLoader> doseLoader; - boost::shared_ptr<DicomStructureSetLoader> rtstructLoader; - - { - // "true" means use progressive quality (jpeg 50 --> jpeg 90 --> 16-bit raw) - ctLoader = OrthancSeriesVolumeProgressiveLoader::Create(*loadersContext_, ctVolume, false); - - // we need to store the CT loader to ask from geometry details later on when geometry is loaded - geometryProvider_ = ctLoader; - - doseLoader = OrthancMultiframeVolumeLoader::Create(*loadersContext_, doseVolume); - rtstructLoader = DicomStructureSetLoader::Create(*loadersContext_); - } - - Register<DicomVolumeImage::GeometryReadyMessage>(*ctLoader, &RtViewerApp::Handle); - Register<OrthancSeriesVolumeProgressiveLoader::VolumeImageReadyInHighQuality>(*ctLoader, &RtViewerApp::HandleCTLoaded); - Register<DicomVolumeImage::ContentUpdatedMessage>(*ctLoader, &RtViewerApp::HandleCTContentUpdated); - Register<DicomVolumeImage::ContentUpdatedMessage>(*doseLoader, &RtViewerApp::HandleDoseLoaded); - Register<DicomStructureSetLoader::StructuresReady>(*rtstructLoader, &RtViewerApp::HandleStructuresReady); - Register<DicomStructureSetLoader::StructuresUpdated>(*rtstructLoader, &RtViewerApp::HandleStructuresUpdated); - - std::auto_ptr<GrayscaleStyleConfigurator> style(new GrayscaleStyleConfigurator); - style->SetLinearInterpolation(true); - - this->SetCtVolume(LAYER_POSITION + 0, ctLoader, style.release()); - - { - std::unique_ptr<LookupTableStyleConfigurator> config(new LookupTableStyleConfigurator); - config->SetLookupTable(Orthanc::EmbeddedResources::COLORMAP_HOT); - - boost::shared_ptr<DicomVolumeImageMPRSlicer> tmp(new DicomVolumeImageMPRSlicer(doseVolume)); - this->SetDoseVolume(LAYER_POSITION + 1, tmp, config.release()); - } - - this->SetStructureSet(LAYER_POSITION + 2, rtstructLoader); - -#if 1 - /* - BGO data - http://localhost:8042/twiga-orthanc-viewer-demo/twiga-orthanc-viewer-demo.html?ct-series=a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa - & - dose-instance=830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb - & - struct-instance=54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9 - */ - ctLoader->LoadSeries("a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa"); // CT - doseLoader->LoadInstance("830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb"); // RT-DOSE - rtstructLoader->LoadInstance("54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9"); // RT-STRUCT -#else - //ctLoader->LoadSeries("cb3ea4d1-d08f3856-ad7b6314-74d88d77-60b05618"); // CT - //doseLoader->LoadInstance("41029085-71718346-811efac4-420e2c15-d39f99b6"); // RT-DOSE - //rtstructLoader->LoadInstance("83d9c0c3-913a7fee-610097d7-cbf0522d-fd75bee6"); // RT-STRUCT - - // 2017-05-16 - ctLoader->LoadSeries("a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa"); // CT - doseLoader->LoadInstance("eac822ef-a395f94e-e8121fe0-8411fef8-1f7bffad"); // RT-DOSE - rtstructLoader->LoadInstance("54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9"); // RT-STRUCT -#endif - - oracle_.Start(); - -//// END from loader - - while (!g_stopApplication) - { - //compositor.Refresh(scene); - -//////// from loader -//// END from loader - - SDL_Event event; - while (!g_stopApplication && SDL_PollEvent(&event)) - { - if (event.type == SDL_QUIT) - { - g_stopApplication = true; - break; - } - else if (event.type == SDL_WINDOWEVENT && - event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) - { - DisableTracker(); // was: tracker.reset(NULL); - } - else if (event.type == SDL_KEYDOWN && - event.key.repeat == 0 /* Ignore key bounce */) - { - switch (event.key.keysym.sym) - { - case SDLK_f: - // TODO: implement GetWindow!!! - // viewport_->GetContext()->GetWindow().ToggleMaximize(); - ORTHANC_ASSERT(false, "Please implement GetWindow()"); - break; - - case SDLK_r: - break; - - case SDLK_s: - FitContent(); - break; - - case SDLK_q: - g_stopApplication = true; - break; - default: - break; - } - } - HandleApplicationEvent(event); - } - SDL_Delay(1); - } - - //// from loader - - //Orthanc::SystemToolbox::ServerBarrier(); - - /** - * WARNING => The oracle must be stopped BEFORE the objects using - * it are destroyed!!! This forces to wait for the completion of - * the running callback methods. Otherwise, the callbacks methods - * might still be running while their parent object is destroyed, - * resulting in crashes. This is very visible if adding a sleep(), - * as in (*). - **/ - - oracle_.Stop(); - //// END from loader - } void RtViewerApp::SetInfoDisplayMessage( std::string key, std::string value) @@ -900,15 +817,12 @@ using namespace OrthancStone; StoneInitialize(); - Orthanc::Logging::EnableInfoLevel(true); - //Orthanc::Logging::EnableTraceLevel(true); try { boost::shared_ptr<RtViewerApp> app = RtViewerApp::Create(); g_app = app; - //app->PrepareScene(); - app->Run(); + app->RunSdl(argc,argv); } catch (Orthanc::OrthancException& e) {