changeset 6482:8f511144bd9f pixel-anon

reverted ServerContext::Modify()
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 25 Nov 2025 14:03:32 +0100
parents a9abcdac2eee
children 42ef092375fd
files OrthancServer/Sources/OrthancRestApi/OrthancRestAnonymizeModify.cpp OrthancServer/Sources/ServerContext.cpp OrthancServer/Sources/ServerContext.h OrthancServer/Sources/ServerJobs/Operations/ModifyInstanceOperation.cpp OrthancServer/Sources/ServerJobs/ResourceModificationJob.cpp
diffstat 5 files changed, 61 insertions(+), 105 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestAnonymizeModify.cpp	Tue Nov 25 13:54:52 2025 +0100
+++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestAnonymizeModify.cpp	Tue Nov 25 14:03:32 2025 +0100
@@ -219,9 +219,35 @@
       ServerContext::DicomCacheLocker locker(context, id);
       modified.reset(locker.GetDicom().Clone(true));
     }
-  
-    context.Modify(modified, modification, transcode, targetSyntax, lossyQuality, false /* keepSOPInstanceUidDuringLossyTranscoding*/);
-    modified->Answer(call.GetOutput());
+    
+    modification.Apply(modified);
+
+    if (transcode)
+    {
+      IDicomTranscoder::DicomImage source;
+      source.AcquireParsed(*modified);  // "modified" is invalid below this point
+      
+      IDicomTranscoder::DicomImage transcoded;
+
+      std::set<DicomTransferSyntax> s;
+      s.insert(targetSyntax);
+      
+      if (context.Transcode(transcoded, source, s, TranscodingSopInstanceUidMode_AllowNew, lossyQuality))
+      {      
+        call.GetOutput().AnswerBuffer(transcoded.GetBufferData(),
+                                      transcoded.GetBufferSize(), MimeType_Dicom);
+      }
+      else
+      {
+        throw OrthancException(ErrorCode_InternalError,
+                               "Cannot transcode to transfer syntax: " +
+                               std::string(GetTransferSyntaxUid(targetSyntax)));
+      }
+    }
+    else
+    {
+      modified->Answer(call.GetOutput());
+    }
   }
 
 
--- a/OrthancServer/Sources/ServerContext.cpp	Tue Nov 25 13:54:52 2025 +0100
+++ b/OrthancServer/Sources/ServerContext.cpp	Tue Nov 25 14:03:32 2025 +0100
@@ -2086,99 +2086,6 @@
     }
   }
 
-  void ServerContext::Modify(std::unique_ptr<ParsedDicomFile>& dicomFile, 
-                             DicomModification& modification,
-                             bool transcode,
-                             DicomTransferSyntax targetSyntax,
-                             unsigned int lossyQuality,
-                             bool keepSOPInstanceUidDuringLossyTranscoding)
-  {
-    const std::string originalSopInstanceUid = IDicomTranscoder::GetSopInstanceUid(dicomFile->GetDcmtkObject());  
-    std::string forceModifiedSopInstanceUid;
-
-    // do we need to transcode before applying e.g custom pixels modifications ?
-    DicomTransferSyntax currentTransferSyntax;
-    if (// modification.RequiresUncompressedTransferSyntax() &&   // TODO-PIXEL-ANON
-        dicomFile->LookupTransferSyntax(currentTransferSyntax) &&
-        !IsRawTransferSyntax(currentTransferSyntax))
-    {
-      IDicomTranscoder::DicomImage source;
-      source.AcquireParsed(*dicomFile);  // "dicomFile" is invalid below this point
-
-      IDicomTranscoder::DicomImage transcoded;
-
-      std::set<DicomTransferSyntax> uncompressedTransferSyntax;
-      uncompressedTransferSyntax.insert(DicomTransferSyntax_LittleEndianExplicit);
-      Transcode(transcoded, source, uncompressedTransferSyntax, TranscodingSopInstanceUidMode_AllowNew);
-
-      dicomFile.reset(transcoded.ReleaseAsParsedDicomFile());
-
-      if (IsLossyTransferSyntax(currentTransferSyntax))
-      {
-        // TODO-PIXEL-ANON:  Test this path with IngestTranscoding = lossy syntax
-        // TODO-PIXEL-ANON:  + Test with source = lossy + modification requires a transcoding to a raw TS -> the transcoding shall not be performed after pixel modification since it is already being done now but the SOPInstance UID must be changed afterwards
-        
-        // this means we have moved from lossy to raw -> the SOPInstanceUID should have changed here but, 
-        // let's keep the SOPInstanceUID unchanged during this pre-transcoding to make sure the orthanc ids are 
-        // still the original ones when the pixelMasker is applied (since the pixelMasker has a filter on Orthanc ids).
-        // however, after the modification, we must make sure that we change the SOPInstanceUID.
-        if (dicomFile.get() && dicomFile->GetDcmtkObject().getDataset())
-        {
-          const char* sopInstanceUid;
-          if (dicomFile->GetDcmtkObject().getDataset()->findAndGetString(DCM_SOPInstanceUID, sopInstanceUid, OFFalse).good())
-          {
-            forceModifiedSopInstanceUid = sopInstanceUid;
-            dicomFile->GetDcmtkObject().getDataset()->putAndInsertString(DCM_SOPInstanceUID, originalSopInstanceUid.c_str(), OFTrue /* replace */);
-          }
-        }
-      }
-
-      if (!transcode) // if we had to change the TS for the modification, we will need to restore the original TS afterwards
-      {
-        transcode = true;
-        targetSyntax = currentTransferSyntax;
-      }
-    }
-
-    modification.Apply(dicomFile);
-
-    if (transcode)
-    {
-      const std::string modifiedUid = IDicomTranscoder::GetSopInstanceUid(dicomFile->GetDcmtkObject());
-
-      IDicomTranscoder::DicomImage source;
-      source.AcquireParsed(*dicomFile);  // "dicomFile" is invalid below this point
-      
-      IDicomTranscoder::DicomImage transcoded;
-
-      std::set<DicomTransferSyntax> s;
-      s.insert(targetSyntax);
-
-      TranscodingSopInstanceUidMode mode;
-      if (keepSOPInstanceUidDuringLossyTranscoding)
-      {
-        mode = TranscodingSopInstanceUidMode_Preserve;
-      }
-      else
-      {
-        mode = TranscodingSopInstanceUidMode_AllowNew;
-      }
-
-      if (Transcode(transcoded, source, s, mode, lossyQuality))
-      {
-        dicomFile.reset(transcoded.ReleaseAsParsedDicomFile());
-      }
-      else
-      {
-        throw OrthancException(ErrorCode_InternalError,
-                               "Cannot transcode to transfer syntax " +
-                               std::string(GetTransferSyntaxUid(targetSyntax)));
-      }
-    }
-    // TODO-PIXEL-ANON: set forceModifiedSopInstanceUid if required
-  }
-
-
 
   const std::string& ServerContext::GetDeidentifiedContent(const DicomElement &element) const
   {
--- a/OrthancServer/Sources/ServerContext.h	Tue Nov 25 13:54:52 2025 +0100
+++ b/OrthancServer/Sources/ServerContext.h	Tue Nov 25 14:03:32 2025 +0100
@@ -604,13 +604,6 @@
                                     const std::string& attachmentId, // for the storage cache
                                     DicomTransferSyntax targetSyntax);
 
-    void Modify(std::unique_ptr<ParsedDicomFile>& toModify, 
-                DicomModification& modification,
-                bool transcode,
-                DicomTransferSyntax targetSyntax,
-                unsigned int lossyQuality,
-                bool keepSOPInstanceUidDuringLossyTranscoding);
-
     bool IsTranscodeDicomProtocol() const
     {
       return transcodeDicomProtocol_;
--- a/OrthancServer/Sources/ServerJobs/Operations/ModifyInstanceOperation.cpp	Tue Nov 25 13:54:52 2025 +0100
+++ b/OrthancServer/Sources/ServerJobs/Operations/ModifyInstanceOperation.cpp	Tue Nov 25 14:03:32 2025 +0100
@@ -92,7 +92,7 @@
 
     try
     {
-      context_.Modify(modified, *modification_, false, DicomTransferSyntax_LittleEndianExplicit /* not used */, 100 /* not used */, false /*keepSOPInstanceUidDuringLossyTranscoding*/);
+      modification_->Apply(modified);
 
       std::unique_ptr<DicomInstanceToStore> toStore(DicomInstanceToStore::CreateFromParsedDicomFile(*modified));
       assert(origin_ == RequestOrigin_Lua);
--- a/OrthancServer/Sources/ServerJobs/ResourceModificationJob.cpp	Tue Nov 25 13:54:52 2025 +0100
+++ b/OrthancServer/Sources/ServerJobs/ResourceModificationJob.cpp	Tue Nov 25 14:03:32 2025 +0100
@@ -238,7 +238,7 @@
     {
       boost::recursive_mutex::scoped_lock lock(mutex_);  // DicomModification object is not thread safe, we must protect it from here
 
-      GetContext().Modify(modified, *modification_, transcode_, transferSyntax_, 100 /* not used */, true /* keepSOPInstanceUidDuringLossyTranscoding*/);  // TODO-PIXEL-ANON: get lossy quality from ???
+      modification_->Apply(modified);
 
       if (modification_->AreLabelsKept())
       {
@@ -252,6 +252,36 @@
 
     const std::string modifiedUid = IDicomTranscoder::GetSopInstanceUid(modified->GetDcmtkObject());
     
+    if (transcode_)
+    {
+      std::set<DicomTransferSyntax> syntaxes;
+      syntaxes.insert(transferSyntax_);
+
+      IDicomTranscoder::DicomImage source;
+      source.AcquireParsed(*modified);  // "modified" is invalid below this point
+      
+      IDicomTranscoder::DicomImage transcoded;
+      if (GetContext().Transcode(transcoded, source, syntaxes, TranscodingSopInstanceUidMode_AllowNew))
+      {
+        modified.reset(transcoded.ReleaseAsParsedDicomFile());
+
+        // Fix the SOP instance UID in order the preserve the
+        // references between instance UIDs in the DICOM hierarchy
+        // (the UID might have changed in the case of lossy transcoding)
+        if (modified.get() == NULL ||
+            modified->GetDcmtkObject().getDataset() == NULL ||
+            !modified->GetDcmtkObject().getDataset()->putAndInsertString(
+              DCM_SOPInstanceUID, modifiedUid.c_str(), OFTrue /* replace */).good())
+        {
+          throw OrthancException(ErrorCode_InternalError);
+        }
+      }
+      else
+      {
+        LOG(WARNING) << "Cannot transcode instance, keeping original transfer syntax: " << instance;
+        modified.reset(source.ReleaseAsParsedDicomFile());
+      }
+    }
 
     assert(modifiedUid == IDicomTranscoder::GetSopInstanceUid(modified->GetDcmtkObject()));