# HG changeset patch # User Sebastien Jodogne # Date 1423646777 -3600 # Node ID f796207e3df1eccbf7917d16e5b15b56f876e962 # Parent 8cd5784a6d80429ce26eaebfd6143cb076867fd5 Fix replacement and insertion of private DICOM tags diff -r 8cd5784a6d80 -r f796207e3df1 NEWS --- a/NEWS Tue Feb 10 17:17:25 2015 +0100 +++ b/NEWS Wed Feb 11 10:26:17 2015 +0100 @@ -31,6 +31,7 @@ * Code refactorings * Fix issue 25 (AET with underscore not allowed) +* Fix replacement and insertion of private DICOM tags Version 0.8.5 (2014/11/04) diff -r 8cd5784a6d80 -r f796207e3df1 OrthancServer/FromDcmtkBridge.cpp --- a/OrthancServer/FromDcmtkBridge.cpp Tue Feb 10 17:17:25 2015 +0100 +++ b/OrthancServer/FromDcmtkBridge.cpp Wed Feb 11 10:26:17 2015 +0100 @@ -186,15 +186,27 @@ bool FromDcmtkBridge::IsPrivateTag(DcmTag& tag) { +#if 1 + DcmTagKey tmp(tag.getGTag(), tag.getETag()); + return tmp.isPrivate(); +#else + // Implementation for Orthanc versions <= 0.8.5 return (tag.getPrivateCreator() != NULL || !strcmp("PrivateCreator", tag.getTagName())); // TODO - This may change with future versions of DCMTK +#endif } bool FromDcmtkBridge::IsPrivateTag(const DicomTag& tag) { +#if 1 + DcmTagKey tmp(tag.GetGroup(), tag.GetElement()); + return tmp.isPrivate(); +#else + // Implementation for Orthanc versions <= 0.8.5 DcmTag tmp(tag.GetGroup(), tag.GetElement()); return IsPrivateTag(tmp); +#endif } diff -r 8cd5784a6d80 -r f796207e3df1 OrthancServer/ParsedDicomFile.cpp --- a/OrthancServer/ParsedDicomFile.cpp Tue Feb 10 17:17:25 2015 +0100 +++ b/OrthancServer/ParsedDicomFile.cpp Wed Feb 11 10:26:17 2015 +0100 @@ -807,13 +807,30 @@ + void ParsedDicomFile::Insert(const DicomTag& tag, const std::string& value) { - std::auto_ptr element(CreateElementForTag(tag)); - FillElementWithString(*element, tag, value); + OFCondition cond; + + if (FromDcmtkBridge::IsPrivateTag(tag)) + { + // This is a private tag + // http://support.dcmtk.org/redmine/projects/dcmtk/wiki/howto_addprivatedata - if (!pimpl_->file_->getDataset()->insert(element.release(), false, false).good()) + DcmTag key(tag.GetGroup(), tag.GetElement(), EVR_OB); + cond = pimpl_->file_->getDataset()->putAndInsertUint8Array + (key, (const Uint8*) value.c_str(), value.size(), false); + } + else + { + std::auto_ptr element(CreateElementForTag(tag)); + FillElementWithString(*element, tag, value); + + cond = pimpl_->file_->getDataset()->insert(element.release(), false, false); + } + + if (!cond.good()) { // This field already exists throw OrthancException(ErrorCode_InternalError); @@ -847,7 +864,17 @@ } else { - FillElementWithString(*element, tag, value); + if (FromDcmtkBridge::IsPrivateTag(tag)) + { + if (!element->putUint8Array((const Uint8*) value.c_str(), value.size()).good()) + { + throw OrthancException(ErrorCode_InternalError); + } + } + else + { + FillElementWithString(*element, tag, value); + } } @@ -888,25 +915,53 @@ { DcmTagKey k(tag.GetGroup(), tag.GetElement()); DcmDataset& dataset = *pimpl_->file_->getDataset(); - DcmElement* element = NULL; - if (!dataset.findAndGetElement(k, element).good() || - element == NULL) + + if (FromDcmtkBridge::IsPrivateTag(tag)) { - return false; - } + const Uint8* data = NULL; // This is freed in the destructor of the dataset + long unsigned int count = 0; - std::auto_ptr v(FromDcmtkBridge::ConvertLeafElement(*element, pimpl_->encoding_)); + if (dataset.findAndGetUint8Array(k, data, &count).good()) + { + if (count > 0) + { + assert(data != NULL); + value.assign(reinterpret_cast(data), count); + } + else + { + value.clear(); + } - if (v.get() == NULL) - { - value = ""; + return true; + } + else + { + return false; + } } else { - value = v->AsString(); + DcmElement* element = NULL; + if (!dataset.findAndGetElement(k, element).good() || + element == NULL) + { + return false; + } + + std::auto_ptr v(FromDcmtkBridge::ConvertLeafElement(*element, pimpl_->encoding_)); + + if (v.get() == NULL) + { + value = ""; + } + else + { + value = v->AsString(); + } + + return true; } - - return true; } diff -r 8cd5784a6d80 -r f796207e3df1 Resources/Samples/Lua/AutoroutingModification.lua --- a/Resources/Samples/Lua/AutoroutingModification.lua Tue Feb 10 17:17:25 2015 +0100 +++ b/Resources/Samples/Lua/AutoroutingModification.lua Wed Feb 11 10:26:17 2015 +0100 @@ -7,6 +7,7 @@ -- The tags to be replaced local replace = {} replace['StationName'] = 'My Medical Device' + replace['0031-1020'] = 'Some private tag' -- The tags to be removed local remove = { 'MilitaryRank' } diff -r 8cd5784a6d80 -r f796207e3df1 UnitTestsSources/FromDcmtkTests.cpp --- a/UnitTestsSources/FromDcmtkTests.cpp Tue Feb 10 17:17:25 2015 +0100 +++ b/UnitTestsSources/FromDcmtkTests.cpp Wed Feb 11 10:26:17 2015 +0100 @@ -89,14 +89,35 @@ TEST(DicomModification, Anonymization) { + ASSERT_EQ(DICOM_TAG_PATIENT_NAME, FromDcmtkBridge::ParseTag("PatientName")); + const DicomTag privateTag(0x0045, 0x0010); + const DicomTag privateTag2(FromDcmtkBridge::ParseTag("0031-1020")); ASSERT_TRUE(FromDcmtkBridge::IsPrivateTag(privateTag)); + ASSERT_TRUE(FromDcmtkBridge::IsPrivateTag(privateTag2)); + ASSERT_EQ(0x0031, privateTag2.GetGroup()); + ASSERT_EQ(0x1020, privateTag2.GetElement()); + std::string s; ParsedDicomFile o; o.Replace(DICOM_TAG_PATIENT_NAME, "coucou"); - o.Replace(privateTag, "private tag"); + ASSERT_FALSE(o.GetTagValue(s, privateTag)); + o.Insert(privateTag, "private tag"); + ASSERT_TRUE(o.GetTagValue(s, privateTag)); + ASSERT_STREQ("private tag", s.c_str()); - std::string s; + ASSERT_FALSE(o.GetTagValue(s, privateTag2)); + ASSERT_THROW(o.Replace(privateTag2, "hello", DicomReplaceMode_ThrowIfAbsent), OrthancException); + ASSERT_FALSE(o.GetTagValue(s, privateTag2)); + o.Replace(privateTag2, "hello", DicomReplaceMode_IgnoreIfAbsent); + ASSERT_FALSE(o.GetTagValue(s, privateTag2)); + o.Replace(privateTag2, "hello", DicomReplaceMode_InsertIfAbsent); + ASSERT_TRUE(o.GetTagValue(s, privateTag2)); + ASSERT_STREQ("hello", s.c_str()); + o.Replace(privateTag2, "hello world"); + ASSERT_TRUE(o.GetTagValue(s, privateTag2)); + ASSERT_STREQ("hello world", s.c_str()); + ASSERT_TRUE(o.GetTagValue(s, DICOM_TAG_PATIENT_NAME)); ASSERT_FALSE(Toolbox::IsUuid(s)); @@ -109,7 +130,7 @@ 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); + ASSERT_STREQ("private tag", s.c_str()); m.SetupAnonymization(); m.Apply(o);