Mercurial > hg > orthanc
changeset 3880:cdd0cb5ec4e4 transcoding
DicomStoreUserConnection::LookupTranscoding()
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 04 May 2020 22:10:55 +0200 |
parents | a18b34dec94a |
children | f23ab7829a8d |
files | Core/DicomNetworking/DicomStoreUserConnection.cpp Core/DicomNetworking/DicomStoreUserConnection.h UnitTestsSources/FromDcmtkTests.cpp |
diffstat | 3 files changed, 98 insertions(+), 27 deletions(-) [+] |
line wrap: on
line diff
--- a/Core/DicomNetworking/DicomStoreUserConnection.cpp Mon May 04 19:17:07 2020 +0200 +++ b/Core/DicomNetworking/DicomStoreUserConnection.cpp Mon May 04 22:10:55 2020 +0200 @@ -84,13 +84,13 @@ it = syntaxes.begin(); it != syntaxes.end(); ++it) { association_->ProposePresentationContext(sopClassUid, *it); + proposedOriginalClasses_.insert(std::make_pair(sopClassUid, *it)); } if (addLittleEndianImplicit) { - std::set<DicomTransferSyntax> uncompressed; - uncompressed.insert(DicomTransferSyntax_LittleEndianImplicit); - association_->ProposePresentationContext(sopClassUid, uncompressed); + association_->ProposePresentationContext(sopClassUid, DicomTransferSyntax_LittleEndianImplicit); + proposedOriginalClasses_.insert(std::make_pair(sopClassUid, DicomTransferSyntax_LittleEndianImplicit)); } if (addLittleEndianExplicit || @@ -109,6 +109,14 @@ } association_->ProposePresentationContext(sopClassUid, uncompressed); + + assert(!uncompressed.empty()); + if (addLittleEndianExplicit ^ addBigEndianExplicit) + { + // Only one transfer syntax was proposed for this presentation context + assert(uncompressed.size() == 1); + proposedOriginalClasses_.insert(std::make_pair(sopClassUid, *uncompressed.begin())); + } } return true; @@ -201,7 +209,7 @@ { /** * Step 1: Check whether this presentation context is already - * available in the previously negociated assocation. + * available in the previously negotiated assocation. **/ if (LookupPresentationContext(presentationContextId, sopClassUid, transferSyntax)) @@ -212,11 +220,21 @@ // The association must be re-negotiated if (association_->IsOpen()) { - LOG(INFO) << "Re-negociating DICOM association with " + LOG(INFO) << "Re-negotiating DICOM association with " << parameters_.GetRemoteModality().GetApplicationEntityTitle(); + + if (proposedOriginalClasses_.find(std::make_pair(sopClassUid, transferSyntax)) != + proposedOriginalClasses_.end()) + { + LOG(INFO) << "The remote modality has already rejected SOP class UID \"" + << sopClassUid << "\" with transfer syntax \"" + << GetTransferSyntaxUid(transferSyntax) << "\", don't renegotiate"; + return false; + } } - + association_->ClearPresentationContexts(); + proposedOriginalClasses_.clear(); RegisterStorageClass(sopClassUid, transferSyntax); // (*) @@ -304,7 +322,7 @@ { DicomTransferSyntax transferSyntax; LookupParameters(sopClassUid, sopInstanceUid, transferSyntax, dataset); - + uint8_t presID; if (!NegotiatePresentationContext(presID, sopClassUid, transferSyntax)) { @@ -390,4 +408,34 @@ StoreInternal(sopClassUid, sopInstanceUid, *dicom->getDataset(), moveOriginatorAET, moveOriginatorID); } + + + bool DicomStoreUserConnection::LookupTranscoding(std::set<DicomTransferSyntax>& acceptedSyntaxes, + const std::string& sopClassUid, + DicomTransferSyntax sourceSyntax) + { + acceptedSyntaxes.clear(); + + // Make sure a negotiation has already occurred for this transfer + // syntax. We don't use the return code: Transcoding is possible + // even if the "sourceSyntax" is not supported. + uint8_t presID; + NegotiatePresentationContext(presID, sopClassUid, sourceSyntax); + + std::map<DicomTransferSyntax, uint8_t> contexts; + if (association_->LookupAcceptedPresentationContext(contexts, sopClassUid)) + { + for (std::map<DicomTransferSyntax, uint8_t>::const_iterator + it = contexts.begin(); it != contexts.end(); ++it) + { + acceptedSyntaxes.insert(it->first); + } + + return true; + } + else + { + return false; + } + } }
--- a/Core/DicomNetworking/DicomStoreUserConnection.h Mon May 04 19:17:07 2020 +0200 +++ b/Core/DicomNetworking/DicomStoreUserConnection.h Mon May 04 22:10:55 2020 +0200 @@ -69,10 +69,15 @@ { private: typedef std::map<std::string, std::set<DicomTransferSyntax> > RegisteredClasses; + + // "ProposedOriginalClasses" keeps track of the storage classes + // that were proposed with a single transfer syntax + typedef std::set< std::pair<std::string, DicomTransferSyntax> > ProposedOriginalClasses; DicomAssociationParameters parameters_; boost::shared_ptr<DicomAssociation> association_; // "shared_ptr" is for PImpl RegisteredClasses registeredClasses_; + ProposedOriginalClasses proposedOriginalClasses_; bool proposeCommonClasses_; bool proposeUncompressedSyntaxes_; bool proposeRetiredBigEndian_; @@ -86,6 +91,14 @@ DicomTransferSyntax& transferSyntax, DcmDataset& dataset); + bool LookupPresentationContext(uint8_t& presentationContextId, + const std::string& sopClassUid, + DicomTransferSyntax transferSyntax); + + bool NegotiatePresentationContext(uint8_t& presentationContextId, + const std::string& sopClassUid, + DicomTransferSyntax transferSyntax); + void StoreInternal(std::string& sopClassUid, std::string& sopInstanceUid, DcmDataset& dataset, @@ -133,17 +146,6 @@ void RegisterStorageClass(const std::string& sopClassUid, DicomTransferSyntax syntax); - // Should only be used if transcoding - // TODO => to private - bool LookupPresentationContext(uint8_t& presentationContextId, - const std::string& sopClassUid, - DicomTransferSyntax transferSyntax); - - // TODO => to private - bool NegotiatePresentationContext(uint8_t& presentationContextId, - const std::string& sopClassUid, - DicomTransferSyntax transferSyntax); - void Store(std::string& sopClassUid, std::string& sopInstanceUid, const void* buffer, @@ -158,5 +160,9 @@ { Store(sopClassUid, sopInstanceUid, buffer, size, "", 0); // Not a C-Move } + + bool LookupTranscoding(std::set<DicomTransferSyntax>& acceptedSyntaxes, + const std::string& sopClassUid, + DicomTransferSyntax sourceSyntax); }; }
--- a/UnitTestsSources/FromDcmtkTests.cpp Mon May 04 19:17:07 2020 +0200 +++ b/UnitTestsSources/FromDcmtkTests.cpp Mon May 04 22:10:55 2020 +0200 @@ -2875,11 +2875,27 @@ const std::string& sopClassUid, DicomTransferSyntax transferSyntax) { - uint8_t id; - - if (scu.NegotiatePresentationContext(id, sopClassUid, transferSyntax)) + std::set<DicomTransferSyntax> accepted; + + if (!scu.LookupTranscoding(accepted, sopClassUid, transferSyntax)) + { + throw OrthancException(ErrorCode_NetworkProtocol, + "The SOP class is not supported by the remote modality"); + } + { - printf("**** OK, without transcoding !! %d\n", id); + unsigned int count = 0; + for (std::set<DicomTransferSyntax>::const_iterator + it = accepted.begin(); it != accepted.end(); ++it) + { + LOG(INFO) << "available for transcoding " << (count++) << ": " << sopClassUid + << " / " << GetTransferSyntaxUid(*it); + } + } + + if (accepted.find(transferSyntax) != accepted.end()) + { + printf("**** OK, without transcoding !! [%s]\n", GetTransferSyntaxUid(transferSyntax)); } else { @@ -2894,10 +2910,9 @@ bool found = false; for (size_t i = 0; i < 3; i++) { - if (scu.LookupPresentationContext(id, sopClassUid, uncompressed[i])) + if (accepted.find(uncompressed[i]) != accepted.end()) { - printf("**** TRANSCODING to %s => %d\n", - GetTransferSyntaxUid(uncompressed[i]), id); + printf("**** TRANSCODING to %s\n", GetTransferSyntaxUid(uncompressed[i])); found = true; break; } @@ -2924,9 +2939,11 @@ //assoc.RegisterStorageClass(UID_MRImageStorage, DicomTransferSyntax_LittleEndianExplicit); //assoc.SetUncompressedSyntaxesProposed(false); // Necessary for transcoding - //assoc.SetCommonClassesProposed(false); + assoc.SetCommonClassesProposed(false); + assoc.SetRetiredBigEndianProposed(true); + TestTranscode(assoc, UID_MRImageStorage, DicomTransferSyntax_LittleEndianExplicit); TestTranscode(assoc, UID_MRImageStorage, DicomTransferSyntax_JPEG2000); - TestTranscode(assoc, UID_MRImageStorage, DicomTransferSyntax_LittleEndianExplicit); + TestTranscode(assoc, UID_MRImageStorage, DicomTransferSyntax_JPEG2000); }