Mercurial > hg > orthanc
changeset 991:2f76b92addd4
keep private tags during anonymization
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 02 Jul 2014 11:56:08 +0200 |
parents | 7cbcd580cd21 |
children | af014624dac1 b3d4f8a30324 40e5255e7dc5 |
files | OrthancServer/DicomModification.cpp OrthancServer/DicomModification.h OrthancServer/FromDcmtkBridge.cpp OrthancServer/FromDcmtkBridge.h OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp OrthancServer/ParsedDicomFile.cpp OrthancServer/ParsedDicomFile.h UnitTestsSources/FromDcmtkTests.cpp |
diffstat | 8 files changed, 108 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancServer/DicomModification.cpp Tue Jul 01 17:17:45 2014 +0200 +++ b/OrthancServer/DicomModification.cpp Wed Jul 02 11:56:08 2014 +0200 @@ -96,12 +96,18 @@ { removals_.erase(tag); replacements_.erase(tag); + + if (FromDcmtkBridge::IsPrivateTag(tag)) + { + privateTagsToKeep_.insert(tag); + } } void DicomModification::Remove(const DicomTag& tag) { removals_.insert(tag); replacements_.erase(tag); + privateTagsToKeep_.erase(tag); } bool DicomModification::IsRemoved(const DicomTag& tag) const @@ -113,6 +119,7 @@ const std::string& value) { removals_.erase(tag); + privateTagsToKeep_.erase(tag); replacements_[tag] = value; } @@ -153,6 +160,7 @@ removePrivateTags_ = true; level_ = ResourceType_Patient; uidMap_.clear(); + privateTagsToKeep_.clear(); // This is Table E.1-1 from PS 3.15-2008 - DICOM Part 15: Security and System Management Profiles removals_.insert(DicomTag(0x0008, 0x0014)); // Instance Creator UID @@ -261,11 +269,11 @@ // (1) Remove the private tags, if need be if (removePrivateTags_) { - toModify.RemovePrivateTags(); + toModify.RemovePrivateTags(privateTagsToKeep_); } // (2) Remove the tags specified by the user - for (Removals::const_iterator it = removals_.begin(); + for (SetOfTags::const_iterator it = removals_.begin(); it != removals_.end(); ++it) { toModify.Remove(*it);
--- a/OrthancServer/DicomModification.h Tue Jul 01 17:17:45 2014 +0200 +++ b/OrthancServer/DicomModification.h Wed Jul 02 11:56:08 2014 +0200 @@ -46,15 +46,16 @@ **/ private: - typedef std::set<DicomTag> Removals; + typedef std::set<DicomTag> SetOfTags; typedef std::map<DicomTag, std::string> Replacements; typedef std::map< std::pair<ResourceType, std::string>, std::string> UidMap; - Removals removals_; + SetOfTags removals_; Replacements replacements_; bool removePrivateTags_; ResourceType level_; UidMap uidMap_; + SetOfTags privateTagsToKeep_; void MapDicomIdentifier(ParsedDicomFile& dicom, ResourceType level);
--- a/OrthancServer/FromDcmtkBridge.cpp Tue Jul 01 17:17:45 2014 +0200 +++ b/OrthancServer/FromDcmtkBridge.cpp Wed Jul 02 11:56:08 2014 +0200 @@ -168,12 +168,32 @@ } + DicomTag FromDcmtkBridge::Convert(const DcmTag& tag) + { + return DicomTag(tag.getGTag(), tag.getETag()); + } + + DicomTag FromDcmtkBridge::GetTag(const DcmElement& element) { return DicomTag(element.getGTag(), element.getETag()); } + bool FromDcmtkBridge::IsPrivateTag(DcmTag& tag) + { + return (tag.getPrivateCreator() != NULL || + !strcmp("PrivateCreator", tag.getTagName())); // TODO - This may change with future versions of DCMTK + } + + + bool FromDcmtkBridge::IsPrivateTag(const DicomTag& tag) + { + DcmTag tmp(tag.GetGroup(), tag.GetElement()); + return IsPrivateTag(tmp); + } + + DicomValue* FromDcmtkBridge::ConvertLeafElement(DcmElement& element, Encoding encoding) { @@ -516,7 +536,7 @@ isxdigit(name[1]) && isxdigit(name[2]) && isxdigit(name[3]) && - name[4] == '-' && + (name[4] == '-' || name[4] == ',') && isxdigit(name[5]) && isxdigit(name[6]) && isxdigit(name[7]) &&
--- a/OrthancServer/FromDcmtkBridge.h Tue Jul 01 17:17:45 2014 +0200 +++ b/OrthancServer/FromDcmtkBridge.h Wed Jul 02 11:56:08 2014 +0200 @@ -48,8 +48,14 @@ static void Convert(DicomMap& target, DcmDataset& dataset); + static DicomTag Convert(const DcmTag& tag); + static DicomTag GetTag(const DcmElement& element); + static bool IsPrivateTag(DcmTag& tag); + + static bool IsPrivateTag(const DicomTag& tag); + static DicomValue* ConvertLeafElement(DcmElement& element, Encoding encoding);
--- a/OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp Tue Jul 01 17:17:45 2014 +0200 +++ b/OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp Wed Jul 02 11:56:08 2014 +0200 @@ -174,7 +174,8 @@ ParseListOfTags(target, request["Keep"], TagOperation_Keep); } - if (target.GetReplacement(DICOM_TAG_PATIENT_NAME) == patientName) + if (target.IsReplaced(DICOM_TAG_PATIENT_NAME) && + target.GetReplacement(DICOM_TAG_PATIENT_NAME) == patientName) { // Overwrite the random Patient's Name by one that is more // user-friendly (provided none was specified by the user)
--- a/OrthancServer/ParsedDicomFile.cpp Tue Jul 01 17:17:45 2014 +0200 +++ b/OrthancServer/ParsedDicomFile.cpp Wed Jul 02 11:56:08 2014 +0200 @@ -756,24 +756,42 @@ - void ParsedDicomFile::RemovePrivateTags() + void ParsedDicomFile::RemovePrivateTagsInternal(const std::set<DicomTag>* toKeep) { + DcmDataset& dataset = *pimpl_->file_->getDataset(); + + // Loop over the dataset to detect its private tags typedef std::list<DcmElement*> Tags; - Tags privateTags; - DcmDataset& dataset = *pimpl_->file_->getDataset(); for (unsigned long i = 0; i < dataset.card(); i++) { DcmElement* element = dataset.getElement(i); DcmTag tag(element->getTag()); - if (!strcmp("PrivateCreator", tag.getTagName()) || // TODO - This may change with future versions of DCMTK - tag.getPrivateCreator() != NULL) + + // Is this a private tag? + if (FromDcmtkBridge::IsPrivateTag(tag)) { - privateTags.push_back(element); + bool remove = true; + + // Check whether this private tag is to be kept + if (toKeep != NULL) + { + DicomTag tmp = FromDcmtkBridge::Convert(tag); + if (toKeep->find(tmp) != toKeep->end()) + { + remove = false; // Keep it + } + } + + if (remove) + { + privateTags.push_back(element); + } } } + // Loop over the detected private tags to remove them for (Tags::iterator it = privateTags.begin(); it != privateTags.end(); ++it) {
--- a/OrthancServer/ParsedDicomFile.h Tue Jul 01 17:17:45 2014 +0200 +++ b/OrthancServer/ParsedDicomFile.h Wed Jul 02 11:56:08 2014 +0200 @@ -51,6 +51,8 @@ void Setup(const char* content, size_t size); + void RemovePrivateTagsInternal(const std::set<DicomTag>* toKeep); + public: ParsedDicomFile(); // Create a minimal DICOM instance @@ -79,7 +81,15 @@ const std::string& value, DicomReplaceMode mode = DicomReplaceMode_InsertIfAbsent); - void RemovePrivateTags(); + void RemovePrivateTags() + { + RemovePrivateTagsInternal(NULL); + } + + void RemovePrivateTags(const std::set<DicomTag>& toKeep) + { + RemovePrivateTagsInternal(&toKeep); + } bool GetTagValue(std::string& value, const DicomTag& tag);
--- a/UnitTestsSources/FromDcmtkTests.cpp Tue Jul 01 17:17:45 2014 +0200 +++ b/UnitTestsSources/FromDcmtkTests.cpp Wed Jul 02 11:56:08 2014 +0200 @@ -40,6 +40,7 @@ #include "../Core/ImageFormats/ImageBuffer.h" #include "../Core/ImageFormats/PngReader.h" #include "../Core/ImageFormats/PngWriter.h" +#include "../Core/Uuid.h" using namespace Orthanc; @@ -85,6 +86,36 @@ } +TEST(DicomModification, Anonymization) +{ + const DicomTag privateTag(0x0045, 0x0010); + ASSERT_TRUE(FromDcmtkBridge::IsPrivateTag(privateTag)); + + ParsedDicomFile o; + o.Replace(DICOM_TAG_PATIENT_NAME, "coucou"); + o.Replace(privateTag, "private tag"); + + std::string s; + ASSERT_TRUE(o.GetTagValue(s, DICOM_TAG_PATIENT_NAME)); + ASSERT_FALSE(Toolbox::IsUuid(s)); + + DicomModification m; + m.SetupAnonymization(); + m.Keep(privateTag); + + m.Apply(o); + + ASSERT_TRUE(o.GetTagValue(s, DICOM_TAG_PATIENT_NAME)); + ASSERT_TRUE(Toolbox::IsUuid(s)); + ASSERT_TRUE(o.GetTagValue(s, privateTag)); + ASSERT_EQ("private tag", s); + + m.SetupAnonymization(); + m.Apply(o); + ASSERT_FALSE(o.GetTagValue(s, privateTag)); +} + + #include <dcmtk/dcmdata/dcuid.h> TEST(DicomModification, Png)