# HG changeset patch # User Sebastien Jodogne # Date 1703237369 -3600 # Node ID 723251b2b71eb293a063900ff38bd19e69d0caec # Parent e7a04f878704715e1e4d77921d0a3a00107f8cdc# Parent f7ac06300f862f173c9d777dd9de184552870002 merge diff -r e7a04f878704 -r 723251b2b71e OrthancFramework/Sources/DicomParsing/DcmtkTranscoder.cpp --- a/OrthancFramework/Sources/DicomParsing/DcmtkTranscoder.cpp Fri Dec 22 10:29:07 2023 +0100 +++ b/OrthancFramework/Sources/DicomParsing/DcmtkTranscoder.cpp Fri Dec 22 10:29:29 2023 +0100 @@ -37,6 +37,7 @@ #include "FromDcmtkBridge.h" #include "../Logging.h" #include "../OrthancException.h" +#include "../Toolbox.h" #include #include // for DJ_RPLossy @@ -83,12 +84,33 @@ return lossyQuality_; } + bool TryTranscode(std::vector& failureReasons, /* out */ + DicomTransferSyntax& selectedSyntax, /* out*/ + DcmFileFormat& dicom, /* in/out */ + const std::set& allowedSyntaxes, + DicomTransferSyntax trySyntax) + { + if (allowedSyntaxes.find(trySyntax) != allowedSyntaxes.end()) + { + if (FromDcmtkBridge::Transcode(dicom, trySyntax, NULL)) + { + selectedSyntax = trySyntax; + return true; + } + + failureReasons.push_back(std::string("Internal error while transcoding to ") + GetTransferSyntaxUid(trySyntax)); + } + return false; + } bool DcmtkTranscoder::InplaceTranscode(DicomTransferSyntax& selectedSyntax /* out */, - DcmFileFormat& dicom, + std::string& failureReason /* out */, + DcmFileFormat& dicom, /* in/out */ const std::set& allowedSyntaxes, bool allowNewSopInstanceUid) { + std::vector failureReasons; + if (dicom.getDataset() == NULL) { throw OrthancException(ErrorCode_InternalError); @@ -109,62 +131,75 @@ // No transcoding is needed return true; } - - if (allowedSyntaxes.find(DicomTransferSyntax_LittleEndianImplicit) != allowedSyntaxes.end() && - FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_LittleEndianImplicit, NULL)) + + if (TryTranscode(failureReasons, selectedSyntax, dicom, allowedSyntaxes, DicomTransferSyntax_LittleEndianImplicit)) + { + return true; + } + + if (TryTranscode(failureReasons, selectedSyntax, dicom, allowedSyntaxes, DicomTransferSyntax_LittleEndianExplicit)) { - selectedSyntax = DicomTransferSyntax_LittleEndianImplicit; + return true; + } + + if (TryTranscode(failureReasons, selectedSyntax, dicom, allowedSyntaxes, DicomTransferSyntax_BigEndianExplicit)) + { + return true; + } + + if (TryTranscode(failureReasons, selectedSyntax, dicom, allowedSyntaxes, DicomTransferSyntax_DeflatedLittleEndianExplicit)) + { return true; } - if (allowedSyntaxes.find(DicomTransferSyntax_LittleEndianExplicit) != allowedSyntaxes.end() && - FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_LittleEndianExplicit, NULL)) - { - selectedSyntax = DicomTransferSyntax_LittleEndianExplicit; - return true; - } - - if (allowedSyntaxes.find(DicomTransferSyntax_BigEndianExplicit) != allowedSyntaxes.end() && - FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_BigEndianExplicit, NULL)) - { - selectedSyntax = DicomTransferSyntax_BigEndianExplicit; - return true; - } - - if (allowedSyntaxes.find(DicomTransferSyntax_DeflatedLittleEndianExplicit) != allowedSyntaxes.end() && - FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_DeflatedLittleEndianExplicit, NULL)) - { - selectedSyntax = DicomTransferSyntax_DeflatedLittleEndianExplicit; - return true; - } #if ORTHANC_ENABLE_DCMTK_JPEG == 1 - if (allowedSyntaxes.find(DicomTransferSyntax_JPEGProcess1) != allowedSyntaxes.end() && - allowNewSopInstanceUid && - (!hasBitsStored || bitsStored == 8)) + if (allowedSyntaxes.find(DicomTransferSyntax_JPEGProcess1) != allowedSyntaxes.end()) { - // Check out "dcmjpeg/apps/dcmcjpeg.cc" - DJ_RPLossy parameters(lossyQuality_); - - if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGProcess1, ¶meters)) + if (!allowNewSopInstanceUid) + { + failureReasons.push_back(std::string("Can not transcode to ") + GetTransferSyntaxUid(DicomTransferSyntax_JPEGProcess1) + " without generating new SOPInstanceUID"); + } + else if (hasBitsStored && bitsStored != 8) + { + failureReasons.push_back(std::string("Can not transcode to ") + GetTransferSyntaxUid(DicomTransferSyntax_JPEGProcess1) + " if BitsStored != 8"); + } + else { - selectedSyntax = DicomTransferSyntax_JPEGProcess1; - return true; + // Check out "dcmjpeg/apps/dcmcjpeg.cc" + DJ_RPLossy parameters(lossyQuality_); + + if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGProcess1, ¶meters)) + { + selectedSyntax = DicomTransferSyntax_JPEGProcess1; + return true; + } + failureReasons.push_back(std::string("Internal error while transcoding to ") + GetTransferSyntaxUid(DicomTransferSyntax_JPEGProcess1)); } } #endif #if ORTHANC_ENABLE_DCMTK_JPEG == 1 - if (allowedSyntaxes.find(DicomTransferSyntax_JPEGProcess2_4) != allowedSyntaxes.end() && - allowNewSopInstanceUid && - (!hasBitsStored || bitsStored <= 12)) + if (allowedSyntaxes.find(DicomTransferSyntax_JPEGProcess2_4) != allowedSyntaxes.end()) { - // Check out "dcmjpeg/apps/dcmcjpeg.cc" - DJ_RPLossy parameters(lossyQuality_); - if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGProcess2_4, ¶meters)) + if (!allowNewSopInstanceUid) + { + failureReasons.push_back(std::string("Can not transcode to ") + GetTransferSyntaxUid(DicomTransferSyntax_JPEGProcess2_4) + " without generating new SOPInstanceUID"); + } + else if (hasBitsStored && bitsStored > 12) { - selectedSyntax = DicomTransferSyntax_JPEGProcess2_4; - return true; + failureReasons.push_back(std::string("Can not transcode to ") + GetTransferSyntaxUid(DicomTransferSyntax_JPEGProcess2_4) + " if BitsStored != 8"); + } + else + { + // Check out "dcmjpeg/apps/dcmcjpeg.cc" + DJ_RPLossy parameters(lossyQuality_); + if (FromDcmtkBridge::Transcode(dicom, DicomTransferSyntax_JPEGProcess2_4, ¶meters)) + { + selectedSyntax = DicomTransferSyntax_JPEGProcess2_4; + return true; + } + failureReasons.push_back(std::string("Internal error while transcoding to ") + GetTransferSyntaxUid(DicomTransferSyntax_JPEGProcess2_4)); } } #endif @@ -180,6 +215,7 @@ selectedSyntax = DicomTransferSyntax_JPEGProcess14; return true; } + failureReasons.push_back(std::string("Internal error while transcoding to ") + GetTransferSyntaxUid(DicomTransferSyntax_JPEGProcess14)); } #endif @@ -194,6 +230,7 @@ selectedSyntax = DicomTransferSyntax_JPEGProcess14SV1; return true; } + failureReasons.push_back(std::string("Internal error while transcoding to ") + GetTransferSyntaxUid(DicomTransferSyntax_JPEGProcess14SV1)); } #endif @@ -213,6 +250,7 @@ selectedSyntax = DicomTransferSyntax_JPEGLSLossless; return true; } + failureReasons.push_back(std::string("Internal error while transcoding to ") + GetTransferSyntaxUid(DicomTransferSyntax_JPEGLSLossless)); } #endif @@ -233,9 +271,11 @@ selectedSyntax = DicomTransferSyntax_JPEGLSLossy; return true; } + failureReasons.push_back(std::string("Internal error while transcoding to ") + GetTransferSyntaxUid(DicomTransferSyntax_JPEGLSLossy)); } #endif + Orthanc::Toolbox::JoinStrings(failureReason, failureReasons, ", "); return false; } @@ -285,28 +325,27 @@ return false; } + std::string failureReason; + std::string s; + for (std::set::const_iterator + it = allowedSyntaxes.begin(); it != allowedSyntaxes.end(); ++it) { - std::string s; - for (std::set::const_iterator - it = allowedSyntaxes.begin(); it != allowedSyntaxes.end(); ++it) + if (!s.empty()) { - if (!s.empty()) - { - s += ", "; - } - - s += GetTransferSyntaxUid(*it); + s += ", "; } - if (s.empty()) - { - s = ""; - } - - LOG(INFO) << "DCMTK transcoding from " << GetTransferSyntaxUid(sourceSyntax) - << " to one of: " << s; + s += GetTransferSyntaxUid(*it); } + if (s.empty()) + { + s = ""; + } + + LOG(INFO) << "DCMTK transcoding from " << GetTransferSyntaxUid(sourceSyntax) + << " to one of: " << s; + #if !defined(NDEBUG) const std::string sourceSopInstanceUid = GetSopInstanceUid(source.GetParsed()); #endif @@ -319,7 +358,7 @@ target.AcquireBuffer(source); return true; } - else if (InplaceTranscode(targetSyntax, source.GetParsed(), + else if (InplaceTranscode(targetSyntax, failureReason, source.GetParsed(), allowedSyntaxes, allowNewSopInstanceUid)) { // Sanity check @@ -347,6 +386,8 @@ else { // Cannot transcode + LOG(WARNING) << "DCMTK was unable to transcode from " << GetTransferSyntaxUid(sourceSyntax) + << " to one of: " << s << " " << failureReason; return false; } } diff -r e7a04f878704 -r 723251b2b71e OrthancFramework/Sources/DicomParsing/DcmtkTranscoder.h --- a/OrthancFramework/Sources/DicomParsing/DcmtkTranscoder.h Fri Dec 22 10:29:07 2023 +0100 +++ b/OrthancFramework/Sources/DicomParsing/DcmtkTranscoder.h Fri Dec 22 10:29:29 2023 +0100 @@ -41,6 +41,7 @@ unsigned int lossyQuality_; bool InplaceTranscode(DicomTransferSyntax& selectedSyntax /* out */, + std::string& failureReason /* out */, DcmFileFormat& dicom, const std::set& allowedSyntaxes, bool allowNewSopInstanceUid); diff -r e7a04f878704 -r 723251b2b71e TODO --- a/TODO Fri Dec 22 10:29:07 2023 +0100 +++ b/TODO Fri Dec 22 10:29:29 2023 +0100 @@ -138,11 +138,9 @@ https://groups.google.com/g/orthanc-users/c/hsZ1jng5rIg/m/8xZL2C1VBgAJ * add an "AutoDeleteIfSuccessful": false option when creating jobs https://discourse.orthanc-server.org/t/job-history-combined-with-auto-forwarding/3729/10 -* Also implement a GET variant of /tools/create-archive + sibling routes - in which resources & transcode options are provided as get arguments. - https://groups.google.com/g/orthanc-users/c/PmaRZ609ztA/m/JdwXvIBKAQAJ * Allow skiping automatic conversion of color-space in transcoding/decoding. The patch that was initialy provided was breaking the IngestTranscoding. + This might require a DCMTK decoding plugin ? https://discourse.orthanc-server.org/t/orthanc-convert-ybr-to-rgb-but-does-not-change-metadata/3533/9 * Implement a 'commit' route to force the Stable status earlier. https://discourse.orthanc-server.org/t/expediting-stability-of-a-dicom-study-new-api-endpoint/1684