diff OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.cpp @ 4734:b51c08bd5c38

added ITagVisitor::Action_Remove
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 05 Jul 2021 16:12:10 +0200
parents 569d9ef165b1
children 979ae3ea3381
line wrap: on
line diff
--- a/OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.cpp	Mon Jun 28 14:25:37 2021 +0200
+++ b/OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.cpp	Mon Jul 05 16:12:10 2021 +0200
@@ -2340,7 +2340,7 @@
 
 
   // Forward declaration
-  static void ApplyVisitorToElement(DcmElement& element,
+  static bool ApplyVisitorToElement(DcmElement& element,
                                     ITagVisitor& visitor,
                                     const std::vector<DicomTag>& parentTags,
                                     const std::vector<size_t>& parentIndexes,
@@ -2356,6 +2356,8 @@
   {
     assert(parentTags.size() == parentIndexes.size());
 
+    std::set<DcmTagKey> toRemove;
+    
     for (unsigned long i = 0; i < dataset.card(); i++)
     {
       DcmElement* element = dataset.getElement(i);
@@ -2365,13 +2367,25 @@
       }
       else
       {
-        ApplyVisitorToElement(*element, visitor, parentTags, parentIndexes, encoding, hasCodeExtensions);
+        if (!ApplyVisitorToElement(*element, visitor, parentTags, parentIndexes, encoding, hasCodeExtensions))
+        {
+          toRemove.insert(element->getTag());
+        }
       }      
     }
+
+    // Remove all the tags that were planned for removal (cf. ITagVisitor::Action_Remove)
+    for (std::set<DcmTagKey>::const_iterator
+           it = toRemove.begin(); it != toRemove.end(); ++it)
+    {
+      std::unique_ptr<DcmElement> tmp(dataset.remove(*it));
+    }
   }
 
 
-  static void ApplyVisitorToLeaf(DcmElement& element,
+  // Returns "true" iff the element must be kept. If "false" is
+  // returned, the element will be removed.
+  static bool ApplyVisitorToLeaf(DcmElement& element,
                                  ITagVisitor& visitor,
                                  const std::vector<DicomTag>& parentTags,
                                  const std::vector<size_t>& parentIndexes,
@@ -2415,11 +2429,13 @@
       Uint16* data16 = NULL;
       Uint8* data = NULL;
 
+      ITagVisitor::Action action;
+      
       if ((element.getTag() == DCM_PixelData ||  // (*) New in Orthanc 1.9.1
            evr == EVR_OW) &&
           element.getUint16Array(data16) == EC_Normal)
       {
-        visitor.VisitBinary(parentTags, parentIndexes, tag, vr, data16, element.getLength());
+        action = visitor.VisitBinary(parentTags, parentIndexes, tag, vr, data16, element.getLength());
       }
       else if (evr != EVR_OW &&
                element.getUint8Array(data) == EC_Normal)
@@ -2432,14 +2448,27 @@
          * reimplemented in derived class "DcmPixelData"). However,
          * "getUint16Array()" works correctly, hence (*).
          **/
-        visitor.VisitBinary(parentTags, parentIndexes, tag, vr, data, element.getLength());
+        action = visitor.VisitBinary(parentTags, parentIndexes, tag, vr, data, element.getLength());
       }
       else
       {
-        visitor.VisitNotSupported(parentTags, parentIndexes, tag, vr);
+        action = visitor.VisitNotSupported(parentTags, parentIndexes, tag, vr);
       }
 
-      return;  // We're done
+      switch (action)
+      {
+        case ITagVisitor::Action_None:
+          return true;  // We're done
+
+        case ITagVisitor::Action_Remove:
+          return false;
+
+        case ITagVisitor::Action_Replace:
+          throw OrthancException(ErrorCode_NotImplemented, "Iterator cannot replace binary data");
+
+        default:
+          throw OrthancException(ErrorCode_ParameterOutOfRange);
+      }
     }
 
 
@@ -2473,7 +2502,10 @@
       switch (action)
       {
         case ITagVisitor::Action_None:
-          break;
+          return true;
+
+        case ITagVisitor::Action_Remove:
+          return false;
 
         case ITagVisitor::Action_Replace:
         {
@@ -2481,20 +2513,20 @@
           if (element.putString(s.c_str()) != EC_Normal)
           {
             throw OrthancException(ErrorCode_InternalError,
-                                   "Cannot replace value of tag: " + tag.Format());
+                                   "Iterator cannot replace value of tag: " + tag.Format());
           }
 
-          break;
+          return true;
         }
 
         default:
           throw OrthancException(ErrorCode_InternalError);
       }
-
-      return;  // We're done
     }
 
 
+    ITagVisitor::Action action;
+    
     try
     {
       // http://support.dcmtk.org/docs/dcvr_8h-source.html
@@ -2522,7 +2554,7 @@
         case EVR_UI:  // unique identifier
         {
           Uint8* data = NULL;
-
+          
           if (element.getUint8Array(data) == EC_Normal)
           {
             const Uint32 length = element.getLength();
@@ -2536,30 +2568,30 @@
             if (l == length)
             {
               // Not a null-terminated plain string
-              visitor.VisitNotSupported(parentTags, parentIndexes, tag, vr);
+              action = visitor.VisitNotSupported(parentTags, parentIndexes, tag, vr);
             }
             else
             {
               std::string ignored;
               std::string s(reinterpret_cast<const char*>(data), l);
-              ITagVisitor::Action action = visitor.VisitString
-                (ignored, parentTags, parentIndexes, tag, vr,
-                 Toolbox::ConvertToUtf8(s, encoding, hasCodeExtensions));
-
-              if (action != ITagVisitor::Action_None)
-              {
-                LOG(WARNING) << "Cannot replace this string tag: "
-                             << FromDcmtkBridge::GetTagName(element)
-                             << " (" << tag.Format() << ")";
-              }
+              action = visitor.VisitString(ignored, parentTags, parentIndexes, tag, vr,
+                                           Toolbox::ConvertToUtf8(s, encoding, hasCodeExtensions));
             }
           }
           else
           {
-            visitor.VisitNotSupported(parentTags, parentIndexes, tag, vr);
+            action = visitor.VisitNotSupported(parentTags, parentIndexes, tag, vr);
           }
 
-          return;
+          if (action == ITagVisitor::Action_Replace)
+          {
+            LOG(WARNING) << "Iterator cannot replace this string tag: "
+                         << FromDcmtkBridge::GetTagName(element)
+                         << " (" << tag.Format() << ")";
+            return true;
+          }
+
+          break;
         }
     
         /**
@@ -2582,7 +2614,7 @@
             }
           }
 
-          visitor.VisitIntegers(parentTags, parentIndexes, tag, vr, values);
+          action = visitor.VisitIntegers(parentTags, parentIndexes, tag, vr, values);
           break;
         }
 
@@ -2602,7 +2634,7 @@
             }
           }
 
-          visitor.VisitIntegers(parentTags, parentIndexes, tag, vr, values);
+          action = visitor.VisitIntegers(parentTags, parentIndexes, tag, vr, values);
           break;
         }
 
@@ -2625,7 +2657,7 @@
             }
           }
 
-          visitor.VisitIntegers(parentTags, parentIndexes, tag, vr, values);
+          action = visitor.VisitIntegers(parentTags, parentIndexes, tag, vr, values);
           break;
         }
 
@@ -2645,7 +2677,7 @@
             }
           }
 
-          visitor.VisitIntegers(parentTags, parentIndexes, tag, vr, values);
+          action = visitor.VisitIntegers(parentTags, parentIndexes, tag, vr, values);
           break;
         }
 
@@ -2666,7 +2698,7 @@
             }
           }
 
-          visitor.VisitDoubles(parentTags, parentIndexes, tag, vr, values);
+          action = visitor.VisitDoubles(parentTags, parentIndexes, tag, vr, values);
           break;
         }
 
@@ -2689,7 +2721,7 @@
             }
           }
 
-          visitor.VisitDoubles(parentTags, parentIndexes, tag, vr, values);
+          action = visitor.VisitDoubles(parentTags, parentIndexes, tag, vr, values);
           break;
         }
 
@@ -2716,7 +2748,7 @@
           }
 
           assert(vr == ValueRepresentation_AttributeTag);
-          visitor.VisitAttributes(parentTags, parentIndexes, tag, values);
+          action = visitor.VisitAttributes(parentTags, parentIndexes, tag, values);
           break;
         }
 
@@ -2728,7 +2760,7 @@
 
         case EVR_SQ:  // sequence of items
         {
-          return;
+          return true;
         }
         
         
@@ -2751,8 +2783,8 @@
         case EVR_PixelData:  // used internally for uncompressed pixeld data
         case EVR_OverlayData:  // used internally for overlay data
         {
-          visitor.VisitNotSupported(parentTags, parentIndexes, tag, vr);
-          return;
+          action = visitor.VisitNotSupported(parentTags, parentIndexes, tag, vr);
+          break;
         }
         
 
@@ -2761,21 +2793,38 @@
          **/ 
 
         default:
-          return;
+          return true;
+      }
+
+      switch (action)
+      {
+        case ITagVisitor::Action_None:
+          return true;  // We're done
+
+        case ITagVisitor::Action_Remove:
+          return false;
+
+        case ITagVisitor::Action_Replace:
+          throw OrthancException(ErrorCode_NotImplemented, "Iterator cannot replace non-string-like data");
+
+        default:
+          throw OrthancException(ErrorCode_ParameterOutOfRange);
       }
     }
     catch (boost::bad_lexical_cast&)
     {
-      return;
+      return true;
     }
     catch (std::bad_cast&)
     {
-      return;
+      return true;
     }
   }
 
 
-  static void ApplyVisitorToElement(DcmElement& element,
+  // Returns "true" iff the element must be kept. If "false" is
+  // returned, the element will be removed.
+  static bool ApplyVisitorToElement(DcmElement& element,
                                     ITagVisitor& visitor,
                                     const std::vector<DicomTag>& parentTags,
                                     const std::vector<size_t>& parentIndexes,
@@ -2788,7 +2837,7 @@
 
     if (element.isLeaf())
     {
-      ApplyVisitorToLeaf(element, visitor, parentTags, parentIndexes, tag, encoding, hasCodeExtensions);
+      return ApplyVisitorToLeaf(element, visitor, parentTags, parentIndexes, tag, encoding, hasCodeExtensions);
     }
     else
     {
@@ -2799,7 +2848,22 @@
 
       if (sequence.card() == 0)
       {
-        visitor.VisitEmptySequence(parentTags, parentIndexes, tag);
+        ITagVisitor::Action action = visitor.VisitEmptySequence(parentTags, parentIndexes, tag);
+
+        switch (action)
+        {
+          case ITagVisitor::Action_None:
+            return true;
+
+          case ITagVisitor::Action_Remove:
+            return false;
+
+          case ITagVisitor::Action_Replace:
+            throw OrthancException(ErrorCode_NotImplemented, "Iterator cannot replace sequences");
+
+          default:
+            throw OrthancException(ErrorCode_ParameterOutOfRange);
+        }
       }
       else
       {
@@ -2814,6 +2878,8 @@
           DcmItem* child = sequence.getItem(i);
           ApplyVisitorToDataset(*child, visitor, tags, indexes, encoding, hasCodeExtensions);
         }
+
+        return true;  // Keep
       }
     }
   }