diff OrthancServer/ParsedDicomFile.cpp @ 1693:558b25228a23

creation of tag hierarchy from json
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 08 Oct 2015 13:45:33 +0200
parents 26083d84d237
children 06d579e82bb8
line wrap: on
line diff
--- a/OrthancServer/ParsedDicomFile.cpp	Thu Oct 08 10:57:29 2015 +0200
+++ b/OrthancServer/ParsedDicomFile.cpp	Thu Oct 08 13:45:33 2015 +0200
@@ -137,6 +137,7 @@
 
 #include <boost/math/special_functions/round.hpp>
 #include <dcmtk/dcmdata/dcostrmb.h>
+#include <boost/algorithm/string/predicate.hpp>
 
 
 static const char* CONTENT_TYPE_OCTET_STREAM = "application/octet-stream";
@@ -579,52 +580,49 @@
   }
 
 
-  void ParsedDicomFile::Insert(const DicomTag& tag,
-                               const std::string& value)
+  static void InsertInternal(DcmDataset& dicom,
+                             DcmElement* element)
   {
-    OFCondition cond;
-
-    if (FromDcmtkBridge::IsPrivateTag(tag) ||
-        FromDcmtkBridge::IsUnknownTag(tag))
-    {
-      // This is a private tag
-      // http://support.dcmtk.org/redmine/projects/dcmtk/wiki/howto_addprivatedata
-
-      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<DcmElement> element(FromDcmtkBridge::CreateElementForTag(tag));
-      FromDcmtkBridge::FillElementWithString(*element, tag, value, false);
-
-      cond = pimpl_->file_->getDataset()->insert(element.release(), false, false);
-    }
-
+    OFCondition cond = dicom.insert(element, false, false);
     if (!cond.good())
     {
       // This field already exists
+      delete element;
       throw OrthancException(ErrorCode_InternalError);
     }
   }
 
 
-  void ParsedDicomFile::Replace(const DicomTag& tag,
-                                const std::string& value,
-                                DicomReplaceMode mode)
+  void ParsedDicomFile::Insert(const DicomTag& tag,
+                               const std::string& value)
+  {
+    std::auto_ptr<DcmElement> element(FromDcmtkBridge::CreateElementForTag(tag));
+    FromDcmtkBridge::FillElementWithString(*element, tag, value, false);
+    InsertInternal(*pimpl_->file_->getDataset(), element.release());
+  }
+
+
+  void ParsedDicomFile::Insert(const DicomTag& tag,
+                               const Json::Value& value,
+                               bool decodeBinaryTags)
   {
-    DcmTagKey key(tag.GetGroup(), tag.GetElement());
-    DcmElement* element = NULL;
+    std::auto_ptr<DcmElement> element(FromDcmtkBridge::FromJson(tag, value, decodeBinaryTags));
+    InsertInternal(*pimpl_->file_->getDataset(), element.release());
+  }
+
 
-    if (!pimpl_->file_->getDataset()->findAndGetElement(key, element).good() ||
-        element == NULL)
+  static void ReplaceInternal(DcmDataset& dicom,
+                              std::auto_ptr<DcmElement>& element,
+                              DicomReplaceMode mode)
+  {
+    const DcmTagKey& tag = element->getTag();
+
+    if (!dicom.findAndDeleteElement(tag).good())
     {
       // This field does not exist, act wrt. the specified "mode"
       switch (mode)
       {
         case DicomReplaceMode_InsertIfAbsent:
-          Insert(tag, value);
           break;
 
         case DicomReplaceMode_ThrowIfAbsent:
@@ -634,11 +632,33 @@
           return;
       }
     }
-    else
+
+    // Either the tag was not existing, or the replace mode was set to
+    // "InsertIfAbsent"
+    InsertInternal(dicom, element.release());
+  }
+
+
+  void ParsedDicomFile::UpdateStorageUid(const DicomTag& tag,
+                                         const std::string& value,
+                                         bool decodeBinaryTags)
+  {
+    if (tag != DICOM_TAG_SOP_CLASS_UID &&
+        tag != DICOM_TAG_SOP_INSTANCE_UID)
     {
-      FromDcmtkBridge::FillElementWithString(*element, tag, value, false);
+      return;
     }
 
+    std::string binary;
+    const std::string* decoded = &value;
+
+    if (decodeBinaryTags &&
+        boost::starts_with(value, "data:application/octet-stream;base64,"))
+    {
+      std::string mime;
+      Toolbox::DecodeDataUriScheme(mime, binary, value);
+      decoded = &binary;
+    }
 
     /**
      * dcmodify will automatically correct 'Media Storage SOP Class
@@ -651,12 +671,44 @@
 
     if (tag == DICOM_TAG_SOP_CLASS_UID)
     {
-      Replace(DICOM_TAG_MEDIA_STORAGE_SOP_CLASS_UID, value, DicomReplaceMode_InsertIfAbsent);
+      Replace(DICOM_TAG_MEDIA_STORAGE_SOP_CLASS_UID, *decoded, DicomReplaceMode_InsertIfAbsent);
     }
 
     if (tag == DICOM_TAG_SOP_INSTANCE_UID)
     {
-      Replace(DICOM_TAG_MEDIA_STORAGE_SOP_INSTANCE_UID, value, DicomReplaceMode_InsertIfAbsent);
+      Replace(DICOM_TAG_MEDIA_STORAGE_SOP_INSTANCE_UID, *decoded, DicomReplaceMode_InsertIfAbsent);
+    }    
+  }
+
+
+  void ParsedDicomFile::Replace(const DicomTag& tag,
+                                const std::string& value,
+                                DicomReplaceMode mode)
+  {
+    std::auto_ptr<DcmElement> element(FromDcmtkBridge::CreateElementForTag(tag));
+    FromDcmtkBridge::FillElementWithString(*element, tag, value, false);
+    ReplaceInternal(*pimpl_->file_->getDataset(), element, mode);
+    UpdateStorageUid(tag, value, false);
+  }
+
+    
+  void ParsedDicomFile::Replace(const DicomTag& tag,
+                                const Json::Value& value,
+                                bool decodeBinaryTags,
+                                DicomReplaceMode mode)
+  {
+    std::auto_ptr<DcmElement> element(FromDcmtkBridge::FromJson(tag, value, decodeBinaryTags));
+    ReplaceInternal(*pimpl_->file_->getDataset(), element, mode);
+
+    if (tag == DICOM_TAG_SOP_CLASS_UID ||
+        tag == DICOM_TAG_SOP_INSTANCE_UID)
+    {
+      if (value.type() != Json::stringValue)
+      {
+        throw OrthancException(ErrorCode_BadParameterType);
+      }
+
+      UpdateStorageUid(tag, value.asString(), decodeBinaryTags);
     }
   }
 
@@ -865,7 +917,7 @@
     }
     else
     {
-      LOG(ERROR) << "Unsupported MIME type for the content of a new DICOM file";
+      LOG(ERROR) << "Unsupported MIME type for the content of a new DICOM file: " << mime;
       throw OrthancException(ErrorCode_NotImplemented);
     }
   }