changeset 260:c887eddd48f1 am-2

merge
author am@osimis.io
date Tue, 17 Jul 2018 14:43:42 +0200
parents e5a9b3d03478 (current diff) 106a0f9781d9 (diff)
children 58ad26032bd6
files Applications/IBasicApplication.cpp Applications/Sdl/BasicSdlApplication.cpp Framework/SmartLoader.cpp Framework/SmartLoader.h Resources/CMake/OrthancStoneConfiguration.cmake
diffstat 6 files changed, 372 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/IBasicApplication.cpp	Tue Jul 10 14:48:13 2018 +0200
+++ b/Applications/IBasicApplication.cpp	Tue Jul 17 14:43:42 2018 +0200
@@ -26,9 +26,267 @@
 
 #include <Core/Logging.h>
 #include <Core/HttpClient.h>
+#include <Core/Toolbox.h>
 #include <Plugins/Samples/Common/OrthancHttpConnection.h>
 
 namespace OrthancStone
 {
+  // Anonymous namespace to avoid clashes against other compilation modules
+  namespace
+  {
+    class LogStatusBar : public IStatusBar
+    {
+    public:
+      virtual void ClearMessage()
+      {
+      }
+
+      virtual void SetMessage(const std::string& message)
+      {
+        LOG(WARNING) << message;
+      }
+    };
+  }
+
+
+#if ORTHANC_ENABLE_SDL == 1
+  static void DeclareSdlCommandLineOptions(boost::program_options::options_description& options)
+  {
+    // Declare the supported parameters
+    boost::program_options::options_description generic("Generic options");
+    generic.add_options()
+      ("help", "Display this help and exit")
+      ("verbose", "Be verbose in logs")
+      ("orthanc", boost::program_options::value<std::string>()->default_value("http://localhost:8042/"),
+       "URL to the Orthanc server")
+      ("username", "Username for the Orthanc server")
+      ("password", "Password for the Orthanc server")
+      ("https-verify", boost::program_options::value<bool>()->default_value(true), "Check HTTPS certificates")
+      ;
+
+    options.add(generic);
+
+    boost::program_options::options_description sdl("SDL options");
+    sdl.add_options()
+      ("width", boost::program_options::value<int>()->default_value(1024), "Initial width of the SDL window")
+      ("height", boost::program_options::value<int>()->default_value(768), "Initial height of the SDL window")
+      ("opengl", boost::program_options::value<bool>()->default_value(true), "Enable OpenGL in SDL")
+      ;
+
+    options.add(sdl);
+  }
+
+
+  int IBasicApplication::ExecuteWithSdl(IBasicApplication& application,
+                                        int argc, 
+                                        char* argv[])
+  {
+    /******************************************************************
+     * Initialize all the subcomponents of Orthanc Stone
+     ******************************************************************/
+
+    Orthanc::Logging::Initialize();
+    Orthanc::Toolbox::InitializeOpenSsl();
+    Orthanc::HttpClient::GlobalInitialize();
+    SdlWindow::GlobalInitialize();
+
+
+    /******************************************************************
+     * Declare and parse the command-line options of the application
+     ******************************************************************/
+
+    boost::program_options::options_description options;
+    DeclareSdlCommandLineOptions(options);   
+    application.DeclareCommandLineOptions(options);
+
+    boost::program_options::variables_map parameters;
+    bool error = false;
+
+    try
+    {
+      boost::program_options::store(boost::program_options::command_line_parser(argc, argv).
+                                    options(options).run(), parameters);
+      boost::program_options::notify(parameters);    
+    }
+    catch (boost::program_options::error& e)
+    {
+      LOG(ERROR) << "Error while parsing the command-line arguments: " << e.what();
+      error = true;
+    }
+
+
+    /******************************************************************
+     * Configure the application with the command-line parameters
+     ******************************************************************/
+
+    if (error || parameters.count("help")) 
+    {
+      std::cout << std::endl
+                << "Usage: " << argv[0] << " [OPTION]..."
+                << std::endl
+                << "Orthanc, lightweight, RESTful DICOM server for healthcare and medical research."
+                << std::endl << std::endl
+                << "Demonstration application of Orthanc Stone using SDL."
+                << std::endl;
+
+      std::cout << options << "\n";
+      return error ? -1 : 0;
+    }
+
+    if (parameters.count("https-verify") &&
+        !parameters["https-verify"].as<bool>())
+    {
+      LOG(WARNING) << "Turning off verification of HTTPS certificates (unsafe)";
+      Orthanc::HttpClient::ConfigureSsl(false, "");
+    }
+
+    if (parameters.count("verbose"))
+    {
+      Orthanc::Logging::EnableInfoLevel(true);
+    }
+
+    if (!parameters.count("width") ||
+        !parameters.count("height") ||
+        !parameters.count("opengl"))
+    {
+      LOG(ERROR) << "Parameter \"width\", \"height\" or \"opengl\" is missing";
+      return -1;
+    }
+
+    int w = parameters["width"].as<int>();
+    int h = parameters["height"].as<int>();
+    if (w <= 0 || h <= 0)
+    {
+      LOG(ERROR) << "Parameters \"width\" and \"height\" must be positive";
+      return -1;
+    }
+
+    unsigned int width = static_cast<unsigned int>(w);
+    unsigned int height = static_cast<unsigned int>(h);
+    LOG(WARNING) << "Initial display size: " << width << "x" << height;
+
+    bool opengl = parameters["opengl"].as<bool>();
+    if (opengl)
+    {
+      LOG(WARNING) << "OpenGL is enabled, disable it with option \"--opengl=off\" if the application crashes";
+    }
+    else
+    {
+      LOG(WARNING) << "OpenGL is disabled, enable it with option \"--opengl=on\" for best performance";
+    }
+
+    bool success = true;
+    try
+    {
+      /****************************************************************
+       * Initialize the connection to the Orthanc server
+       ****************************************************************/
+
+      Orthanc::WebServiceParameters webService;
+
+      if (parameters.count("orthanc"))
+      {
+        webService.SetUrl(parameters["orthanc"].as<std::string>());
+      }
+
+      if (parameters.count("username"))
+      {
+        webService.SetUsername(parameters["username"].as<std::string>());
+      }
+
+      if (parameters.count("password"))
+      {
+        webService.SetPassword(parameters["password"].as<std::string>());
+      }
+
+      LOG(WARNING) << "URL to the Orthanc REST API: " << webService.GetUrl();
+
+      {
+        OrthancPlugins::OrthancHttpConnection orthanc(webService);
+        if (!MessagingToolbox::CheckOrthancVersion(orthanc))
+        {
+          LOG(ERROR) << "Your version of Orthanc is incompatible with Stone of Orthanc, please upgrade";
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol);
+        }
+      }
+
+
+      /****************************************************************
+       * Initialize the application
+       ****************************************************************/
+
+      LOG(WARNING) << "Creating the widgets of the application";
+
+      LogStatusBar statusBar;
+      BasicApplicationContext context(webService);
+
+      application.Initialize(context, statusBar, parameters);
+
+      {
+        BasicApplicationContext::ViewportLocker locker(context);
+        locker.GetViewport().SetStatusBar(statusBar);
+      }
+
+      std::string title = application.GetTitle();
+      if (title.empty())
+      {
+        title = "Stone of Orthanc";
+      }
+
+      {
+        /**************************************************************
+         * Run the application inside a SDL window
+         **************************************************************/
+
+        LOG(WARNING) << "Starting the application";
+
+        SdlWindow window(title.c_str(), width, height, opengl);
+        SdlEngine sdl(window, context);
+
+        {
+          BasicApplicationContext::ViewportLocker locker(context);
+          locker.GetViewport().Register(sdl);  // (*)
+        }
+
+        context.Start();
+        sdl.Run();
+
+        LOG(WARNING) << "Stopping the application";
+
+        // Don't move the "Stop()" command below out of the block,
+        // otherwise the application might crash, because the
+        // "SdlEngine" is an observer of the viewport (*) and the
+        // update thread started by "context.Start()" would call a
+        // destructed object (the "SdlEngine" is deleted with the
+        // lexical scope).
+        context.Stop();
+      }
+
+
+      /****************************************************************
+       * Finalize the application
+       ****************************************************************/
+
+      LOG(WARNING) << "The application has stopped";
+      application.Finalize();
+    }
+    catch (Orthanc::OrthancException& e)
+    {
+      LOG(ERROR) << "EXCEPTION: " << e.What();
+      success = false;
+    }
+
+
+    /******************************************************************
+     * Finalize all the subcomponents of Orthanc Stone
+     ******************************************************************/
+
+    SdlWindow::GlobalFinalize();
+    Orthanc::HttpClient::GlobalFinalize();
+    Orthanc::Toolbox::FinalizeOpenSsl();
+
+    return (success ? 0 : -1);
+  }
+#endif
 
 }
--- a/Applications/Sdl/BasicSdlApplication.cpp	Tue Jul 10 14:48:13 2018 +0200
+++ b/Applications/Sdl/BasicSdlApplication.cpp	Tue Jul 17 14:43:42 2018 +0200
@@ -31,6 +31,7 @@
 
 #include <Core/Logging.h>
 #include <Core/HttpClient.h>
+#include <Core/Toolbox.h>
 #include <Plugins/Samples/Common/OrthancHttpConnection.h>
 
 namespace OrthancStone
@@ -90,7 +91,7 @@
      ******************************************************************/
 
     Orthanc::Logging::Initialize();
-    Orthanc::HttpClient::InitializeOpenSsl();
+    Orthanc::Toolbox::InitializeOpenSsl();
     Orthanc::HttpClient::GlobalInitialize();
     SdlWindow::GlobalInitialize();
 
@@ -292,7 +293,7 @@
 
     SdlWindow::GlobalFinalize();
     Orthanc::HttpClient::GlobalFinalize();
-    Orthanc::HttpClient::FinalizeOpenSsl();
+    Orthanc::Toolbox::FinalizeOpenSsl();
 
     return (success ? 0 : -1);
   }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Framework/SmartLoader.cpp	Tue Jul 17 14:43:42 2018 +0200
@@ -0,0 +1,51 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2018 Osimis S.A., Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "SmartLoader.h"
+#include "Layers/OrthancFrameLayerSource.h"
+
+namespace OrthancStone
+{
+  SmartLoader::SmartLoader(MessageBroker& broker, IWebService& webService) :
+    IObservable(broker),
+    IObserver(broker),
+    imageQuality_(SliceImageQuality_FullPam),
+    webService_(webService)
+  {}
+
+  void SmartLoader::HandleMessage(IObservable& from, const IMessage& message)
+  {
+    // forward messages to its own observers
+    IObservable::broker_.EmitMessage(from, IObservable::observers_, message);
+  }
+
+  ILayerSource* SmartLoader::GetFrame(const std::string& instanceId, unsigned int frame)
+  {
+    std::auto_ptr<OrthancFrameLayerSource> layerSource (new OrthancFrameLayerSource(IObserver::broker_, webService_));
+    layerSource->SetImageQuality(imageQuality_);
+    layerSource->RegisterObserver(*this);
+    layerSource->LoadFrame(instanceId, frame);
+
+    return layerSource.release();
+  }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Framework/SmartLoader.h	Tue Jul 17 14:43:42 2018 +0200
@@ -0,0 +1,49 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2018 Osimis S.A., Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "Layers/ILayerSource.h"
+#include "Messages/IObservable.h"
+#include "../Platforms/Generic/OracleWebService.h"
+
+namespace OrthancStone
+{
+  class SmartLoader : public IObservable, IObserver
+  {
+    SliceImageQuality imageQuality_;
+    IWebService& webService_;
+
+  public:
+    SmartLoader(MessageBroker& broker, IWebService& webService);  // TODO: add maxPreloadStorageSizeInBytes
+
+    virtual void HandleMessage(IObservable& from, const IMessage& message);
+
+    void PreloadStudy(const std::string studyId) {/* TODO */}
+    void PreloadSeries(const std::string seriesId) {/* TODO */}
+
+    void SetImageQuality(SliceImageQuality imageQuality) { imageQuality_ = imageQuality; }
+
+    ILayerSource* GetFrame(const std::string& instanceId, unsigned int frame);
+
+  };
+
+}
--- a/Resources/CMake/OrthancStoneConfiguration.cmake	Tue Jul 10 14:48:13 2018 +0200
+++ b/Resources/CMake/OrthancStoneConfiguration.cmake	Tue Jul 17 14:43:42 2018 +0200
@@ -100,6 +100,12 @@
 #####################################################################
 
 EmbedResources(
+  # Resources coming from the core of Orthanc. They must be copied
+  # here, as HAS_EMBEDDED_RESOURCES is set to ON in
+  # "OrthancStoneParameters.cmake"
+  ${DCMTK_DICTIONARIES}
+
+  # Resources specific to the Stone of Orthanc
   COLORMAP_HOT    ${ORTHANC_STONE_ROOT}/Resources/Colormaps/hot.lut
   COLORMAP_JET    ${ORTHANC_STONE_ROOT}/Resources/Colormaps/jet.lut
   COLORMAP_RED    ${ORTHANC_STONE_ROOT}/Resources/Colormaps/red.lut
@@ -238,6 +244,7 @@
   ${PLATFORM_SOURCES}
   ${APPLICATIONS_SOURCES}
   ${ORTHANC_CORE_SOURCES}
+  ${ORTHANC_DICOM_SOURCES}
   ${AUTOGENERATED_SOURCES}
 
   # Mandatory components
--- a/Resources/CMake/OrthancStoneParameters.cmake	Tue Jul 10 14:48:13 2018 +0200
+++ b/Resources/CMake/OrthancStoneParameters.cmake	Tue Jul 17 14:43:42 2018 +0200
@@ -28,9 +28,10 @@
 set(ENABLE_LOCALE OFF)         # Disable support for locales (notably in Boost)
 set(ENABLE_GOOGLE_TEST ON)
 set(ENABLE_SQLITE OFF)
-SET(ENABLE_JPEG ON)
-SET(ENABLE_PNG ON)
-SET(ENABLE_ZLIB ON)
+set(ENABLE_JPEG ON)
+set(ENABLE_PNG ON)
+set(ENABLE_ZLIB ON)
+set(HAS_EMBEDDED_RESOURCES ON)
 
 
 #####################################################################