# HG changeset patch # User Sebastien Jodogne # Date 1764075812 -3600 # Node ID 8f511144bd9f93b285726cede080237b71fcdeae # Parent a9abcdac2eee38cc85cc31b127f4b75618d57231 reverted ServerContext::Modify() diff -r a9abcdac2eee -r 8f511144bd9f OrthancServer/Sources/OrthancRestApi/OrthancRestAnonymizeModify.cpp --- 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 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()); + } } diff -r a9abcdac2eee -r 8f511144bd9f OrthancServer/Sources/ServerContext.cpp --- 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& 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 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 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 { diff -r a9abcdac2eee -r 8f511144bd9f OrthancServer/Sources/ServerContext.h --- 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& toModify, - DicomModification& modification, - bool transcode, - DicomTransferSyntax targetSyntax, - unsigned int lossyQuality, - bool keepSOPInstanceUidDuringLossyTranscoding); - bool IsTranscodeDicomProtocol() const { return transcodeDicomProtocol_; diff -r a9abcdac2eee -r 8f511144bd9f OrthancServer/Sources/ServerJobs/Operations/ModifyInstanceOperation.cpp --- 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 toStore(DicomInstanceToStore::CreateFromParsedDicomFile(*modified)); assert(origin_ == RequestOrigin_Lua); diff -r a9abcdac2eee -r 8f511144bd9f OrthancServer/Sources/ServerJobs/ResourceModificationJob.cpp --- 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 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()));