changeset 4384:7e0d015ad109

new configuration options IngestTranscodingOfUncompressed and IngestTranscodingOfCompressed
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 18 Dec 2020 11:13:00 +0100
parents e49cf50b54c8
children 92737070b301
files NEWS OrthancServer/Resources/Configuration.json OrthancServer/Sources/ServerContext.cpp OrthancServer/Sources/ServerContext.h
diffstat 4 files changed, 87 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Thu Dec 17 15:10:57 2020 +0100
+++ b/NEWS	Fri Dec 18 11:13:00 2020 +0100
@@ -8,12 +8,15 @@
 * New config option "MallocArenaMax" to control memory usage on GNU/Linux
 * Explicit error log if trying to load a 32bit (resp. 64bit) plugin into
   a 64bit (resp. 32bit) version of Orthanc
-* New configuration options (contributions by Varian):
+* New configuration options contributed by Varian Medical Systems:
   - "DeidentifyLogs" to remove patient identification from the logs (C-GET, C-MOVE, C-FIND)
   - "DeidentifyLogsDicomVersion" to specify the deidentification rules for the logs
   - "OrthancExplorerEnabled" to enable/disable the Orthanc Explorer Web user interface
   - "SslMinimumProtocolVersion" to set the minimal SSL protocol version (now defaults to SSL 1.2)
   - "SslCiphersAccepted" to set the accepted ciphers over SSL (now defaults to FIPS 140-2)
+* New configuration options related to ingest transcoding:
+  - "IngestTranscodingOfUncompressed" to control whether uncompressed transfer syntaxes are transcoded
+  - "IngestTranscodingOfCompressed" to control whether compressed transfer syntaxes are transcoded
 
 REST API
 --------
--- a/OrthancServer/Resources/Configuration.json	Thu Dec 17 15:10:57 2020 +0100
+++ b/OrthancServer/Resources/Configuration.json	Fri Dec 18 11:13:00 2020 +0100
@@ -634,6 +634,16 @@
      "IngestTranscoding" : "1.2.840.10008.1.2",
   **/
 
+  // Whether ingest transcoding is applied to incoming DICOM instances
+  // that have an uncompressed transfer syntax, i.e. Little Endian
+  // Implicit, Little Endian Explicit or Big Endian Explicit (new in
+  // Orthanc 1.8.2).
+  "IngestTranscodingOfUncompressed" : true,
+  
+  // Whether ingest transcoding is applied to incoming DICOM instances
+  // that have a compressed transfer syntax (new in Orthanc 1.8.2).
+  "IngestTranscodingOfCompressed" : true,
+  
   // The compression level that is used when transcoding to one of the
   // lossy/JPEG transfer syntaxes (integer between 1 and 100).
   "DicomLossyTranscodingQuality" : 90,
--- a/OrthancServer/Sources/ServerContext.cpp	Thu Dec 17 15:10:57 2020 +0100
+++ b/OrthancServer/Sources/ServerContext.cpp	Fri Dec 18 11:13:00 2020 +0100
@@ -74,6 +74,34 @@
 
 namespace Orthanc
 {
+  static bool IsUncompressedTransferSyntax(DicomTransferSyntax transferSyntax)
+  {
+    return (transferSyntax == DicomTransferSyntax_LittleEndianImplicit ||
+            transferSyntax == DicomTransferSyntax_LittleEndianExplicit ||
+            transferSyntax == DicomTransferSyntax_BigEndianExplicit);
+  }
+
+
+  static bool IsTranscodableTransferSyntax(DicomTransferSyntax transferSyntax)
+  {
+    return (
+      // Do not try to transcode DICOM videos (new in Orthanc 1.8.2)
+      transferSyntax != DicomTransferSyntax_MPEG2MainProfileAtMainLevel &&
+      transferSyntax != DicomTransferSyntax_MPEG2MainProfileAtHighLevel &&
+      transferSyntax != DicomTransferSyntax_MPEG4HighProfileLevel4_1 &&
+      transferSyntax != DicomTransferSyntax_MPEG4BDcompatibleHighProfileLevel4_1 &&
+      transferSyntax != DicomTransferSyntax_MPEG4HighProfileLevel4_2_For2DVideo &&
+      transferSyntax != DicomTransferSyntax_MPEG4HighProfileLevel4_2_For3DVideo &&
+      transferSyntax != DicomTransferSyntax_MPEG4StereoHighProfileLevel4_2 &&
+      transferSyntax != DicomTransferSyntax_HEVCMainProfileLevel5_1 &&
+      transferSyntax != DicomTransferSyntax_HEVCMain10ProfileLevel5_1 &&
+
+      // Do not try to transcode special transfer syntaxes
+      transferSyntax != DicomTransferSyntax_RFC2557MimeEncapsulation &&
+      transferSyntax != DicomTransferSyntax_XML);
+  }
+
+  
   void ServerContext::ChangeThread(ServerContext* that,
                                    unsigned int sleepDelay)
   {
@@ -270,6 +298,8 @@
     overwriteInstances_(false),
     dcmtkTranscoder_(new DcmtkTranscoder),
     isIngestTranscoding_(false),
+    ingestTranscodingOfUncompressed_(true),
+    ingestTranscodingOfCompressed_(true),
     deidentifyLogs_(false)
   {
     try
@@ -309,6 +339,17 @@
             isIngestTranscoding_ = true;
             LOG(WARNING) << "Incoming DICOM instances will automatically be transcoded to "
                          << "transfer syntax: " << GetTransferSyntaxUid(ingestTransferSyntax_);
+
+            ingestTranscodingOfUncompressed_ = lock.GetConfiguration().GetBooleanParameter("IngestTranscodingOfUncompressed", true);
+            ingestTranscodingOfCompressed_ = lock.GetConfiguration().GetBooleanParameter("IngestTranscodingOfCompressed", true);
+
+            LOG(WARNING) << "  Ingest transcoding will "
+                         << (ingestTranscodingOfUncompressed_ ? "be applied" : "*not* be applied")
+                         << " to uncompressed transfer syntaxes (Little Endian Implicit/Explicit, Big Endian Explicit)";
+
+            LOG(WARNING) << "  Ingest transcoding will "
+                         << (ingestTranscodingOfCompressed_ ? "be applied" : "*not* be applied")
+                         << " to compressed transfer syntaxes";
           }
           else
           {
@@ -591,24 +632,50 @@
     }
     else
     {
-      // Automated transcoding of incoming DICOM files
+      // Automated transcoding of incoming DICOM instance
+
+      bool transcode = false;
 
       DicomTransferSyntax sourceSyntax;
       if (!FromDcmtkBridge::LookupOrthancTransferSyntax(
             sourceSyntax, dicom.GetParsedDicomFile().GetDcmtkObject()) ||
           sourceSyntax == ingestTransferSyntax_)
       {
+        // Don't transcode if the incoming DICOM is already in the proper transfer syntax
+        transcode = false;
+      }
+      else if (!IsTranscodableTransferSyntax(sourceSyntax))
+      {
+        // Don't try to transcode video files, this is useless (new in
+        // Orthanc 1.8.2). This could be accepted in the future if
+        // video transcoding gets implemented.
+        transcode = false;
+      }
+      else if (IsUncompressedTransferSyntax(sourceSyntax))
+      {
+        // This is an uncompressed transfer syntax (new in Orthanc 1.8.2)
+        transcode = ingestTranscodingOfUncompressed_;
+      }
+      else
+      {
+        // This is an compressed transfer syntax (new in Orthanc 1.8.2)
+        transcode = ingestTranscodingOfCompressed_;
+      }
+
+      if (!transcode)
+      {
         // No transcoding
         return StoreAfterTranscoding(resultPublicId, dicom, mode);
       }
       else
-      {      
+      {
+        // Trancoding
         std::set<DicomTransferSyntax> syntaxes;
         syntaxes.insert(ingestTransferSyntax_);
-
+        
         IDicomTranscoder::DicomImage source;
         source.SetExternalBuffer(dicom.GetBufferData(), dicom.GetBufferSize());
-
+        
         IDicomTranscoder::DicomImage transcoded;
         if (Transcode(transcoded, source, syntaxes, true /* allow new SOP instance UID */))
         {
--- a/OrthancServer/Sources/ServerContext.h	Thu Dec 17 15:10:57 2020 +0100
+++ b/OrthancServer/Sources/ServerContext.h	Fri Dec 18 11:13:00 2020 +0100
@@ -236,6 +236,8 @@
     BuiltinDecoderTranscoderOrder builtinDecoderTranscoderOrder_;
     bool isIngestTranscoding_;
     DicomTransferSyntax ingestTransferSyntax_;
+    bool ingestTranscodingOfUncompressed_;
+    bool ingestTranscodingOfCompressed_;
 
     StoreStatus StoreAfterTranscoding(std::string& resultPublicId,
                                       DicomInstanceToStore& dicom,