# HG changeset patch # User Sebastien Jodogne # Date 1601299384 -7200 # Node ID be2eca8b02e174cdf4936cd9dc3ea90548c1738c # Parent cb3af14626d4b16abe5938cef89f07a713738006 testing DicomMap::ParseDicomMetaInformation() diff -r cb3af14626d4 -r be2eca8b02e1 OrthancFramework/Sources/DicomFormat/DicomMap.cpp --- 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(dicom)); + const uint8_t* p = reinterpret_cast(dicom); + + return (static_cast(p[0]) | + (static_cast(p[1]) << 8)); } - static uint32_t ReadUnsignedInteger32(const char* dicom) + static uint32_t ReadLittleEndianUint32(const char* dicom) { - return le32toh(*reinterpret_cast(dicom)); + const uint8_t* p = reinterpret_cast(dicom); + + return (static_cast(p[0]) | + (static_cast(p[1]) << 8) | + (static_cast(p[2]) << 16) | + (static_cast(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; diff -r cb3af14626d4 -r be2eca8b02e1 OrthancFramework/UnitTestsSources/DicomMapTests.cpp --- 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 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::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); + } +}