Mercurial > hg > orthanc
changeset 6039:4742b4fe824b pixel-anon
pixel-anon: multiple frames
author | Alain Mazy <am@orthanc.team> |
---|---|
date | Wed, 12 Mar 2025 09:59:38 +0100 |
parents | ee903fefedbf |
children | 100a0371fc85 |
files | .hgignore OrthancFramework/Resources/CodeGeneration/DicomTransferSyntaxes.json OrthancFramework/Resources/CodeGeneration/GenerateTransferSyntaxesEnumerations.mustache OrthancFramework/Sources/DicomParsing/DicomPixelMasker.cpp OrthancFramework/Sources/Enumerations.h OrthancFramework/Sources/Enumerations_TransferSyntaxes.impl.h OrthancServer/Sources/ServerContext.cpp TODO |
diffstat | 8 files changed, 457 insertions(+), 55 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Tue Mar 11 10:47:31 2025 +0100 +++ b/.hgignore Wed Mar 12 09:59:38 2025 +0100 @@ -8,6 +8,7 @@ *~ *.cmake.orig .idea/ +OrthancFramework/Resources/CodeGeneration/.venv/ # when opening Orthanc in VSCode, it might find a java project and create files we wan't to ignore: .settings/
--- a/OrthancFramework/Resources/CodeGeneration/DicomTransferSyntaxes.json Tue Mar 11 10:47:31 2025 +0100 +++ b/OrthancFramework/Resources/CodeGeneration/DicomTransferSyntaxes.json Wed Mar 12 09:59:38 2025 +0100 @@ -5,7 +5,8 @@ "Value" : "LittleEndianImplicit", "Retired" : false, "DCMTK" : "EXS_LittleEndianImplicit", - "GDCM" : "gdcm::TransferSyntax::ImplicitVRLittleEndian" + "GDCM" : "gdcm::TransferSyntax::ImplicitVRLittleEndian", + "Raw": true, "Lossless": true }, { @@ -14,7 +15,8 @@ "Value" : "LittleEndianExplicit", "Retired" : false, "DCMTK" : "EXS_LittleEndianExplicit", - "GDCM" : "gdcm::TransferSyntax::ExplicitVRLittleEndian" + "GDCM" : "gdcm::TransferSyntax::ExplicitVRLittleEndian", + "Raw": true, "Lossless": true }, { @@ -22,7 +24,8 @@ "Name" : "Deflated Explicit VR Little Endian", "Value" : "DeflatedLittleEndianExplicit", "Retired" : false, - "DCMTK" : "EXS_DeflatedLittleEndianExplicit" + "DCMTK" : "EXS_DeflatedLittleEndianExplicit", + "Raw": false, "Lossless": true }, { @@ -30,7 +33,8 @@ "Name" : "Explicit VR Big Endian", "Value" : "BigEndianExplicit", "Retired" : false, - "DCMTK" : "EXS_BigEndianExplicit" + "DCMTK" : "EXS_BigEndianExplicit", + "Raw": true, "Lossless": true }, { @@ -41,7 +45,8 @@ "Note" : "Default Transfer Syntax for Lossy JPEG 8-bit Image Compression", "DCMTK" : "EXS_JPEGProcess1", "DCMTK360" : "EXS_JPEGProcess1TransferSyntax", - "GDCM" : "gdcm::TransferSyntax::JPEGBaselineProcess1" + "GDCM" : "gdcm::TransferSyntax::JPEGBaselineProcess1", + "Raw": false, "Lossless": false }, { @@ -52,7 +57,8 @@ "Note" : "Default Transfer Syntax for Lossy JPEG (lossy, 8/12 bit), 12-bit Image Compression (Process 4 only)", "DCMTK" : "EXS_JPEGProcess2_4", "DCMTK360" : "EXS_JPEGProcess2_4TransferSyntax", - "GDCM" : "gdcm::TransferSyntax::JPEGExtendedProcess2_4" + "GDCM" : "gdcm::TransferSyntax::JPEGExtendedProcess2_4", + "Raw": false, "Lossless": false }, { @@ -61,7 +67,8 @@ "Value" : "JPEGProcess3_5", "Retired" : true, "DCMTK" : "EXS_JPEGProcess3_5", - "DCMTK360" : "EXS_JPEGProcess3_5TransferSyntax" + "DCMTK360" : "EXS_JPEGProcess3_5TransferSyntax", + "Raw": false, "Lossless": false }, { @@ -70,7 +77,8 @@ "Value" : "JPEGProcess6_8", "Retired" : true, "DCMTK" : "EXS_JPEGProcess6_8", - "DCMTK360" : "EXS_JPEGProcess6_8TransferSyntax" + "DCMTK360" : "EXS_JPEGProcess6_8TransferSyntax", + "Raw": false, "Lossless": false }, { @@ -79,7 +87,8 @@ "Value" : "JPEGProcess7_9", "Retired" : true, "DCMTK" : "EXS_JPEGProcess7_9", - "DCMTK360" : "EXS_JPEGProcess7_9TransferSyntax" + "DCMTK360" : "EXS_JPEGProcess7_9TransferSyntax", + "Raw": false, "Lossless": false }, { @@ -88,7 +97,8 @@ "Value" : "JPEGProcess10_12", "Retired" : true, "DCMTK" : "EXS_JPEGProcess10_12", - "DCMTK360" : "EXS_JPEGProcess10_12TransferSyntax" + "DCMTK360" : "EXS_JPEGProcess10_12TransferSyntax", + "Raw": false, "Lossless": false }, { @@ -97,7 +107,8 @@ "Value" : "JPEGProcess11_13", "Retired" : true, "DCMTK" : "EXS_JPEGProcess11_13", - "DCMTK360" : "EXS_JPEGProcess11_13TransferSyntax" + "DCMTK360" : "EXS_JPEGProcess11_13TransferSyntax", + "Raw": false, "Lossless": false }, { @@ -107,7 +118,8 @@ "Retired" : false, "DCMTK" : "EXS_JPEGProcess14", "DCMTK360" : "EXS_JPEGProcess14TransferSyntax", - "GDCM" : "gdcm::TransferSyntax::JPEGLosslessProcess14" + "GDCM" : "gdcm::TransferSyntax::JPEGLosslessProcess14", + "Raw": false, "Lossless": true }, { @@ -116,7 +128,8 @@ "Value" : "JPEGProcess15", "Retired" : true, "DCMTK" : "EXS_JPEGProcess15", - "DCMTK360" : "EXS_JPEGProcess15TransferSyntax" + "DCMTK360" : "EXS_JPEGProcess15TransferSyntax", + "Raw": false, "Lossless": true }, { @@ -125,7 +138,8 @@ "Value" : "JPEGProcess16_18", "Retired" : true, "DCMTK" : "EXS_JPEGProcess16_18", - "DCMTK360" : "EXS_JPEGProcess16_18TransferSyntax" + "DCMTK360" : "EXS_JPEGProcess16_18TransferSyntax", + "Raw": false, "Lossless": false }, { @@ -134,7 +148,8 @@ "Value" : "JPEGProcess17_19", "Retired" : true, "DCMTK" : "EXS_JPEGProcess17_19", - "DCMTK360" : "EXS_JPEGProcess17_19TransferSyntax" + "DCMTK360" : "EXS_JPEGProcess17_19TransferSyntax", + "Raw": false, "Lossless": false }, { @@ -143,7 +158,8 @@ "Value" : "JPEGProcess20_22", "Retired" : true, "DCMTK" : "EXS_JPEGProcess20_22", - "DCMTK360" : "EXS_JPEGProcess20_22TransferSyntax" + "DCMTK360" : "EXS_JPEGProcess20_22TransferSyntax", + "Raw": false, "Lossless": false }, { @@ -152,7 +168,8 @@ "Value" : "JPEGProcess21_23", "Retired" : true, "DCMTK" : "EXS_JPEGProcess21_23", - "DCMTK360" : "EXS_JPEGProcess21_23TransferSyntax" + "DCMTK360" : "EXS_JPEGProcess21_23TransferSyntax", + "Raw": false, "Lossless": false }, { @@ -161,7 +178,8 @@ "Value" : "JPEGProcess24_26", "Retired" : true, "DCMTK" : "EXS_JPEGProcess24_26", - "DCMTK360" : "EXS_JPEGProcess24_26TransferSyntax" + "DCMTK360" : "EXS_JPEGProcess24_26TransferSyntax", + "Raw": false, "Lossless": false }, { @@ -170,7 +188,8 @@ "Value" : "JPEGProcess25_27", "Retired" : true, "DCMTK" : "EXS_JPEGProcess25_27", - "DCMTK360" : "EXS_JPEGProcess25_27TransferSyntax" + "DCMTK360" : "EXS_JPEGProcess25_27TransferSyntax", + "Raw": false, "Lossless": false }, { @@ -179,7 +198,8 @@ "Value" : "JPEGProcess28", "Retired" : true, "DCMTK" : "EXS_JPEGProcess28", - "DCMTK360" : "EXS_JPEGProcess28TransferSyntax" + "DCMTK360" : "EXS_JPEGProcess28TransferSyntax", + "Raw": false, "Lossless": true }, { @@ -188,7 +208,8 @@ "Value" : "JPEGProcess29", "Retired" : true, "DCMTK" : "EXS_JPEGProcess29", - "DCMTK360" : "EXS_JPEGProcess29TransferSyntax" + "DCMTK360" : "EXS_JPEGProcess29TransferSyntax", + "Raw": false, "Lossless": true }, { @@ -199,7 +220,8 @@ "Note" : "Default Transfer Syntax for Lossless JPEG Image Compression", "DCMTK" : "EXS_JPEGProcess14SV1", "DCMTK360" : "EXS_JPEGProcess14SV1TransferSyntax", - "GDCM" : "gdcm::TransferSyntax::JPEGLosslessProcess14_1" + "GDCM" : "gdcm::TransferSyntax::JPEGLosslessProcess14_1", + "Raw": false, "Lossless": true }, { @@ -208,7 +230,8 @@ "Value" : "JPEGLSLossless", "Retired" : false, "DCMTK" : "EXS_JPEGLSLossless", - "GDCM" : "gdcm::TransferSyntax::JPEGLSLossless" + "GDCM" : "gdcm::TransferSyntax::JPEGLSLossless", + "Raw": false, "Lossless": true }, { @@ -217,7 +240,8 @@ "Value" : "JPEGLSLossy", "Retired" : false, "DCMTK" : "EXS_JPEGLSLossy", - "GDCM" : "gdcm::TransferSyntax::JPEGLSNearLossless" + "GDCM" : "gdcm::TransferSyntax::JPEGLSNearLossless", + "Raw": false, "Lossless": false }, { @@ -226,7 +250,8 @@ "Value" : "JPEG2000LosslessOnly", "Retired" : false, "DCMTK" : "EXS_JPEG2000LosslessOnly", - "GDCM" : "gdcm::TransferSyntax::JPEG2000Lossless" + "GDCM" : "gdcm::TransferSyntax::JPEG2000Lossless", + "Raw": false, "Lossless": true }, { @@ -235,7 +260,8 @@ "Value" : "JPEG2000", "Retired" : false, "DCMTK" : "EXS_JPEG2000", - "GDCM" : "gdcm::TransferSyntax::JPEG2000" + "GDCM" : "gdcm::TransferSyntax::JPEG2000", + "Raw": false, "Lossless": false }, { @@ -244,7 +270,8 @@ "Value" : "JPEG2000MulticomponentLosslessOnly", "Retired" : false, "DCMTK" : "EXS_JPEG2000MulticomponentLosslessOnly", - "GDCM" : "gdcm::TransferSyntax::JPEG2000Part2Lossless" + "GDCM" : "gdcm::TransferSyntax::JPEG2000Part2Lossless", + "Raw": false, "Lossless": true }, { @@ -253,7 +280,8 @@ "Value" : "JPEG2000Multicomponent", "Retired" : false, "DCMTK" : "EXS_JPEG2000Multicomponent", - "GDCM" : "gdcm::TransferSyntax::JPEG2000Part2" + "GDCM" : "gdcm::TransferSyntax::JPEG2000Part2", + "Raw": false, "Lossless": false }, { @@ -261,7 +289,8 @@ "Name" : "JPIP Referenced", "Value" : "JPIPReferenced", "Retired" : false, - "DCMTK" : "EXS_JPIPReferenced" + "DCMTK" : "EXS_JPIPReferenced", + "Raw": false, "Lossless": true }, { @@ -269,7 +298,8 @@ "Name" : "JPIP Referenced Deflate", "Value" : "JPIPReferencedDeflate", "Retired" : false, - "DCMTK" : "EXS_JPIPReferencedDeflate" + "DCMTK" : "EXS_JPIPReferencedDeflate", + "Raw": false, "Lossless": true }, { @@ -277,7 +307,8 @@ "Name" : "MPEG2 Main Profile / Main Level", "Value" : "MPEG2MainProfileAtMainLevel", "Retired" : false, - "DCMTK" : "EXS_MPEG2MainProfileAtMainLevel" + "DCMTK" : "EXS_MPEG2MainProfileAtMainLevel", + "Raw": false, "Lossless": false }, { @@ -285,7 +316,8 @@ "Name" : "MPEG2 Main Profile / High Level", "Value" : "MPEG2MainProfileAtHighLevel", "Retired" : false, - "DCMTK" : "EXS_MPEG2MainProfileAtHighLevel" + "DCMTK" : "EXS_MPEG2MainProfileAtHighLevel", + "Raw": false, "Lossless": false }, { @@ -294,7 +326,8 @@ "Value" : "MPEG4HighProfileLevel4_1", "Retired" : false, "DCMTK" : "EXS_MPEG4HighProfileLevel4_1", - "SinceDCMTK" : "361" + "SinceDCMTK" : "361", + "Raw": false, "Lossless": false }, { @@ -303,7 +336,8 @@ "Value" : "MPEG4BDcompatibleHighProfileLevel4_1", "Retired" : false, "DCMTK" : "EXS_MPEG4BDcompatibleHighProfileLevel4_1", - "SinceDCMTK" : "361" + "SinceDCMTK" : "361", + "Raw": false, "Lossless": false }, { @@ -312,7 +346,8 @@ "Value" : "MPEG4HighProfileLevel4_2_For2DVideo", "Retired" : false, "DCMTK" : "EXS_MPEG4HighProfileLevel4_2_For2DVideo", - "SinceDCMTK" : "361" + "SinceDCMTK" : "361", + "Raw": false, "Lossless": false }, { @@ -321,7 +356,8 @@ "Value" : "MPEG4HighProfileLevel4_2_For3DVideo", "Retired" : false, "DCMTK" : "EXS_MPEG4HighProfileLevel4_2_For3DVideo", - "SinceDCMTK" : "361" + "SinceDCMTK" : "361", + "Raw": false, "Lossless": false }, { @@ -330,7 +366,8 @@ "Value" : "MPEG4StereoHighProfileLevel4_2", "Retired" : false, "DCMTK" : "EXS_MPEG4StereoHighProfileLevel4_2", - "SinceDCMTK" : "361" + "SinceDCMTK" : "361", + "Raw": false, "Lossless": false }, { @@ -339,7 +376,8 @@ "Value" : "HEVCMainProfileLevel5_1", "Retired" : false, "DCMTK" : "EXS_HEVCMainProfileLevel5_1", - "SinceDCMTK" : "362" + "SinceDCMTK" : "362", + "Raw": false, "Lossless": false }, { @@ -348,7 +386,8 @@ "Value" : "HEVCMain10ProfileLevel5_1", "Retired" : false, "DCMTK" : "EXS_HEVCMain10ProfileLevel5_1", - "SinceDCMTK" : "362" + "SinceDCMTK" : "362", + "Raw": false, "Lossless": false }, { @@ -357,7 +396,8 @@ "Value" : "RLELossless", "Retired" : false, "DCMTK" : "EXS_RLELossless", - "GDCM" : "gdcm::TransferSyntax::RLELossless" + "GDCM" : "gdcm::TransferSyntax::RLELossless", + "Raw": false, "Lossless": true }, {
--- a/OrthancFramework/Resources/CodeGeneration/GenerateTransferSyntaxesEnumerations.mustache Tue Mar 11 10:47:31 2025 +0100 +++ b/OrthancFramework/Resources/CodeGeneration/GenerateTransferSyntaxesEnumerations.mustache Wed Mar 12 09:59:38 2025 +0100 @@ -82,4 +82,44 @@ target.insert(DicomTransferSyntax_{{Value}}); {{/Syntaxes}} } + + + bool IsLossyTransferSyntax(DicomTransferSyntax syntax) + { + switch (syntax) + { + {{#Syntaxes}} + case DicomTransferSyntax_{{Value}}: + {{#Lossless}} + return false; + {{/Lossless}} + {{^Lossless}} + return true; + {{/Lossless}} + + {{/Syntaxes}} + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } + + + bool IsRawTransferSyntax(DicomTransferSyntax syntax) + { + switch (syntax) + { + {{#Syntaxes}} + case DicomTransferSyntax_{{Value}}: + {{#Raw}} + return true; + {{/Raw}} + {{^Raw}} + return false; + {{/Raw}} + + {{/Syntaxes}} + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } }
--- a/OrthancFramework/Sources/DicomParsing/DicomPixelMasker.cpp Tue Mar 11 10:47:31 2025 +0100 +++ b/OrthancFramework/Sources/DicomParsing/DicomPixelMasker.cpp Wed Mar 12 09:59:38 2025 +0100 @@ -58,7 +58,6 @@ for (std::list<Region>::const_iterator r = regions_.begin(); r != regions_.end(); ++r) { - // LOG(INFO) << " +++ " << seriesId << " " << instanceId; if (r->targetSeries_.size() > 0 && r->targetSeries_.find(seriesId) == r->targetSeries_.end()) { continue; @@ -69,16 +68,21 @@ continue; } - ImageAccessor imageRegion; - toModify.GetRawFrame(0)->GetRegion(imageRegion, r->x_, r->y_, r->width_, r->height_); // TODO-PIXEL-ANON: handle frames - - if (r->mode_ == DicomPixelMaskerMode_MeanFilter) + for (unsigned int i = 0; i < toModify.GetFramesCount(); ++i) { - ImageProcessing::MeanFilter(imageRegion, r->filterWidth_, r->filterWidth_); - } - else if (r->mode_ == DicomPixelMaskerMode_Fill) - { - ImageProcessing::Set(imageRegion, r->fillValue_); + // TODO-PIXEL-ANON: skip unwanted frames + + ImageAccessor imageRegion; + toModify.GetRawFrame(i)->GetRegion(imageRegion, r->x_, r->y_, r->width_, r->height_); + + if (r->mode_ == DicomPixelMaskerMode_MeanFilter) + { + ImageProcessing::MeanFilter(imageRegion, r->filterWidth_, r->filterWidth_); + } + else if (r->mode_ == DicomPixelMaskerMode_Fill) + { + ImageProcessing::Set(imageRegion, r->fillValue_); + } } } }
--- a/OrthancFramework/Sources/Enumerations.h Tue Mar 11 10:47:31 2025 +0100 +++ b/OrthancFramework/Sources/Enumerations.h Wed Mar 12 09:59:38 2025 +0100 @@ -953,6 +953,12 @@ DicomTransferSyntax GetTransferSyntax(const std::string& uid); ORTHANC_PUBLIC + bool IsRawTransferSyntax(DicomTransferSyntax syntax); + + ORTHANC_PUBLIC + bool IsLossyTransferSyntax(DicomTransferSyntax syntax); + + ORTHANC_PUBLIC const char* GetResourceTypeText(ResourceType type, bool isPlural, bool isUpperCase);
--- a/OrthancFramework/Sources/Enumerations_TransferSyntaxes.impl.h Tue Mar 11 10:47:31 2025 +0100 +++ b/OrthancFramework/Sources/Enumerations_TransferSyntaxes.impl.h Wed Mar 12 09:59:38 2025 +0100 @@ -602,4 +602,276 @@ target.insert(DicomTransferSyntax_RFC2557MimeEncapsulation); target.insert(DicomTransferSyntax_XML); } + + + bool IsLossyTransferSyntax(DicomTransferSyntax syntax) + { + switch (syntax) + { + case DicomTransferSyntax_LittleEndianImplicit: + return false; + + case DicomTransferSyntax_LittleEndianExplicit: + return false; + + case DicomTransferSyntax_DeflatedLittleEndianExplicit: + return false; + + case DicomTransferSyntax_BigEndianExplicit: + return false; + + case DicomTransferSyntax_JPEGProcess1: + return true; + + case DicomTransferSyntax_JPEGProcess2_4: + return true; + + case DicomTransferSyntax_JPEGProcess3_5: + return true; + + case DicomTransferSyntax_JPEGProcess6_8: + return true; + + case DicomTransferSyntax_JPEGProcess7_9: + return true; + + case DicomTransferSyntax_JPEGProcess10_12: + return true; + + case DicomTransferSyntax_JPEGProcess11_13: + return true; + + case DicomTransferSyntax_JPEGProcess14: + return false; + + case DicomTransferSyntax_JPEGProcess15: + return false; + + case DicomTransferSyntax_JPEGProcess16_18: + return true; + + case DicomTransferSyntax_JPEGProcess17_19: + return true; + + case DicomTransferSyntax_JPEGProcess20_22: + return true; + + case DicomTransferSyntax_JPEGProcess21_23: + return true; + + case DicomTransferSyntax_JPEGProcess24_26: + return true; + + case DicomTransferSyntax_JPEGProcess25_27: + return true; + + case DicomTransferSyntax_JPEGProcess28: + return false; + + case DicomTransferSyntax_JPEGProcess29: + return false; + + case DicomTransferSyntax_JPEGProcess14SV1: + return false; + + case DicomTransferSyntax_JPEGLSLossless: + return false; + + case DicomTransferSyntax_JPEGLSLossy: + return true; + + case DicomTransferSyntax_JPEG2000LosslessOnly: + return false; + + case DicomTransferSyntax_JPEG2000: + return true; + + case DicomTransferSyntax_JPEG2000MulticomponentLosslessOnly: + return false; + + case DicomTransferSyntax_JPEG2000Multicomponent: + return true; + + case DicomTransferSyntax_JPIPReferenced: + return false; + + case DicomTransferSyntax_JPIPReferencedDeflate: + return false; + + case DicomTransferSyntax_MPEG2MainProfileAtMainLevel: + return true; + + case DicomTransferSyntax_MPEG2MainProfileAtHighLevel: + return true; + + case DicomTransferSyntax_MPEG4HighProfileLevel4_1: + return true; + + case DicomTransferSyntax_MPEG4BDcompatibleHighProfileLevel4_1: + return true; + + case DicomTransferSyntax_MPEG4HighProfileLevel4_2_For2DVideo: + return true; + + case DicomTransferSyntax_MPEG4HighProfileLevel4_2_For3DVideo: + return true; + + case DicomTransferSyntax_MPEG4StereoHighProfileLevel4_2: + return true; + + case DicomTransferSyntax_HEVCMainProfileLevel5_1: + return true; + + case DicomTransferSyntax_HEVCMain10ProfileLevel5_1: + return true; + + case DicomTransferSyntax_RLELossless: + return false; + + case DicomTransferSyntax_RFC2557MimeEncapsulation: + return true; + + case DicomTransferSyntax_XML: + return true; + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } + + + bool IsRawTransferSyntax(DicomTransferSyntax syntax) + { + switch (syntax) + { + case DicomTransferSyntax_LittleEndianImplicit: + return true; + + case DicomTransferSyntax_LittleEndianExplicit: + return true; + + case DicomTransferSyntax_DeflatedLittleEndianExplicit: + return false; + + case DicomTransferSyntax_BigEndianExplicit: + return true; + + case DicomTransferSyntax_JPEGProcess1: + return false; + + case DicomTransferSyntax_JPEGProcess2_4: + return false; + + case DicomTransferSyntax_JPEGProcess3_5: + return false; + + case DicomTransferSyntax_JPEGProcess6_8: + return false; + + case DicomTransferSyntax_JPEGProcess7_9: + return false; + + case DicomTransferSyntax_JPEGProcess10_12: + return false; + + case DicomTransferSyntax_JPEGProcess11_13: + return false; + + case DicomTransferSyntax_JPEGProcess14: + return false; + + case DicomTransferSyntax_JPEGProcess15: + return false; + + case DicomTransferSyntax_JPEGProcess16_18: + return false; + + case DicomTransferSyntax_JPEGProcess17_19: + return false; + + case DicomTransferSyntax_JPEGProcess20_22: + return false; + + case DicomTransferSyntax_JPEGProcess21_23: + return false; + + case DicomTransferSyntax_JPEGProcess24_26: + return false; + + case DicomTransferSyntax_JPEGProcess25_27: + return false; + + case DicomTransferSyntax_JPEGProcess28: + return false; + + case DicomTransferSyntax_JPEGProcess29: + return false; + + case DicomTransferSyntax_JPEGProcess14SV1: + return false; + + case DicomTransferSyntax_JPEGLSLossless: + return false; + + case DicomTransferSyntax_JPEGLSLossy: + return false; + + case DicomTransferSyntax_JPEG2000LosslessOnly: + return false; + + case DicomTransferSyntax_JPEG2000: + return false; + + case DicomTransferSyntax_JPEG2000MulticomponentLosslessOnly: + return false; + + case DicomTransferSyntax_JPEG2000Multicomponent: + return false; + + case DicomTransferSyntax_JPIPReferenced: + return false; + + case DicomTransferSyntax_JPIPReferencedDeflate: + return false; + + case DicomTransferSyntax_MPEG2MainProfileAtMainLevel: + return false; + + case DicomTransferSyntax_MPEG2MainProfileAtHighLevel: + return false; + + case DicomTransferSyntax_MPEG4HighProfileLevel4_1: + return false; + + case DicomTransferSyntax_MPEG4BDcompatibleHighProfileLevel4_1: + return false; + + case DicomTransferSyntax_MPEG4HighProfileLevel4_2_For2DVideo: + return false; + + case DicomTransferSyntax_MPEG4HighProfileLevel4_2_For3DVideo: + return false; + + case DicomTransferSyntax_MPEG4StereoHighProfileLevel4_2: + return false; + + case DicomTransferSyntax_HEVCMainProfileLevel5_1: + return false; + + case DicomTransferSyntax_HEVCMain10ProfileLevel5_1: + return false; + + case DicomTransferSyntax_RLELossless: + return false; + + case DicomTransferSyntax_RFC2557MimeEncapsulation: + return false; + + case DicomTransferSyntax_XML: + return false; + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } }
--- a/OrthancServer/Sources/ServerContext.cpp Tue Mar 11 10:47:31 2025 +0100 +++ b/OrthancServer/Sources/ServerContext.cpp Wed Mar 12 09:59:38 2025 +0100 @@ -2027,7 +2027,7 @@ DicomTransferSyntax currentTransferSyntax; if (modification.RequiresUncompressedTransferSyntax() && dicomFile->LookupTransferSyntax(currentTransferSyntax) && - currentTransferSyntax > DicomTransferSyntax_BigEndianExplicit) // TODO-PIXEL-ANON: write a function IsRawTransferSyntax() + !IsRawTransferSyntax(currentTransferSyntax)) { IDicomTranscoder::DicomImage source; source.AcquireParsed(*dicomFile); // "dicomFile" is invalid below this point @@ -2038,13 +2038,15 @@ uncompressedTransferSyntax.insert(DicomTransferSyntax_LittleEndianExplicit); Transcode(transcoded, source, uncompressedTransferSyntax, true); - if (currentTransferSyntax == DicomTransferSyntax_JPEGProcess1) // TODO-PIXEL-ANON: write a function IsLossyTransferSyntax() + 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, - // keep the SOPInstanceUID unchanged during this pre-transcoding to make sure the orthanc ids are + // 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()) @@ -2063,7 +2065,7 @@ transcode = true; targetSyntax = currentTransferSyntax; } - dicomFile.reset(transcoded.ReleaseAsParsedDicomFile()); + } modification.Apply(*dicomFile);
--- a/TODO Tue Mar 11 10:47:31 2025 +0100 +++ b/TODO Wed Mar 12 09:59:38 2025 +0100 @@ -465,7 +465,7 @@ curl -X POST http://localhost:8043/studies/321d3848-40c81c82-49f6f235-df6b1ec7-ed52f2fa/modify \ --data-binary @- << EOF { - "Replace" : {"StudyInstanceUID": "1.2.3", "StudyDescription": "modified-all-slices"}, + "Replace" : {"StudyInstanceUID": "1.2.2", "StudyDescription": "modified-all-slices"}, "Force": true, "MaskPixelData": { "Regions": [{ @@ -499,3 +499,40 @@ } } EOF + + +# modify all frames of a multiframe study (CARDIO) +curl -X POST http://localhost:8043/studies/595df1a1-74fe920a-4b9e3509-826f17a3-762a2dc3/modify \ +--data-binary @- << EOF +{ + "Replace" : {"StudyInstanceUID": "1.2.4", "StudyDescription": "modified-multi-frame"}, + "Force": true, + "MaskPixelData": { + "Regions": [{ + "MaskType": "MeanFilter", + "FilterWidth": 30, + "RegionType" : "Pixels", + "Origin": [150, 100], + "End": [400, 200] + }] + } +} +EOF + +# modify all frames of a multiframe US study (Cine US, TS = .50) +curl -X POST http://localhost:8043/studies/50f2961c-c35755eb-8762b05b-0e01cd97-dd8a294c/modify \ +--data-binary @- << EOF +{ + "Replace" : {"StudyInstanceUID": "1.2.5", "StudyDescription": "modified-multi-frame-us"}, + "Force": true, + "MaskPixelData": { + "Regions": [{ + "MaskType": "MeanFilter", + "FilterWidth": 30, + "RegionType" : "Pixels", + "Origin": [0, 0], + "End": [768, 45] + }] + } +} +EOF \ No newline at end of file