Mercurial > hg > orthanc
annotate Core/DicomFormat/DicomMap.cpp @ 1082:601c5f4631d1 Orthanc-0.8.1
fix
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 29 Jul 2014 12:44:42 +0200 |
parents | a811bdf8b8eb |
children | c2c28dd17e87 f5b0207967bc |
rev | line source |
---|---|
0 | 1 /** |
59 | 2 * Orthanc - A Lightweight, RESTful DICOM Store |
689 | 3 * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, |
0 | 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 | |
824
a811bdf8b8eb
precompiled headers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
730
diff
changeset
|
33 #include "../PrecompiledHeaders.h" |
0 | 34 #include "DicomMap.h" |
35 | |
36 #include <stdio.h> | |
37 #include <memory> | |
38 #include "DicomString.h" | |
59 | 39 #include "../OrthancException.h" |
0 | 40 |
41 | |
59 | 42 namespace Orthanc |
0 | 43 { |
44 static DicomTag patientTags[] = | |
45 { | |
38 | 46 //DicomTag(0x0010, 0x1010), // PatientAge |
47 //DicomTag(0x0010, 0x1040) // PatientAddress | |
77 | 48 DicomTag(0x0010, 0x0010), // PatientName |
49 DicomTag(0x0010, 0x0030), // PatientBirthDate | |
50 DicomTag(0x0010, 0x0040), // PatientSex | |
51 DicomTag(0x0010, 0x1000), // OtherPatientIDs | |
80 | 52 DICOM_TAG_PATIENT_ID |
0 | 53 }; |
54 | |
55 static DicomTag studyTags[] = | |
56 { | |
38 | 57 //DicomTag(0x0010, 0x1020), // PatientSize |
58 //DicomTag(0x0010, 0x1030) // PatientWeight | |
77 | 59 DicomTag(0x0008, 0x0020), // StudyDate |
60 DicomTag(0x0008, 0x0030), // StudyTime | |
61 DicomTag(0x0008, 0x1030), // StudyDescription | |
62 DicomTag(0x0020, 0x0010), // StudyID | |
80 | 63 DICOM_TAG_ACCESSION_NUMBER, |
64 DICOM_TAG_STUDY_INSTANCE_UID | |
0 | 65 }; |
66 | |
67 static DicomTag seriesTags[] = | |
68 { | |
38 | 69 //DicomTag(0x0010, 0x1080), // MilitaryRank |
77 | 70 DicomTag(0x0008, 0x0021), // SeriesDate |
71 DicomTag(0x0008, 0x0031), // SeriesTime | |
72 DicomTag(0x0008, 0x0060), // Modality | |
73 DicomTag(0x0008, 0x0070), // Manufacturer | |
74 DicomTag(0x0008, 0x1010), // StationName | |
75 DicomTag(0x0008, 0x103e), // SeriesDescription | |
76 DicomTag(0x0018, 0x0015), // BodyPartExamined | |
77 DicomTag(0x0018, 0x0024), // SequenceName | |
78 DicomTag(0x0018, 0x1030), // ProtocolName | |
79 DicomTag(0x0020, 0x0011), // SeriesNumber | |
433 | 80 DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES, |
80 | 81 DICOM_TAG_IMAGES_IN_ACQUISITION, |
433 | 82 DICOM_TAG_NUMBER_OF_TEMPORAL_POSITIONS, |
80 | 83 DICOM_TAG_NUMBER_OF_SLICES, |
433 | 84 DICOM_TAG_NUMBER_OF_TIME_SLICES, |
80 | 85 DICOM_TAG_SERIES_INSTANCE_UID |
0 | 86 }; |
87 | |
88 static DicomTag instanceTags[] = | |
89 { | |
77 | 90 DicomTag(0x0008, 0x0012), // InstanceCreationDate |
91 DicomTag(0x0008, 0x0013), // InstanceCreationTime | |
92 DicomTag(0x0020, 0x0012), // AcquisitionNumber | |
80 | 93 DICOM_TAG_IMAGE_INDEX, |
94 DICOM_TAG_INSTANCE_NUMBER, | |
84 | 95 DICOM_TAG_NUMBER_OF_FRAMES, |
433 | 96 DICOM_TAG_TEMPORAL_POSITION_IDENTIFIER, |
80 | 97 DICOM_TAG_SOP_INSTANCE_UID |
0 | 98 }; |
99 | |
100 | |
101 | |
102 | |
103 void DicomMap::SetValue(uint16_t group, | |
104 uint16_t element, | |
105 DicomValue* value) | |
106 { | |
107 DicomTag tag(group, element); | |
108 Map::iterator it = map_.find(tag); | |
109 | |
110 if (it != map_.end()) | |
111 { | |
112 delete it->second; | |
113 it->second = value; | |
114 } | |
115 else | |
116 { | |
117 map_.insert(std::make_pair(tag, value)); | |
118 } | |
119 } | |
120 | |
121 void DicomMap::SetValue(DicomTag tag, | |
122 DicomValue* value) | |
123 { | |
124 SetValue(tag.GetGroup(), tag.GetElement(), value); | |
125 } | |
126 | |
127 | |
128 | |
129 | |
130 void DicomMap::Clear() | |
131 { | |
656 | 132 for (Map::iterator it = map_.begin(); it != map_.end(); ++it) |
0 | 133 { |
134 delete it->second; | |
135 } | |
136 | |
137 map_.clear(); | |
138 } | |
139 | |
140 | |
141 void DicomMap::ExtractTags(DicomMap& result, | |
142 const DicomTag* tags, | |
143 size_t count) const | |
144 { | |
145 result.Clear(); | |
146 | |
147 for (unsigned int i = 0; i < count; i++) | |
148 { | |
149 Map::const_iterator it = map_.find(tags[i]); | |
150 if (it != map_.end()) | |
151 { | |
152 result.SetValue(it->first, it->second->Clone()); | |
153 } | |
154 } | |
155 } | |
156 | |
157 | |
158 void DicomMap::ExtractPatientInformation(DicomMap& result) const | |
159 { | |
160 ExtractTags(result, patientTags, sizeof(patientTags) / sizeof(DicomTag)); | |
161 } | |
162 | |
163 void DicomMap::ExtractStudyInformation(DicomMap& result) const | |
164 { | |
165 ExtractTags(result, studyTags, sizeof(studyTags) / sizeof(DicomTag)); | |
166 } | |
167 | |
168 void DicomMap::ExtractSeriesInformation(DicomMap& result) const | |
169 { | |
170 ExtractTags(result, seriesTags, sizeof(seriesTags) / sizeof(DicomTag)); | |
171 } | |
172 | |
173 void DicomMap::ExtractInstanceInformation(DicomMap& result) const | |
174 { | |
175 ExtractTags(result, instanceTags, sizeof(instanceTags) / sizeof(DicomTag)); | |
176 } | |
177 | |
178 | |
80 | 179 |
0 | 180 DicomMap* DicomMap::Clone() const |
181 { | |
182 std::auto_ptr<DicomMap> result(new DicomMap); | |
183 | |
656 | 184 for (Map::const_iterator it = map_.begin(); it != map_.end(); ++it) |
0 | 185 { |
186 result->map_.insert(std::make_pair(it->first, it->second->Clone())); | |
187 } | |
188 | |
189 return result.release(); | |
190 } | |
191 | |
192 | |
193 const DicomValue& DicomMap::GetValue(const DicomTag& tag) const | |
194 { | |
80 | 195 const DicomValue* value = TestAndGetValue(tag); |
196 | |
197 if (value) | |
198 { | |
199 return *value; | |
200 } | |
201 else | |
202 { | |
730
309e686b41e7
better logging about nonexistent tags
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
689
diff
changeset
|
203 throw OrthancException(ErrorCode_InexistentTag); |
80 | 204 } |
205 } | |
206 | |
207 | |
208 const DicomValue* DicomMap::TestAndGetValue(const DicomTag& tag) const | |
209 { | |
0 | 210 Map::const_iterator it = map_.find(tag); |
211 | |
212 if (it == map_.end()) | |
213 { | |
80 | 214 return NULL; |
0 | 215 } |
216 else | |
217 { | |
80 | 218 return it->second; |
0 | 219 } |
220 } | |
221 | |
222 | |
223 void DicomMap::Remove(const DicomTag& tag) | |
224 { | |
225 Map::iterator it = map_.find(tag); | |
226 if (it != map_.end()) | |
227 { | |
228 delete it->second; | |
229 map_.erase(it); | |
230 } | |
231 } | |
232 | |
233 | |
234 static void SetupFindTemplate(DicomMap& result, | |
235 const DicomTag* tags, | |
236 size_t count) | |
237 { | |
238 result.Clear(); | |
239 | |
240 for (size_t i = 0; i < count; i++) | |
241 { | |
242 result.SetValue(tags[i], ""); | |
243 } | |
244 } | |
245 | |
246 void DicomMap::SetupFindPatientTemplate(DicomMap& result) | |
247 { | |
248 SetupFindTemplate(result, patientTags, sizeof(patientTags) / sizeof(DicomTag)); | |
249 } | |
250 | |
251 void DicomMap::SetupFindStudyTemplate(DicomMap& result) | |
252 { | |
253 SetupFindTemplate(result, studyTags, sizeof(studyTags) / sizeof(DicomTag)); | |
80 | 254 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, ""); |
255 result.SetValue(DICOM_TAG_PATIENT_ID, ""); | |
0 | 256 } |
257 | |
258 void DicomMap::SetupFindSeriesTemplate(DicomMap& result) | |
259 { | |
260 SetupFindTemplate(result, seriesTags, sizeof(seriesTags) / sizeof(DicomTag)); | |
80 | 261 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, ""); |
262 result.SetValue(DICOM_TAG_PATIENT_ID, ""); | |
263 result.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, ""); | |
0 | 264 } |
265 | |
266 void DicomMap::SetupFindInstanceTemplate(DicomMap& result) | |
267 { | |
268 SetupFindTemplate(result, instanceTags, sizeof(instanceTags) / sizeof(DicomTag)); | |
80 | 269 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, ""); |
270 result.SetValue(DICOM_TAG_PATIENT_ID, ""); | |
271 result.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, ""); | |
272 result.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, ""); | |
0 | 273 } |
274 | |
275 | |
276 void DicomMap::CopyTagIfExists(const DicomMap& source, | |
277 const DicomTag& tag) | |
278 { | |
279 if (source.HasTag(tag)) | |
280 { | |
281 SetValue(tag, source.GetValue(tag)); | |
282 } | |
283 } | |
562
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
284 |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
285 |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
286 bool DicomMap::IsMainDicomTag(const DicomTag& tag, ResourceType level) |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
287 { |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
288 DicomTag *tags = NULL; |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
289 size_t size; |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
290 |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
291 switch (level) |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
292 { |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
293 case ResourceType_Patient: |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
294 tags = patientTags; |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
295 size = sizeof(patientTags) / sizeof(DicomTag); |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
296 break; |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
297 |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
298 case ResourceType_Study: |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
299 tags = studyTags; |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
300 size = sizeof(studyTags) / sizeof(DicomTag); |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
301 break; |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
302 |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
303 case ResourceType_Series: |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
304 tags = seriesTags; |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
305 size = sizeof(seriesTags) / sizeof(DicomTag); |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
306 break; |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
307 |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
308 case ResourceType_Instance: |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
309 tags = instanceTags; |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
310 size = sizeof(instanceTags) / sizeof(DicomTag); |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
311 break; |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
312 |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
313 default: |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
314 throw OrthancException(ErrorCode_ParameterOutOfRange); |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
315 } |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
316 |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
317 for (size_t i = 0; i < size; i++) |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
318 { |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
319 if (tags[i] == tag) |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
320 { |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
321 return true; |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
322 } |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
323 } |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
324 |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
325 return false; |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
326 } |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
327 |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
328 bool DicomMap::IsMainDicomTag(const DicomTag& tag) |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
329 { |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
330 return (IsMainDicomTag(tag, ResourceType_Patient) || |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
331 IsMainDicomTag(tag, ResourceType_Study) || |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
332 IsMainDicomTag(tag, ResourceType_Series) || |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
333 IsMainDicomTag(tag, ResourceType_Instance)); |
f64e3838d6e1
refactoring enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
433
diff
changeset
|
334 } |
567 | 335 |
336 | |
337 void DicomMap::GetMainDicomTagsInternal(std::set<DicomTag>& result, ResourceType level) | |
338 { | |
339 DicomTag *tags = NULL; | |
340 size_t size; | |
341 | |
342 switch (level) | |
343 { | |
344 case ResourceType_Patient: | |
345 tags = patientTags; | |
346 size = sizeof(patientTags) / sizeof(DicomTag); | |
347 break; | |
348 | |
349 case ResourceType_Study: | |
350 tags = studyTags; | |
351 size = sizeof(studyTags) / sizeof(DicomTag); | |
352 break; | |
353 | |
354 case ResourceType_Series: | |
355 tags = seriesTags; | |
356 size = sizeof(seriesTags) / sizeof(DicomTag); | |
357 break; | |
358 | |
359 case ResourceType_Instance: | |
360 tags = instanceTags; | |
361 size = sizeof(instanceTags) / sizeof(DicomTag); | |
362 break; | |
363 | |
364 default: | |
365 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
366 } | |
367 | |
368 for (size_t i = 0; i < size; i++) | |
369 { | |
370 result.insert(tags[i]); | |
371 } | |
372 } | |
373 | |
374 | |
375 void DicomMap::GetMainDicomTags(std::set<DicomTag>& result, ResourceType level) | |
376 { | |
377 result.clear(); | |
378 GetMainDicomTagsInternal(result, level); | |
379 } | |
380 | |
381 | |
382 void DicomMap::GetMainDicomTags(std::set<DicomTag>& result) | |
383 { | |
384 result.clear(); | |
385 GetMainDicomTagsInternal(result, ResourceType_Patient); | |
386 GetMainDicomTagsInternal(result, ResourceType_Study); | |
387 GetMainDicomTagsInternal(result, ResourceType_Series); | |
388 GetMainDicomTagsInternal(result, ResourceType_Instance); | |
389 } | |
0 | 390 } |