diff OrthancServer/ServerJobs/ArchiveJob.cpp @ 3913:6ddad3e0b569 transcoding

transcoding ZIP archive and media
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 08 May 2020 19:15:28 +0200
parents 56f2397f027a
children b99acc213937
line wrap: on
line diff
--- a/OrthancServer/ServerJobs/ArchiveJob.cpp	Fri May 08 13:43:50 2020 +0200
+++ b/OrthancServer/ServerJobs/ArchiveJob.cpp	Fri May 08 19:15:28 2020 +0200
@@ -37,6 +37,7 @@
 #include "../../Core/Cache/SharedArchive.h"
 #include "../../Core/Compression/HierarchicalZipWriter.h"
 #include "../../Core/DicomParsing/DicomDirWriter.h"
+#include "../../Core/DicomParsing/FromDcmtkBridge.h"
 #include "../../Core/Logging.h"
 #include "../../Core/OrthancException.h"
 #include "../OrthancConfiguration.h"
@@ -55,6 +56,7 @@
 static const char* const KEY_DESCRIPTION = "Description";
 static const char* const KEY_INSTANCES_COUNT = "InstancesCount";
 static const char* const KEY_UNCOMPRESSED_SIZE_MB = "UncompressedSizeMB";
+static const char* const KEY_TRANSCODE = "Transcode";
 
 
 namespace Orthanc
@@ -399,7 +401,9 @@
       void Apply(HierarchicalZipWriter& writer,
                  ServerContext& context,
                  DicomDirWriter* dicomDir,
-                 const std::string& dicomDirFolder) const
+                 const std::string& dicomDirFolder,
+                 bool transcode,
+                 DicomTransferSyntax transferSyntax) const
       {
         switch (type_)
         {
@@ -426,14 +430,65 @@
             }
 
             //boost::this_thread::sleep(boost::posix_time::milliseconds(300));
-            
+
             writer.OpenFile(filename_.c_str());
-            writer.Write(content);
+
+            bool transcodeSuccess = false;
+
+            std::unique_ptr<ParsedDicomFile> parsed;
+            
+            if (transcode)
+            {
+              // New in Orthanc 1.7.0
+              std::set<DicomTransferSyntax> syntaxes;
+              syntaxes.insert(transferSyntax);
+              
+              parsed.reset(new ParsedDicomFile(content));
+              const char* data = content.empty() ? NULL : content.c_str();
+              
+              std::unique_ptr<IDicomTranscoder::TranscodedDicom> transcodedDicom(
+                context.GetTranscoder().TranscodeToParsed(
+                  parsed->GetDcmtkObject(), data, content.size(),
+                  syntaxes, true /* allow new SOP instance UID */));
+
+              if (transcodedDicom.get() != NULL &&
+                  transcodedDicom->GetDicom().getDataset() != NULL)
+              {
+                std::string transcoded;
+                FromDcmtkBridge::SaveToMemoryBuffer(
+                  transcoded, *transcodedDicom->GetDicom().getDataset());
+              
+                writer.Write(transcoded);
 
-            if (dicomDir != NULL)
+                if (dicomDir != NULL)
+                {
+                  std::unique_ptr<ParsedDicomFile> tmp(
+                    ParsedDicomFile::AcquireDcmtkObject(transcodedDicom->ReleaseDicom()));
+                  dicomDir->Add(dicomDirFolder, filename_, *tmp);
+                }
+                
+                transcodeSuccess = true;
+              }
+              else
+              {
+                LOG(INFO) << "Cannot transcode instance " << instanceId_
+                          << " to transfer syntax: " << GetTransferSyntaxUid(transferSyntax);
+              }
+            }
+
+            if (!transcodeSuccess)
             {
-              ParsedDicomFile parsed(content);
-              dicomDir->Add(dicomDirFolder, filename_, parsed);
+              writer.Write(content);
+
+              if (dicomDir != NULL)
+              {
+                if (parsed.get() == NULL)
+                {
+                  parsed.reset(new ParsedDicomFile(content));
+                }
+
+                dicomDir->Add(dicomDirFolder, filename_, *parsed);
+              }
             }
               
             break;
@@ -454,14 +509,16 @@
                        ServerContext& context,
                        size_t index,
                        DicomDirWriter* dicomDir,
-                       const std::string& dicomDirFolder) const
+                       const std::string& dicomDirFolder,
+                       bool transcode,
+                       DicomTransferSyntax transferSyntax) const
     {
       if (index >= commands_.size())
       {
         throw OrthancException(ErrorCode_ParameterOutOfRange);
       }
 
-      commands_[index]->Apply(writer, context, dicomDir, dicomDirFolder);
+      commands_[index]->Apply(writer, context, dicomDir, dicomDirFolder, transcode, transferSyntax);
     }
       
   public:
@@ -496,20 +553,26 @@
       return uncompressedSize_;
     }
 
+    // "media" flavor (with DICOMDIR)
     void Apply(HierarchicalZipWriter& writer,
                ServerContext& context,
                size_t index,
                DicomDirWriter& dicomDir,
-               const std::string& dicomDirFolder) const
+               const std::string& dicomDirFolder,
+               bool transcode,
+               DicomTransferSyntax transferSyntax) const
     {
-      ApplyInternal(writer, context, index, &dicomDir, dicomDirFolder);
+      ApplyInternal(writer, context, index, &dicomDir, dicomDirFolder, transcode, transferSyntax);
     }
 
+    // "archive" flavor (without DICOMDIR)
     void Apply(HierarchicalZipWriter& writer,
                ServerContext& context,
-               size_t index) const
+               size_t index,
+               bool transcode,
+               DicomTransferSyntax transferSyntax) const
     {
-      ApplyInternal(writer, context, index, NULL, "");
+      ApplyInternal(writer, context, index, NULL, "", transcode, transferSyntax);
     }
       
     void AddOpenDirectory(const std::string& filename)
@@ -740,7 +803,9 @@
       return commands_.GetSize() + 1;
     }
 
-    void RunStep(size_t index)
+    void RunStep(size_t index,
+                 bool transcode,
+                 DicomTransferSyntax transferSyntax)
     {
       if (index > commands_.GetSize())
       {
@@ -764,12 +829,13 @@
         if (isMedia_)
         {
           assert(dicomDir_.get() != NULL);
-          commands_.Apply(*zip_, context_, index, *dicomDir_, MEDIA_IMAGES_FOLDER);
+          commands_.Apply(*zip_, context_, index, *dicomDir_,
+                          MEDIA_IMAGES_FOLDER, transcode, transferSyntax);
         }
         else
         {
           assert(dicomDir_.get() == NULL);
-          commands_.Apply(*zip_, context_, index);
+          commands_.Apply(*zip_, context_, index, transcode, transferSyntax);
         }
       }
     }
@@ -795,7 +861,9 @@
     enableExtendedSopClass_(enableExtendedSopClass),
     currentStep_(0),
     instancesCount_(0),
-    uncompressedSize_(0)
+    uncompressedSize_(0),
+    transcode_(false),
+    transferSyntax_(DicomTransferSyntax_LittleEndianImplicit)
   {
   }
 
@@ -854,6 +922,20 @@
     }
   }
 
+
+  void ArchiveJob::SetTranscode(DicomTransferSyntax transferSyntax)
+  {
+    if (writer_.get() != NULL)   // Already started
+    {
+      throw OrthancException(ErrorCode_BadSequenceOfCalls);
+    }
+    else
+    {
+      transcode_ = true;
+      transferSyntax_ = transferSyntax;
+    }
+  }
+
   
   void ArchiveJob::Reset()
   {
@@ -954,7 +1036,7 @@
     }
     else
     {
-      writer_->RunStep(currentStep_);
+      writer_->RunStep(currentStep_, transcode_, transferSyntax_);
 
       currentStep_ ++;
 
@@ -1006,6 +1088,11 @@
     value[KEY_INSTANCES_COUNT] = instancesCount_;
     value[KEY_UNCOMPRESSED_SIZE_MB] =
       static_cast<unsigned int>(uncompressedSize_ / MEGA_BYTES);
+
+    if (transcode_)
+    {
+      value[KEY_TRANSCODE] = GetTransferSyntaxUid(transferSyntax_);
+    }
   }