changeset 3519:fc26659493b6

added support for COLUMNS/ROWS tags with invalid 800\0 value observed in some US images
author amazy
date Thu, 19 Sep 2019 13:10:10 +0200
parents 7db879b014ff
children 77bede920d22
files Core/DicomFormat/DicomImageInformation.cpp Core/DicomFormat/DicomValue.cpp Core/DicomFormat/DicomValue.h UnitTestsSources/DicomMapTests.cpp
diffstat 4 files changed, 74 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/Core/DicomFormat/DicomImageInformation.cpp	Thu Sep 05 13:11:35 2019 +0200
+++ b/Core/DicomFormat/DicomImageInformation.cpp	Thu Sep 19 13:10:10 2019 +0200
@@ -116,8 +116,9 @@
         photometric_ = PhotometricInterpretation_Unknown;
       }
 
-      width_ = boost::lexical_cast<unsigned int>(values.GetValue(DICOM_TAG_COLUMNS).GetContent());
-      height_ = boost::lexical_cast<unsigned int>(values.GetValue(DICOM_TAG_ROWS).GetContent());
+      values.GetValue(DICOM_TAG_COLUMNS).ParseFirstUnsignedInteger(width_); // in some US images, we've seen tag values of "800\0"; that's why we parse the 'first' value
+      values.GetValue(DICOM_TAG_ROWS).ParseFirstUnsignedInteger(height_);
+
       bitsAllocated_ = boost::lexical_cast<unsigned int>(values.GetValue(DICOM_TAG_BITS_ALLOCATED).GetContent());
 
       try
--- a/Core/DicomFormat/DicomValue.cpp	Thu Sep 05 13:11:35 2019 +0200
+++ b/Core/DicomFormat/DicomValue.cpp	Thu Sep 19 13:10:10 2019 +0200
@@ -94,6 +94,60 @@
   }
 #endif
 
+  // same as ParseValue but in case the value actually contains a sequence,
+  // it will return the first value
+  // this has been introduced to support invalid "width/height" DICOM tags in some US
+  // images where the width is stored as "800\0" !
+  template <typename T,
+            bool allowSigned>
+  static bool ParseFirstValue(T& result,
+                              const DicomValue& source)
+  {
+    if (source.IsBinary() ||
+        source.IsNull())
+    {
+      return false;
+    }
+
+    try
+    {
+      std::string value = Toolbox::StripSpaces(source.GetContent());
+      if (value.empty())
+      {
+        return false;
+      }
+
+      if (!allowSigned &&
+          value[0] == '-')
+      {
+        return false;
+      }
+
+      if (value.find("\\") == std::string::npos)
+      {
+        result = boost::lexical_cast<T>(value);
+        return true;
+      }
+      else
+      {
+        std::vector<std::string> tokens;
+        Toolbox::TokenizeString(tokens, value, '\\');
+
+        if (tokens.size() >= 1)
+        {
+          result = boost::lexical_cast<T>(tokens[0]);
+          return true;
+        }
+
+        return false;
+      }
+    }
+    catch (boost::bad_lexical_cast&)
+    {
+      return false;
+    }
+  }
+
 
   template <typename T,
             bool allowSigned>
@@ -177,6 +231,11 @@
     return ParseValue<double, true>(result, *this);
   }
 
+  bool DicomValue::ParseFirstUnsignedInteger(unsigned int& result) const
+  {
+    return ParseFirstValue<unsigned int, true>(result, *this);
+  }
+
   bool DicomValue::CopyToString(std::string& result,
                                 bool allowBinary) const
   {
--- a/Core/DicomFormat/DicomValue.h	Thu Sep 05 13:11:35 2019 +0200
+++ b/Core/DicomFormat/DicomValue.h	Thu Sep 19 13:10:10 2019 +0200
@@ -112,6 +112,8 @@
 
     bool ParseDouble(double& result) const;
 
+    bool ParseFirstUnsignedInteger(unsigned int& result) const;
+
     void Serialize(Json::Value& target) const;
 
     void Unserialize(const Json::Value& source);
--- a/UnitTestsSources/DicomMapTests.cpp	Thu Sep 05 13:11:35 2019 +0200
+++ b/UnitTestsSources/DicomMapTests.cpp	Thu Sep 19 13:10:10 2019 +0200
@@ -239,6 +239,7 @@
   int64_t j;
   uint32_t k;
   uint64_t l;
+  unsigned int ui;
   std::string s;
   
   m.SetValue(DICOM_TAG_PATIENT_NAME, "      ", false);  // Empty value
@@ -375,6 +376,15 @@
   ASSERT_FLOAT_EQ(-2147483649.0f, f);
   ASSERT_DOUBLE_EQ(-2147483649.0, d); 
   ASSERT_EQ(-2147483649ll, j);
+
+
+  // "800\0" in US COLMUNS tag
+  m.SetValue(DICOM_TAG_COLUMNS, "800\0", false);
+  ASSERT_TRUE(m.GetValue(DICOM_TAG_COLUMNS).ParseFirstUnsignedInteger(ui));
+  ASSERT_EQ(800, ui);
+  m.SetValue(DICOM_TAG_COLUMNS, "800", false);
+  ASSERT_TRUE(m.GetValue(DICOM_TAG_COLUMNS).ParseFirstUnsignedInteger(ui));
+  ASSERT_EQ(800, ui);
 }