changeset 6880:2b54c2e520a0 streaming

added ServerContext::ReadTranscodedDicom()
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 01 Jun 2026 13:59:13 +0200
parents a148e4a7970a
children 7f1d9c7f33f0
files OrthancFramework/Sources/DataSource/TranscoderDataSource.cpp OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp OrthancServer/Sources/ServerContext.cpp OrthancServer/Sources/ServerContext.h
diffstat 4 files changed, 44 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancFramework/Sources/DataSource/TranscoderDataSource.cpp	Sun May 31 18:05:15 2026 +0200
+++ b/OrthancFramework/Sources/DataSource/TranscoderDataSource.cpp	Mon Jun 01 13:59:13 2026 +0200
@@ -69,23 +69,33 @@
         throw OrthancException(ErrorCode_NullPointer);
       }
 
-      if (transcoded->HasParsed() &&
+      if (!transcoded->HasParsed() &&
           !transcoded->HasInternalBuffer())
       {
+        throw OrthancException(ErrorCode_InternalError, "No transcoded image is available");
+      }
+
+      /**
+       * Note that both "transcoded->HasParsed()" and
+       * "transcoded->HasInternalBuffer()" could be true in debug
+       * mode, because of "IDicomTranscoder::CheckTranscoding()".
+       **/
+
+      if (transcoded->HasParsed())
+      {
         parsed_.reset(transcoded->ReleaseAsParsedDicomFile());
+      }
 
-        DcmFileFormat& f = parsed_->GetDcmtkObject();
-        size_ = f.calcElementLength(f.getDataset()->getOriginalXfer(), EET_ExplicitLength);
-      }
-      else if (!transcoded->HasParsed() &&
-               transcoded->HasInternalBuffer())
+      if (transcoded->HasInternalBuffer())
       {
         raw_.reset(transcoded->ReleaseInternalBuffer());
-        size_ = raw_->size();
+        size_ = raw_->size();  // This is more accurate than "f.calcElementLength()" below
       }
       else
       {
-        throw OrthancException(ErrorCode_InternalError);
+        assert(parsed_.get() != NULL);
+        DcmFileFormat& f = parsed_->GetDcmtkObject();
+        size_ = f.calcElementLength(f.getDataset()->getOriginalXfer(), EET_ExplicitLength);
       }
     }
 
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp	Sun May 31 18:05:15 2026 +0200
+++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp	Mon Jun 01 13:59:13 2026 +0200
@@ -34,7 +34,6 @@
 #include "../../../OrthancFramework/Sources/DicomParsing/DicomWebJsonVisitor.h"
 #include "../../../OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.h"
 #include "../../../OrthancFramework/Sources/DicomParsing/Internals/DicomImageDecoder.h"
-#include "../../../OrthancFramework/Sources/DicomParsing/TranscodingCallable.h"
 #include "../../../OrthancFramework/Sources/HttpServer/HttpContentNegociation.h"
 #include "../../../OrthancFramework/Sources/Images/Image.h"
 #include "../../../OrthancFramework/Sources/Images/ImageProcessing.h"
@@ -413,6 +412,8 @@
 
     if (call.HasArgument(GET_TRANSCODE))
     {
+      const DicomTransferSyntax transferSyntax = GetTransferSyntax(call.GetArgument(GET_TRANSCODE, ""));
+
       unsigned int lossyQuality;
       unsigned int defaultLossyQuality;
 
@@ -423,23 +424,13 @@
 
       lossyQuality = call.GetUnsignedInteger32Argument(GET_LOSSY_QUALITY, defaultLossyQuality);
 
-      std::unique_ptr<TranscodingCallable> callable(new TranscodingCallable);
-
-      {
-        std::unique_ptr<DicomDataSource::Dicom> dicom(context.ReadParsedDicom(publicId));
-        std::unique_ptr<ParsedDicomFile> clone(dicom->Clone());
-        callable->AcquireParsed(*clone);  // "clone" is invalid below this point
-      }
-
-      callable->AddTransferSyntax(GetTransferSyntax(call.GetArgument(GET_TRANSCODE, "")));
-      callable->SetLossyQuality(lossyQuality);
-
-      std::unique_ptr<Future> future(context.SubmitTranscodingRequest(callable.release()));
-      std::unique_ptr<IDicomTranscoder::DicomImage> transcoded(dynamic_cast<IDicomTranscoder::DicomImage*>(future->ReleaseResult()));
+      std::unique_ptr<TranscoderDataSource::Transcoded> transcoded2(
+        context.ReadTranscodedDicom(publicId, transferSyntax, TranscodingSopInstanceUidMode_AllowNew, true, lossyQuality));
+
+      TranscoderDataSource::Transcoded::LockAsBuffer lock(*transcoded2);
 
       call.GetOutput().SetContentFilename(filename.c_str());
-      call.GetOutput().AnswerBuffer(transcoded->GetBufferData(),
-                                    transcoded->GetBufferSize(), MimeType_Dicom);
+      call.GetOutput().AnswerBuffer(lock.GetContent(), MimeType_Dicom);
     }
     else
     {
--- a/OrthancServer/Sources/ServerContext.cpp	Sun May 31 18:05:15 2026 +0200
+++ b/OrthancServer/Sources/ServerContext.cpp	Mon Jun 01 13:59:13 2026 +0200
@@ -28,7 +28,6 @@
 #include "../../OrthancFramework/Sources/Constants.h"
 #include "../../OrthancFramework/Sources/DataSource/DataSourceReader.h"
 #include "../../OrthancFramework/Sources/DataSource/DicomSequentialReader.h"
-#include "../../OrthancFramework/Sources/DataSource/TranscoderDataSource.h"
 #include "../../OrthancFramework/Sources/DicomFormat/DicomElement.h"
 #include "../../OrthancFramework/Sources/DicomFormat/DicomImageInformation.h"
 #include "../../OrthancFramework/Sources/DicomFormat/DicomStreamReader.h"
@@ -1588,6 +1587,18 @@
   }
 
 
+  TranscoderDataSource::Transcoded* ServerContext::ReadTranscodedDicom(const std::string& instancePublicId,
+                                                                       DicomTransferSyntax targetSyntax,
+                                                                       TranscodingSopInstanceUidMode mode,
+                                                                       bool hasLossyQuality,
+                                                                       unsigned int lossyQuality)
+  {
+    const FileInfo& attachment = LookupDicomForInstance(instancePublicId);
+    return TranscoderDataSource::Execute(*transcoderReader_, TranscoderDataSource::CreateRequest(
+                                           attachment, targetSyntax, mode, hasLossyQuality, lossyQuality));
+  }
+
+
   void ServerContext::SetStoreMD5ForAttachments(bool storeMD5)
   {
     LOG(INFO) << "Storing MD5 for attachments: " << (storeMD5 ? "yes" : "no");
--- a/OrthancServer/Sources/ServerContext.h	Sun May 31 18:05:15 2026 +0200
+++ b/OrthancServer/Sources/ServerContext.h	Mon Jun 01 13:59:13 2026 +0200
@@ -32,6 +32,7 @@
 #include "../../OrthancFramework/Sources/DataSource/DicomDataSource.h"
 #include "../../OrthancFramework/Sources/DataSource/DicomSequentialReader.h"
 #include "../../OrthancFramework/Sources/DataSource/StorageAreaDataSource.h"
+#include "../../OrthancFramework/Sources/DataSource/TranscoderDataSource.h"
 #include "../../OrthancFramework/Sources/DicomParsing/DicomModification.h"
 #include "../../OrthancFramework/Sources/JobsEngine/JobsEngine.h"
 #include "../../OrthancFramework/Sources/MetricsRegistry.h"
@@ -399,6 +400,12 @@
 
     DicomDataSource::Dicom* ReadDicomUntilPixelData(const std::string& instancePublicId);
 
+    TranscoderDataSource::Transcoded* ReadTranscodedDicom(const std::string& instancePublicId,
+                                                          DicomTransferSyntax targetSyntax,
+                                                          TranscodingSopInstanceUidMode mode,
+                                                          bool hasLossyQuality,
+                                                          unsigned int lossyQuality);
+
     void SetStoreMD5ForAttachments(bool storeMD5);
 
     bool IsStoreMD5ForAttachments() const