diff OrthancServer/FromDcmtkBridge.cpp @ 2115:a657f7772e69

Handling of private tags/creators in the "Dictionary" configuration option
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 31 Oct 2016 15:23:32 +0100
parents ec2ad6ac741e
children 2fabd1073728
line wrap: on
line diff
--- a/OrthancServer/FromDcmtkBridge.cpp	Thu Oct 27 12:37:30 2016 +0200
+++ b/OrthancServer/FromDcmtkBridge.cpp	Mon Oct 31 15:23:32 2016 +0100
@@ -237,7 +237,8 @@
                                               ValueRepresentation vr,
                                               const std::string& name,
                                               unsigned int minMultiplicity,
-                                              unsigned int maxMultiplicity)
+                                              unsigned int maxMultiplicity,
+                                              const std::string& privateCreator)
   {
     if (minMultiplicity < 1)
     {
@@ -261,14 +262,55 @@
               << name << " (multiplicity: " << minMultiplicity << "-" 
               << (arbitrary ? "n" : boost::lexical_cast<std::string>(maxMultiplicity)) << ")";
 
-    std::auto_ptr<DcmDictEntry>  entry(new DcmDictEntry(tag.GetGroup(),
-                                                        tag.GetElement(),
-                                                        evr, name.c_str(),
-                                                        static_cast<int>(minMultiplicity),
-                                                        static_cast<int>(maxMultiplicity),
-                                                        NULL    /* version */,
-                                                        OFTrue  /* doCopyString */,
-                                                        NULL    /* private creator */));
+    std::auto_ptr<DcmDictEntry>  entry;
+    if (privateCreator.empty())
+    {
+      if (tag.GetGroup() % 2 == 1)
+      {
+        char buf[128];
+        sprintf(buf, "Warning: You are registering a private tag (%04x,%04x), "
+                "but no private creator was associated with it", 
+                tag.GetGroup(), tag.GetElement());
+        LOG(WARNING) << buf;
+      }
+
+      entry.reset(new DcmDictEntry(tag.GetGroup(),
+                                   tag.GetElement(),
+                                   evr, name.c_str(),
+                                   static_cast<int>(minMultiplicity),
+                                   static_cast<int>(maxMultiplicity),
+                                   NULL    /* version */,
+                                   OFTrue  /* doCopyString */,
+                                   NULL    /* private creator */));
+    }
+    else
+    {
+      // "Private Data Elements have an odd Group Number that is not
+      // (0001,eeee), (0003,eeee), (0005,eeee), (0007,eeee), or
+      // (FFFF,eeee)."
+      if (tag.GetGroup() % 2 == 0 /* even */ ||
+          tag.GetGroup() == 0x0001 ||
+          tag.GetGroup() == 0x0003 ||
+          tag.GetGroup() == 0x0005 ||
+          tag.GetGroup() == 0x0007 ||
+          tag.GetGroup() == 0xffff)
+      {
+        char buf[128];
+        sprintf(buf, "Trying to register private tag (%04x,%04x), but it must have an odd group >= 0x0009",
+                tag.GetGroup(), tag.GetElement());
+        LOG(ERROR) << buf;
+        throw OrthancException(ErrorCode_ParameterOutOfRange);
+      }
+
+      entry.reset(new DcmDictEntry(tag.GetGroup(),
+                                   tag.GetElement(),
+                                   evr, name.c_str(),
+                                   static_cast<int>(minMultiplicity),
+                                   static_cast<int>(maxMultiplicity),
+                                   "private" /* version */,
+                                   OFTrue    /* doCopyString */,
+                                   privateCreator.c_str()));
+    }
 
     entry->setGroupRangeRestriction(DcmDictRange_Unspecified);
     entry->setElementRangeRestriction(DcmDictRange_Unspecified);
@@ -429,7 +471,7 @@
         }
     
         /**
-         * Numberic types
+         * Numeric types
          **/ 
       
         case EVR_SL:  // signed long
@@ -571,7 +613,7 @@
     }
 
     // This code gives access to the name of the private tags
-    const std::string tagName = FromDcmtkBridge::GetName(tag);
+    std::string tagName = FromDcmtkBridge::GetTagName(element);
     
     switch (format)
     {
@@ -818,19 +860,23 @@
   }
 
 
-  std::string FromDcmtkBridge::GetName(const DicomTag& t)
+
+  static std::string GetTagNameInternal(DcmTag& tag)
   {
-    // Some patches for important tags because of different DICOM
-    // dictionaries between DCMTK versions
-    std::string n = t.GetMainTagsName();
-    if (n.size() != 0)
     {
-      return n;
+      // Some patches for important tags because of different DICOM
+      // dictionaries between DCMTK versions
+      DicomTag tmp(tag.getGroup(), tag.getElement());
+      std::string n = tmp.GetMainTagsName();
+      if (n.size() != 0)
+      {
+        return n;
+      }
+      // End of patches
     }
-    // End of patches
 
 #if 0
-    DcmTagKey tag(t.GetGroup(), t.GetElement());
+    // This version explicitly calls the dictionary
     const DcmDataDictionary& dict = dcmDataDict.rdlock();
     const DcmDictEntry* entry = dict.findEntry(tag, NULL);
 
@@ -843,7 +889,6 @@
     dcmDataDict.unlock();
     return s;
 #else
-    DcmTag tag(t.GetGroup(), t.GetElement());
     const char* name = tag.getTagName();
     if (name == NULL)
     {
@@ -857,6 +902,31 @@
   }
 
 
+  std::string FromDcmtkBridge::GetTagName(const DicomTag& t,
+                                          const std::string& privateCreator)
+  {
+    DcmTag tag(t.GetGroup(), t.GetElement());
+
+    if (!privateCreator.empty())
+    {
+      tag.setPrivateCreator(privateCreator.c_str());
+    }
+
+    return GetTagNameInternal(tag);
+  }
+
+
+  std::string FromDcmtkBridge::GetTagName(const DcmElement& element)
+  {
+    // Copy the tag to ensure const-correctness of DcmElement. Note
+    // that the private creator information is also copied.
+    DcmTag tag(element.getTag());  
+
+    return GetTagNameInternal(tag);
+  }
+
+
+
   DicomTag FromDcmtkBridge::ParseTag(const char* name)
   {
     if (strlen(name) == 9 &&
@@ -941,23 +1011,26 @@
     for (DicomMap::Map::const_iterator 
            it = values.map_.begin(); it != values.map_.end(); ++it)
     {
+      // TODO Inject PrivateCreator if some is available in the DicomMap?
+      const std::string tagName = GetTagName(it->first, "");
+
       if (simplify)
       {
         if (it->second->IsNull())
         {
-          result[GetName(it->first)] = Json::nullValue;
+          result[tagName] = Json::nullValue;
         }
         else
         {
           // TODO IsBinary
-          result[GetName(it->first)] = it->second->GetContent();
+          result[tagName] = it->second->GetContent();
         }
       }
       else
       {
         Json::Value value = Json::objectValue;
 
-        value["Name"] = GetName(it->first);
+        value["Name"] = tagName;
 
         if (it->second->IsNull())
         {