Mercurial > hg > orthanc
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); }