changeset 4221:e4c0218b6b23

better normalization in stream reader
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 30 Sep 2020 15:49:23 +0200
parents 92a21efa5c96
children 7461f98c23a0
files OrthancFramework/Sources/DicomFormat/DicomStreamReader.cpp OrthancFramework/Sources/DicomFormat/DicomStreamReader.h
diffstat 2 files changed, 47 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancFramework/Sources/DicomFormat/DicomStreamReader.cpp	Wed Sep 30 15:33:47 2020 +0200
+++ b/OrthancFramework/Sources/DicomFormat/DicomStreamReader.cpp	Wed Sep 30 15:49:23 2020 +0200
@@ -27,6 +27,39 @@
 
 namespace Orthanc
 {
+  static bool IsNormalizationNeeded(const std::string& source,
+                                    ValueRepresentation vr)
+  {
+    return (!source.empty() &&
+            (source[source.size() - 1] == ' ' ||
+             source[source.size() - 1] == '\0') &&
+            // Normalization only applies to string-based VR
+            (vr == ValueRepresentation_ApplicationEntity ||
+             vr == ValueRepresentation_AgeString ||
+             vr == ValueRepresentation_CodeString ||
+             vr == ValueRepresentation_DecimalString ||
+             vr == ValueRepresentation_IntegerString ||
+             vr == ValueRepresentation_LongString ||
+             vr == ValueRepresentation_LongText ||
+             vr == ValueRepresentation_PersonName ||
+             vr == ValueRepresentation_ShortString ||
+             vr == ValueRepresentation_ShortText ||
+             vr == ValueRepresentation_UniqueIdentifier ||
+             vr == ValueRepresentation_UnlimitedText));
+  }
+
+  
+  static void NormalizeValue(std::string& inplace,
+                             ValueRepresentation vr)
+  {
+    if (IsNormalizationNeeded(inplace, vr))
+    {
+      assert(!inplace.empty());
+      inplace.resize(inplace.size() - 1);
+    }
+  }
+
+    
   static uint16_t ReadUnsignedInteger16(const char* dicom,
                                         bool littleEndian)
   {
@@ -158,7 +191,7 @@
     state_ = State_MetaHeader;
   }
 
-    
+
   void DicomStreamReader::HandleMetaHeader(IVisitor& visitor,
                                            const std::string& block)
   {
@@ -182,6 +215,7 @@
 
         std::string value;
         value.assign(p + pos + 8, length);
+        NormalizeValue(value, vr);
 
         if (tag.GetGroup() == 0x0002)
         {
@@ -190,13 +224,6 @@
 
         if (tag == DICOM_TAG_TRANSFER_SYNTAX_UID)
         {
-          // Remove possible padding byte
-          if (!value.empty() &&
-              value[value.size() - 1] == '\0')
-          {
-            value.resize(value.size() - 1);
-          }
-            
           if (LookupTransferSyntax(transferSyntax_, value))
           {
             hasTransferSyntax = true;
@@ -219,11 +246,11 @@
           
         uint32_t length = ReadUnsignedInteger32(p + pos + 8, true);
 
-        std::string value;
-        value.assign(p + pos + 12, length);
-
         if (tag.GetGroup() == 0x0002)
         {
+          std::string value;
+          value.assign(p + pos + 12, length);
+          NormalizeValue(value, vr);
           visitor.VisitMetaHeaderTag(tag, vr, value);
         }                  
           
@@ -486,22 +513,8 @@
     if (sequenceDepth_ == 0)
     {
       bool c;
-        
-      if (!block.empty() &&
-          (block[block.size() - 1] == ' ' ||
-           block[block.size() - 1] == '\0') &&
-          (danglingVR_ == ValueRepresentation_ApplicationEntity ||
-           danglingVR_ == ValueRepresentation_AgeString ||
-           danglingVR_ == ValueRepresentation_CodeString ||
-           danglingVR_ == ValueRepresentation_DecimalString ||
-           danglingVR_ == ValueRepresentation_IntegerString ||
-           danglingVR_ == ValueRepresentation_LongString ||
-           danglingVR_ == ValueRepresentation_LongText ||
-           danglingVR_ == ValueRepresentation_PersonName ||
-           danglingVR_ == ValueRepresentation_ShortString ||
-           danglingVR_ == ValueRepresentation_ShortText ||
-           danglingVR_ == ValueRepresentation_UniqueIdentifier ||
-           danglingVR_ == ValueRepresentation_UnlimitedText))
+
+      if (IsNormalizationNeeded(block, danglingVR_))
       {
         std::string s(block.begin(), block.end() - 1);
         c = visitor.VisitDatasetTag(danglingTag_, danglingVR_, s, IsLittleEndian());
--- a/OrthancFramework/Sources/DicomFormat/DicomStreamReader.h	Wed Sep 30 15:33:47 2020 +0200
+++ b/OrthancFramework/Sources/DicomFormat/DicomStreamReader.h	Wed Sep 30 15:49:23 2020 +0200
@@ -28,10 +28,13 @@
 namespace Orthanc
 {
   /**
-   * This class parses a stream containing a DICOM instance. It does
-   * *not* support the visit of sequences (it only works at the first
-   * level of the hierarchy), and as a consequence, it doesn't give
-   * access to the pixel data of compressed transfer syntaxes.
+   * This class parses a stream containing a DICOM instance, using a
+   * state machine.
+   *
+   * It does *not* support the visit of sequences (it only works at
+   * the first level of the hierarchy), and as a consequence, it
+   * doesn't give access to the pixel data of compressed transfer
+   * syntaxes.
    **/
   class DicomStreamReader : public boost::noncopyable
   {