comparison OrthancStone/Sources/Toolbox/OrthancDatasets/DicomWebDataset.cpp @ 2174:2410a171ebfb

refactoring using DicomWebDataset and OrthancNativeDataset
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 22 Oct 2024 21:52:34 +0200
parents
children
comparison
equal deleted inserted replaced
2172:239fb2c893c1 2174:2410a171ebfb
1 /**
2 * Stone of Orthanc
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2023 Osimis S.A., Belgium
6 * Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
7 *
8 * This program is free software: you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation, either version 3 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this program. If not, see
20 * <http://www.gnu.org/licenses/>.
21 **/
22
23
24 #include "DicomWebDataset.h"
25
26 #include <OrthancException.h>
27
28 #include <boost/lexical_cast.hpp>
29
30
31 static const char* const VALUE = "Value";
32 static const char* const VR = "vr";
33 static const char* const SQ = "SQ";
34 static const char* const ALPHABETIC = "Alphabetic";
35
36
37 namespace OrthancStone
38 {
39 static const Json::Value* GetValue(std::string& vr,
40 const Json::Value& node,
41 const Orthanc::DicomTag& tag)
42 {
43 char id[16];
44 sprintf(id, "%04X%04X", tag.GetGroup(), tag.GetElement());
45
46 if (node.type() != Json::objectValue)
47 {
48 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
49 }
50
51 if (!node.isMember(id))
52 {
53 return NULL;
54 }
55
56 if (node[id].type() == Json::objectValue &&
57 node[id].isMember(VALUE) &&
58 node[id].isMember(VR) &&
59 node[id][VR].type() == Json::stringValue)
60 {
61 vr = node[id][VR].asString();
62 return &node[id][VALUE];
63 }
64 else
65 {
66 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
67 }
68 }
69
70
71 static const Json::Value* GetSequenceArray(const Json::Value& node,
72 const Orthanc::DicomTag& tag)
73 {
74 std::string vr;
75 const Json::Value* value = GetValue(vr, node, tag);
76
77 if (value != NULL &&
78 vr == SQ &&
79 value->type() == Json::arrayValue)
80 {
81 return value;
82 }
83 else
84 {
85 return NULL;
86 }
87 }
88
89
90 const Json::Value* DicomWebDataset::LookupValue(std::string& vr,
91 const Orthanc::DicomPath& path) const
92 {
93 const Json::Value* current = &dicomweb_;
94
95 for (size_t i = 0; i < path.GetPrefixLength(); i++)
96 {
97 if (path.IsPrefixUniversal(i))
98 {
99 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
100 }
101
102 Json::ArrayIndex index = path.GetPrefixIndex(i);
103
104 const Json::Value* next = GetSequenceArray(*current, path.GetPrefixTag(i));
105 if (next != NULL &&
106 index < next->size())
107 {
108 current = &((*next) [index]);
109 }
110 else
111 {
112 return NULL;
113 }
114 }
115
116 return GetValue(vr, *current, path.GetFinalTag());
117 }
118
119
120 DicomWebDataset::DicomWebDataset(const Json::Value& dicomweb) :
121 dicomweb_(dicomweb)
122 {
123 if (dicomweb.type() != Json::objectValue)
124 {
125 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
126 }
127 }
128
129
130 bool DicomWebDataset::GetStringValue(std::string& result,
131 const Orthanc::DicomPath& path) const
132 {
133 std::string vr;
134 const Json::Value* value = LookupValue(vr, path);
135
136 if (value == NULL)
137 {
138 return false;
139 }
140 else if (value->type() == Json::arrayValue &&
141 value->size() == 1u &&
142 (*value) [0].type() == Json::stringValue && (
143 // This is the list of all the string value representations:
144 // https://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_6.2.html
145 vr == "AE" ||
146 vr == "AS" ||
147 vr == "CS" ||
148 vr == "DA" ||
149 vr == "DS" ||
150 vr == "DT" ||
151 vr == "IS" ||
152 vr == "LO" ||
153 vr == "LT" ||
154 vr == "SH" ||
155 vr == "ST" ||
156 vr == "TM" ||
157 vr == "UC" ||
158 vr == "UI" ||
159 vr == "UR" ||
160 vr == "UT"))
161 {
162 result = (*value) [0].asString();
163 return true;
164 }
165 else if (value->type() == Json::arrayValue &&
166 value->size() == 1u &&
167 vr == "PN" &&
168 (*value) [0].type() == Json::objectValue &&
169 (*value) [0].isMember(ALPHABETIC) &&
170 (*value) [0][ALPHABETIC].type() == Json::stringValue)
171 {
172 result = (*value) [0][ALPHABETIC].asString();
173 return true;
174 }
175 else if (value->type() == Json::arrayValue &&
176 value->size() == 1u &&
177 (vr == "FD" || vr == "FL") &&
178 (*value) [0].isDouble())
179 {
180 result = boost::lexical_cast<std::string>((*value) [0].asDouble());
181 return true;
182 }
183 else if (value->type() == Json::arrayValue &&
184 value->size() == 1u &&
185 (vr == "UL" ||
186 vr == "US") &&
187 (*value) [0].isUInt64())
188 {
189 result = boost::lexical_cast<std::string>((*value) [0].asUInt64());
190 return true;
191 }
192 else if (value->type() == Json::arrayValue &&
193 value->size() == 1u &&
194 (vr == "SL" ||
195 vr == "SS") &&
196 (*value) [0].isInt64())
197 {
198 result = boost::lexical_cast<std::string>((*value) [0].asInt64());
199 return true;
200 }
201 else if (value->type() == Json::arrayValue &&
202 vr == "SQ")
203 {
204 return false;
205 }
206 else
207 {
208 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
209 }
210 }
211
212
213 bool DicomWebDataset::GetSequenceSize(size_t& size,
214 const Orthanc::DicomPath& path) const
215 {
216 std::string vr;
217 const Json::Value* value = LookupValue(vr, path);
218
219 if (value != NULL &&
220 vr == SQ &&
221 value->type() == Json::arrayValue)
222 {
223 size = value->size();
224 return true;
225 }
226 else
227 {
228 return false;
229 }
230 }
231 }