changeset 3906:f0dd5ded8927 transcoding

refactoring using IDicomTranscoder::TranscodedDicom
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 08 May 2020 11:16:16 +0200
parents 061f3d031b5d
children 1555feda39e2
files Core/DicomNetworking/DicomStoreUserConnection.cpp Core/DicomParsing/DcmtkTranscoder.cpp Core/DicomParsing/DcmtkTranscoder.h Core/DicomParsing/IDicomTranscoder.cpp Core/DicomParsing/IDicomTranscoder.h Core/DicomParsing/MemoryBufferTranscoder.cpp Core/DicomParsing/MemoryBufferTranscoder.h OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp OrthancServer/ServerContext.cpp OrthancServer/ServerContext.h Plugins/Engine/OrthancPlugins.cpp Plugins/Engine/OrthancPlugins.h Resources/CMake/OrthancFrameworkConfiguration.cmake
diffstat 13 files changed, 358 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
--- a/Core/DicomNetworking/DicomStoreUserConnection.cpp	Fri May 08 08:27:18 2020 +0200
+++ b/Core/DicomNetworking/DicomStoreUserConnection.cpp	Fri May 08 11:16:16 2020 +0200
@@ -491,35 +491,14 @@
         uncompressedSyntaxes.insert(DicomTransferSyntax_BigEndianExplicit);
       }
 
-      std::unique_ptr<DcmFileFormat> transcoded;
+      std::unique_ptr<IDicomTranscoder::TranscodedDicom> transcoded(
+        transcoder.TranscodeToParsed2(*dicom, buffer, size, uncompressedSyntaxes, false));
 
-      bool hasSopInstanceUidChanged;
+      // WARNING: Below this point, "transcoded->GetDicom()" is possibly
+      // a reference to "*dicom", if the DCMTK transcoder was used
       
-      if (transcoder.HasInplaceTranscode(inputSyntax, uncompressedSyntaxes))
-      {
-        if (transcoder.InplaceTranscode(hasSopInstanceUidChanged, *dicom, uncompressedSyntaxes, false))
-        {
-          // In-place transcoding is supported and has succeeded
-          transcoded.reset(dicom.release());
-        }
-      }
-      else
-      {
-        transcoded.reset(transcoder.TranscodeToParsed(hasSopInstanceUidChanged, buffer, size, uncompressedSyntaxes, false));
-      }
-
-      if (hasSopInstanceUidChanged)
-      {
-        throw OrthancException(ErrorCode_Plugin, "The transcoder has changed the SOP "
-                               "instance UID while transcoding to an uncompressed transfer syntax");
-      }
-
-      // WARNING: The "dicom" variable must not be used below this
-      // point. The "sopInstanceUid" might also have changed (if
-      // using lossy compression).
-        
-      if (transcoded == NULL ||
-          transcoded->getDataset() == NULL)
+      if (transcoded.get() == NULL ||
+          transcoded->GetDicom().getDataset() == NULL)
       {
         throw OrthancException(
           ErrorCode_NotImplemented,
@@ -527,19 +506,24 @@
           "\" to an uncompressed syntax for modality: " +
           GetParameters().GetRemoteModality().GetApplicationEntityTitle());
       }
+      else if (transcoded->HasSopInstanceUidChanged())
+      {
+        throw OrthancException(ErrorCode_Plugin, "The transcoder has changed the SOP "
+                               "instance UID while transcoding to an uncompressed transfer syntax");
+      }
       else
       {
         DicomTransferSyntax transcodedSyntax;
 
         // Sanity check
-        if (!FromDcmtkBridge::LookupOrthancTransferSyntax(transcodedSyntax, *transcoded) ||
+        if (!FromDcmtkBridge::LookupOrthancTransferSyntax(transcodedSyntax, transcoded->GetDicom()) ||
             accepted.find(transcodedSyntax) == accepted.end())
         {
           throw OrthancException(ErrorCode_InternalError);
         }
         else
         {
-          Store(sopClassUid, sopInstanceUid, *transcoded,
+          Store(sopClassUid, sopInstanceUid, transcoded->GetDicom(),
                 hasMoveOriginator, moveOriginatorAET, moveOriginatorID);
         }
       }
--- a/Core/DicomParsing/DcmtkTranscoder.cpp	Fri May 08 08:27:18 2020 +0200
+++ b/Core/DicomParsing/DcmtkTranscoder.cpp	Fri May 08 11:16:16 2020 +0200
@@ -371,4 +371,80 @@
     
     return false;
   }
+
+
+
+  bool DcmtkTranscoder::TranscodeParsedToBuffer(
+    std::string& target /* out */,
+    DicomTransferSyntax& sourceSyntax /* out */,
+    DicomTransferSyntax& targetSyntax /* out */,
+    bool& hasSopInstanceUidChanged /* out */,
+    DcmFileFormat& dicom /* in, possibly modified */,
+    const std::set<DicomTransferSyntax>& allowedSyntaxes,
+    bool allowNewSopInstanceUid)
+  {
+    if (dicom.getDataset() == NULL)
+    {
+      throw OrthancException(ErrorCode_InternalError);
+    }
+
+    if (!FromDcmtkBridge::LookupOrthancTransferSyntax(sourceSyntax, dicom))
+    {
+      LOG(ERROR) << "Unsupport transfer syntax for transcoding";
+      return false;
+    }
+
+    if (InplaceTranscode(hasSopInstanceUidChanged, dicom, allowedSyntaxes, allowNewSopInstanceUid))
+    {
+      if (FromDcmtkBridge::LookupOrthancTransferSyntax(targetSyntax, dicom) &&
+          allowedSyntaxes.find(targetSyntax) != allowedSyntaxes.end() &&
+          dicom.getDataset() != NULL)
+      {
+        FromDcmtkBridge::SaveToMemoryBuffer(target, *dicom.getDataset());
+        return true;
+      }
+      else
+      {
+        throw OrthancException(ErrorCode_InternalError);
+      }      
+    }
+    else
+    {
+      return false;
+    }    
+  }
+
+
+  IDicomTranscoder::TranscodedDicom* DcmtkTranscoder::TranscodeToParsed2(
+    DcmFileFormat& dicom /* in, possibly modified */,
+    const void* buffer /* in, same DICOM file as "dicom" */,
+    size_t size,
+    const std::set<DicomTransferSyntax>& allowedSyntaxes,
+    bool allowNewSopInstanceUid)
+  {
+    DicomTransferSyntax sourceSyntax;
+    if (!FromDcmtkBridge::LookupOrthancTransferSyntax(sourceSyntax, dicom))
+    {
+      LOG(ERROR) << "Unsupport transfer syntax for transcoding";
+      return NULL;
+    }
+
+    bool hasSopInstanceUidChanged;
+    
+    if (allowedSyntaxes.find(sourceSyntax) != allowedSyntaxes.end())
+    {
+      // No transcoding is needed
+      return TranscodedDicom::CreateFromExternal(dicom, false /* no change in UID */);
+    }
+    else if (InplaceTranscode(hasSopInstanceUidChanged, dicom,
+                              allowedSyntaxes, allowNewSopInstanceUid))
+    {
+      return TranscodedDicom::CreateFromExternal(dicom, hasSopInstanceUidChanged);
+    }
+    else
+    {
+      // Cannot transcode
+      return NULL;
+    }
+  }
 }
--- a/Core/DicomParsing/DcmtkTranscoder.h	Fri May 08 08:27:18 2020 +0200
+++ b/Core/DicomParsing/DcmtkTranscoder.h	Fri May 08 11:16:16 2020 +0200
@@ -88,5 +88,21 @@
                                    bool allowNewSopInstanceUid) ORTHANC_OVERRIDE;
 
     static bool IsSupported(DicomTransferSyntax syntax);
+
+
+    virtual bool TranscodeParsedToBuffer(std::string& target /* out */,
+                                         DicomTransferSyntax& sourceSyntax /* out */,
+                                         DicomTransferSyntax& targetSyntax /* out */,
+                                         bool& hasSopInstanceUidChanged /* out */,
+                                         DcmFileFormat& dicom /* in, possibly modified */,
+                                         const std::set<DicomTransferSyntax>& allowedSyntaxes,
+                                         bool allowNewSopInstanceUid) ORTHANC_OVERRIDE;
+
+    virtual TranscodedDicom* TranscodeToParsed2(
+      DcmFileFormat& dicom /* in, possibly modified */,
+      const void* buffer /* in, same DICOM file as "dicom" */,
+      size_t size,
+      const std::set<DicomTransferSyntax>& allowedSyntaxes,
+      bool allowNewSopInstanceUid) ORTHANC_OVERRIDE;
   };
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Core/DicomParsing/IDicomTranscoder.cpp	Fri May 08 11:16:16 2020 +0200
@@ -0,0 +1,92 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2020 Osimis S.A., Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * In addition, as a special exception, the copyright holders of this
+ * program give permission to link the code of its release with the
+ * OpenSSL project's "OpenSSL" library (or with modified versions of it
+ * that use the same license as the "OpenSSL" library), and distribute
+ * the linked executables. You must obey the GNU General Public License
+ * in all respects for all of the code used other than "OpenSSL". If you
+ * modify file(s) with this exception, you may extend this exception to
+ * your version of the file(s), but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source files
+ * in the program, then also delete it here.
+ * 
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "../PrecompiledHeaders.h"
+#include "IDicomTranscoder.h"
+
+#include "../OrthancException.h"
+
+#include <dcmtk/dcmdata/dcfilefo.h>
+
+namespace Orthanc
+{
+  IDicomTranscoder::TranscodedDicom::TranscodedDicom(bool hasSopInstanceUidChanged) :
+    external_(NULL),
+    hasSopInstanceUidChanged_(hasSopInstanceUidChanged)
+  {
+  }
+  
+
+  IDicomTranscoder::TranscodedDicom*
+  IDicomTranscoder::TranscodedDicom::CreateFromExternal(DcmFileFormat& dicom,
+                                                        bool hasSopInstanceUidChanged)
+  {
+    std::unique_ptr<TranscodedDicom> transcoded(new TranscodedDicom(hasSopInstanceUidChanged));
+    transcoded->external_ = &dicom;
+    return transcoded.release();
+  }        
+
+  
+  IDicomTranscoder::TranscodedDicom*
+  IDicomTranscoder::TranscodedDicom::CreateFromInternal(DcmFileFormat* dicom,
+                                                        bool hasSopInstanceUidChanged)
+  {
+    if (dicom == NULL)
+    {
+      throw OrthancException(ErrorCode_NullPointer);
+    }
+    else
+    {
+      std::unique_ptr<TranscodedDicom> transcoded(new TranscodedDicom(hasSopInstanceUidChanged));
+      transcoded->internal_.reset(dicom);
+      return transcoded.release();
+    }
+  }
+
+  
+  DcmFileFormat& IDicomTranscoder::TranscodedDicom::GetDicom() const
+  {
+    if (internal_.get() != NULL)
+    {
+      return *internal_.get();
+    }
+    else if (external_ != NULL)
+    {
+      return *external_;
+    }
+    else
+    {
+      throw OrthancException(ErrorCode_InternalError);
+    }
+  }
+}
--- a/Core/DicomParsing/IDicomTranscoder.h	Fri May 08 08:27:18 2020 +0200
+++ b/Core/DicomParsing/IDicomTranscoder.h	Fri May 08 11:16:16 2020 +0200
@@ -33,6 +33,7 @@
 
 #pragma once
 
+#include "../Compatibility.h"
 #include "../Enumerations.h"
 
 #include <boost/noncopyable.hpp>
@@ -83,5 +84,51 @@
                                   DcmFileFormat& dicom,
                                   const std::set<DicomTransferSyntax>& allowedSyntaxes,
                                   bool allowNewSopInstanceUid) = 0;
+
+
+
+    virtual bool TranscodeParsedToBuffer(std::string& target /* out */,
+                                         DicomTransferSyntax& sourceSyntax /* out */,
+                                         DicomTransferSyntax& targetSyntax /* out */,
+                                         bool& hasSopInstanceUidChanged /* out */,
+                                         DcmFileFormat& dicom /* in, possibly modified */,
+                                         const std::set<DicomTransferSyntax>& allowedSyntaxes,  // TODO => is a set needed?
+                                         bool allowNewSopInstanceUid) = 0;
+
+
+    class TranscodedDicom : public boost::noncopyable
+    {
+    private:
+      std::unique_ptr<DcmFileFormat>  internal_;
+      DcmFileFormat*                  external_;
+      bool                            hasSopInstanceUidChanged_;
+
+      TranscodedDicom(bool hasSopInstanceUidChanged);
+
+    public:
+      static TranscodedDicom* CreateFromExternal(DcmFileFormat& dicom,
+                                                 bool hasSopInstanceUidChanged);
+        
+      static TranscodedDicom* CreateFromInternal(DcmFileFormat* dicom,
+                                                 bool hasSopInstanceUidChanged);
+
+      // TODO - Is this information used somewhere?
+      bool HasSopInstanceUidChanged() const
+      {
+        return hasSopInstanceUidChanged_;
+      }
+      
+      DcmFileFormat& GetDicom() const;      
+    };
+    
+    /**
+     * This flavor is used by C-STORE.
+     **/
+    virtual TranscodedDicom* TranscodeToParsed2(
+      DcmFileFormat& dicom /* in, possibly modified */,
+      const void* buffer /* in, same DICOM file as "dicom" */,
+      size_t size,
+      const std::set<DicomTransferSyntax>& allowedSyntaxes,
+      bool allowNewSopInstanceUid) = 0;
   };
 }
--- a/Core/DicomParsing/MemoryBufferTranscoder.cpp	Fri May 08 08:27:18 2020 +0200
+++ b/Core/DicomParsing/MemoryBufferTranscoder.cpp	Fri May 08 11:16:16 2020 +0200
@@ -81,7 +81,8 @@
     }
 #endif
 
-    return Transcode(target, hasSopInstanceUidChanged, buffer, size,
+    DicomTransferSyntax sourceSyntax, targetSyntax;
+    return Transcode(target, sourceSyntax, targetSyntax, hasSopInstanceUidChanged, buffer, size,
                      allowedSyntaxes, allowNewSopInstanceUid);
   }
 
@@ -106,7 +107,9 @@
 #endif
 
     std::string transcoded;
-    if (Transcode(transcoded, hasSopInstanceUidChanged, buffer, size, allowedSyntaxes, allowNewSopInstanceUid))
+    DicomTransferSyntax sourceSyntax, targetSyntax;
+    if (Transcode(transcoded, sourceSyntax, targetSyntax, hasSopInstanceUidChanged,
+                  buffer, size, allowedSyntaxes, allowNewSopInstanceUid))
     {
       return FromDcmtkBridge::LoadFromMemoryBuffer(
         transcoded.empty() ? NULL : transcoded.c_str(), transcoded.size());
@@ -176,4 +179,73 @@
       throw OrthancException(ErrorCode_BadSequenceOfCalls);
     }
   }
+
+
+
+  
+  bool MemoryBufferTranscoder::TranscodeParsedToBuffer(
+    std::string& target /* out */,
+    DicomTransferSyntax& sourceSyntax /* out */,
+    DicomTransferSyntax& targetSyntax /* out */,
+    bool& hasSopInstanceUidChanged /* out */,
+    DcmFileFormat& dicom /* in, possibly modified */,
+    const std::set<DicomTransferSyntax>& allowedSyntaxes,
+    bool allowNewSopInstanceUid)
+  {
+    if (dicom.getDataset() == NULL)
+    {
+      throw OrthancException(ErrorCode_InternalError);
+    }
+
+    std::string source;
+    FromDcmtkBridge::SaveToMemoryBuffer(source, *dicom.getDataset());
+
+    const void* data = source.empty() ? NULL : source.c_str();
+
+    bool success = Transcode(target, sourceSyntax, targetSyntax, hasSopInstanceUidChanged,
+                             data, source.size(), allowedSyntaxes, allowNewSopInstanceUid);
+
+#if ORTHANC_ENABLE_DCMTK_TRANSCODING == 1
+    if (useDcmtk_ &&
+        dcmtk_.TranscodeParsedToBuffer(
+          target, sourceSyntax, targetSyntax,hasSopInstanceUidChanged,
+          dicom, allowedSyntaxes, allowNewSopInstanceUid))
+    {
+      success = true;
+    }
+#endif
+
+    return success;
+  }
+  
+
+  IDicomTranscoder::TranscodedDicom* MemoryBufferTranscoder::TranscodeToParsed2(
+    DcmFileFormat& dicom /* in, possibly modified */,
+    const void* buffer /* in, same DICOM file as "dicom" */,
+    size_t size,
+    const std::set<DicomTransferSyntax>& allowedSyntaxes,
+    bool allowNewSopInstanceUid)
+  {
+    DicomTransferSyntax sourceSyntax, targetSyntax;
+    bool hasSopInstanceUidChanged;
+    
+    std::string target;
+    if (Transcode(target, sourceSyntax, targetSyntax, hasSopInstanceUidChanged,
+                  buffer, size, allowedSyntaxes, allowNewSopInstanceUid))
+    {
+      const void* data = target.empty() ? NULL : target.c_str();
+      return IDicomTranscoder::TranscodedDicom::CreateFromInternal(
+        FromDcmtkBridge::LoadFromMemoryBuffer(data, target.size()), hasSopInstanceUidChanged);
+    }
+#if ORTHANC_ENABLE_DCMTK_TRANSCODING == 1
+    else if (useDcmtk_)
+    {
+      return dcmtk_.TranscodeToParsed2(dicom, buffer, size, allowedSyntaxes, allowNewSopInstanceUid);
+    }
+#endif
+    else
+    {
+      return NULL;
+    }
+  }
 }
--- a/Core/DicomParsing/MemoryBufferTranscoder.h	Fri May 08 08:27:18 2020 +0200
+++ b/Core/DicomParsing/MemoryBufferTranscoder.h	Fri May 08 11:16:16 2020 +0200
@@ -55,6 +55,8 @@
 
   protected:
     virtual bool Transcode(std::string& target,
+                           DicomTransferSyntax& sourceSyntax /* out */,
+                           DicomTransferSyntax& targetSyntax /* out */,
                            bool& hasSopInstanceUidChanged /* out */,
                            const void* buffer,
                            size_t size,
@@ -96,5 +98,22 @@
                                   DcmFileFormat& dicom,
                                   const std::set<DicomTransferSyntax>& allowedSyntaxes,
                                   bool allowNewSopInstanceUid) ORTHANC_OVERRIDE;
+
+
+
+    virtual bool TranscodeParsedToBuffer(std::string& target /* out */,
+                                         DicomTransferSyntax& sourceSyntax /* out */,
+                                         DicomTransferSyntax& targetSyntax /* out */,
+                                         bool& hasSopInstanceUidChanged /* out */,
+                                         DcmFileFormat& dicom /* in, possibly modified */,
+                                         const std::set<DicomTransferSyntax>& allowedSyntaxes,
+                                         bool allowNewSopInstanceUid) ORTHANC_OVERRIDE;
+
+    virtual TranscodedDicom* TranscodeToParsed2(
+      DcmFileFormat& dicom /* in, possibly modified */,
+      const void* buffer /* in, same DICOM file as "dicom" */,
+      size_t size,
+      const std::set<DicomTransferSyntax>& allowedSyntaxes,
+      bool allowNewSopInstanceUid) ORTHANC_OVERRIDE;
   };
 }
--- a/OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp	Fri May 08 08:27:18 2020 +0200
+++ b/OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp	Fri May 08 11:16:16 2020 +0200
@@ -134,9 +134,11 @@
       ts.insert(targetSyntax);
 
       std::string transcoded;
+      DicomTransferSyntax sourceSyntax, targetSyntax;
       bool hasSopInstanceUidChanged;
 
-      if (context.Transcode(transcoded, hasSopInstanceUidChanged, *modified, ts, true))
+      if (context.Transcode(transcoded, sourceSyntax, targetSyntax,
+                            hasSopInstanceUidChanged, *modified, ts, true))
       {      
         call.GetOutput().AnswerBuffer(transcoded, MimeType_Dicom);
       }
--- a/OrthancServer/ServerContext.cpp	Fri May 08 08:27:18 2020 +0200
+++ b/OrthancServer/ServerContext.cpp	Fri May 08 11:16:16 2020 +0200
@@ -1155,19 +1155,14 @@
   }
 
 
-  bool ServerContext::Transcode(std::string& target,
-                                bool& hasSopInstanceUidChanged,
+  bool ServerContext::Transcode(std::string& target /* out */,
+                                DicomTransferSyntax& sourceSyntax /* out */,
+                                DicomTransferSyntax& targetSyntax /* out */,
+                                bool& hasSopInstanceUidChanged /* out */,
                                 ParsedDicomFile& dicom, // Possibly modified
                                 const std::set<DicomTransferSyntax>& allowedSyntaxes,
                                 bool allowNewSopInstanceUid)
   {
-    DicomTransferSyntax inputSyntax;
-    if (!FromDcmtkBridge::LookupOrthancTransferSyntax(inputSyntax, dicom.GetDcmtkObject()))
-    {
-      throw OrthancException(ErrorCode_BadFileFormat,
-                             "Cannot determine the source transfer syntax during transcoding");
-    }
-
     IDicomTranscoder* transcoder = dcmtkTranscoder_.get();
     
 #if ORTHANC_ENABLE_PLUGINS == 1
@@ -1181,29 +1176,9 @@
     {
       throw OrthancException(ErrorCode_InternalError);
     }
-    else if (transcoder->HasInplaceTranscode(inputSyntax, allowedSyntaxes))
-    {
-      if (transcoder->InplaceTranscode(hasSopInstanceUidChanged, dicom.GetDcmtkObject(),
-                                       allowedSyntaxes, allowNewSopInstanceUid))
-      {
-        // In-place transcoding is supported and has succeeded
-        dicom.SaveToMemoryBuffer(target);
-        return true;
-      }
-      else
-      {
-        return false;
-      }
-    }
-    else
-    {
-      std::string source;
-      dicom.SaveToMemoryBuffer(source);
-      
-      const char* data = source.empty() ? NULL : source.c_str();
-    
-      return transcoder->TranscodeToBuffer(
-        target, hasSopInstanceUidChanged, data, source.size(), allowedSyntaxes, allowNewSopInstanceUid);
-    }
+
+    return transcoder->TranscodeParsedToBuffer(
+      target, sourceSyntax, targetSyntax, hasSopInstanceUidChanged,
+      dicom.GetDcmtkObject(), allowedSyntaxes, allowNewSopInstanceUid);
   }
 }
--- a/OrthancServer/ServerContext.h	Fri May 08 08:27:18 2020 +0200
+++ b/OrthancServer/ServerContext.h	Fri May 08 11:16:16 2020 +0200
@@ -465,9 +465,11 @@
 
     // This method can be used even if the global option
     // "TranscodingEnabled" is set to "false"
-    bool Transcode(std::string& target,
-                   bool& hasSopInstanceUidChanged,
-                   ParsedDicomFile& dicom, // Can possibly be modified
+    bool Transcode(std::string& target /* out */,
+                   DicomTransferSyntax& sourceSyntax /* out */,
+                   DicomTransferSyntax& targetSyntax /* out */,
+                   bool& hasSopInstanceUidChanged /* out */,
+                   ParsedDicomFile& dicom, // Possibly modified
                    const std::set<DicomTransferSyntax>& allowedSyntaxes,
                    bool allowNewSopInstanceUid);
   };
--- a/Plugins/Engine/OrthancPlugins.cpp	Fri May 08 08:27:18 2020 +0200
+++ b/Plugins/Engine/OrthancPlugins.cpp	Fri May 08 11:16:16 2020 +0200
@@ -4796,6 +4796,8 @@
 
 
   bool OrthancPlugins::Transcode(std::string& target,
+                                 DicomTransferSyntax& sourceSyntax /* out */,
+                                 DicomTransferSyntax& targetSyntax /* out */,
                                  bool& hasSopInstanceUidChanged /* out */,
                                  const void* buffer,
                                  size_t size,
--- a/Plugins/Engine/OrthancPlugins.h	Fri May 08 08:27:18 2020 +0200
+++ b/Plugins/Engine/OrthancPlugins.h	Fri May 08 11:16:16 2020 +0200
@@ -228,6 +228,8 @@
   protected:
     // From "MemoryBufferTranscoder"
     virtual bool Transcode(std::string& target,
+                           DicomTransferSyntax& sourceSyntax /* out */,
+                           DicomTransferSyntax& targetSyntax /* out */,
                            bool& hasSopInstanceUidChanged /* out */,
                            const void* buffer,
                            size_t size,
--- a/Resources/CMake/OrthancFrameworkConfiguration.cmake	Fri May 08 08:27:18 2020 +0200
+++ b/Resources/CMake/OrthancFrameworkConfiguration.cmake	Fri May 08 11:16:16 2020 +0200
@@ -503,6 +503,7 @@
     add_definitions(-DORTHANC_ENABLE_DCMTK_TRANSCODING=1)
     list(APPEND ORTHANC_DICOM_SOURCES_INTERNAL
       ${ORTHANC_ROOT}/Core/DicomParsing/DcmtkTranscoder.cpp
+      ${ORTHANC_ROOT}/Core/DicomParsing/IDicomTranscoder.cpp
       ${ORTHANC_ROOT}/Core/DicomParsing/MemoryBufferTranscoder.cpp
       )
   else()