diff OrthancFramework/Sources/DicomParsing/ParsedDicomFile.cpp @ 4683:7182f5732480

use of DicomPath in ParsedDicomFile
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 08 Jun 2021 12:37:48 +0200
parents 94147ce2f097
children 9f207131c7f4
line wrap: on
line diff
--- a/OrthancFramework/Sources/DicomParsing/ParsedDicomFile.cpp	Mon Jun 07 18:35:46 2021 +0200
+++ b/OrthancFramework/Sources/DicomParsing/ParsedDicomFile.cpp	Tue Jun 08 12:37:48 2021 +0200
@@ -482,44 +482,14 @@
 
   void ParsedDicomFile::Remove(const DicomTag& tag)
   {
-    InvalidateCache();
-
-    DcmTagKey key(tag.GetGroup(), tag.GetElement());
-    DcmElement* element = GetDcmtkObject().getDataset()->remove(key);
-    if (element != NULL)
-    {
-      delete element;
-    }
+    RemovePath(DicomPath(tag));
   }
 
 
   void ParsedDicomFile::Clear(const DicomTag& tag,
                               bool onlyIfExists)
   {
-    if (tag.GetElement() == 0x0000)
-    {
-      // Prevent manually modifying generic group length tags: This is
-      // handled by DCMTK serialization
-      return;
-    }
-
-    InvalidateCache();
-
-    DcmItem* dicom = GetDcmtkObject().getDataset();
-    DcmTagKey key(tag.GetGroup(), tag.GetElement());
-
-    if (onlyIfExists &&
-        !dicom->tagExists(key))
-    {
-      // The tag is non-existing, do not clear it
-    }
-    else
-    {
-      if (!dicom->insertEmptyElement(key, OFTrue /* replace old value */).good())
-      {
-        throw OrthancException(ErrorCode_InternalError);
-      }
-    }
+    ClearPath(DicomPath(tag), onlyIfExists);
   }
 
 
@@ -678,7 +648,8 @@
           return true;
 
         case DicomReplaceMode_ThrowIfAbsent:
-          throw OrthancException(ErrorCode_InexistentItem);
+          throw OrthancException(ErrorCode_InexistentItem, "Cannot replace inexistent tag: " +
+                                 FromDcmtkBridge::GetTagName(DicomTag(tag.getGroup(), tag.getElement()), ""));
 
         case DicomReplaceMode_IgnoreIfAbsent:
           return false;
@@ -758,36 +729,59 @@
       // handled by DCMTK serialization
       return;
     }
-
-    InvalidateCache();
-
-    DcmDataset& dicom = *GetDcmtkObject().getDataset();
-    if (CanReplaceProceed(dicom, ToDcmtkBridge::Convert(tag), mode))
+    else
     {
-      // Either the tag was previously existing (and now removed), or
-      // the replace mode was set to "InsertIfAbsent"
+      InvalidateCache();
+
+      DcmDataset& dicom = *GetDcmtkObject().getDataset();
+      if (CanReplaceProceed(dicom, ToDcmtkBridge::Convert(tag), mode))
+      {
+        // Either the tag was previously existing (and now removed), or
+        // the replace mode was set to "InsertIfAbsent"
+
+        if (decodeDataUriScheme &&
+            (tag == DICOM_TAG_ENCAPSULATED_DOCUMENT ||
+             tag == DICOM_TAG_PIXEL_DATA))
+        {
+          if (EmbedContentInternal(utf8Value))
+          {
+            return;
+          }
+        }
+
+        std::unique_ptr<DcmElement> element(FromDcmtkBridge::CreateElementForTag(tag, privateCreator));
 
-      if (decodeDataUriScheme &&
-          (tag == DICOM_TAG_ENCAPSULATED_DOCUMENT ||
-           tag == DICOM_TAG_PIXEL_DATA))
-      {
-        if (EmbedContentInternal(utf8Value))
+        if (!utf8Value.empty())
+        {
+          bool hasCodeExtensions;
+          Encoding encoding = DetectEncoding(hasCodeExtensions);
+          FromDcmtkBridge::FillElementWithString(*element, utf8Value, decodeDataUriScheme, encoding);
+        }
+
+        InsertInternal(dicom, element.release());
+
+        if (tag == DICOM_TAG_SOP_CLASS_UID ||
+            tag == DICOM_TAG_SOP_INSTANCE_UID)
         {
-          return;
+          if (decodeDataUriScheme &&
+              boost::starts_with(utf8Value, URI_SCHEME_PREFIX_BINARY))
+          {
+            std::string mime, decoded;
+            if (!Toolbox::DecodeDataUriScheme(mime, decoded, utf8Value))
+            {
+              throw OrthancException(ErrorCode_BadFileFormat);
+            }
+            else
+            {
+              UpdateStorageUid(tag, decoded, false);
+            }
+          }
+          else
+          {
+            UpdateStorageUid(tag, utf8Value, false);
+          }
         }
       }
-
-      std::unique_ptr<DcmElement> element(FromDcmtkBridge::CreateElementForTag(tag, privateCreator));
-
-      if (!utf8Value.empty())
-      {
-        bool hasCodeExtensions;
-        Encoding encoding = DetectEncoding(hasCodeExtensions);
-        FromDcmtkBridge::FillElementWithString(*element, utf8Value, decodeDataUriScheme, encoding);
-      }
-
-      InsertInternal(dicom, element.release());
-      UpdateStorageUid(tag, utf8Value, false);
     }
   }
 
@@ -804,39 +798,30 @@
       // handled by DCMTK serialization
       return;
     }
-
-    InvalidateCache();
-
-    DcmDataset& dicom = *GetDcmtkObject().getDataset();
-    if (CanReplaceProceed(dicom, ToDcmtkBridge::Convert(tag), mode))
+    else if (value.type() == Json::stringValue)
     {
-      // Either the tag was previously existing (and now removed), or
-      // the replace mode was set to "InsertIfAbsent"
-
-      if (decodeDataUriScheme &&
-          value.type() == Json::stringValue &&
-          (tag == DICOM_TAG_ENCAPSULATED_DOCUMENT ||
-           tag == DICOM_TAG_PIXEL_DATA))
-      {
-        if (EmbedContentInternal(value.asString()))
-        {
-          return;
-        }
-      }
-
-      bool hasCodeExtensions;
-      Encoding encoding = DetectEncoding(hasCodeExtensions);
-      InsertInternal(dicom, FromDcmtkBridge::FromJson(tag, value, decodeDataUriScheme, encoding, privateCreator));
-
+      Replace(tag, value.asString(), decodeDataUriScheme, mode, privateCreator);
+    }
+    else
+    {
       if (tag == DICOM_TAG_SOP_CLASS_UID ||
           tag == DICOM_TAG_SOP_INSTANCE_UID)
       {
-        if (value.type() != Json::stringValue)
-        {
-          throw OrthancException(ErrorCode_BadParameterType);
-        }
+        // Must be a string
+        throw OrthancException(ErrorCode_BadParameterType);
+      }
+
+      InvalidateCache();
 
-        UpdateStorageUid(tag, value.asString(), decodeDataUriScheme);
+      DcmDataset& dicom = *GetDcmtkObject().getDataset();
+      if (CanReplaceProceed(dicom, ToDcmtkBridge::Convert(tag), mode))
+      {
+        // Either the tag was previously existing (and now removed), or
+        // the replace mode was set to "InsertIfAbsent"
+
+        bool hasCodeExtensions;
+        Encoding encoding = DetectEncoding(hasCodeExtensions);
+        InsertInternal(dicom, FromDcmtkBridge::FromJson(tag, value, decodeDataUriScheme, encoding, privateCreator));
       }
     }
   }
@@ -1724,6 +1709,74 @@
   }
 
 
+  static bool HasGenericGroupLength(const DicomPath& path)
+  {
+    for (size_t i = 0; i < path.GetPrefixLength(); i++)
+    {
+      if (path.GetPrefixTag(i).GetElement() == 0x0000)
+      {
+        return true;
+      }
+    }
+    
+    return (path.GetFinalTag().GetElement() == 0x0000);
+  }
+  
+
+  void ParsedDicomFile::ReplacePath(const DicomPath& path,
+                                    const Json::Value& value,
+                                    bool decodeDataUriScheme,
+                                    DicomReplaceMode mode,
+                                    const std::string& privateCreator)
+  {
+    if (HasGenericGroupLength(path))
+    {
+      // Prevent manually modifying generic group length tags: This is
+      // handled by DCMTK serialization
+      return;
+    }
+    else if (path.GetPrefixLength() == 0)
+    {
+      Replace(path.GetFinalTag(), value, decodeDataUriScheme, mode, privateCreator);
+    }
+    else
+    {
+      InvalidateCache();
+
+      bool hasCodeExtensions;
+      Encoding encoding = DetectEncoding(hasCodeExtensions);
+      std::unique_ptr<DcmElement> element(
+        FromDcmtkBridge::FromJson(path.GetFinalTag(), value, decodeDataUriScheme, encoding, privateCreator));
+
+      FromDcmtkBridge::ReplacePath(*GetDcmtkObject().getDataset(), path, *element, mode);
+    }
+  }
+  
+
+  void ParsedDicomFile::RemovePath(const DicomPath& path)
+  {
+    InvalidateCache();
+    FromDcmtkBridge::RemovePath(*GetDcmtkObject().getDataset(), path);
+  }
+
+
+  void ParsedDicomFile::ClearPath(const DicomPath& path,
+                                  bool onlyIfExists)
+  {
+    if (HasGenericGroupLength(path))
+    {
+      // Prevent manually modifying generic group length tags: This is
+      // handled by DCMTK serialization
+      return;
+    }
+    else
+    {
+      InvalidateCache();
+      FromDcmtkBridge::ClearPath(*GetDcmtkObject().getDataset(), path, onlyIfExists);
+    }
+  }
+
+
 #if ORTHANC_BUILDING_FRAMEWORK_LIBRARY == 1
   // Alias for binary compatibility with Orthanc Framework 1.7.2 => don't use it anymore
   void ParsedDicomFile::DatasetToJson(Json::Value& target,