# HG changeset patch # User amazy # Date 1568891410 -7200 # Node ID fc26659493b6ee77a45c1dbe80852e9e8c0030f9 # Parent 7db879b014ffbacb2080bd9a160500cfafad16f7 added support for COLUMNS/ROWS tags with invalid 800\0 value observed in some US images diff -r 7db879b014ff -r fc26659493b6 Core/DicomFormat/DicomImageInformation.cpp --- 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(values.GetValue(DICOM_TAG_COLUMNS).GetContent()); - height_ = boost::lexical_cast(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(values.GetValue(DICOM_TAG_BITS_ALLOCATED).GetContent()); try diff -r 7db879b014ff -r fc26659493b6 Core/DicomFormat/DicomValue.cpp --- 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 + 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(value); + return true; + } + else + { + std::vector tokens; + Toolbox::TokenizeString(tokens, value, '\\'); + + if (tokens.size() >= 1) + { + result = boost::lexical_cast(tokens[0]); + return true; + } + + return false; + } + } + catch (boost::bad_lexical_cast&) + { + return false; + } + } + template @@ -177,6 +231,11 @@ return ParseValue(result, *this); } + bool DicomValue::ParseFirstUnsignedInteger(unsigned int& result) const + { + return ParseFirstValue(result, *this); + } + bool DicomValue::CopyToString(std::string& result, bool allowBinary) const { diff -r 7db879b014ff -r fc26659493b6 Core/DicomFormat/DicomValue.h --- 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); diff -r 7db879b014ff -r fc26659493b6 UnitTestsSources/DicomMapTests.cpp --- 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); }