changeset 4213:be2eca8b02e1

testing DicomMap::ParseDicomMetaInformation()
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 28 Sep 2020 15:23:04 +0200
parents cb3af14626d4
children 7b011cfda135
files OrthancFramework/Sources/DicomFormat/DicomMap.cpp OrthancFramework/UnitTestsSources/DicomMapTests.cpp
diffstat 2 files changed, 112 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancFramework/Sources/DicomFormat/DicomMap.cpp	Wed Sep 23 07:41:11 2020 +0200
+++ b/OrthancFramework/Sources/DicomFormat/DicomMap.cpp	Mon Sep 28 15:23:04 2020 +0200
@@ -493,15 +493,23 @@
   }
 
 
-  static uint16_t ReadUnsignedInteger16(const char* dicom)
+  static uint16_t ReadLittleEndianUint16(const char* dicom)
   {
-    return le16toh(*reinterpret_cast<const uint16_t*>(dicom));
+    const uint8_t* p = reinterpret_cast<const uint8_t*>(dicom);
+
+    return (static_cast<uint16_t>(p[0]) |
+            (static_cast<uint16_t>(p[1]) << 8));
   }
 
 
-  static uint32_t ReadUnsignedInteger32(const char* dicom)
+  static uint32_t ReadLittleEndianUint32(const char* dicom)
   {
-    return le32toh(*reinterpret_cast<const uint32_t*>(dicom));
+    const uint8_t* p = reinterpret_cast<const uint8_t*>(dicom);
+
+    return (static_cast<uint16_t>(p[0]) |
+            (static_cast<uint16_t>(p[1]) << 8) |
+            (static_cast<uint16_t>(p[2]) << 16) |
+            (static_cast<uint16_t>(p[3]) << 24));
   }
 
 
@@ -670,8 +678,8 @@
       return false;
     }
 
-    tag = DicomTag(ReadUnsignedInteger16(dicom + position),
-                   ReadUnsignedInteger16(dicom + position + 2));
+    tag = DicomTag(ReadLittleEndianUint16(dicom + position),
+                   ReadLittleEndianUint16(dicom + position + 2));
 
     vr = StringToValueRepresentation(std::string(dicom + position + 4, 2), true);
     if (vr == ValueRepresentation_NotSupported)
@@ -679,24 +687,66 @@
       return false;
     }
 
-    if (vr == ValueRepresentation_OtherByte ||
-        vr == ValueRepresentation_OtherDouble ||
-        vr == ValueRepresentation_OtherFloat ||
-        vr == ValueRepresentation_OtherLong ||
-        vr == ValueRepresentation_OtherWord ||
-        vr == ValueRepresentation_Sequence ||
-        vr == ValueRepresentation_UnlimitedCharacters ||
-        vr == ValueRepresentation_UniversalResource ||
-        vr == ValueRepresentation_UnlimitedText ||
-        vr == ValueRepresentation_Unknown)    // Note that "UN" should never appear in the Meta Information
+    // http://dicom.nema.org/medical/dicom/current/output/chtml/part05/chapter_7.html#sect_7.1.2
+    if (vr == ValueRepresentation_ApplicationEntity   /* AE */ ||
+        vr == ValueRepresentation_AgeString           /* AS */ ||
+        vr == ValueRepresentation_AttributeTag        /* AT */ ||
+        vr == ValueRepresentation_CodeString          /* CS */ ||
+        vr == ValueRepresentation_Date                /* DA */ ||
+        vr == ValueRepresentation_DecimalString       /* DS */ ||
+        vr == ValueRepresentation_DateTime            /* DT */ ||
+        vr == ValueRepresentation_FloatingPointSingle /* FL */ ||
+        vr == ValueRepresentation_FloatingPointDouble /* FD */ ||
+        vr == ValueRepresentation_IntegerString       /* IS */ ||
+        vr == ValueRepresentation_LongString          /* LO */ ||
+        vr == ValueRepresentation_LongText            /* LT */ ||
+        vr == ValueRepresentation_PersonName          /* PN */ ||
+        vr == ValueRepresentation_ShortString         /* SH */ ||
+        vr == ValueRepresentation_SignedLong          /* SL */ ||
+        vr == ValueRepresentation_SignedShort         /* SS */ ||
+        vr == ValueRepresentation_ShortText           /* ST */ ||
+        vr == ValueRepresentation_Time                /* TM */ ||
+        vr == ValueRepresentation_UniqueIdentifier    /* UI */ ||
+        vr == ValueRepresentation_UnsignedLong        /* UL */ ||
+        vr == ValueRepresentation_UnsignedShort       /* US */)
     {
+      /**
+       * This is Table 7.1-2. "Data Element with Explicit VR of AE,
+       * AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, PN, SH, SL, SS,
+       * ST, TM, UI, UL and US"
+       **/
+      if (position + 8 > size)
+      {
+        return false;
+      }
+
+      uint16_t length = ReadLittleEndianUint16(dicom + position + 6);
+      if (position + 8 + length > size)
+      {
+        return false;
+      }
+
+      value.assign(dicom + position + 8, length);
+      position += (8 + length);
+    }
+    else
+    {
+      /**
+       * This is Table 7.1-1. "Data Element with Explicit VR other
+       * than as shown in Table 7.1-2"
+       **/
       if (position + 12 > size)
       {
         return false;
       }
+      
+      uint16_t reserved = ReadLittleEndianUint16(dicom + position + 6);
+      if (reserved != 0)
+      {
+        return false;
+      }
 
-      uint32_t length = ReadUnsignedInteger32(dicom + position + 8);
-
+      uint32_t length = ReadLittleEndianUint32(dicom + position + 8);
       if (position + 12 + length > size)
       {
         return false;
@@ -705,23 +755,6 @@
       value.assign(dicom + position + 12, length);
       position += (12 + length);
     }
-    else
-    {
-      if (position + 8 > size)
-      {
-        return false;
-      }
-
-      uint16_t length = ReadUnsignedInteger16(dicom + position + 6);
-
-      if (position + 8 + length > size)
-      {
-        return false;
-      }
-
-      value.assign(dicom + position + 8, length);
-      position += (8 + length);
-    }
 
     if (!ValidateTag(vr, value))
     {
@@ -788,7 +821,7 @@
       return false;
     }
 
-    size_t stopPosition = position + ReadUnsignedInteger32(value.c_str());
+    size_t stopPosition = position + ReadLittleEndianUint32(value.c_str());
     if (stopPosition > size)
     {
       return false;
--- a/OrthancFramework/UnitTestsSources/DicomMapTests.cpp	Wed Sep 23 07:41:11 2020 +0200
+++ b/OrthancFramework/UnitTestsSources/DicomMapTests.cpp	Mon Sep 28 15:23:04 2020 +0200
@@ -650,3 +650,46 @@
     }
   }
 }
+
+
+
+
+#include "../Sources/SystemToolbox.h"
+
+TEST(DicomMap, DISABLED_ParseDicomMetaInformation)
+{
+  static const std::string PATH = "/home/jodogne/Subversion/orthanc-tests/Database/TransferSyntaxes/";
+  
+  std::map<std::string, DicomTransferSyntax> f;
+  f.insert(std::make_pair(PATH + "../ColorTestMalaterre.dcm", DicomTransferSyntax_LittleEndianImplicit));  // 1.2.840.10008.1.2
+  f.insert(std::make_pair(PATH + "1.2.840.10008.1.2.1.dcm", DicomTransferSyntax_LittleEndianExplicit));
+  f.insert(std::make_pair(PATH + "1.2.840.10008.1.2.2.dcm", DicomTransferSyntax_BigEndianExplicit));
+  f.insert(std::make_pair(PATH + "1.2.840.10008.1.2.4.50.dcm", DicomTransferSyntax_JPEGProcess1));
+  f.insert(std::make_pair(PATH + "1.2.840.10008.1.2.4.51.dcm", DicomTransferSyntax_JPEGProcess2_4));
+  f.insert(std::make_pair(PATH + "1.2.840.10008.1.2.4.57.dcm", DicomTransferSyntax_JPEGProcess14));
+  f.insert(std::make_pair(PATH + "1.2.840.10008.1.2.4.70.dcm", DicomTransferSyntax_JPEGProcess14SV1));
+  f.insert(std::make_pair(PATH + "1.2.840.10008.1.2.4.80.dcm", DicomTransferSyntax_JPEGLSLossless));
+  f.insert(std::make_pair(PATH + "1.2.840.10008.1.2.4.81.dcm", DicomTransferSyntax_JPEGLSLossy));
+  f.insert(std::make_pair(PATH + "1.2.840.10008.1.2.4.90.dcm", DicomTransferSyntax_JPEG2000LosslessOnly));
+  f.insert(std::make_pair(PATH + "1.2.840.10008.1.2.4.91.dcm", DicomTransferSyntax_JPEG2000));
+  f.insert(std::make_pair(PATH + "1.2.840.10008.1.2.5.dcm", DicomTransferSyntax_RLELossless));
+
+  for (std::map<std::string, DicomTransferSyntax>::const_iterator it = f.begin(); it != f.end(); ++it)
+  {
+    printf("\n== %s ==\n\n", it->first.c_str());
+    
+    std::string dicom;
+    SystemToolbox::ReadFile(dicom, it->first, false);
+
+    DicomMap d;
+    ASSERT_TRUE(DicomMap::ParseDicomMetaInformation(d, dicom.c_str(), dicom.size()));
+    d.Print(stdout);
+
+    std::string s;
+    ASSERT_TRUE(d.LookupStringValue(s, DICOM_TAG_TRANSFER_SYNTAX_UID, false));
+    
+    DicomTransferSyntax ts;
+    ASSERT_TRUE(LookupTransferSyntax(ts, s));
+    ASSERT_EQ(ts, it->second);
+  }
+}