changeset 2381:b8969010b534

uncoupling DCMTK primitives from Orthanc::Configuration
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 29 Aug 2017 19:59:01 +0200
parents 96b3ec054b69
children 7284093111b0
files CMakeLists.txt Core/Enumerations.cpp Core/Enumerations.h OrthancServer/DicomInstanceToStore.cpp OrthancServer/DicomProtocol/DicomFindAnswers.cpp OrthancServer/DicomProtocol/DicomServer.cpp OrthancServer/DicomProtocol/DicomServer.h OrthancServer/DicomProtocol/DicomUserConnection.cpp OrthancServer/FromDcmtkBridge.cpp OrthancServer/FromDcmtkBridge.h OrthancServer/Internals/CommandDispatcher.cpp OrthancServer/Internals/DicomFrameIndex.cpp OrthancServer/Internals/DicomFrameIndex.h OrthancServer/Internals/DicomImageDecoder.cpp OrthancServer/Internals/FindScp.cpp OrthancServer/Internals/FindScp.h OrthancServer/Internals/MoveScp.cpp OrthancServer/Internals/StoreScp.cpp OrthancServer/OrthancInitialization.cpp OrthancServer/OrthancInitialization.h OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp OrthancServer/OrthancRestApi/OrthancRestSystem.cpp OrthancServer/ParsedDicomFile.cpp OrthancServer/main.cpp UnitTestsSources/FromDcmtkTests.cpp UnitTestsSources/ImageTests.cpp
diffstat 26 files changed, 238 insertions(+), 132 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Tue Aug 29 16:49:44 2017 +0200
+++ b/CMakeLists.txt	Tue Aug 29 19:59:01 2017 +0200
@@ -458,7 +458,8 @@
   -DORTHANC_HAS_EMBEDDED_RESOURCES=1
   -DORTHANC_MAXIMUM_TAG_LENGTH=256
   -DORTHANC_SANDBOXED=0
-
+  -DORTHANC_DEFAULT_DICOM_ENCODING=Encoding_Latin1
+  
   # Macros for the plugins
   -DHAS_ORTHANC_EXCEPTION=0
   -DMODALITY_WORKLISTS_VERSION="${ORTHANC_VERSION}"
--- a/Core/Enumerations.cpp	Tue Aug 29 16:49:44 2017 +0200
+++ b/Core/Enumerations.cpp	Tue Aug 29 19:59:01 2017 +0200
@@ -1475,5 +1475,28 @@
       default:
         throw OrthancException(ErrorCode_ParameterOutOfRange);
     }
+  }  
+
+
+  static boost::mutex  defaultEncodingMutex_;  // Should not be necessary
+  static Encoding      defaultEncoding_ = ORTHANC_DEFAULT_DICOM_ENCODING;
+  
+  Encoding GetDefaultDicomEncoding()
+  {
+    boost::mutex::scoped_lock lock(defaultEncodingMutex_);
+    return defaultEncoding_;
   }
+
+  void SetDefaultDicomEncoding(Encoding encoding)
+  {
+    std::string name = EnumerationToString(encoding);
+    
+    {
+      boost::mutex::scoped_lock lock(defaultEncodingMutex_);
+      defaultEncoding_ = encoding;
+    }
+
+    LOG(INFO) << "Default encoding for DICOM was changed to: " << name;
+  }
+
 }
--- a/Core/Enumerations.h	Tue Aug 29 16:49:44 2017 +0200
+++ b/Core/Enumerations.h	Tue Aug 29 19:59:01 2017 +0200
@@ -544,4 +544,8 @@
   bool IsUserContentType(FileContentType type);
 
   bool IsBinaryValueRepresentation(ValueRepresentation vr);
+  
+  Encoding GetDefaultDicomEncoding();
+
+  void SetDefaultDicomEncoding(Encoding encoding);
 }
--- a/OrthancServer/DicomInstanceToStore.cpp	Tue Aug 29 16:49:44 2017 +0200
+++ b/OrthancServer/DicomInstanceToStore.cpp	Tue Aug 29 19:59:01 2017 +0200
@@ -35,7 +35,6 @@
 #include "DicomInstanceToStore.h"
 
 #include "FromDcmtkBridge.h"
-#include "OrthancInitialization.h"
 #include "../Core/Logging.h"
 
 #include <dcmtk/dcmdata/dcfilefo.h>
@@ -106,15 +105,15 @@
     if (!summary_.HasContent())
     {
       summary_.Allocate();
-      Configuration::ExtractDicomSummary(summary_.GetContent(), 
-                                         *parsed_.GetContent().GetDcmtkObject().getDataset());
+      FromDcmtkBridge::ExtractDicomSummary(summary_.GetContent(), 
+                                           *parsed_.GetContent().GetDcmtkObject().getDataset());
     }
     
     if (!json_.HasContent())
     {
       json_.Allocate();
-      Configuration::ExtractDicomAsJson(json_.GetContent(), 
-                                        *parsed_.GetContent().GetDcmtkObject().getDataset());
+      FromDcmtkBridge::ExtractDicomAsJson(json_.GetContent(), 
+                                          *parsed_.GetContent().GetDcmtkObject().getDataset());
     }
   }
 
--- a/OrthancServer/DicomProtocol/DicomFindAnswers.cpp	Tue Aug 29 16:49:44 2017 +0200
+++ b/OrthancServer/DicomProtocol/DicomFindAnswers.cpp	Tue Aug 29 19:59:01 2017 +0200
@@ -64,7 +64,7 @@
 
 
   DicomFindAnswers::DicomFindAnswers(bool isWorklist) : 
-    encoding_(Configuration::GetDefaultEncoding()),
+    encoding_(GetDefaultDicomEncoding()),
     isWorklist_(isWorklist),
     complete_(true)
   {
--- a/OrthancServer/DicomProtocol/DicomServer.cpp	Tue Aug 29 16:49:44 2017 +0200
+++ b/OrthancServer/DicomProtocol/DicomServer.cpp	Tue Aug 29 19:59:01 2017 +0200
@@ -39,7 +39,6 @@
 #include "../../Core/OrthancException.h"
 #include "../../Core/Toolbox.h"
 #include "../Internals/CommandDispatcher.h"
-#include "../OrthancInitialization.h"
 
 #include <boost/thread.hpp>
 
@@ -90,6 +89,7 @@
     aet_("ANY-SCP")
   {
     port_ = 104;
+    modalities_ = NULL;
     findRequestHandlerFactory_ = NULL;
     moveRequestHandlerFactory_ = NULL;
     storeRequestHandlerFactory_ = NULL;
@@ -179,6 +179,24 @@
     return aet_;
   }
 
+  void DicomServer::SetRemoteModalities(IRemoteModalities& modalities)
+  {
+    Stop();
+    modalities_ = &modalities;
+  }
+  
+  DicomServer::IRemoteModalities& DicomServer::GetRemoteModalities() const
+  {
+    if (modalities_ == NULL)
+    {
+      throw OrthancException(ErrorCode_BadSequenceOfCalls);
+    }
+    else
+    {
+      return *modalities_;
+    }
+  }
+    
   void DicomServer::SetFindRequestHandlerFactory(IFindRequestHandlerFactory& factory)
   {
     Stop();
@@ -296,6 +314,12 @@
 
   void DicomServer::Start()
   {
+    if (modalities_ == NULL)
+    {
+      LOG(ERROR) << "No list of modalities was provided to the DICOM server";
+      throw OrthancException(ErrorCode_BadSequenceOfCalls);
+    }
+    
     Stop();
 
     /* initialize network, i.e. create an instance of T_ASC_Network*. */
@@ -339,13 +363,20 @@
 
   bool DicomServer::IsMyAETitle(const std::string& aet) const
   {
+    if (modalities_ == NULL)
+    {
+      throw OrthancException(ErrorCode_BadSequenceOfCalls);
+    }
+    
     if (!HasCalledApplicationEntityTitleCheck())
     {
       // OK, no check on the AET.
       return true;
     }
-
-    return Configuration::IsSameAETitle(aet, GetApplicationEntityTitle());
+    else
+    {
+      return modalities_->IsSameAETitle(aet, GetApplicationEntityTitle());
+    }
   }
 
 }
--- a/OrthancServer/DicomProtocol/DicomServer.h	Tue Aug 29 16:49:44 2017 +0200
+++ b/OrthancServer/DicomProtocol/DicomServer.h	Tue Aug 29 19:59:01 2017 +0200
@@ -42,6 +42,7 @@
 #include "IStoreRequestHandlerFactory.h"
 #include "IWorklistRequestHandlerFactory.h"
 #include "IApplicationEntityFilter.h"
+#include "RemoteModalityParameters.h"
 
 #include <boost/shared_ptr.hpp>
 #include <boost/noncopyable.hpp>
@@ -51,6 +52,22 @@
 {
   class DicomServer : public boost::noncopyable
   {
+  public:
+    // WARNING: The methods of this class must be thread-safe
+    class IRemoteModalities : public boost::noncopyable
+    {
+    public:
+      virtual ~IRemoteModalities()
+      {
+      }
+      
+      virtual bool IsSameAETitle(const std::string& aet1,
+                                 const std::string& aet2) = 0;
+
+      virtual bool LookupAETitle(RemoteModalityParameters& modality,
+                                 const std::string& aet) = 0;
+    };
+    
   private:
     struct PImpl;
     boost::shared_ptr<PImpl> pimpl_;
@@ -60,6 +77,7 @@
     uint16_t port_;
     bool continue_;
     uint32_t associationTimeout_;
+    IRemoteModalities* modalities_;
     IFindRequestHandlerFactory* findRequestHandlerFactory_;
     IMoveRequestHandlerFactory* moveRequestHandlerFactory_;
     IStoreRequestHandlerFactory* storeRequestHandlerFactory_;
@@ -85,6 +103,9 @@
     void SetApplicationEntityTitle(const std::string& aet);
     const std::string& GetApplicationEntityTitle() const;
 
+    void SetRemoteModalities(IRemoteModalities& modalities);
+    IRemoteModalities& GetRemoteModalities() const;
+    
     void SetFindRequestHandlerFactory(IFindRequestHandlerFactory& handler);
     bool HasFindRequestHandlerFactory() const;
     IFindRequestHandlerFactory& GetFindRequestHandlerFactory() const;
--- a/OrthancServer/DicomProtocol/DicomUserConnection.cpp	Tue Aug 29 16:49:44 2017 +0200
+++ b/OrthancServer/DicomProtocol/DicomUserConnection.cpp	Tue Aug 29 19:59:01 2017 +0200
@@ -87,7 +87,6 @@
 #include "../../Core/OrthancException.h"
 #include "../FromDcmtkBridge.h"
 #include "../ToDcmtkBridge.h"
-#include "../OrthancInitialization.h"
 
 #include <dcmtk/dcmdata/dcistrmb.h>
 #include <dcmtk/dcmdata/dcistrmf.h>
@@ -402,8 +401,8 @@
       else
       {
         DicomMap m;
-        Configuration::ExtractDicomSummary(m, *responseIdentifiers);
-
+        FromDcmtkBridge::ExtractDicomSummary(m, *responseIdentifiers);
+        
         if (!m.HasTag(DICOM_TAG_QUERY_RETRIEVE_LEVEL))
         {
           m.SetValue(DICOM_TAG_QUERY_RETRIEVE_LEVEL, payload.level, false);
--- a/OrthancServer/FromDcmtkBridge.cpp	Tue Aug 29 16:49:44 2017 +0200
+++ b/OrthancServer/FromDcmtkBridge.cpp	Tue Aug 29 19:59:01 2017 +0200
@@ -84,9 +84,16 @@
 #include <dcmtk/dcmdata/dcvrus.h>
 #include <dcmtk/dcmdata/dcvrut.h>
 
+#if DCMTK_USE_EMBEDDED_DICTIONARIES == 1
+#  include <EmbeddedResources.h>
+#endif
 
-#if DCMTK_USE_EMBEDDED_DICTIONARIES == 1
-#include <EmbeddedResources.h>
+#if ORTHANC_ENABLE_DCMTK_JPEG == 1
+#  include <dcmtk/dcmjpeg/djdecode.h>
+#endif
+
+#if ORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS == 1
+#  include <dcmtk/dcmjpls/djdecode.h>
 #endif
 
 
@@ -2017,4 +2024,52 @@
     }
   }
 #endif
+
+
+  void FromDcmtkBridge::ExtractDicomSummary(DicomMap& target, 
+                                            DcmItem& dataset)
+  {
+    ExtractDicomSummary(target, dataset,
+                        ORTHANC_MAXIMUM_TAG_LENGTH,
+                        GetDefaultDicomEncoding());
+  }
+
+  
+  void FromDcmtkBridge::ExtractDicomAsJson(Json::Value& target, 
+                                           DcmDataset& dataset)
+  {
+    ExtractDicomAsJson(target, dataset, 
+                       DicomToJsonFormat_Full,
+                       DicomToJsonFlags_Default, 
+                       ORTHANC_MAXIMUM_TAG_LENGTH,
+                       GetDefaultDicomEncoding());
+  }
+
+
+  void FromDcmtkBridge::InitializeCodecs()
+  {
+#if ORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS == 1
+    LOG(WARNING) << "Registering JPEG Lossless codecs in DCMTK";
+    DJLSDecoderRegistration::registerCodecs();    
+#endif
+
+#if ORTHANC_ENABLE_DCMTK_JPEG == 1
+    LOG(WARNING) << "Registering JPEG codecs in DCMTK";
+    DJDecoderRegistration::registerCodecs(); 
+#endif
+  }
+
+
+  void FromDcmtkBridge::FinalizeCodecs()
+  {
+#if ORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS == 1
+    // Unregister JPEG-LS codecs
+    DJLSDecoderRegistration::cleanup();
+#endif
+
+#if ORTHANC_ENABLE_DCMTK_JPEG == 1
+    // Unregister JPEG codecs
+    DJDecoderRegistration::cleanup();
+#endif
+  }
 }
--- a/OrthancServer/FromDcmtkBridge.h	Tue Aug 29 16:49:44 2017 +0200
+++ b/OrthancServer/FromDcmtkBridge.h	Tue Aug 29 19:59:01 2017 +0200
@@ -60,6 +60,14 @@
 #  include "../Core/Lua/LuaFunctionCall.h"
 #endif
 
+#if !defined(ORTHANC_ENABLE_DCMTK_JPEG)
+#  error The macro ORTHANC_ENABLE_DCMTK_JPEG must be defined
+#endif
+
+#if !defined(ORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS)
+#  error The macro ORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS must be defined
+#endif
+
 
 namespace Orthanc
 {
@@ -70,7 +78,6 @@
 #endif
 
     friend class ParsedDicomFile;
-    friend class Configuration;
 
   private:
     FromDcmtkBridge();  // Pure static class
@@ -220,5 +227,15 @@
     static void ExecuteToDicom(DicomMap& target,
                                LuaFunctionCall& call);
 #endif
+
+    static void ExtractDicomSummary(DicomMap& target, 
+                                    DcmItem& dataset);
+
+    static void ExtractDicomAsJson(Json::Value& target, 
+                                   DcmDataset& dataset);
+
+    static void InitializeCodecs();
+
+    static void FinalizeCodecs();
   };
 }
--- a/OrthancServer/Internals/CommandDispatcher.cpp	Tue Aug 29 16:49:44 2017 +0200
+++ b/OrthancServer/Internals/CommandDispatcher.cpp	Tue Aug 29 19:59:01 2017 +0200
@@ -871,8 +871,9 @@
                   worklistHandler.reset(server_.GetWorklistRequestHandlerFactory().ConstructWorklistRequestHandler());
                 }
 
-                cond = Internals::findScp(assoc_, &msg, presID, findHandler.get(), 
-                                          worklistHandler.get(), remoteIp_, remoteAet_, calledAet_);
+                cond = Internals::findScp(assoc_, &msg, presID, server_.GetRemoteModalities(),
+                                          findHandler.get(), worklistHandler.get(),
+                                          remoteIp_, remoteAet_, calledAet_);
               }
               break;
 
--- a/OrthancServer/Internals/DicomFrameIndex.cpp	Tue Aug 29 16:49:44 2017 +0200
+++ b/OrthancServer/Internals/DicomFrameIndex.cpp	Tue Aug 29 19:59:01 2017 +0200
@@ -37,7 +37,6 @@
 #include "../../Core/OrthancException.h"
 #include "../../Core/DicomFormat/DicomImageInformation.h"
 #include "../FromDcmtkBridge.h"
-#include "../OrthancInitialization.h"
 #include "../../Core/Endianness.h"
 #include "DicomImageDecoder.h"
 
@@ -405,7 +404,7 @@
 
     // Extract information about the image structure
     DicomMap tags;
-    Configuration::ExtractDicomSummary(tags, dataset);
+    FromDcmtkBridge::ExtractDicomSummary(tags, dataset);
 
     DicomImageInformation information(tags);
 
--- a/OrthancServer/Internals/DicomFrameIndex.h	Tue Aug 29 16:49:44 2017 +0200
+++ b/OrthancServer/Internals/DicomFrameIndex.h	Tue Aug 29 19:59:01 2017 +0200
@@ -33,6 +33,8 @@
 
 #pragma once
 
+#include "../../Core/Enumerations.h"
+
 #include <dcmtk/dcmdata/dcdatset.h>
 #include <dcmtk/dcmdata/dcfilefo.h>
 #include <vector>
--- a/OrthancServer/Internals/DicomImageDecoder.cpp	Tue Aug 29 16:49:44 2017 +0200
+++ b/OrthancServer/Internals/DicomImageDecoder.cpp	Tue Aug 29 19:59:01 2017 +0200
@@ -85,7 +85,6 @@
 #include "../ToDcmtkBridge.h"
 #include "../FromDcmtkBridge.h"
 #include "../ParsedDicomFile.h"
-#include "../OrthancInitialization.h"
 
 #if ORTHANC_ENABLE_PNG == 1
 #  include "../../Core/Images/PngWriter.h"
@@ -257,7 +256,7 @@
       // See also: http://support.dcmtk.org/wiki/dcmtk/howto/accessing-compressed-data
 
       DicomMap m;
-      Configuration::ExtractDicomSummary(m, dataset);
+      FromDcmtkBridge::ExtractDicomSummary(m, dataset);
 
       /**
        * Create an accessor to the raw values of the DICOM image.
@@ -329,7 +328,7 @@
                                                 bool ignorePhotometricInterpretation)
   {
     DicomMap m;
-    Configuration::ExtractDicomSummary(m, dataset);
+    FromDcmtkBridge::ExtractDicomSummary(m, dataset);
 
     DicomImageInformation info(m);
     PixelFormat format;
--- a/OrthancServer/Internals/FindScp.cpp	Tue Aug 29 16:49:44 2017 +0200
+++ b/OrthancServer/Internals/FindScp.cpp	Tue Aug 29 19:59:01 2017 +0200
@@ -139,6 +139,7 @@
   {  
     struct FindScpData
     {
+      DicomServer::IRemoteModalities* modalities_;
       IFindRequestHandler* findHandler_;
       IWorklistRequestHandler* worklistHandler_;
       DicomFindAnswers answers_;
@@ -197,7 +198,8 @@
            * Ensure that the remote modality is known to Orthanc for C-FIND requests.
            **/
 
-          if (!Configuration::LookupDicomModalityUsingAETitle(modality, *data.remoteAet_))
+          assert(data.modalities_ != NULL);
+          if (!data.modalities_->LookupAETitle(modality, *data.remoteAet_))
           {
             LOG(ERROR) << "Modality with AET \"" << *data.remoteAet_
                        << "\" is not defined in the \"DicomModalities\" configuration option";
@@ -252,7 +254,7 @@
               }
 
               DicomMap input;
-              Configuration::ExtractDicomSummary(input, *requestIdentifiers);
+              FromDcmtkBridge::ExtractDicomSummary(input, *requestIdentifiers);
 
               data.findHandler_->Handle(data.answers_, input, sequencesToReturn,
                                         *data.remoteIp_, *data.remoteAet_,
@@ -314,6 +316,7 @@
   OFCondition Internals::findScp(T_ASC_Association * assoc, 
                                  T_DIMSE_Message * msg, 
                                  T_ASC_PresentationContextID presID,
+                                 DicomServer::IRemoteModalities& modalities,
                                  IFindRequestHandler* findHandler,
                                  IWorklistRequestHandler* worklistHandler,
                                  const std::string& remoteIp,
@@ -321,9 +324,10 @@
                                  const std::string& calledAet)
   {
     FindScpData data;
-    data.lastRequest_ = NULL;
+    data.modalities_ = &modalities;
     data.findHandler_ = findHandler;
     data.worklistHandler_ = worklistHandler;
+    data.lastRequest_ = NULL;
     data.remoteIp_ = &remoteIp;
     data.remoteAet_ = &remoteAet;
     data.calledAet_ = &calledAet;
--- a/OrthancServer/Internals/FindScp.h	Tue Aug 29 16:49:44 2017 +0200
+++ b/OrthancServer/Internals/FindScp.h	Tue Aug 29 19:59:01 2017 +0200
@@ -33,8 +33,7 @@
 
 #pragma once
 
-#include "../DicomProtocol/IFindRequestHandler.h"
-#include "../DicomProtocol/IWorklistRequestHandler.h"
+#include "../DicomProtocol/DicomServer.h"
 
 #include <dcmtk/dcmnet/dimse.h>
 
@@ -45,6 +44,7 @@
     OFCondition findScp(T_ASC_Association * assoc, 
                         T_DIMSE_Message * msg, 
                         T_ASC_PresentationContextID presID,
+                        DicomServer::IRemoteModalities& modalities,
                         IFindRequestHandler* findHandler,   // can be NULL
                         IWorklistRequestHandler* worklistHandler,   // can be NULL
                         const std::string& remoteIp,
--- a/OrthancServer/Internals/MoveScp.cpp	Tue Aug 29 16:49:44 2017 +0200
+++ b/OrthancServer/Internals/MoveScp.cpp	Tue Aug 29 19:59:01 2017 +0200
@@ -87,7 +87,6 @@
 
 #include "../FromDcmtkBridge.h"
 #include "../ToDcmtkBridge.h"
-#include "../OrthancInitialization.h"
 #include "../../Core/Logging.h"
 #include "../../Core/OrthancException.h"
 
@@ -169,7 +168,7 @@
       if (data.lastRequest_ == NULL)
       {
         DicomMap input;
-        Configuration::ExtractDicomSummary(input, *requestIdentifiers);
+        FromDcmtkBridge::ExtractDicomSummary(input, *requestIdentifiers);
 
         try
         {
--- a/OrthancServer/Internals/StoreScp.cpp	Tue Aug 29 16:49:44 2017 +0200
+++ b/OrthancServer/Internals/StoreScp.cpp	Tue Aug 29 19:59:01 2017 +0200
@@ -85,7 +85,6 @@
 
 #include "../FromDcmtkBridge.h"
 #include "../ToDcmtkBridge.h"
-#include "../OrthancInitialization.h"
 #include "../../Core/OrthancException.h"
 #include "../../Core/Logging.h"
 
@@ -168,8 +167,8 @@
 
           try
           {
-            Configuration::ExtractDicomSummary(summary, **imageDataSet);
-            Configuration::ExtractDicomAsJson(dicomJson, **imageDataSet);
+            FromDcmtkBridge::ExtractDicomSummary(summary, **imageDataSet);
+            FromDcmtkBridge::ExtractDicomAsJson(dicomJson, **imageDataSet);
 
             if (!FromDcmtkBridge::SaveToMemoryBuffer(buffer, **imageDataSet))
             {
--- a/OrthancServer/OrthancInitialization.cpp	Tue Aug 29 16:49:44 2017 +0200
+++ b/OrthancServer/OrthancInitialization.cpp	Tue Aug 29 19:59:01 2017 +0200
@@ -43,25 +43,13 @@
 #include "ServerEnumerations.h"
 #include "DatabaseWrapper.h"
 #include "FromDcmtkBridge.h"
-#include "ToDcmtkBridge.h"
 
 #include <boost/lexical_cast.hpp>
 #include <boost/filesystem.hpp>
 #include <curl/curl.h>
 #include <boost/thread/recursive_mutex.hpp>
 
-
-#if ORTHANC_ENABLE_DCMTK_JPEG == 1
-#  include <dcmtk/dcmjpeg/djdecode.h>
-#endif
-
-
-#if ORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS == 1
-#  include <dcmtk/dcmjpls/djdecode.h>
-#endif
-
-
-#include <dcmtk/dcmnet/dul.h>
+#include <dcmtk/dcmnet/dul.h>   // For dcmDisableGethostbyaddr()
 
 
 
@@ -482,6 +470,16 @@
       Toolbox::InitializeGlobalLocale(NULL);
     }
 
+    if (configuration_.isMember("DefaultEncoding"))
+    {
+      std::string encoding = GetGlobalStringParameterInternal("DefaultEncoding", "");
+      SetDefaultDicomEncoding(StringToEncoding(encoding.c_str()));
+    }
+    else
+    {
+      SetDefaultDicomEncoding(ORTHANC_DEFAULT_DICOM_ENCODING);
+    }
+
     if (configuration_.isMember("Pkcs11"))
     {
       ConfigurePkcs11(configuration_["Pkcs11"]);
@@ -495,15 +493,7 @@
     FromDcmtkBridge::InitializeDictionary(GetGlobalBoolParameterInternal("LoadPrivateDictionary", true));
     LoadCustomDictionary(configuration_);
 
-#if ORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS == 1
-    LOG(WARNING) << "Registering JPEG Lossless codecs";
-    DJLSDecoderRegistration::registerCodecs();    
-#endif
-
-#if ORTHANC_ENABLE_DCMTK_JPEG == 1
-    LOG(WARNING) << "Registering JPEG codecs";
-    DJDecoderRegistration::registerCodecs(); 
-#endif
+    FromDcmtkBridge::InitializeCodecs();
 
     fontRegistry_.AddFromResource(EmbeddedResources::FONT_UBUNTU_MONO_BOLD_16);
 
@@ -517,17 +507,7 @@
   {
     boost::recursive_mutex::scoped_lock lock(globalMutex_);
     HttpClient::GlobalFinalize();
-
-#if ORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS == 1
-    // Unregister JPEG-LS codecs
-    DJLSDecoderRegistration::cleanup();
-#endif
-
-#if ORTHANC_ENABLE_DCMTK_JPEG == 1
-    // Unregister JPEG codecs
-    DJDecoderRegistration::cleanup();
-#endif
-
+    FromDcmtkBridge::FinalizeCodecs();
     HttpClient::FinalizeOpenSsl();
     Toolbox::FinalizeGlobalLocale();
   }
@@ -1134,25 +1114,16 @@
   }
 
 
-  Encoding Configuration::GetDefaultEncoding()
-  {
-    std::string s = GetGlobalStringParameter("DefaultEncoding", "Latin1");
-
-    // By default, Latin1 encoding is assumed
-    return s.empty() ? Encoding_Latin1 : StringToEncoding(s.c_str());
-  }
-
-
   void Configuration::SetDefaultEncoding(Encoding encoding)
   {
-    std::string name = EnumerationToString(encoding);
+    SetDefaultDicomEncoding(encoding);
 
     {
+      // Propagate the encoding to the configuration file that is
+      // stored in memory
       boost::recursive_mutex::scoped_lock lock(globalMutex_);
-      configuration_["DefaultEncoding"] = name;
+      configuration_["DefaultEncoding"] = EnumerationToString(encoding);
     }
-
-    LOG(INFO) << "Default encoding was changed to: " << name;
   }
 
 
@@ -1170,21 +1141,4 @@
 
     return a != b;
   }
-
-
-  void Configuration::ExtractDicomSummary(DicomMap& target, 
-                                          DcmItem& dataset)
-  {
-    FromDcmtkBridge::ExtractDicomSummary(target, dataset, 
-                                         ORTHANC_MAXIMUM_TAG_LENGTH, GetDefaultEncoding());
-  }
-
-  
-  void Configuration::ExtractDicomAsJson(Json::Value& target, 
-                                         DcmDataset& dataset)
-  {
-    FromDcmtkBridge::ExtractDicomAsJson(target, dataset, 
-                                        DicomToJsonFormat_Full, DicomToJsonFlags_Default, 
-                                        ORTHANC_MAXIMUM_TAG_LENGTH, GetDefaultEncoding());
-  }
 }
--- a/OrthancServer/OrthancInitialization.h	Tue Aug 29 16:49:44 2017 +0200
+++ b/OrthancServer/OrthancInitialization.h	Tue Aug 29 19:59:01 2017 +0200
@@ -47,17 +47,6 @@
 #include "IDatabaseWrapper.h"
 #include "ServerEnumerations.h"
 
-#if !defined(ORTHANC_ENABLE_DCMTK_JPEG)
-#  error The macro ORTHANC_ENABLE_DCMTK_JPEG must be defined
-#endif
-
-#if !defined(ORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS)
-#  error The macro ORTHANC_ENABLE_DCMTK_JPEG_LOSSLESS must be defined
-#endif
-
-
-class DcmDataset;
-class DcmItem;
 
 namespace Orthanc
 {
@@ -138,16 +127,8 @@
 
     static const FontRegistry& GetFontRegistry();
 
-    static Encoding GetDefaultEncoding();
-
     static void SetDefaultEncoding(Encoding encoding);
 
     static bool HasConfigurationChanged();
-
-    static void ExtractDicomSummary(DicomMap& target, 
-                                    DcmItem& dataset);
-
-    static void ExtractDicomAsJson(Json::Value& target, 
-                                   DcmDataset& dataset);
   };
 }
--- a/OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp	Tue Aug 29 16:49:44 2017 +0200
+++ b/OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp	Tue Aug 29 19:59:01 2017 +0200
@@ -710,7 +710,7 @@
       }
       else
       {
-        encoding = Configuration::GetDefaultEncoding();
+        encoding = GetDefaultDicomEncoding();
       }
 
       dicom.SetEncoding(encoding);
--- a/OrthancServer/OrthancRestApi/OrthancRestSystem.cpp	Tue Aug 29 16:49:44 2017 +0200
+++ b/OrthancServer/OrthancRestApi/OrthancRestSystem.cpp	Tue Aug 29 19:59:01 2017 +0200
@@ -251,7 +251,7 @@
 
   static void GetDefaultEncoding(RestApiGetCall& call)
   {
-    Encoding encoding = Configuration::GetDefaultEncoding();
+    Encoding encoding = GetDefaultDicomEncoding();
     call.GetOutput().AnswerBuffer(EnumerationToString(encoding), "text/plain");
   }
 
--- a/OrthancServer/ParsedDicomFile.cpp	Tue Aug 29 16:49:44 2017 +0200
+++ b/OrthancServer/ParsedDicomFile.cpp	Tue Aug 29 19:59:01 2017 +0200
@@ -81,13 +81,13 @@
 
 #include "ParsedDicomFile.h"
 
-#include "OrthancInitialization.h"
 #include "FromDcmtkBridge.h"
 #include "ToDcmtkBridge.h"
 #include "Internals/DicomFrameIndex.h"
 #include "../Core/Logging.h"
 #include "../Core/OrthancException.h"
 #include "../Core/Toolbox.h"
+#include "../Core/SystemToolbox.h"
 
 #if ORTHANC_ENABLE_JPEG == 1
 #  include "../Core/Images/JpegReader.h"
@@ -948,7 +948,7 @@
   ParsedDicomFile::ParsedDicomFile(const DicomMap& map) : 
     pimpl_(new PImpl)
   {
-    CreateFromDicomMap(map, Configuration::GetDefaultEncoding());
+    CreateFromDicomMap(map, GetDefaultDicomEncoding());
   }
 
 
@@ -1212,7 +1212,7 @@
   Encoding ParsedDicomFile::GetEncoding() const
   {
     return FromDcmtkBridge::DetectEncoding(*pimpl_->file_->getDataset(),
-                                           Configuration::GetDefaultEncoding());
+                                           GetDefaultDicomEncoding());
   }
 
 
@@ -1235,13 +1235,13 @@
                                       unsigned int maxStringLength)
   {
     FromDcmtkBridge::ExtractDicomAsJson(target, *pimpl_->file_->getDataset(),
-                                        format, flags, maxStringLength, Configuration::GetDefaultEncoding());
+                                        format, flags, maxStringLength, GetDefaultDicomEncoding());
   }
 
 
   void ParsedDicomFile::DatasetToJson(Json::Value& target)
   {
-    Configuration::ExtractDicomAsJson(target, *pimpl_->file_->getDataset());
+    FromDcmtkBridge::ExtractDicomAsJson(target, *pimpl_->file_->getDataset());
   }
 
 
@@ -1351,7 +1351,7 @@
 	const bool decodeDataUriScheme = (flags & DicomFromJsonFlags_DecodeDataUriScheme) ? true : false;
 
     std::auto_ptr<ParsedDicomFile> result(new ParsedDicomFile(generateIdentifiers));
-    result->SetEncoding(FromDcmtkBridge::ExtractEncoding(json, Configuration::GetDefaultEncoding()));
+    result->SetEncoding(FromDcmtkBridge::ExtractEncoding(json, GetDefaultDicomEncoding()));
 
     const Json::Value::Members tags = json.getMemberNames();
     
@@ -1438,13 +1438,13 @@
 
   void ParsedDicomFile::ExtractDicomSummary(DicomMap& target) const
   {
-    Configuration::ExtractDicomSummary(target, *pimpl_->file_->getDataset());
+    FromDcmtkBridge::ExtractDicomSummary(target, *pimpl_->file_->getDataset());
   }
 
 
   void ParsedDicomFile::ExtractDicomAsJson(Json::Value& target) const
   {
-    Configuration::ExtractDicomAsJson(target, *pimpl_->file_->getDataset());
+    FromDcmtkBridge::ExtractDicomAsJson(target, *pimpl_->file_->getDataset());
   }
 
 
--- a/OrthancServer/main.cpp	Tue Aug 29 16:49:44 2017 +0200
+++ b/OrthancServer/main.cpp	Tue Aug 29 19:59:01 2017 +0200
@@ -89,6 +89,23 @@
 
 
 
+class ModalitiesFromConfiguration : public Orthanc::DicomServer::IRemoteModalities
+{
+public:
+  virtual bool IsSameAETitle(const std::string& aet1,
+                             const std::string& aet2) 
+  {
+    return Orthanc::Configuration::IsSameAETitle(aet1, aet2);
+  }
+
+  virtual bool LookupAETitle(RemoteModalityParameters& modality,
+                             const std::string& aet) 
+  {
+    return Orthanc::Configuration::LookupDicomModalityUsingAETitle(modality, aet);
+  }
+};
+
+
 class MyDicomServerFactory : 
   public IStoreRequestHandlerFactory,
   public IFindRequestHandlerFactory, 
@@ -797,10 +814,12 @@
   }
 
   MyDicomServerFactory serverFactory(context);
-
-  // DICOM server
+  OrthancApplicationEntityFilter dicomFilter(context);
+  ModalitiesFromConfiguration modalities;
+  
+  // Setup the DICOM server  
   DicomServer dicomServer;
-  OrthancApplicationEntityFilter dicomFilter(context);
+  dicomServer.SetRemoteModalities(modalities);
   dicomServer.SetCalledApplicationEntityTitleCheck(Configuration::GetGlobalBoolParameter("DicomCheckCalledAet", false));
   dicomServer.SetStoreRequestHandlerFactory(serverFactory);
   dicomServer.SetMoveRequestHandlerFactory(serverFactory);
--- a/UnitTestsSources/FromDcmtkTests.cpp	Tue Aug 29 16:49:44 2017 +0200
+++ b/UnitTestsSources/FromDcmtkTests.cpp	Tue Aug 29 19:59:01 2017 +0200
@@ -36,7 +36,6 @@
 
 #include "../OrthancServer/FromDcmtkBridge.h"
 #include "../OrthancServer/ToDcmtkBridge.h"
-#include "../OrthancServer/OrthancInitialization.h"
 #include "../OrthancServer/DicomModification.h"
 #include "../OrthancServer/ServerToolbox.h"
 #include "../Core/OrthancException.h"
@@ -1062,8 +1061,8 @@
 
 TEST(ParsedDicomFile, DicomMapEncodings1)
 {
-  Configuration::SetDefaultEncoding(Encoding_Ascii);
-  ASSERT_EQ(Encoding_Ascii, Configuration::GetDefaultEncoding());
+  SetDefaultDicomEncoding(Encoding_Ascii);
+  ASSERT_EQ(Encoding_Ascii, GetDefaultDicomEncoding());
 
   {
     DicomMap m;
--- a/UnitTestsSources/ImageTests.cpp	Tue Aug 29 16:49:44 2017 +0200
+++ b/UnitTestsSources/ImageTests.cpp	Tue Aug 29 19:59:01 2017 +0200
@@ -43,7 +43,7 @@
 #include "../Core/Images/PngWriter.h"
 #include "../Core/Toolbox.h"
 #include "../Core/TemporaryFile.h"
-#include "../OrthancServer/OrthancInitialization.h"
+#include "../OrthancServer/OrthancInitialization.h"  // For the FontRegistry
 
 #include <stdint.h>