Mercurial > hg > orthanc
changeset 3194:47ef29168698
support of value multiplicity in ITagVisitor
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 05 Feb 2019 18:34:27 +0100 |
parents | c6cfd502bf79 |
children | 880e4161c312 |
files | Core/DicomParsing/DicomModification.cpp Core/DicomParsing/FromDcmtkBridge.cpp Core/DicomParsing/ITagVisitor.h UnitTestsSources/DicomMapTests.cpp |
diffstat | 4 files changed, 191 insertions(+), 86 deletions(-) [+] |
line wrap: on
line diff
--- a/Core/DicomParsing/DicomModification.cpp Tue Feb 05 17:00:45 2019 +0100 +++ b/Core/DicomParsing/DicomModification.cpp Tue Feb 05 18:34:27 2019 +0100 @@ -95,27 +95,27 @@ { } - virtual void VisitInteger(const std::vector<DicomTag>& parentTags, - const std::vector<size_t>& parentIndexes, - const DicomTag& tag, - ValueRepresentation vr, - int64_t value) + virtual void VisitIntegers(const std::vector<DicomTag>& parentTags, + const std::vector<size_t>& parentIndexes, + const DicomTag& tag, + ValueRepresentation vr, + const std::vector<int64_t>& values) { } - virtual void VisitDouble(const std::vector<DicomTag>& parentTags, - const std::vector<size_t>& parentIndexes, - const DicomTag& tag, - ValueRepresentation vr, - double value) + virtual void VisitDoubles(const std::vector<DicomTag>& parentTags, + const std::vector<size_t>& parentIndexes, + const DicomTag& tag, + ValueRepresentation vr, + const std::vector<double>& value) { } - virtual void VisitAttribute(const std::vector<DicomTag>& parentTags, - const std::vector<size_t>& parentIndexes, - const DicomTag& tag, - ValueRepresentation vr, - const DicomTag& value) + virtual void VisitAttributes(const std::vector<DicomTag>& parentTags, + const std::vector<size_t>& parentIndexes, + const DicomTag& tag, + ValueRepresentation vr, + const std::vector<DicomTag>& value) { }
--- a/Core/DicomParsing/FromDcmtkBridge.cpp Tue Feb 05 17:00:45 2019 +0100 +++ b/Core/DicomParsing/FromDcmtkBridge.cpp Tue Feb 05 18:34:27 2019 +0100 @@ -2265,67 +2265,121 @@ case EVR_SL: // signed long { - Sint32 f; - if (dynamic_cast<DcmSignedLong&>(element).getSint32(f).good()) + DcmSignedLong& content = dynamic_cast<DcmSignedLong&>(element); + + std::vector<int64_t> values; + values.reserve(content.getVM()); + + for (unsigned long i = 0; i < content.getVM(); i++) { - visitor.VisitInteger(parentTags, parentIndexes, tag, vr, f); + Sint32 f; + if (content.getSint32(f, i).good()) + { + values.push_back(f); + } } + visitor.VisitIntegers(parentTags, parentIndexes, tag, vr, values); break; } case EVR_SS: // signed short { - Sint16 f; - if (dynamic_cast<DcmSignedShort&>(element).getSint16(f).good()) + DcmSignedShort& content = dynamic_cast<DcmSignedShort&>(element); + + std::vector<int64_t> values; + values.reserve(content.getVM()); + + for (unsigned long i = 0; i < content.getVM(); i++) { - visitor.VisitInteger(parentTags, parentIndexes, tag, vr, f); + Sint16 f; + if (content.getSint16(f, i).good()) + { + values.push_back(f); + } } + visitor.VisitIntegers(parentTags, parentIndexes, tag, vr, values); break; } case EVR_UL: // unsigned long { - Uint32 f; - if (dynamic_cast<DcmUnsignedLong&>(element).getUint32(f).good()) + DcmUnsignedLong& content = dynamic_cast<DcmUnsignedLong&>(element); + + std::vector<int64_t> values; + values.reserve(content.getVM()); + + for (unsigned long i = 0; i < content.getVM(); i++) { - visitor.VisitInteger(parentTags, parentIndexes, tag, vr, f); + Uint32 f; + if (content.getUint32(f, i).good()) + { + values.push_back(f); + } } + visitor.VisitIntegers(parentTags, parentIndexes, tag, vr, values); break; } case EVR_US: // unsigned short { - Uint16 f; - if (dynamic_cast<DcmUnsignedShort&>(element).getUint16(f).good()) + DcmUnsignedShort& content = dynamic_cast<DcmUnsignedShort&>(element); + + std::vector<int64_t> values; + values.reserve(content.getVM()); + + for (unsigned long i = 0; i < content.getVM(); i++) { - visitor.VisitInteger(parentTags, parentIndexes, tag, vr, f); + Uint16 f; + if (content.getUint16(f, i).good()) + { + values.push_back(f); + } } + visitor.VisitIntegers(parentTags, parentIndexes, tag, vr, values); break; } case EVR_FL: // float single-precision { - Float32 f; - if (dynamic_cast<DcmFloatingPointSingle&>(element).getFloat32(f).good()) + DcmFloatingPointSingle& content = dynamic_cast<DcmFloatingPointSingle&>(element); + + std::vector<double> values; + values.reserve(content.getVM()); + + for (unsigned long i = 0; i < content.getVM(); i++) { - visitor.VisitDouble(parentTags, parentIndexes, tag, vr, f); + Float32 f; + if (content.getFloat32(f, i).good()) + { + values.push_back(f); + } } + visitor.VisitDoubles(parentTags, parentIndexes, tag, vr, values); break; } case EVR_FD: // float double-precision { - Float64 f; - if (dynamic_cast<DcmFloatingPointDouble&>(element).getFloat64(f).good()) + DcmFloatingPointDouble& content = dynamic_cast<DcmFloatingPointDouble&>(element); + + std::vector<double> values; + values.reserve(content.getVM()); + + for (unsigned long i = 0; i < content.getVM(); i++) { - visitor.VisitDouble(parentTags, parentIndexes, tag, vr, f); + Float64 f; + if (content.getFloat64(f, i).good()) + { + values.push_back(f); + } } + visitor.VisitDoubles(parentTags, parentIndexes, tag, vr, values); break; } @@ -2336,13 +2390,22 @@ case EVR_AT: { - DcmTagKey tagKey; - if (dynamic_cast<DcmAttributeTag&>(element).getTagVal(tagKey, 0).good()) + DcmAttributeTag& content = dynamic_cast<DcmAttributeTag&>(element); + + std::vector<DicomTag> values; + values.reserve(content.getVM()); + + for (unsigned long i = 0; i < content.getVM(); i++) { - DicomTag t(tagKey.getGroup(), tagKey.getElement()); - visitor.VisitAttribute(parentTags, parentIndexes, tag, vr, t); + DcmTagKey f; + if (content.getTagVal(f, i).good()) + { + DicomTag t(f.getGroup(), f.getElement()); + values.push_back(t); + } } + visitor.VisitAttributes(parentTags, parentIndexes, tag, vr, values); break; }
--- a/Core/DicomParsing/ITagVisitor.h Tue Feb 05 17:00:45 2019 +0100 +++ b/Core/DicomParsing/ITagVisitor.h Tue Feb 05 18:34:27 2019 +0100 @@ -65,23 +65,23 @@ const void* data, size_t size) = 0; - virtual void VisitInteger(const std::vector<DicomTag>& parentTags, + virtual void VisitIntegers(const std::vector<DicomTag>& parentTags, + const std::vector<size_t>& parentIndexes, + const DicomTag& tag, + ValueRepresentation vr, + const std::vector<int64_t>& values) = 0; + + virtual void VisitDoubles(const std::vector<DicomTag>& parentTags, const std::vector<size_t>& parentIndexes, const DicomTag& tag, ValueRepresentation vr, - int64_t value) = 0; + const std::vector<double>& values) = 0; - virtual void VisitDouble(const std::vector<DicomTag>& parentTags, - const std::vector<size_t>& parentIndexes, - const DicomTag& tag, - ValueRepresentation vr, - double value) = 0; - - virtual void VisitAttribute(const std::vector<DicomTag>& parentTags, - const std::vector<size_t>& parentIndexes, - const DicomTag& tag, - ValueRepresentation vr, - const DicomTag& value) = 0; + virtual void VisitAttributes(const std::vector<DicomTag>& parentTags, + const std::vector<size_t>& parentIndexes, + const DicomTag& tag, + ValueRepresentation vr, + const std::vector<DicomTag>& values) = 0; virtual Action VisitString(std::string& newValue, const std::vector<DicomTag>& parentTags,
--- a/UnitTestsSources/DicomMapTests.cpp Tue Feb 05 17:00:45 2019 +0100 +++ b/UnitTestsSources/DicomMapTests.cpp Tue Feb 05 18:34:27 2019 +0100 @@ -557,6 +557,8 @@ #if 0 +#include <boost/math/special_functions/round.hpp> + namespace Orthanc { class DicomJsonVisitor : public ITagVisitor @@ -636,7 +638,35 @@ (*node) [t] = Json::objectValue; return (*node) [t]; } - } + } + + static Json::Value FormatInteger(int64_t value) + { + if (value < 0) + { + return Json::Value(static_cast<int32_t>(value)); + } + else + { + return Json::Value(static_cast<uint32_t>(value)); + } + } + + static Json::Value FormatDouble(double value) + { + long long a = boost::math::llround<double>(value); + + double d = fabs(value - static_cast<double>(a)); + + if (d <= std::numeric_limits<double>::epsilon() * 100.0) + { + return FormatInteger(a); + } + else + { + return Json::Value(value); + } + } public: DicomJsonVisitor() @@ -664,6 +694,8 @@ const DicomTag& tag, ValueRepresentation vr) ORTHANC_OVERRIDE { + Json::Value& node = CreateNode(parentTags, parentIndexes, tag); + node["vr"] = EnumerationToString(vr); } virtual void VisitBinary(const std::vector<DicomTag>& parentTags, @@ -681,11 +713,11 @@ } } - virtual void VisitInteger(const std::vector<DicomTag>& parentTags, - const std::vector<size_t>& parentIndexes, - const DicomTag& tag, - ValueRepresentation vr, - int64_t value) ORTHANC_OVERRIDE + virtual void VisitIntegers(const std::vector<DicomTag>& parentTags, + const std::vector<size_t>& parentIndexes, + const DicomTag& tag, + ValueRepresentation vr, + const std::vector<int64_t>& values) ORTHANC_OVERRIDE { if (vr != ValueRepresentation_NotSupported) { @@ -693,23 +725,20 @@ node["vr"] = EnumerationToString(vr); Json::Value content = Json::arrayValue; - if (value < 0) + for (size_t i = 0; i < values.size(); i++) { - content.append(static_cast<int32_t>(value)); + content.append(FormatInteger(values[i])); } - else - { - content.append(static_cast<uint32_t>(value)); - } + node["Value"] = content; } } - virtual void VisitDouble(const std::vector<DicomTag>& parentTags, - const std::vector<size_t>& parentIndexes, - const DicomTag& tag, - ValueRepresentation vr, - double value) ORTHANC_OVERRIDE + virtual void VisitDoubles(const std::vector<DicomTag>& parentTags, + const std::vector<size_t>& parentIndexes, + const DicomTag& tag, + ValueRepresentation vr, + const std::vector<double>& values) ORTHANC_OVERRIDE { if (vr != ValueRepresentation_NotSupported) { @@ -717,21 +746,26 @@ node["vr"] = EnumerationToString(vr); Json::Value content = Json::arrayValue; - content.append(value); + for (size_t i = 0; i < values.size(); i++) + { + content.append(FormatDouble(values[i])); + } node["Value"] = content; } } - virtual void VisitAttribute(const std::vector<DicomTag>& parentTags, - const std::vector<size_t>& parentIndexes, - const DicomTag& tag, - ValueRepresentation vr, - const DicomTag& value) ORTHANC_OVERRIDE + virtual void VisitAttributes(const std::vector<DicomTag>& parentTags, + const std::vector<size_t>& parentIndexes, + const DicomTag& tag, + ValueRepresentation vr, + const std::vector<DicomTag>& values) ORTHANC_OVERRIDE { if (vr != ValueRepresentation_NotSupported) { Json::Value& node = CreateNode(parentTags, parentIndexes, tag); node["vr"] = EnumerationToString(vr); + + } } @@ -768,27 +802,30 @@ case ValueRepresentation_IntegerString: { int64_t value = boost::lexical_cast<int64_t>(tokens[i]); - if (value < 0) - { - node["Value"].append(static_cast<int32_t>(value)); - } - else - { - node["Value"].append(static_cast<uint32_t>(value)); - } + node["Value"].append(FormatInteger(value)); break; } case ValueRepresentation_DecimalString: { double value = boost::lexical_cast<double>(tokens[i]); - node["Value"].append(value); + node["Value"].append(FormatDouble(value)); break; } default: + { + size_t l = tokens[i].size(); + + if (l > 0 && + tokens[i][l - 1] == '\0') + { + tokens[i] = tokens[i].substr(0, l - 1); + } + node["Value"].append(tokens[i]); break; + } } } catch (boost::bad_lexical_cast&) @@ -808,11 +845,16 @@ /* - cd /home/jodogne/Subversion/orthanc/s/dcmtk-3.6.2/i/bin - DCMDICTPATH=/home/jodogne/Downloads/dcmtk-3.6.2/dcmdata/data/dicom.dic ./dcm2json ~/Subversion/orthanc-tests/Database/DummyCT.dcm | python -mjson.tool > /tmp/a.json +cat << EOF > /tmp/tutu.py +import json +import sys +j = json.loads(sys.stdin.read().decode("utf-8-sig")) +print(json.dumps(j, indent=4, sort_keys=True, ensure_ascii=False).encode('utf-8')) +EOF - make -j4 && ./UnitTests --gtest_filter=DicomWeb* && python -mjson.tool /tmp/tutu.json > /tmp/b.json - diff /tmp/a.json /tmp/b.json +DCMDICTPATH=/home/jodogne/Downloads/dcmtk-3.6.2/dcmdata/data/dicom.dic /home/jodogne/Downloads/dcmtk-3.6.2/i/bin/dcm2json ~/Subversion/orthanc-tests/Database/DummyCT.dcm | tr -d '\0' | sed 's/\\u0000//g' | sed 's/\.0$//' | python /tmp/tutu.py | grep -v 'InlineBinary' > /tmp/a.json + +make -j4 && ./UnitTests --gtest_filter=DicomWeb* && python /tmp/tutu.py < /tmp/tutu.json > /tmp/b.json && diff -i /tmp/a.json /tmp/b.json */