diff OrthancServer/ServerContext.cpp @ 3920:82e88ff003d7 c-get

merge default -> c-get
author Alain Mazy <alain@mazy.be>
date Tue, 12 May 2020 14:58:24 +0200
parents 6ddad3e0b569
children 4cdc875510d1
line wrap: on
line diff
--- a/OrthancServer/ServerContext.cpp	Tue May 12 07:50:38 2020 +0200
+++ b/OrthancServer/ServerContext.cpp	Tue May 12 14:58:24 2020 +0200
@@ -35,6 +35,7 @@
 #include "ServerContext.h"
 
 #include "../Core/Cache/SharedArchive.h"
+#include "../Core/DicomParsing/DcmtkTranscoder.h"
 #include "../Core/DicomParsing/FromDcmtkBridge.h"
 #include "../Core/FileStorage/StorageAccessor.h"
 #include "../Core/HttpServer/FilesystemHttpSender.h"
@@ -242,7 +243,9 @@
     isJobsEngineUnserialized_(false),
     metricsRegistry_(new MetricsRegistry),
     isHttpServerSecure_(true),
-    isExecuteLuaEnabled_(false)
+    isExecuteLuaEnabled_(false),
+    overwriteInstances_(false),
+    dcmtkTranscoder_(new DcmtkTranscoder)
   {
     {
       OrthancConfiguration::ReaderLock lock;
@@ -263,6 +266,9 @@
 
       // New configuration option in Orthanc 1.6.0
       storageCommitmentReports_.reset(new StorageCommitmentReports(lock.GetConfiguration().GetUnsignedIntegerParameter("StorageCommitmentReportsSize", 100)));
+
+      // New option in Orthanc 1.7.0
+      transcodeDicomProtocol_ = lock.GetConfiguration().GetBooleanParameter("TranscodeDicomProtocol", true);
     }
 
     jobsEngine_.SetThreadSleep(unitTesting ? 20 : 200);
@@ -338,9 +344,29 @@
   }
 
 
-  StoreStatus ServerContext::Store(std::string& resultPublicId,
-                                   DicomInstanceToStore& dicom)
+  StoreStatus ServerContext::StoreAfterTranscoding(std::string& resultPublicId,
+                                                   DicomInstanceToStore& dicom,
+                                                   StoreInstanceMode mode)
   {
+    bool overwrite;
+    switch (mode)
+    {
+      case StoreInstanceMode_Default:
+        overwrite = overwriteInstances_;
+        break;
+        
+      case StoreInstanceMode_OverwriteDuplicate:
+        overwrite = true;
+        break;
+        
+      case StoreInstanceMode_IgnoreDuplicate:
+        overwrite = false;
+        break;
+
+      default:
+        throw OrthancException(ErrorCode_ParameterOutOfRange);
+    }    
+    
     try
     {
       MetricsRegistry::Timer timer(GetMetricsRegistry(), "orthanc_store_dicom_duration_ms");
@@ -404,7 +430,8 @@
 
       typedef std::map<MetadataType, std::string>  InstanceMetadata;
       InstanceMetadata  instanceMetadata;
-      StoreStatus status = index_.Store(instanceMetadata, dicom, attachments);
+      StoreStatus status = index_.Store(
+        instanceMetadata, dicom, attachments, overwrite);
 
       // Only keep the metadata for the "instance" level
       dicom.GetMetadata().clear();
@@ -475,6 +502,62 @@
   }
 
 
+  StoreStatus ServerContext::Store(std::string& resultPublicId,
+                                   DicomInstanceToStore& dicom,
+                                   StoreInstanceMode mode)
+  {
+    //const DicomTransferSyntax option = DicomTransferSyntax_JPEGProcess1;
+    const DicomTransferSyntax option = DicomTransferSyntax_LittleEndianExplicit;
+    
+    if (1)
+    {
+      return StoreAfterTranscoding(resultPublicId, dicom, mode);
+    }
+    else
+    {
+      // TODO => Automated transcoding of incoming DICOM files
+      
+      DicomTransferSyntax sourceSyntax;
+      if (!FromDcmtkBridge::LookupOrthancTransferSyntax(
+            sourceSyntax, dicom.GetParsedDicomFile().GetDcmtkObject()) ||
+          sourceSyntax == option)
+      {
+        // No transcoding
+        return StoreAfterTranscoding(resultPublicId, dicom, mode);
+      }
+      else
+      {      
+        std::set<DicomTransferSyntax> syntaxes;
+        syntaxes.insert(option);
+
+        std::unique_ptr<IDicomTranscoder::TranscodedDicom> transcoded(
+          GetTranscoder().TranscodeToParsed(dicom.GetParsedDicomFile().GetDcmtkObject(),
+                                            dicom.GetBufferData(), dicom.GetBufferSize(),
+                                            syntaxes, true /* allow new SOP instance UID */));
+
+        if (transcoded.get() == NULL)
+        {
+          // Cannot transcode => store the original file
+          return StoreAfterTranscoding(resultPublicId, dicom, mode);
+        }
+        else
+        {
+          std::unique_ptr<ParsedDicomFile> tmp(
+            ParsedDicomFile::AcquireDcmtkObject(transcoded->ReleaseDicom()));
+      
+          DicomInstanceToStore toStore;
+          toStore.SetParsedDicomFile(*tmp);
+          toStore.SetOrigin(dicom.GetOrigin());
+
+          StoreStatus ok = StoreAfterTranscoding(resultPublicId, toStore, mode);
+          printf(">> %s\n", resultPublicId.c_str());
+          return ok;
+        }
+      }
+    }
+  }
+
+  
   void ServerContext::AnswerAttachment(RestApiOutput& output,
                                        const std::string& resourceId,
                                        FileContentType content)
@@ -1086,4 +1169,50 @@
 
     return NULL;
   }
+
+
+  IDicomTranscoder& ServerContext::GetTranscoder()
+  {
+    IDicomTranscoder* transcoder = dcmtkTranscoder_.get();
+
+#if ORTHANC_ENABLE_PLUGINS == 1
+    if (HasPlugins())
+    {
+      transcoder = &GetPlugins();
+    }
+#endif
+
+    if (transcoder == NULL)
+    {
+      throw OrthancException(ErrorCode_InternalError);
+    }
+    else
+    {
+      return *transcoder;
+    }
+  }   
+
+
+  void ServerContext::StoreWithTranscoding(std::string& sopClassUid,
+                                           std::string& sopInstanceUid,
+                                           DicomStoreUserConnection& connection,
+                                           const std::string& dicom,
+                                           bool hasMoveOriginator,
+                                           const std::string& moveOriginatorAet,
+                                           uint16_t moveOriginatorId)
+  {
+    const void* data = dicom.empty() ? NULL : dicom.c_str();
+    
+    if (!transcodeDicomProtocol_ ||
+        !connection.GetParameters().GetRemoteModality().IsTranscodingAllowed())
+    {
+      connection.Store(sopClassUid, sopInstanceUid, data, dicom.size(),
+                       hasMoveOriginator, moveOriginatorAet, moveOriginatorId);
+    }
+    else
+    {
+      connection.Transcode(sopClassUid, sopInstanceUid, GetTranscoder(), data, dicom.size(),
+                           hasMoveOriginator, moveOriginatorAet, moveOriginatorId);
+    }
+  }
 }