# HG changeset patch # User Sebastien Jodogne # Date 1589876226 -7200 # Node ID aae045f802f4507425610b687b65c5c735cb80e2 # Parent b26d25d3c1c71d354e63761200cfc5d0246e8386 preparing simplified interface for IDicomTranscoder diff -r b26d25d3c1c7 -r aae045f802f4 Core/DicomParsing/DcmtkTranscoder.cpp --- a/Core/DicomParsing/DcmtkTranscoder.cpp Mon May 18 21:37:31 2020 +0200 +++ b/Core/DicomParsing/DcmtkTranscoder.cpp Tue May 19 10:17:06 2020 +0200 @@ -398,4 +398,51 @@ return NULL; } } + + + bool DcmtkTranscoder::Transcode(DicomImage& target, + bool& hasSopInstanceUidChanged /* out */, + DicomImage& source /* in, "GetParsed()" possibly modified */, + const std::set& allowedSyntaxes, + bool allowNewSopInstanceUid) + { + target.Clear(); + + DicomTransferSyntax sourceSyntax; + if (!FromDcmtkBridge::LookupOrthancTransferSyntax(sourceSyntax, source.GetParsed())) + { + LOG(ERROR) << "Unsupport transfer syntax for transcoding"; + return false; + } + + if (allowedSyntaxes.find(sourceSyntax) != allowedSyntaxes.end()) + { + // No transcoding is needed + target.AcquireParsed(source); + target.AcquireBuffer(source); + return true; + } + else if (InplaceTranscode(hasSopInstanceUidChanged, source.GetParsed(), + allowedSyntaxes, allowNewSopInstanceUid)) + { + // Sanity check + DicomTransferSyntax targetSyntax; + if (FromDcmtkBridge::LookupOrthancTransferSyntax(targetSyntax, source.GetParsed()) && + allowedSyntaxes.find(targetSyntax) != allowedSyntaxes.end()) + { + target.AcquireParsed(source); + source.Clear(); + return true; + } + else + { + throw OrthancException(ErrorCode_InternalError); + } + } + else + { + // Cannot transcode + return false; + } + } } diff -r b26d25d3c1c7 -r aae045f802f4 Core/DicomParsing/DcmtkTranscoder.h --- a/Core/DicomParsing/DcmtkTranscoder.h Mon May 18 21:37:31 2020 +0200 +++ b/Core/DicomParsing/DcmtkTranscoder.h Tue May 19 10:17:06 2020 +0200 @@ -82,5 +82,11 @@ size_t size, const std::set& allowedSyntaxes, bool allowNewSopInstanceUid) ORTHANC_OVERRIDE; + + virtual bool Transcode(DicomImage& target, + bool& hasSopInstanceUidChanged /* out */, + DicomImage& source /* in, "GetParsed()" possibly modified */, + const std::set& allowedSyntaxes, + bool allowNewSopInstanceUid) ORTHANC_OVERRIDE; }; } diff -r b26d25d3c1c7 -r aae045f802f4 Core/DicomParsing/IDicomTranscoder.cpp --- a/Core/DicomParsing/IDicomTranscoder.cpp Mon May 18 21:37:31 2020 +0200 +++ b/Core/DicomParsing/IDicomTranscoder.cpp Tue May 19 10:17:06 2020 +0200 @@ -35,11 +35,187 @@ #include "IDicomTranscoder.h" #include "../OrthancException.h" +#include "FromDcmtkBridge.h" +#include "ParsedDicomFile.h" #include namespace Orthanc { + void IDicomTranscoder::DicomImage::Parse() + { + if (parsed_.get() != NULL || + buffer_.get() == NULL) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + parsed_.reset(FromDcmtkBridge::LoadFromMemoryBuffer( + buffer_->empty() ? NULL : buffer_->c_str(), buffer_->size())); + + if (parsed_.get() == NULL) + { + throw OrthancException(ErrorCode_BadFileFormat); + } + } + } + + + void IDicomTranscoder::DicomImage::Serialize() + { + if (parsed_.get() == NULL || + buffer_.get() != NULL) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else if (parsed_->getDataset() == NULL) + { + throw OrthancException(ErrorCode_InternalError); + } + else + { + buffer_.reset(new std::string); + FromDcmtkBridge::SaveToMemoryBuffer(*buffer_, *parsed_->getDataset()); + } + } + + + void IDicomTranscoder::DicomImage::Clear() + { + parsed_.reset(NULL); + buffer_.reset(NULL); + } + + + void IDicomTranscoder::DicomImage::AcquireParsed(ParsedDicomFile& parsed) + { + AcquireParsed(parsed.ReleaseDcmtkObject()); + } + + + void IDicomTranscoder::DicomImage::AcquireParsed(DcmFileFormat* parsed) + { + if (parsed == NULL) + { + throw OrthancException(ErrorCode_NullPointer); + } + else if (parsed_.get() != NULL) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else if (parsed->getDataset() == NULL) + { + throw OrthancException(ErrorCode_InternalError); + } + else + { + parsed_.reset(parsed); + } + } + + + void IDicomTranscoder::DicomImage::AcquireParsed(DicomImage& other) + { + AcquireParsed(other.ReleaseParsed()); + } + + + void IDicomTranscoder::DicomImage::AcquireBuffer(std::string& buffer /* will be swapped */) + { + if (buffer_.get() != NULL) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + buffer_.reset(new std::string); + buffer_->swap(buffer); + } + } + + + void IDicomTranscoder::DicomImage::AcquireBuffer(DicomImage& other) + { + if (buffer_.get() != NULL) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else if (other.buffer_.get() == NULL) + { + buffer_.reset(NULL); + } + else + { + buffer_.reset(other.buffer_.release()); + } + } + + + DcmFileFormat& IDicomTranscoder::DicomImage::GetParsed() + { + if (parsed_.get() != NULL) + { + return *parsed_; + } + else if (buffer_.get() != NULL) + { + Parse(); + return *parsed_; + } + else + { + throw OrthancException(ErrorCode_BadSequenceOfCalls, + "AcquireParsed() or AcquireBuffer() should have been called"); + } + } + + + DcmFileFormat* IDicomTranscoder::DicomImage::ReleaseParsed() + { + if (parsed_.get() != NULL) + { + buffer_.reset(NULL); + return parsed_.release(); + } + else if (buffer_.get() != NULL) + { + Parse(); + buffer_.reset(NULL); + return parsed_.release(); + } + else + { + throw OrthancException(ErrorCode_BadSequenceOfCalls, + "AcquireParsed() or AcquireBuffer() should have been called"); + } + } + + + const void* IDicomTranscoder::DicomImage::GetBufferData() + { + if (buffer_.get() == NULL) + { + Serialize(); + } + + assert(buffer_.get() != NULL); + return buffer_->empty() ? NULL : buffer_->c_str(); + } + + + size_t IDicomTranscoder::DicomImage::GetBufferSize() + { + if (buffer_.get() == NULL) + { + Serialize(); + } + + assert(buffer_.get() != NULL); + return buffer_->size(); + } + + IDicomTranscoder::TranscodedDicom::TranscodedDicom(bool hasSopInstanceUidChanged) : external_(NULL), hasSopInstanceUidChanged_(hasSopInstanceUidChanged) diff -r b26d25d3c1c7 -r aae045f802f4 Core/DicomParsing/IDicomTranscoder.h --- a/Core/DicomParsing/IDicomTranscoder.h Mon May 18 21:37:31 2020 +0200 +++ b/Core/DicomParsing/IDicomTranscoder.h Tue May 19 10:17:06 2020 +0200 @@ -47,14 +47,59 @@ * WARNING: This class might be called from several threads at * once. Make sure to implement proper locking. **/ + + class ParsedDicomFile; class IDicomTranscoder : public boost::noncopyable { public: + class DicomImage : public boost::noncopyable + { + private: + std::unique_ptr parsed_; + std::unique_ptr buffer_; + + void Parse(); + + void Serialize(); + + DcmFileFormat* ReleaseParsed(); + + public: + void Clear(); + + // Calling this method will invalidate the "ParsedDicomFile" object + void AcquireParsed(ParsedDicomFile& parsed); + + void AcquireParsed(DcmFileFormat* parsed); + + void AcquireParsed(DicomImage& other); + + void AcquireBuffer(std::string& buffer /* will be swapped */); + + void AcquireBuffer(DicomImage& other); + + DcmFileFormat& GetParsed(); + + const void* GetBufferData(); + + size_t GetBufferSize(); + }; + + virtual ~IDicomTranscoder() { } + + virtual bool Transcode(DicomImage& target, + bool& hasSopInstanceUidChanged /* out */, + DicomImage& source /* in, "GetParsed()" possibly modified */, + const std::set& allowedSyntaxes, + bool allowNewSopInstanceUid) = 0; + + + virtual bool TranscodeParsedToBuffer(std::string& target /* out */, bool& hasSopInstanceUidChanged /* out */, DcmFileFormat& dicom /* in, possibly modified */, diff -r b26d25d3c1c7 -r aae045f802f4 Core/DicomParsing/MemoryBufferTranscoder.cpp --- a/Core/DicomParsing/MemoryBufferTranscoder.cpp Mon May 18 21:37:31 2020 +0200 +++ b/Core/DicomParsing/MemoryBufferTranscoder.cpp Tue May 19 10:17:06 2020 +0200 @@ -86,8 +86,8 @@ std::set allowedSyntaxes; allowedSyntaxes.insert(targetSyntax); - if (Transcode(target, hasSopInstanceUidChanged, - data, source.size(), allowedSyntaxes, allowNewSopInstanceUid)) + if (TranscodeBuffer(target, hasSopInstanceUidChanged, + data, source.size(), allowedSyntaxes, allowNewSopInstanceUid)) { CheckTargetSyntax(target, allowedSyntaxes); return true; @@ -109,8 +109,8 @@ bool hasSopInstanceUidChanged; std::string target; - if (Transcode(target, hasSopInstanceUidChanged, - buffer, size, allowedSyntaxes, allowNewSopInstanceUid)) + if (TranscodeBuffer(target, hasSopInstanceUidChanged, + buffer, size, allowedSyntaxes, allowNewSopInstanceUid)) { CheckTargetSyntax(target, allowedSyntaxes); @@ -123,4 +123,27 @@ return NULL; } } + + + bool MemoryBufferTranscoder::Transcode(DicomImage& target, + bool& hasSopInstanceUidChanged /* out */, + DicomImage& source, + const std::set& allowedSyntaxes, + bool allowNewSopInstanceUid) + { + target.Clear(); + + std::string buffer; + if (TranscodeBuffer(buffer, hasSopInstanceUidChanged, source.GetBufferData(), + source.GetBufferSize(), allowedSyntaxes, allowNewSopInstanceUid)) + { + CheckTargetSyntax(buffer, allowedSyntaxes); // For debug only + target.AcquireBuffer(buffer); + return true; + } + else + { + return false; + } + } } diff -r b26d25d3c1c7 -r aae045f802f4 Core/DicomParsing/MemoryBufferTranscoder.h --- a/Core/DicomParsing/MemoryBufferTranscoder.h Mon May 18 21:37:31 2020 +0200 +++ b/Core/DicomParsing/MemoryBufferTranscoder.h Tue May 19 10:17:06 2020 +0200 @@ -41,12 +41,12 @@ class MemoryBufferTranscoder : public IDicomTranscoder { protected: - virtual bool Transcode(std::string& target, - bool& hasSopInstanceUidChanged /* out */, - const void* buffer, - size_t size, - const std::set& allowedSyntaxes, - bool allowNewSopInstanceUid) = 0; + virtual bool TranscodeBuffer(std::string& target, + bool& hasSopInstanceUidChanged /* out */, + const void* buffer, + size_t size, + const std::set& allowedSyntaxes, + bool allowNewSopInstanceUid) = 0; public: virtual bool TranscodeParsedToBuffer(std::string& target /* out */, @@ -61,5 +61,11 @@ size_t size, const std::set& allowedSyntaxes, bool allowNewSopInstanceUid) ORTHANC_OVERRIDE; + + virtual bool Transcode(DicomImage& target /* out */, + bool& hasSopInstanceUidChanged /* out */, + DicomImage& source, + const std::set& allowedSyntaxes, + bool allowNewSopInstanceUid) ORTHANC_OVERRIDE; }; } diff -r b26d25d3c1c7 -r aae045f802f4 Core/DicomParsing/ParsedDicomFile.cpp --- a/Core/DicomParsing/ParsedDicomFile.cpp Mon May 18 21:37:31 2020 +0200 +++ b/Core/DicomParsing/ParsedDicomFile.cpp Tue May 19 10:17:06 2020 +0200 @@ -455,8 +455,8 @@ void ParsedDicomFile::SendPathValue(RestApiOutput& output, const UriComponents& uri) { - DcmItem* dicom = pimpl_->file_->getDataset(); - E_TransferSyntax transferSyntax = pimpl_->file_->getDataset()->getCurrentXfer(); + DcmItem* dicom = GetDcmtkObject().getDataset(); + E_TransferSyntax transferSyntax = GetDcmtkObject().getDataset()->getCurrentXfer(); // Special case: Accessing the pixel data if (uri.size() == 1 || @@ -516,7 +516,7 @@ InvalidateCache(); DcmTagKey key(tag.GetGroup(), tag.GetElement()); - DcmElement* element = pimpl_->file_->getDataset()->remove(key); + DcmElement* element = GetDcmtkObject().getDataset()->remove(key); if (element != NULL) { delete element; @@ -536,7 +536,7 @@ InvalidateCache(); - DcmItem* dicom = pimpl_->file_->getDataset(); + DcmItem* dicom = GetDcmtkObject().getDataset(); DcmTagKey key(tag.GetGroup(), tag.GetElement()); if (onlyIfExists && @@ -558,7 +558,7 @@ { InvalidateCache(); - DcmDataset& dataset = *pimpl_->file_->getDataset(); + DcmDataset& dataset = *GetDcmtkObject().getDataset(); // Loop over the dataset to detect its private tags typedef std::list Tags; @@ -629,7 +629,7 @@ return; } - if (pimpl_->file_->getDataset()->tagExists(ToDcmtkBridge::Convert(tag))) + if (GetDcmtkObject().getDataset()->tagExists(ToDcmtkBridge::Convert(tag))) { throw OrthancException(ErrorCode_AlreadyExistingTag); } @@ -650,7 +650,7 @@ bool hasCodeExtensions; Encoding encoding = DetectEncoding(hasCodeExtensions); std::unique_ptr element(FromDcmtkBridge::FromJson(tag, value, decodeDataUriScheme, encoding, privateCreator)); - InsertInternal(*pimpl_->file_->getDataset(), element.release()); + InsertInternal(*GetDcmtkObject().getDataset(), element.release()); } @@ -782,7 +782,7 @@ InvalidateCache(); - DcmDataset& dicom = *pimpl_->file_->getDataset(); + DcmDataset& dicom = *GetDcmtkObject().getDataset(); if (CanReplaceProceed(dicom, ToDcmtkBridge::Convert(tag), mode)) { // Either the tag was previously existing (and now removed), or @@ -828,7 +828,7 @@ InvalidateCache(); - DcmDataset& dicom = *pimpl_->file_->getDataset(); + DcmDataset& dicom = *GetDcmtkObject().getDataset(); if (CanReplaceProceed(dicom, ToDcmtkBridge::Convert(tag), mode)) { // Either the tag was previously existing (and now removed), or @@ -867,7 +867,7 @@ void ParsedDicomFile::Answer(RestApiOutput& output) { std::string serialized; - if (FromDcmtkBridge::SaveToMemoryBuffer(serialized, *pimpl_->file_->getDataset())) + if (FromDcmtkBridge::SaveToMemoryBuffer(serialized, *GetDcmtkObject().getDataset())) { output.AnswerBuffer(serialized, MimeType_Dicom); } @@ -879,7 +879,7 @@ const DicomTag& tag) { DcmTagKey k(tag.GetGroup(), tag.GetElement()); - DcmDataset& dataset = *pimpl_->file_->getDataset(); + DcmDataset& dataset = *GetDcmtkObject().getDataset(); if (tag.IsPrivate() || FromDcmtkBridge::IsUnknownTag(tag) || @@ -970,7 +970,7 @@ void ParsedDicomFile::SaveToMemoryBuffer(std::string& buffer) { - FromDcmtkBridge::SaveToMemoryBuffer(buffer, *pimpl_->file_->getDataset()); + FromDcmtkBridge::SaveToMemoryBuffer(buffer, *GetDcmtkObject().getDataset()); } @@ -1004,6 +1004,7 @@ bool permissive) { pimpl_->file_.reset(new DcmFileFormat); + pimpl_->frameIndex_.reset(NULL); const DicomValue* tmp = source.TestAndGetValue(DICOM_TAG_SPECIFIC_CHARACTER_SET); @@ -1091,7 +1092,7 @@ bool keepSopInstanceUid) : pimpl_(new PImpl) { - pimpl_->file_.reset(dynamic_cast(other.pimpl_->file_->clone())); + pimpl_->file_.reset(dynamic_cast(other.GetDcmtkObject().clone())); if (!keepSopInstanceUid) { @@ -1121,7 +1122,30 @@ DcmFileFormat& ParsedDicomFile::GetDcmtkObject() const { - return *pimpl_->file_.get(); + if (pimpl_->file_.get() == NULL) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls, + "ReleaseDcmtkObject() was called"); + } + else + { + return *pimpl_->file_; + } + } + + + DcmFileFormat* ParsedDicomFile::ReleaseDcmtkObject() + { + if (pimpl_->file_.get() == NULL) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls, + "ReleaseDcmtkObject() was called"); + } + else + { + pimpl_->frameIndex_.reset(NULL); + return pimpl_->file_.release(); + } } @@ -1354,7 +1378,7 @@ } } - if (!pimpl_->file_->getDataset()->insert(pixels.release(), false, false).good()) + if (!GetDcmtkObject().getDataset()->insert(pixels.release(), false, false).good()) { throw OrthancException(ErrorCode_InternalError); } @@ -1364,7 +1388,7 @@ Encoding ParsedDicomFile::DetectEncoding(bool& hasCodeExtensions) const { return FromDcmtkBridge::DetectEncoding(hasCodeExtensions, - *pimpl_->file_->getDataset(), + *GetDcmtkObject().getDataset(), GetDefaultDicomEncoding()); } @@ -1388,7 +1412,7 @@ unsigned int maxStringLength) { std::set ignoreTagLength; - FromDcmtkBridge::ExtractDicomAsJson(target, *pimpl_->file_->getDataset(), + FromDcmtkBridge::ExtractDicomAsJson(target, *GetDcmtkObject().getDataset(), format, flags, maxStringLength, GetDefaultDicomEncoding(), ignoreTagLength); } @@ -1400,7 +1424,7 @@ unsigned int maxStringLength, const std::set& ignoreTagLength) { - FromDcmtkBridge::ExtractDicomAsJson(target, *pimpl_->file_->getDataset(), + FromDcmtkBridge::ExtractDicomAsJson(target, *GetDcmtkObject().getDataset(), format, flags, maxStringLength, GetDefaultDicomEncoding(), ignoreTagLength); } @@ -1409,28 +1433,28 @@ void ParsedDicomFile::DatasetToJson(Json::Value& target, const std::set& ignoreTagLength) { - FromDcmtkBridge::ExtractDicomAsJson(target, *pimpl_->file_->getDataset(), ignoreTagLength); + FromDcmtkBridge::ExtractDicomAsJson(target, *GetDcmtkObject().getDataset(), ignoreTagLength); } void ParsedDicomFile::DatasetToJson(Json::Value& target) { const std::set ignoreTagLength; - FromDcmtkBridge::ExtractDicomAsJson(target, *pimpl_->file_->getDataset(), ignoreTagLength); + FromDcmtkBridge::ExtractDicomAsJson(target, *GetDcmtkObject().getDataset(), ignoreTagLength); } void ParsedDicomFile::HeaderToJson(Json::Value& target, DicomToJsonFormat format) { - FromDcmtkBridge::ExtractHeaderAsJson(target, *pimpl_->file_->getMetaInfo(), format, DicomToJsonFlags_None, 0); + FromDcmtkBridge::ExtractHeaderAsJson(target, *GetDcmtkObject().getMetaInfo(), format, DicomToJsonFlags_None, 0); } bool ParsedDicomFile::HasTag(const DicomTag& tag) const { DcmTag key(tag.GetGroup(), tag.GetElement()); - return pimpl_->file_->getDataset()->tagExists(key); + return GetDcmtkObject().getDataset()->tagExists(key); } @@ -1472,7 +1496,7 @@ memcpy(bytes, pdf.c_str(), pdf.size()); DcmPolymorphOBOW* obj = element.release(); - result = pimpl_->file_->getDataset()->insert(obj); + result = GetDcmtkObject().getDataset()->insert(obj); if (!result.good()) { @@ -1564,13 +1588,13 @@ if (pimpl_->frameIndex_.get() == NULL) { assert(pimpl_->file_ != NULL && - pimpl_->file_->getDataset() != NULL); - pimpl_->frameIndex_.reset(new DicomFrameIndex(*pimpl_->file_->getDataset())); + GetDcmtkObject().getDataset() != NULL); + pimpl_->frameIndex_.reset(new DicomFrameIndex(*GetDcmtkObject().getDataset())); } pimpl_->frameIndex_->GetRawFrame(target, frameId); - E_TransferSyntax transferSyntax = pimpl_->file_->getDataset()->getCurrentXfer(); + E_TransferSyntax transferSyntax = GetDcmtkObject().getDataset()->getCurrentXfer(); switch (transferSyntax) { case EXS_JPEGProcess1: @@ -1598,8 +1622,8 @@ unsigned int ParsedDicomFile::GetFramesCount() const { assert(pimpl_->file_ != NULL && - pimpl_->file_->getDataset() != NULL); - return DicomFrameIndex::GetFramesCount(*pimpl_->file_->getDataset()); + GetDcmtkObject().getDataset() != NULL); + return DicomFrameIndex::GetFramesCount(*GetDcmtkObject().getDataset()); } @@ -1611,21 +1635,21 @@ if (source != target) // Avoid unnecessary conversion { ReplacePlainString(DICOM_TAG_SPECIFIC_CHARACTER_SET, GetDicomSpecificCharacterSet(target)); - FromDcmtkBridge::ChangeStringEncoding(*pimpl_->file_->getDataset(), source, hasCodeExtensions, target); + FromDcmtkBridge::ChangeStringEncoding(*GetDcmtkObject().getDataset(), source, hasCodeExtensions, target); } } void ParsedDicomFile::ExtractDicomSummary(DicomMap& target) const { - FromDcmtkBridge::ExtractDicomSummary(target, *pimpl_->file_->getDataset()); + FromDcmtkBridge::ExtractDicomSummary(target, *GetDcmtkObject().getDataset()); } void ParsedDicomFile::ExtractDicomSummary(DicomMap& target, const std::set& ignoreTagLength) const { - FromDcmtkBridge::ExtractDicomSummary(target, *pimpl_->file_->getDataset(), ignoreTagLength); + FromDcmtkBridge::ExtractDicomSummary(target, *GetDcmtkObject().getDataset(), ignoreTagLength); } @@ -1635,9 +1659,8 @@ // using the meta header? const char* value = NULL; - assert(pimpl_->file_ != NULL); - if (pimpl_->file_->getMetaInfo() != NULL && - pimpl_->file_->getMetaInfo()->findAndGetString(DCM_TransferSyntaxUID, value).good() && + if (GetDcmtkObject().getMetaInfo() != NULL && + GetDcmtkObject().getMetaInfo()->findAndGetString(DCM_TransferSyntaxUID, value).good() && value != NULL) { result.assign(value); @@ -1655,7 +1678,7 @@ DcmTagKey k(DICOM_TAG_PHOTOMETRIC_INTERPRETATION.GetGroup(), DICOM_TAG_PHOTOMETRIC_INTERPRETATION.GetElement()); - DcmDataset& dataset = *pimpl_->file_->getDataset(); + DcmDataset& dataset = *GetDcmtkObject().getDataset(); const char *c = NULL; if (dataset.findAndGetString(k, c).good() && @@ -1673,6 +1696,6 @@ void ParsedDicomFile::Apply(ITagVisitor& visitor) { - FromDcmtkBridge::Apply(*pimpl_->file_->getDataset(), visitor, GetDefaultDicomEncoding()); + FromDcmtkBridge::Apply(*GetDcmtkObject().getDataset(), visitor, GetDefaultDicomEncoding()); } } diff -r b26d25d3c1c7 -r aae045f802f4 Core/DicomParsing/ParsedDicomFile.h --- a/Core/DicomParsing/ParsedDicomFile.h Mon May 18 21:37:31 2020 +0200 +++ b/Core/DicomParsing/ParsedDicomFile.h Tue May 19 10:17:06 2020 +0200 @@ -127,6 +127,9 @@ DcmFileFormat& GetDcmtkObject() const; + // The "ParsedDicomFile" object cannot be used after calling this method + DcmFileFormat* ReleaseDcmtkObject(); + ParsedDicomFile* Clone(bool keepSopInstanceUid); #if ORTHANC_ENABLE_CIVETWEB == 1 || ORTHANC_ENABLE_MONGOOSE == 1 diff -r b26d25d3c1c7 -r aae045f802f4 OrthancServer/ServerContext.cpp --- a/OrthancServer/ServerContext.cpp Mon May 18 21:37:31 2020 +0200 +++ b/OrthancServer/ServerContext.cpp Tue May 19 10:17:06 2020 +0200 @@ -1413,4 +1413,48 @@ return NULL; } } + + + bool ServerContext::Transcode(DicomImage& target, + bool& hasSopInstanceUidChanged /* out */, + DicomImage& source /* in, "GetParsed()" possibly modified */, + const std::set& allowedSyntaxes, + bool allowNewSopInstanceUid) + { + if (builtinDecoderTranscoderOrder_ == BuiltinDecoderTranscoderOrder_Before) + { + if (dcmtkTranscoder_->Transcode(target, hasSopInstanceUidChanged, source, + allowedSyntaxes, allowNewSopInstanceUid)) + { + return true; + } + } + +#if ORTHANC_ENABLE_PLUGINS == 1 + if (HasPlugins() && + GetPlugins().HasCustomTranscoder()) + { + if (GetPlugins().Transcode(target, hasSopInstanceUidChanged, source, + allowedSyntaxes, allowNewSopInstanceUid)) + { + return true; + } + else if (builtinDecoderTranscoderOrder_ == BuiltinDecoderTranscoderOrder_After) + { + LOG(INFO) << "The installed transcoding plugins cannot handle an image, " + << "fallback to the built-in DCMTK transcoder"; + } + } +#endif + + if (builtinDecoderTranscoderOrder_ == BuiltinDecoderTranscoderOrder_After) + { + return dcmtkTranscoder_->Transcode(target, hasSopInstanceUidChanged, source, + allowedSyntaxes, allowNewSopInstanceUid); + } + else + { + return false; + } + } } diff -r b26d25d3c1c7 -r aae045f802f4 OrthancServer/ServerContext.h --- a/OrthancServer/ServerContext.h Mon May 18 21:37:31 2020 +0200 +++ b/OrthancServer/ServerContext.h Tue May 19 10:17:06 2020 +0200 @@ -493,5 +493,11 @@ size_t size, const std::set& allowedSyntaxes, bool allowNewSopInstanceUid) ORTHANC_OVERRIDE; + + virtual bool Transcode(DicomImage& target, + bool& hasSopInstanceUidChanged /* out */, + DicomImage& source /* in, "GetParsed()" possibly modified */, + const std::set& allowedSyntaxes, + bool allowNewSopInstanceUid) ORTHANC_OVERRIDE; }; } diff -r b26d25d3c1c7 -r aae045f802f4 Plugins/Engine/OrthancPlugins.cpp --- a/Plugins/Engine/OrthancPlugins.cpp Mon May 18 21:37:31 2020 +0200 +++ b/Plugins/Engine/OrthancPlugins.cpp Tue May 19 10:17:06 2020 +0200 @@ -5212,12 +5212,12 @@ }; - bool OrthancPlugins::Transcode(std::string& target, - bool& hasSopInstanceUidChanged /* out */, - const void* buffer, - size_t size, - const std::set& allowedSyntaxes, - bool allowNewSopInstanceUid) + bool OrthancPlugins::TranscodeBuffer(std::string& target, + bool& hasSopInstanceUidChanged /* out */, + const void* buffer, + size_t size, + const std::set& allowedSyntaxes, + bool allowNewSopInstanceUid) { boost::shared_lock lock(pimpl_->decoderTranscoderMutex_); diff -r b26d25d3c1c7 -r aae045f802f4 Plugins/Engine/OrthancPlugins.h --- a/Plugins/Engine/OrthancPlugins.h Mon May 18 21:37:31 2020 +0200 +++ b/Plugins/Engine/OrthancPlugins.h Tue May 19 10:17:06 2020 +0200 @@ -239,12 +239,12 @@ protected: // From "MemoryBufferTranscoder" - virtual bool Transcode(std::string& target, - bool& hasSopInstanceUidChanged /* out */, - const void* buffer, - size_t size, - const std::set& allowedSyntaxes, - bool allowNewSopInstanceUid) ORTHANC_OVERRIDE; + virtual bool TranscodeBuffer(std::string& target, + bool& hasSopInstanceUidChanged /* out */, + const void* buffer, + size_t size, + const std::set& allowedSyntaxes, + bool allowNewSopInstanceUid) ORTHANC_OVERRIDE; public: OrthancPlugins();