Mercurial > hg > orthanc
diff OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.cpp @ 4682:d38a7040474a
FromDcmtkBridge::RemovePath() and FromDcmtkBridge::ReplacePath()
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 07 Jun 2021 18:35:46 +0200 |
parents | 72af097bb92b |
children | 7182f5732480 |
line wrap: on
line diff
--- a/OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.cpp Mon Jun 07 17:05:48 2021 +0200 +++ b/OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.cpp Mon Jun 07 18:35:46 2021 +0200 @@ -2794,6 +2794,121 @@ DicomMap::LogMissingTagsForStore(patientId, studyInstanceUid, seriesInstanceUid, sopInstanceUid); } + + + static void ApplyInternal(FromDcmtkBridge::IDicomPathVisitor& visitor, + DcmItem& item, + const DicomPath& path, + size_t level) + { + if (level == path.GetPrefixLength()) + { + visitor.Visit(item, path.GetFinalTag()); + } + else + { + const DicomTag& tmp = path.GetPrefixTag(level); + DcmTagKey tag(tmp.GetGroup(), tmp.GetElement()); + + DcmSequenceOfItems *sequence = NULL; + if (item.findAndGetSequence(tag, sequence).good() && + sequence != NULL) + { + for (unsigned long i = 0; i < sequence->card(); i++) + { + if (path.IsPrefixUniversal(level) || + path.GetPrefixIndex(level) == static_cast<size_t>(i)) + { + DcmItem *child = sequence->getItem(i); + if (child != NULL) + { + ApplyInternal(visitor, *child, path, level + 1); + } + } + } + } + } + } + + + void FromDcmtkBridge::Apply(IDicomPathVisitor& visitor, + DcmDataset& dataset, + const DicomPath& path) + { + ApplyInternal(visitor, dataset, path, 0); + } + + + void FromDcmtkBridge::RemovePath(DcmDataset& dataset, + const DicomPath& path) + { + class Visitor : public FromDcmtkBridge::IDicomPathVisitor + { + public: + virtual void Visit(DcmItem& item, + const DicomTag& tag) ORTHANC_OVERRIDE + { + DcmTagKey tmp(tag.GetGroup(), tag.GetElement()); + std::unique_ptr<DcmElement> removed(item.remove(tmp)); + } + }; + + Visitor visitor; + Apply(visitor, dataset, path); + } + + + void FromDcmtkBridge::ReplacePath(DcmDataset& dataset, + const DicomPath& path, + const DcmElement& element) + { + class Visitor : public FromDcmtkBridge::IDicomPathVisitor + { + private: + std::unique_ptr<DcmElement> element_; + + public: + Visitor(const DcmElement& element) : + element_(dynamic_cast<DcmElement*>(element.clone())) + { + if (element_.get() == NULL) + { + throw OrthancException(ErrorCode_InternalError, "Cannot clone DcmElement"); + } + } + + virtual void Visit(DcmItem& item, + const DicomTag& tag) ORTHANC_OVERRIDE + { + std::unique_ptr<DcmElement> cloned(dynamic_cast<DcmElement*>(element_->clone())); + if (cloned.get() == NULL) + { + throw OrthancException(ErrorCode_InternalError, "Cannot clone DcmElement"); + } + else + { + DcmTagKey tmp(tag.GetGroup(), tag.GetElement()); + if (!item.insert(cloned.release(), OFTrue /* replace old */).good()) + { + throw OrthancException(ErrorCode_InternalError, "Cannot replace an element"); + } + } + } + }; + + DcmTagKey tmp(path.GetFinalTag().GetGroup(), path.GetFinalTag().GetElement()); + + if (element.getTag() != tmp) + { + throw OrthancException(ErrorCode_ParameterOutOfRange, + "The final tag must be the same as the tag of the element during a replacement"); + } + else + { + Visitor visitor(element); + Apply(visitor, dataset, path); + } + } }