Mercurial > hg > orthanc
annotate OrthancServer/OrthancRestApi.cpp @ 213:4ce7fdcc8879
access to tags, simplified-tags and file of an instance
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 29 Nov 2012 10:59:40 +0100 |
parents | f276b175dcaf |
children | 03817919169b |
rev | line source |
---|---|
0 | 1 /** |
62 | 2 * Orthanc - A Lightweight, RESTful DICOM Store |
0 | 3 * Copyright (C) 2012 Medical Physics Department, CHU of Liege, |
4 * Belgium | |
5 * | |
6 * This program is free software: you can redistribute it and/or | |
7 * modify it under the terms of the GNU General Public License as | |
8 * published by the Free Software Foundation, either version 3 of the | |
9 * License, or (at your option) any later version. | |
136 | 10 * |
11 * In addition, as a special exception, the copyright holders of this | |
12 * program give permission to link the code of its release with the | |
13 * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
14 * that use the same license as the "OpenSSL" library), and distribute | |
15 * the linked executables. You must obey the GNU General Public License | |
16 * in all respects for all of the code used other than "OpenSSL". If you | |
17 * modify file(s) with this exception, you may extend this exception to | |
18 * your version of the file(s), but you are not obligated to do so. If | |
19 * you do not wish to do so, delete this exception statement from your | |
20 * version. If you delete this exception statement from all source files | |
21 * in the program, then also delete it here. | |
0 | 22 * |
23 * This program is distributed in the hope that it will be useful, but | |
24 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 * General Public License for more details. | |
27 * | |
28 * You should have received a copy of the GNU General Public License | |
29 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
30 **/ | |
31 | |
32 | |
62 | 33 #include "OrthancRestApi.h" |
0 | 34 |
62 | 35 #include "OrthancInitialization.h" |
0 | 36 #include "FromDcmtkBridge.h" |
213
4ce7fdcc8879
access to tags, simplified-tags and file of an instance
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
212
diff
changeset
|
37 #include "ServerToolbox.h" |
0 | 38 #include "../Core/Uuid.h" |
208 | 39 #include "../Core/HttpServer/FilesystemHttpSender.h" |
0 | 40 |
41 #include <dcmtk/dcmdata/dcistrmb.h> | |
42 #include <dcmtk/dcmdata/dcfilefo.h> | |
43 #include <boost/lexical_cast.hpp> | |
44 | |
62 | 45 namespace Orthanc |
0 | 46 { |
47 static void SendJson(HttpOutput& output, | |
48 const Json::Value& value) | |
49 { | |
50 Json::StyledWriter writer; | |
51 std::string s = writer.write(value); | |
52 output.AnswerBufferWithContentType(s, "application/json"); | |
53 } | |
54 | |
62 | 55 bool OrthancRestApi::Store(Json::Value& result, |
50 | 56 const std::string& postData) |
0 | 57 { |
58 // Prepare an input stream for the memory buffer | |
59 DcmInputBufferStream is; | |
60 if (postData.size() > 0) | |
61 { | |
62 is.setBuffer(&postData[0], postData.size()); | |
63 } | |
64 is.setEos(); | |
65 | |
34
96e57b863dd9
option to disallow remote access
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
8
diff
changeset
|
66 //printf("[%d]\n", postData.size()); |
0 | 67 |
68 DcmFileFormat dicomFile; | |
69 if (dicomFile.read(is).good()) | |
70 { | |
71 DicomMap dicomSummary; | |
72 FromDcmtkBridge::Convert(dicomSummary, *dicomFile.getDataset()); | |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
155
diff
changeset
|
73 |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
155
diff
changeset
|
74 DicomInstanceHasher hasher(dicomSummary); |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
155
diff
changeset
|
75 |
0 | 76 Json::Value dicomJson; |
77 FromDcmtkBridge::ToJson(dicomJson, *dicomFile.getDataset()); | |
78 | |
79 StoreStatus status = StoreStatus_Failure; | |
80 if (postData.size() > 0) | |
81 { | |
82 status = index_.Store | |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
155
diff
changeset
|
83 (storage_, reinterpret_cast<const char*>(&postData[0]), |
0 | 84 postData.size(), dicomSummary, dicomJson, ""); |
85 } | |
86 | |
187
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
155
diff
changeset
|
87 result["ID"] = hasher.HashInstance(); |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
155
diff
changeset
|
88 result["Path"] = "/instances/" + hasher.HashInstance(); |
8e673a65564d
refactoring of storing new instances
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
155
diff
changeset
|
89 |
0 | 90 switch (status) |
91 { | |
92 case StoreStatus_Success: | |
93 result["Status"] = "Success"; | |
94 return true; | |
95 | |
96 case StoreStatus_AlreadyStored: | |
97 result["Status"] = "AlreadyStored"; | |
98 return true; | |
99 | |
100 default: | |
101 return false; | |
102 } | |
103 } | |
104 | |
105 return false; | |
106 } | |
107 | |
62 | 108 void OrthancRestApi::ConnectToModality(DicomUserConnection& c, |
50 | 109 const std::string& name) |
0 | 110 { |
111 std::string aet, address; | |
112 int port; | |
113 GetDicomModality(name, aet, address, port); | |
62 | 114 c.SetLocalApplicationEntityTitle(GetGlobalStringParameter("DicomAet", "ORTHANC")); |
0 | 115 c.SetDistantApplicationEntityTitle(aet); |
116 c.SetDistantHost(address); | |
117 c.SetDistantPort(port); | |
118 c.Open(); | |
119 } | |
120 | |
62 | 121 bool OrthancRestApi::MergeQueryAndTemplate(DicomMap& result, |
50 | 122 const std::string& postData) |
0 | 123 { |
124 Json::Value query; | |
125 Json::Reader reader; | |
126 | |
127 if (!reader.parse(postData, query) || | |
8 | 128 query.type() != Json::objectValue) |
0 | 129 { |
130 return false; | |
131 } | |
132 | |
133 Json::Value::Members members = query.getMemberNames(); | |
134 for (size_t i = 0; i < members.size(); i++) | |
135 { | |
136 DicomTag t = FromDcmtkBridge::FindTag(members[i]); | |
137 result.SetValue(t, query[members[i]].asString()); | |
138 } | |
139 | |
140 return true; | |
141 } | |
142 | |
62 | 143 bool OrthancRestApi::DicomFindPatient(Json::Value& result, |
50 | 144 DicomUserConnection& c, |
145 const std::string& postData) | |
0 | 146 { |
147 DicomMap m; | |
148 DicomMap::SetupFindPatientTemplate(m); | |
149 if (!MergeQueryAndTemplate(m, postData)) | |
150 { | |
151 return false; | |
152 } | |
153 | |
154 DicomFindAnswers answers; | |
155 c.FindPatient(answers, m); | |
156 answers.ToJson(result); | |
157 return true; | |
158 } | |
159 | |
62 | 160 bool OrthancRestApi::DicomFindStudy(Json::Value& result, |
50 | 161 DicomUserConnection& c, |
162 const std::string& postData) | |
0 | 163 { |
164 DicomMap m; | |
165 DicomMap::SetupFindStudyTemplate(m); | |
166 if (!MergeQueryAndTemplate(m, postData)) | |
167 { | |
168 return false; | |
169 } | |
170 | |
80 | 171 if (m.GetValue(DICOM_TAG_ACCESSION_NUMBER).AsString().size() <= 2 && |
172 m.GetValue(DICOM_TAG_PATIENT_ID).AsString().size() <= 2) | |
0 | 173 { |
174 return false; | |
175 } | |
176 | |
177 DicomFindAnswers answers; | |
178 c.FindStudy(answers, m); | |
179 answers.ToJson(result); | |
180 return true; | |
181 } | |
182 | |
62 | 183 bool OrthancRestApi::DicomFindSeries(Json::Value& result, |
50 | 184 DicomUserConnection& c, |
185 const std::string& postData) | |
0 | 186 { |
187 DicomMap m; | |
188 DicomMap::SetupFindSeriesTemplate(m); | |
189 if (!MergeQueryAndTemplate(m, postData)) | |
190 { | |
191 return false; | |
192 } | |
193 | |
80 | 194 if ((m.GetValue(DICOM_TAG_ACCESSION_NUMBER).AsString().size() <= 2 && |
195 m.GetValue(DICOM_TAG_PATIENT_ID).AsString().size() <= 2) || | |
196 m.GetValue(DICOM_TAG_STUDY_INSTANCE_UID).AsString().size() <= 2) | |
0 | 197 { |
198 return false; | |
199 } | |
200 | |
201 DicomFindAnswers answers; | |
202 c.FindSeries(answers, m); | |
203 answers.ToJson(result); | |
204 return true; | |
205 } | |
206 | |
62 | 207 bool OrthancRestApi::DicomFind(Json::Value& result, |
50 | 208 DicomUserConnection& c, |
209 const std::string& postData) | |
0 | 210 { |
211 DicomMap m; | |
212 DicomMap::SetupFindPatientTemplate(m); | |
213 if (!MergeQueryAndTemplate(m, postData)) | |
214 { | |
215 return false; | |
216 } | |
217 | |
218 DicomFindAnswers patients; | |
219 c.FindPatient(patients, m); | |
220 | |
221 // Loop over the found patients | |
222 result = Json::arrayValue; | |
223 for (size_t i = 0; i < patients.GetSize(); i++) | |
224 { | |
225 Json::Value patient(Json::objectValue); | |
226 FromDcmtkBridge::ToJson(patient, patients.GetAnswer(i)); | |
227 | |
228 DicomMap::SetupFindStudyTemplate(m); | |
229 if (!MergeQueryAndTemplate(m, postData)) | |
230 { | |
231 return false; | |
232 } | |
80 | 233 m.CopyTagIfExists(patients.GetAnswer(i), DICOM_TAG_PATIENT_ID); |
0 | 234 |
235 DicomFindAnswers studies; | |
236 c.FindStudy(studies, m); | |
237 | |
238 patient["Studies"] = Json::arrayValue; | |
239 | |
240 // Loop over the found studies | |
241 for (size_t j = 0; j < studies.GetSize(); j++) | |
242 { | |
243 Json::Value study(Json::objectValue); | |
244 FromDcmtkBridge::ToJson(study, studies.GetAnswer(j)); | |
245 | |
246 DicomMap::SetupFindSeriesTemplate(m); | |
247 if (!MergeQueryAndTemplate(m, postData)) | |
248 { | |
249 return false; | |
250 } | |
80 | 251 m.CopyTagIfExists(studies.GetAnswer(j), DICOM_TAG_PATIENT_ID); |
252 m.CopyTagIfExists(studies.GetAnswer(j), DICOM_TAG_STUDY_INSTANCE_UID); | |
0 | 253 |
254 DicomFindAnswers series; | |
255 c.FindSeries(series, m); | |
256 | |
257 // Loop over the found series | |
258 study["Series"] = Json::arrayValue; | |
259 for (size_t k = 0; k < series.GetSize(); k++) | |
260 { | |
261 Json::Value series2(Json::objectValue); | |
262 FromDcmtkBridge::ToJson(series2, series.GetAnswer(k)); | |
263 study["Series"].append(series2); | |
264 } | |
265 | |
266 patient["Studies"].append(study); | |
267 } | |
268 | |
269 result.append(patient); | |
270 } | |
271 | |
272 return true; | |
273 } | |
274 | |
275 | |
276 | |
62 | 277 bool OrthancRestApi::DicomStore(Json::Value& result, |
50 | 278 DicomUserConnection& c, |
279 const std::string& postData) | |
0 | 280 { |
281 Json::Value found(Json::objectValue); | |
282 | |
283 if (!Toolbox::IsUuid(postData)) | |
284 { | |
285 // This is not a UUID, assume this is a DICOM instance | |
286 c.Store(postData); | |
287 } | |
212 | 288 else if (index_.LookupResource(found, postData, ResourceType_Series)) |
0 | 289 { |
290 // The UUID corresponds to a series | |
126 | 291 for (Json::Value::ArrayIndex i = 0; i < found["Instances"].size(); i++) |
0 | 292 { |
293 std::string uuid = found["Instances"][i].asString(); | |
294 Json::Value instance(Json::objectValue); | |
212 | 295 if (index_.LookupResource(instance, uuid, ResourceType_Instance)) |
0 | 296 { |
297 std::string content; | |
298 storage_.ReadFile(content, instance["FileUuid"].asString()); | |
299 c.Store(content); | |
300 } | |
301 else | |
302 { | |
303 return false; | |
304 } | |
305 } | |
306 } | |
212 | 307 else if (index_.LookupResource(found, postData, ResourceType_Instance)) |
0 | 308 { |
309 // The UUID corresponds to an instance | |
310 std::string content; | |
311 storage_.ReadFile(content, found["FileUuid"].asString()); | |
312 c.Store(content); | |
313 } | |
314 else | |
315 { | |
316 return false; | |
317 } | |
318 | |
319 return true; | |
320 } | |
321 | |
322 | |
62 | 323 OrthancRestApi::OrthancRestApi(ServerIndex& index, |
50 | 324 const std::string& path) : |
0 | 325 index_(index), |
326 storage_(path) | |
327 { | |
328 GetListOfDicomModalities(modalities_); | |
329 } | |
330 | |
331 | |
62 | 332 void OrthancRestApi::Handle( |
0 | 333 HttpOutput& output, |
334 const std::string& method, | |
335 const UriComponents& uri, | |
336 const Arguments& headers, | |
207 | 337 const Arguments& getArguments, |
0 | 338 const std::string& postData) |
339 { | |
340 bool existingResource = false; | |
341 Json::Value result(Json::objectValue); | |
342 | |
343 | |
344 // List all the instances --------------------------------------------------- | |
345 | |
346 if (uri.size() == 1 && uri[0] == "instances") | |
347 { | |
348 if (method == "GET") | |
349 { | |
350 result = Json::Value(Json::arrayValue); | |
190 | 351 index_.GetAllUuids(result, ResourceType_Instance); |
0 | 352 existingResource = true; |
353 } | |
354 else if (method == "POST") | |
355 { | |
356 // Add a new instance to the storage | |
357 if (Store(result, postData)) | |
358 { | |
359 SendJson(output, result); | |
360 return; | |
361 } | |
362 else | |
363 { | |
62 | 364 output.SendHeader(Orthanc_HttpStatus_415_UnsupportedMediaType); |
0 | 365 return; |
366 } | |
367 } | |
368 else | |
369 { | |
370 output.SendMethodNotAllowedError("GET,POST"); | |
371 return; | |
372 } | |
373 } | |
374 | |
375 | |
376 // Get the DICOM or the JSON file of one instance --------------------------- | |
377 | |
378 else if (uri.size() == 3 && | |
379 uri[0] == "instances" && | |
380 (uri[2] == "file" || | |
34
96e57b863dd9
option to disallow remote access
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
8
diff
changeset
|
381 uri[2] == "tags" || |
35
f6d12037f886
full json vs. simplified json
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
34
diff
changeset
|
382 uri[2] == "simplified-tags")) |
0 | 383 { |
193
a1b9d1e1497b
failed attempt to compile with linux standard base
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
192
diff
changeset
|
384 CompressionType compressionType; |
155
93e1b0e3b83a
filenames when downloading json/dicom
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
151
diff
changeset
|
385 std::string fileUuid, contentType, filename; |
0 | 386 if (uri[2] == "file") |
387 { | |
197
530a25320461
removal of text as ids in sqlite db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
193
diff
changeset
|
388 existingResource = index_.GetFile(fileUuid, compressionType, uri[1], AttachedFileType_Dicom); |
0 | 389 contentType = "application/dicom"; |
155
93e1b0e3b83a
filenames when downloading json/dicom
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
151
diff
changeset
|
390 filename = fileUuid + ".dcm"; |
0 | 391 } |
34
96e57b863dd9
option to disallow remote access
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
8
diff
changeset
|
392 else if (uri[2] == "tags" || |
35
f6d12037f886
full json vs. simplified json
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
34
diff
changeset
|
393 uri[2] == "simplified-tags") |
0 | 394 { |
197
530a25320461
removal of text as ids in sqlite db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
193
diff
changeset
|
395 existingResource = index_.GetFile(fileUuid, compressionType, uri[1], AttachedFileType_Json); |
0 | 396 contentType = "application/json"; |
155
93e1b0e3b83a
filenames when downloading json/dicom
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
151
diff
changeset
|
397 filename = fileUuid + ".json"; |
0 | 398 } |
399 | |
400 if (existingResource) | |
401 { | |
35
f6d12037f886
full json vs. simplified json
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
34
diff
changeset
|
402 if (uri[2] == "simplified-tags") |
f6d12037f886
full json vs. simplified json
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
34
diff
changeset
|
403 { |
213
4ce7fdcc8879
access to tags, simplified-tags and file of an instance
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
212
diff
changeset
|
404 Json::Value simplified, full; |
4ce7fdcc8879
access to tags, simplified-tags and file of an instance
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
212
diff
changeset
|
405 ReadJson(full, storage_, fileUuid); |
4ce7fdcc8879
access to tags, simplified-tags and file of an instance
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
212
diff
changeset
|
406 SimplifyTags(simplified, full); |
4ce7fdcc8879
access to tags, simplified-tags and file of an instance
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
212
diff
changeset
|
407 SendJson(output, simplified); |
35
f6d12037f886
full json vs. simplified json
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
34
diff
changeset
|
408 return; |
f6d12037f886
full json vs. simplified json
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
34
diff
changeset
|
409 } |
f6d12037f886
full json vs. simplified json
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
34
diff
changeset
|
410 else |
f6d12037f886
full json vs. simplified json
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
34
diff
changeset
|
411 { |
155
93e1b0e3b83a
filenames when downloading json/dicom
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
151
diff
changeset
|
412 output.AnswerFile(storage_, fileUuid, contentType, filename.c_str()); |
35
f6d12037f886
full json vs. simplified json
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
34
diff
changeset
|
413 return; |
f6d12037f886
full json vs. simplified json
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
34
diff
changeset
|
414 } |
0 | 415 } |
416 } | |
417 | |
418 | |
419 else if (uri.size() == 3 && | |
420 uri[0] == "instances" && | |
53
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
421 uri[2] == "frames") |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
422 { |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
423 Json::Value instance(Json::objectValue); |
212 | 424 existingResource = index_.LookupResource(instance, uri[1], ResourceType_Instance); |
53
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
425 |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
426 if (existingResource) |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
427 { |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
428 result = Json::arrayValue; |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
429 |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
430 unsigned int numberOfFrames = 1; |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
431 try |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
432 { |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
433 Json::Value tmp = instance["MainDicomTags"]["NumberOfFrames"]; |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
434 numberOfFrames = boost::lexical_cast<unsigned int>(tmp.asString()); |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
435 } |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
436 catch (boost::bad_lexical_cast) |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
437 { |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
438 } |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
439 |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
440 for (unsigned int i = 0; i < numberOfFrames; i++) |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
441 { |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
442 result.append(i); |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
443 } |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
444 } |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
445 } |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
446 |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
447 |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
448 else if (uri[0] == "instances" && |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
449 ((uri.size() == 3 && |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
450 (uri[2] == "preview" || |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
451 uri[2] == "image-uint8" || |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
452 uri[2] == "image-uint16")) || |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
453 (uri.size() == 5 && |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
454 uri[2] == "frames" && |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
455 (uri[4] == "preview" || |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
456 uri[4] == "image-uint8" || |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
457 uri[4] == "image-uint16")))) |
0 | 458 { |
459 std::string uuid; | |
193
a1b9d1e1497b
failed attempt to compile with linux standard base
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
192
diff
changeset
|
460 CompressionType compressionType; |
197
530a25320461
removal of text as ids in sqlite db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
193
diff
changeset
|
461 existingResource = index_.GetFile(uuid, compressionType, uri[1], AttachedFileType_Dicom); |
0 | 462 |
53
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
463 std::string action = uri[2]; |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
464 |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
465 unsigned int frame = 0; |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
466 if (existingResource && |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
467 uri.size() == 5) |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
468 { |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
469 // Access to multi-frame image |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
470 action = uri[4]; |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
471 try |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
472 { |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
473 frame = boost::lexical_cast<unsigned int>(uri[3]); |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
474 } |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
475 catch (boost::bad_lexical_cast) |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
476 { |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
477 existingResource = false; |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
478 } |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
479 } |
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
480 |
0 | 481 if (existingResource) |
482 { | |
483 std::string dicomContent, png; | |
484 storage_.ReadFile(dicomContent, uuid); | |
485 try | |
486 { | |
53
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
487 if (action == "preview") |
42
ea48f38afe5f
access to raw images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
41
diff
changeset
|
488 { |
53
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
489 FromDcmtkBridge::ExtractPngImage(png, dicomContent, frame, ImageExtractionMode_Preview); |
42
ea48f38afe5f
access to raw images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
41
diff
changeset
|
490 } |
53
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
491 else if (action == "image-uint8") |
42
ea48f38afe5f
access to raw images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
41
diff
changeset
|
492 { |
53
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
493 FromDcmtkBridge::ExtractPngImage(png, dicomContent, frame, ImageExtractionMode_UInt8); |
42
ea48f38afe5f
access to raw images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
41
diff
changeset
|
494 } |
53
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
495 else if (action == "image-uint16") |
42
ea48f38afe5f
access to raw images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
41
diff
changeset
|
496 { |
53
293038baf8f1
access to multi-frame images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
50
diff
changeset
|
497 FromDcmtkBridge::ExtractPngImage(png, dicomContent, frame, ImageExtractionMode_UInt16); |
42
ea48f38afe5f
access to raw images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
41
diff
changeset
|
498 } |
ea48f38afe5f
access to raw images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
41
diff
changeset
|
499 else |
ea48f38afe5f
access to raw images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
41
diff
changeset
|
500 { |
62 | 501 throw OrthancException(ErrorCode_InternalError); |
42
ea48f38afe5f
access to raw images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
41
diff
changeset
|
502 } |
ea48f38afe5f
access to raw images
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
41
diff
changeset
|
503 |
0 | 504 output.AnswerBufferWithContentType(png, "image/png"); |
505 return; | |
506 } | |
62 | 507 catch (OrthancException&) |
0 | 508 { |
85
ebce15865cce
relative redirection
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
80
diff
changeset
|
509 std::string root = ""; |
ebce15865cce
relative redirection
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
80
diff
changeset
|
510 for (size_t i = 1; i < uri.size(); i++) |
ebce15865cce
relative redirection
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
80
diff
changeset
|
511 { |
ebce15865cce
relative redirection
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
80
diff
changeset
|
512 root += "../"; |
ebce15865cce
relative redirection
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
80
diff
changeset
|
513 } |
ebce15865cce
relative redirection
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
80
diff
changeset
|
514 |
129 | 515 output.Redirect(root + "app/images/unsupported.png"); |
0 | 516 return; |
517 } | |
518 } | |
519 } | |
520 | |
521 | |
522 // DICOM bridge ------------------------------------------------------------- | |
523 | |
524 if ((uri.size() == 2 || | |
525 uri.size() == 3) && | |
526 uri[0] == "modalities") | |
527 { | |
528 if (modalities_.find(uri[1]) == modalities_.end()) | |
529 { | |
530 // Unknown modality | |
531 } | |
532 else if (uri.size() == 2) | |
533 { | |
534 if (method != "GET") | |
535 { | |
536 output.SendMethodNotAllowedError("POST"); | |
537 return; | |
538 } | |
539 else | |
540 { | |
541 existingResource = true; | |
542 result = Json::arrayValue; | |
543 result.append("find-patient"); | |
544 result.append("find-study"); | |
545 result.append("find-series"); | |
546 result.append("find"); | |
547 result.append("store"); | |
548 } | |
549 } | |
550 else if (uri.size() == 3) | |
551 { | |
552 if (uri[2] != "find-patient" && | |
553 uri[2] != "find-study" && | |
554 uri[2] != "find-series" && | |
555 uri[2] != "find" && | |
556 uri[2] != "store") | |
557 { | |
558 // Unknown request | |
559 } | |
560 else if (method != "POST") | |
561 { | |
562 output.SendMethodNotAllowedError("POST"); | |
563 return; | |
564 } | |
565 else | |
566 { | |
567 DicomUserConnection connection; | |
568 ConnectToModality(connection, uri[1]); | |
569 existingResource = true; | |
570 | |
571 if ((uri[2] == "find-patient" && !DicomFindPatient(result, connection, postData)) || | |
572 (uri[2] == "find-study" && !DicomFindStudy(result, connection, postData)) || | |
573 (uri[2] == "find-series" && !DicomFindSeries(result, connection, postData)) || | |
574 (uri[2] == "find" && !DicomFind(result, connection, postData)) || | |
575 (uri[2] == "store" && !DicomStore(result, connection, postData))) | |
576 { | |
62 | 577 output.SendHeader(Orthanc_HttpStatus_400_BadRequest); |
0 | 578 return; |
579 } | |
580 } | |
581 } | |
582 } | |
583 | |
584 | |
585 if (existingResource) | |
586 { | |
587 SendJson(output, result); | |
588 } | |
589 else | |
590 { | |
62 | 591 output.SendHeader(Orthanc_HttpStatus_404_NotFound); |
0 | 592 } |
593 } | |
594 } |