# HG changeset patch # User am@osimis.io # Date 1531831422 -7200 # Node ID c887eddd48f19b1dc020c439387c2f76730a0e70 # Parent e5a9b3d0347842ebbd20a08693acc09e133e721c# Parent 106a0f9781d91b9964555b93f62d19afaa748278 merge diff -r e5a9b3d03478 -r c887eddd48f1 Applications/IBasicApplication.cpp --- 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 #include +#include #include 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()->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()->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()->default_value(1024), "Initial width of the SDL window") + ("height", boost::program_options::value()->default_value(768), "Initial height of the SDL window") + ("opengl", boost::program_options::value()->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()) + { + 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 h = parameters["height"].as(); + if (w <= 0 || h <= 0) + { + LOG(ERROR) << "Parameters \"width\" and \"height\" must be positive"; + return -1; + } + + unsigned int width = static_cast(w); + unsigned int height = static_cast(h); + LOG(WARNING) << "Initial display size: " << width << "x" << height; + + bool opengl = parameters["opengl"].as(); + 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()); + } + + if (parameters.count("username")) + { + webService.SetUsername(parameters["username"].as()); + } + + if (parameters.count("password")) + { + webService.SetPassword(parameters["password"].as()); + } + + 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 } diff -r e5a9b3d03478 -r c887eddd48f1 Applications/Sdl/BasicSdlApplication.cpp --- 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 #include +#include #include 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); } diff -r e5a9b3d03478 -r c887eddd48f1 Framework/SmartLoader.cpp --- /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 . + **/ + + +#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 layerSource (new OrthancFrameLayerSource(IObserver::broker_, webService_)); + layerSource->SetImageQuality(imageQuality_); + layerSource->RegisterObserver(*this); + layerSource->LoadFrame(instanceId, frame); + + return layerSource.release(); + } + + +} diff -r e5a9b3d03478 -r c887eddd48f1 Framework/SmartLoader.h --- /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 . + **/ + + +#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); + + }; + +} diff -r e5a9b3d03478 -r c887eddd48f1 Resources/CMake/OrthancStoneConfiguration.cmake --- 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 diff -r e5a9b3d03478 -r c887eddd48f1 Resources/CMake/OrthancStoneParameters.cmake --- 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) #####################################################################