comparison Core/DicomFormat/DicomMap.cpp @ 3651:46cb00e4adbb

DicomMap::DumpMainDicomTags() and DicomMap::ParseMainDicomTags()
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 05 Feb 2020 13:22:02 +0100
parents e5811a9f8df0
children 335611d2b6cd 468181e2f090
comparison
equal deleted inserted replaced
3650:e5811a9f8df0 3651:46cb00e4adbb
44 #include "DicomArray.h" 44 #include "DicomArray.h"
45 45
46 46
47 namespace Orthanc 47 namespace Orthanc
48 { 48 {
49 static DicomTag patientTags[] = 49 namespace
50 { 50 {
51 //DicomTag(0x0010, 0x1010), // PatientAge 51 struct MainDicomTag
52 //DicomTag(0x0010, 0x1040) // PatientAddress 52 {
53 DicomTag(0x0010, 0x0010), // PatientName 53 const DicomTag tag_;
54 DicomTag(0x0010, 0x0030), // PatientBirthDate 54 const char* name_;
55 DicomTag(0x0010, 0x0040), // PatientSex 55 };
56 DicomTag(0x0010, 0x1000), // OtherPatientIDs 56 }
57 DICOM_TAG_PATIENT_ID 57
58 static const MainDicomTag PATIENT_MAIN_DICOM_TAGS[] =
59 {
60 // { DicomTag(0x0010, 0x1010), "PatientAge" },
61 // { DicomTag(0x0010, 0x1040), "PatientAddress" },
62 { DicomTag(0x0010, 0x0010), "PatientName" },
63 { DicomTag(0x0010, 0x0030), "PatientBirthDate" },
64 { DicomTag(0x0010, 0x0040), "PatientSex" },
65 { DicomTag(0x0010, 0x1000), "OtherPatientIDs" },
66 { DICOM_TAG_PATIENT_ID, "PatientID" }
58 }; 67 };
59 68
60 static DicomTag studyTags[] = 69 static const MainDicomTag STUDY_MAIN_DICOM_TAGS[] =
61 { 70 {
62 //DicomTag(0x0010, 0x1020), // PatientSize 71 // { DicomTag(0x0010, 0x1020), "PatientSize" },
63 //DicomTag(0x0010, 0x1030) // PatientWeight 72 // { DicomTag(0x0010, 0x1030), "PatientWeight" },
64 DICOM_TAG_STUDY_DATE, 73 { DICOM_TAG_STUDY_DATE, "StudyDate" },
65 DicomTag(0x0008, 0x0030), // StudyTime 74 { DicomTag(0x0008, 0x0030), "StudyTime" },
66 DicomTag(0x0020, 0x0010), // StudyID 75 { DicomTag(0x0020, 0x0010), "StudyID" },
67 DICOM_TAG_STUDY_DESCRIPTION, 76 { DICOM_TAG_STUDY_DESCRIPTION, "StudyDescription" },
68 DICOM_TAG_ACCESSION_NUMBER, 77 { DICOM_TAG_ACCESSION_NUMBER, "AccessionNumber" },
69 DICOM_TAG_STUDY_INSTANCE_UID, 78 { DICOM_TAG_STUDY_INSTANCE_UID, "StudyInstanceUID" },
70 DICOM_TAG_REQUESTED_PROCEDURE_DESCRIPTION, // New in db v6 79
71 DICOM_TAG_INSTITUTION_NAME, // New in db v6 80 // New in db v6
72 DICOM_TAG_REQUESTING_PHYSICIAN, // New in db v6 81 { DICOM_TAG_REQUESTED_PROCEDURE_DESCRIPTION, "RequestedProcedureDescription" },
73 DICOM_TAG_REFERRING_PHYSICIAN_NAME // New in db v6 82 { DICOM_TAG_INSTITUTION_NAME, "InstitutionName" },
83 { DICOM_TAG_REQUESTING_PHYSICIAN, "RequestingPhysician" },
84 { DICOM_TAG_REFERRING_PHYSICIAN_NAME, "ReferringPhysicianName" }
74 }; 85 };
75 86
76 static DicomTag seriesTags[] = 87 static const MainDicomTag SERIES_MAIN_DICOM_TAGS[] =
77 { 88 {
78 //DicomTag(0x0010, 0x1080), // MilitaryRank 89 // { DicomTag(0x0010, 0x1080), "MilitaryRank" },
79 DicomTag(0x0008, 0x0021), // SeriesDate 90 { DicomTag(0x0008, 0x0021), "SeriesDate" },
80 DicomTag(0x0008, 0x0031), // SeriesTime 91 { DicomTag(0x0008, 0x0031), "SeriesTime" },
81 DICOM_TAG_MODALITY, 92 { DICOM_TAG_MODALITY, "Modality" },
82 DicomTag(0x0008, 0x0070), // Manufacturer 93 { DicomTag(0x0008, 0x0070), "Manufacturer" },
83 DicomTag(0x0008, 0x1010), // StationName 94 { DicomTag(0x0008, 0x1010), "StationName" },
84 DICOM_TAG_SERIES_DESCRIPTION, 95 { DICOM_TAG_SERIES_DESCRIPTION, "SeriesDescription" },
85 DicomTag(0x0018, 0x0015), // BodyPartExamined 96 { DicomTag(0x0018, 0x0015), "BodyPartExamined" },
86 DicomTag(0x0018, 0x0024), // SequenceName 97 { DicomTag(0x0018, 0x0024), "SequenceName" },
87 DicomTag(0x0018, 0x1030), // ProtocolName 98 { DicomTag(0x0018, 0x1030), "ProtocolName" },
88 DicomTag(0x0020, 0x0011), // SeriesNumber 99 { DicomTag(0x0020, 0x0011), "SeriesNumber" },
89 DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES, 100 { DICOM_TAG_CARDIAC_NUMBER_OF_IMAGES, "CardiacNumberOfImages" },
90 DICOM_TAG_IMAGES_IN_ACQUISITION, 101 { DICOM_TAG_IMAGES_IN_ACQUISITION, "ImagesInAcquisition" },
91 DICOM_TAG_NUMBER_OF_TEMPORAL_POSITIONS, 102 { DICOM_TAG_NUMBER_OF_TEMPORAL_POSITIONS, "NumberOfTemporalPositions" },
92 DICOM_TAG_NUMBER_OF_SLICES, 103 { DICOM_TAG_NUMBER_OF_SLICES, "NumberOfSlices" },
93 DICOM_TAG_NUMBER_OF_TIME_SLICES, 104 { DICOM_TAG_NUMBER_OF_TIME_SLICES, "NumberOfTimeSlices" },
94 DICOM_TAG_SERIES_INSTANCE_UID, 105 { DICOM_TAG_SERIES_INSTANCE_UID, "SeriesInstanceUID" },
95 DICOM_TAG_IMAGE_ORIENTATION_PATIENT, // New in db v6 106
96 DICOM_TAG_SERIES_TYPE, // New in db v6 107 // New in db v6
97 DICOM_TAG_OPERATOR_NAME, // New in db v6 108 { DICOM_TAG_IMAGE_ORIENTATION_PATIENT, "ImageOrientationPatient" },
98 DICOM_TAG_PERFORMED_PROCEDURE_STEP_DESCRIPTION, // New in db v6 109 { DICOM_TAG_SERIES_TYPE, "SeriesType" },
99 DICOM_TAG_ACQUISITION_DEVICE_PROCESSING_DESCRIPTION, // New in db v6 110 { DICOM_TAG_OPERATOR_NAME, "OperatorsName" },
100 DICOM_TAG_CONTRAST_BOLUS_AGENT // New in db v6 111 { DICOM_TAG_PERFORMED_PROCEDURE_STEP_DESCRIPTION, "PerformedProcedureStepDescription" },
112 { DICOM_TAG_ACQUISITION_DEVICE_PROCESSING_DESCRIPTION, "AcquisitionDeviceProcessingDescription" },
113 { DICOM_TAG_CONTRAST_BOLUS_AGENT, "ContrastBolusAgent" }
101 }; 114 };
102 115
103 static DicomTag instanceTags[] = 116 static const MainDicomTag INSTANCE_MAIN_DICOM_TAGS[] =
104 { 117 {
105 DicomTag(0x0008, 0x0012), // InstanceCreationDate 118 { DicomTag(0x0008, 0x0012), "InstanceCreationDate" },
106 DicomTag(0x0008, 0x0013), // InstanceCreationTime 119 { DicomTag(0x0008, 0x0013), "InstanceCreationTime" },
107 DicomTag(0x0020, 0x0012), // AcquisitionNumber 120 { DicomTag(0x0020, 0x0012), "AcquisitionNumber" },
108 DICOM_TAG_IMAGE_INDEX, 121 { DICOM_TAG_IMAGE_INDEX, "ImageIndex" },
109 DICOM_TAG_INSTANCE_NUMBER, 122 { DICOM_TAG_INSTANCE_NUMBER, "InstanceNumber" },
110 DICOM_TAG_NUMBER_OF_FRAMES, 123 { DICOM_TAG_NUMBER_OF_FRAMES, "NumberOfFrames" },
111 DICOM_TAG_TEMPORAL_POSITION_IDENTIFIER, 124 { DICOM_TAG_TEMPORAL_POSITION_IDENTIFIER, "TemporalPositionIdentifier" },
112 DICOM_TAG_SOP_INSTANCE_UID, 125 { DICOM_TAG_SOP_INSTANCE_UID, "SOPInstanceUID" },
113 DICOM_TAG_IMAGE_POSITION_PATIENT, // New in db v6 126
114 DICOM_TAG_IMAGE_COMMENTS, // New in db v6 127 // New in db v6
128 { DICOM_TAG_IMAGE_POSITION_PATIENT, "ImagePositionPatient" },
129 { DICOM_TAG_IMAGE_COMMENTS, "ImageComments" },
115 130
116 /** 131 /**
117 * Main DICOM tags that are not part of any release of the 132 * Main DICOM tags that are not part of any release of the
118 * database schema yet, and that will be part of future db v7. In 133 * database schema yet, and that will be part of future db v7. In
119 * the meantime, the user must call "/tools/reconstruct" once to 134 * the meantime, the user must call "/tools/reconstruct" once to
120 * access these tags if the corresponding DICOM files where 135 * access these tags if the corresponding DICOM files where
121 * indexed in the database by an older version of Orthanc. 136 * indexed in the database by an older version of Orthanc.
122 **/ 137 **/
123 DICOM_TAG_IMAGE_ORIENTATION_PATIENT // New in Orthanc 1.4.2 138 { DICOM_TAG_IMAGE_ORIENTATION_PATIENT, "ImageOrientationPatient" } // New in Orthanc 1.4.2
124 }; 139 };
125 140
126 141
127 static void LoadMainDicomTags(const DicomTag*& tags, 142 static void LoadMainDicomTags(const MainDicomTag*& tags,
128 size_t& size, 143 size_t& size,
129 ResourceType level) 144 ResourceType level)
130 { 145 {
131 switch (level) 146 switch (level)
132 { 147 {
133 case ResourceType_Patient: 148 case ResourceType_Patient:
134 tags = patientTags; 149 tags = PATIENT_MAIN_DICOM_TAGS;
135 size = sizeof(patientTags) / sizeof(DicomTag); 150 size = sizeof(PATIENT_MAIN_DICOM_TAGS) / sizeof(MainDicomTag);
136 break; 151 break;
137 152
138 case ResourceType_Study: 153 case ResourceType_Study:
139 tags = studyTags; 154 tags = STUDY_MAIN_DICOM_TAGS;
140 size = sizeof(studyTags) / sizeof(DicomTag); 155 size = sizeof(STUDY_MAIN_DICOM_TAGS) / sizeof(MainDicomTag);
141 break; 156 break;
142 157
143 case ResourceType_Series: 158 case ResourceType_Series:
144 tags = seriesTags; 159 tags = SERIES_MAIN_DICOM_TAGS;
145 size = sizeof(seriesTags) / sizeof(DicomTag); 160 size = sizeof(SERIES_MAIN_DICOM_TAGS) / sizeof(MainDicomTag);
146 break; 161 break;
147 162
148 case ResourceType_Instance: 163 case ResourceType_Instance:
149 tags = instanceTags; 164 tags = INSTANCE_MAIN_DICOM_TAGS;
150 size = sizeof(instanceTags) / sizeof(DicomTag); 165 size = sizeof(INSTANCE_MAIN_DICOM_TAGS) / sizeof(MainDicomTag);
151 break; 166 break;
152 167
153 default: 168 default:
154 throw OrthancException(ErrorCode_ParameterOutOfRange); 169 throw OrthancException(ErrorCode_ParameterOutOfRange);
155 } 170 }
156 } 171 }
157 172
158 173
159 void DicomMap::SetValue(uint16_t group, 174 static void LoadMainDicomTags(std::map<DicomTag, std::string>& target,
160 uint16_t element, 175 ResourceType level)
161 DicomValue* value) 176 {
177 const MainDicomTag* tags = NULL;
178 size_t size;
179 LoadMainDicomTags(tags, size, level);
180
181 assert(tags != NULL &&
182 size != 0);
183
184 for (size_t i = 0; i < size; i++)
185 {
186 assert(target.find(tags[i].tag_) == target.end());
187
188 target[tags[i].tag_] = tags[i].name_;
189 }
190 }
191
192
193 namespace
194 {
195 class DicomTag2 : public DicomTag
196 {
197 public:
198 DicomTag2() :
199 DicomTag(0, 0) // To make std::map<> happy
200 {
201 }
202
203 DicomTag2(const DicomTag& tag) :
204 DicomTag(tag)
205 {
206 }
207 };
208 }
209
210
211 static void LoadMainDicomTags(std::map<std::string, DicomTag2>& target,
212 ResourceType level)
213 {
214 const MainDicomTag* tags = NULL;
215 size_t size;
216 LoadMainDicomTags(tags, size, level);
217
218 assert(tags != NULL &&
219 size != 0);
220
221 for (size_t i = 0; i < size; i++)
222 {
223 assert(target.find(tags[i].name_) == target.end());
224
225 target[tags[i].name_] = tags[i].tag_;
226 }
227 }
228
229
230 void DicomMap::SetValueInternal(uint16_t group,
231 uint16_t element,
232 DicomValue* value)
162 { 233 {
163 DicomTag tag(group, element); 234 DicomTag tag(group, element);
164 Map::iterator it = map_.find(tag); 235 Content::iterator it = content_.find(tag);
165 236
166 if (it != map_.end()) 237 if (it != content_.end())
167 { 238 {
168 delete it->second; 239 delete it->second;
169 it->second = value; 240 it->second = value;
170 } 241 }
171 else 242 else
172 { 243 {
173 map_.insert(std::make_pair(tag, value)); 244 content_.insert(std::make_pair(tag, value));
174 } 245 }
175 }
176
177 void DicomMap::SetValue(DicomTag tag,
178 DicomValue* value)
179 {
180 SetValue(tag.GetGroup(), tag.GetElement(), value);
181 } 246 }
182 247
183 248
184 void DicomMap::Clear() 249 void DicomMap::Clear()
185 { 250 {
186 for (Map::iterator it = map_.begin(); it != map_.end(); ++it) 251 for (Content::iterator it = content_.begin(); it != content_.end(); ++it)
187 { 252 {
188 assert(it->second != NULL); 253 assert(it->second != NULL);
189 delete it->second; 254 delete it->second;
190 } 255 }
191 256
192 map_.clear(); 257 content_.clear();
193 } 258 }
194 259
195 260
196 void DicomMap::ExtractTags(DicomMap& result, 261 static void ExtractTags(DicomMap& result,
197 const DicomTag* tags, 262 const DicomMap::Content& source,
198 size_t count) const 263 const MainDicomTag* tags,
264 size_t count)
199 { 265 {
200 result.Clear(); 266 result.Clear();
201 267
202 for (unsigned int i = 0; i < count; i++) 268 for (unsigned int i = 0; i < count; i++)
203 { 269 {
204 Map::const_iterator it = map_.find(tags[i]); 270 DicomMap::Content::const_iterator it = source.find(tags[i].tag_);
205 if (it != map_.end()) 271 if (it != source.end())
206 { 272 {
207 result.SetValue(it->first, it->second->Clone()); 273 result.SetValue(it->first, *it->second /* value will be cloned */);
208 } 274 }
209 } 275 }
210 } 276 }
211 277
212 278
213 void DicomMap::ExtractPatientInformation(DicomMap& result) const 279 void DicomMap::ExtractPatientInformation(DicomMap& result) const
214 { 280 {
215 ExtractTags(result, patientTags, sizeof(patientTags) / sizeof(DicomTag)); 281 ExtractTags(result, content_, PATIENT_MAIN_DICOM_TAGS, sizeof(PATIENT_MAIN_DICOM_TAGS) / sizeof(MainDicomTag));
216 } 282 }
217 283
218 void DicomMap::ExtractStudyInformation(DicomMap& result) const 284 void DicomMap::ExtractStudyInformation(DicomMap& result) const
219 { 285 {
220 ExtractTags(result, studyTags, sizeof(studyTags) / sizeof(DicomTag)); 286 ExtractTags(result, content_, STUDY_MAIN_DICOM_TAGS, sizeof(STUDY_MAIN_DICOM_TAGS) / sizeof(MainDicomTag));
221 } 287 }
222 288
223 void DicomMap::ExtractSeriesInformation(DicomMap& result) const 289 void DicomMap::ExtractSeriesInformation(DicomMap& result) const
224 { 290 {
225 ExtractTags(result, seriesTags, sizeof(seriesTags) / sizeof(DicomTag)); 291 ExtractTags(result, content_, SERIES_MAIN_DICOM_TAGS, sizeof(SERIES_MAIN_DICOM_TAGS) / sizeof(MainDicomTag));
226 } 292 }
227 293
228 void DicomMap::ExtractInstanceInformation(DicomMap& result) const 294 void DicomMap::ExtractInstanceInformation(DicomMap& result) const
229 { 295 {
230 ExtractTags(result, instanceTags, sizeof(instanceTags) / sizeof(DicomTag)); 296 ExtractTags(result, content_, INSTANCE_MAIN_DICOM_TAGS, sizeof(INSTANCE_MAIN_DICOM_TAGS) / sizeof(MainDicomTag));
231 } 297 }
232 298
233 299
234 300
235 DicomMap* DicomMap::Clone() const 301 DicomMap* DicomMap::Clone() const
236 { 302 {
237 std::auto_ptr<DicomMap> result(new DicomMap); 303 std::auto_ptr<DicomMap> result(new DicomMap);
238 304
239 for (Map::const_iterator it = map_.begin(); it != map_.end(); ++it) 305 for (Content::const_iterator it = content_.begin(); it != content_.end(); ++it)
240 { 306 {
241 result->map_.insert(std::make_pair(it->first, it->second->Clone())); 307 result->content_.insert(std::make_pair(it->first, it->second->Clone()));
242 } 308 }
243 309
244 return result.release(); 310 return result.release();
245 } 311 }
246 312
247 313
248 void DicomMap::Assign(const DicomMap& other) 314 void DicomMap::Assign(const DicomMap& other)
249 { 315 {
250 Clear(); 316 Clear();
251 317
252 for (Map::const_iterator it = other.map_.begin(); it != other.map_.end(); ++it) 318 for (Content::const_iterator it = other.content_.begin(); it != other.content_.end(); ++it)
253 { 319 {
254 map_.insert(std::make_pair(it->first, it->second->Clone())); 320 content_.insert(std::make_pair(it->first, it->second->Clone()));
255 } 321 }
256 } 322 }
257 323
258 324
259 const DicomValue& DicomMap::GetValue(const DicomTag& tag) const 325 const DicomValue& DicomMap::GetValue(const DicomTag& tag) const
271 } 337 }
272 338
273 339
274 const DicomValue* DicomMap::TestAndGetValue(const DicomTag& tag) const 340 const DicomValue* DicomMap::TestAndGetValue(const DicomTag& tag) const
275 { 341 {
276 Map::const_iterator it = map_.find(tag); 342 Content::const_iterator it = content_.find(tag);
277 343
278 if (it == map_.end()) 344 if (it == content_.end())
279 { 345 {
280 return NULL; 346 return NULL;
281 } 347 }
282 else 348 else
283 { 349 {
286 } 352 }
287 353
288 354
289 void DicomMap::Remove(const DicomTag& tag) 355 void DicomMap::Remove(const DicomTag& tag)
290 { 356 {
291 Map::iterator it = map_.find(tag); 357 Content::iterator it = content_.find(tag);
292 if (it != map_.end()) 358 if (it != content_.end())
293 { 359 {
294 delete it->second; 360 delete it->second;
295 map_.erase(it); 361 content_.erase(it);
296 } 362 }
297 } 363 }
298 364
299 365
300 static void SetupFindTemplate(DicomMap& result, 366 static void SetupFindTemplate(DicomMap& result,
301 const DicomTag* tags, 367 const MainDicomTag* tags,
302 size_t count) 368 size_t count)
303 { 369 {
304 result.Clear(); 370 result.Clear();
305 371
306 for (size_t i = 0; i < count; i++) 372 for (size_t i = 0; i < count; i++)
307 { 373 {
308 result.SetValue(tags[i], "", false); 374 result.SetValue(tags[i].tag_, "", false);
309 } 375 }
310 } 376 }
311 377
312 void DicomMap::SetupFindPatientTemplate(DicomMap& result) 378 void DicomMap::SetupFindPatientTemplate(DicomMap& result)
313 { 379 {
314 SetupFindTemplate(result, patientTags, sizeof(patientTags) / sizeof(DicomTag)); 380 SetupFindTemplate(result, PATIENT_MAIN_DICOM_TAGS, sizeof(PATIENT_MAIN_DICOM_TAGS) / sizeof(MainDicomTag));
315 } 381 }
316 382
317 void DicomMap::SetupFindStudyTemplate(DicomMap& result) 383 void DicomMap::SetupFindStudyTemplate(DicomMap& result)
318 { 384 {
319 SetupFindTemplate(result, studyTags, sizeof(studyTags) / sizeof(DicomTag)); 385 SetupFindTemplate(result, STUDY_MAIN_DICOM_TAGS, sizeof(STUDY_MAIN_DICOM_TAGS) / sizeof(MainDicomTag));
320 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false); 386 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false);
321 result.SetValue(DICOM_TAG_PATIENT_ID, "", false); 387 result.SetValue(DICOM_TAG_PATIENT_ID, "", false);
322 388
323 // These main DICOM tags are only indirectly related to the 389 // These main DICOM tags are only indirectly related to the
324 // General Study Module, remove them 390 // General Study Module, remove them
327 result.Remove(DICOM_TAG_REQUESTED_PROCEDURE_DESCRIPTION); 393 result.Remove(DICOM_TAG_REQUESTED_PROCEDURE_DESCRIPTION);
328 } 394 }
329 395
330 void DicomMap::SetupFindSeriesTemplate(DicomMap& result) 396 void DicomMap::SetupFindSeriesTemplate(DicomMap& result)
331 { 397 {
332 SetupFindTemplate(result, seriesTags, sizeof(seriesTags) / sizeof(DicomTag)); 398 SetupFindTemplate(result, SERIES_MAIN_DICOM_TAGS, sizeof(SERIES_MAIN_DICOM_TAGS) / sizeof(MainDicomTag));
333 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false); 399 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false);
334 result.SetValue(DICOM_TAG_PATIENT_ID, "", false); 400 result.SetValue(DICOM_TAG_PATIENT_ID, "", false);
335 result.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "", false); 401 result.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "", false);
336 402
337 // These tags are considered as "main" by Orthanc, but are not in the Series module 403 // These tags are considered as "main" by Orthanc, but are not in the Series module
349 result.Remove(DICOM_TAG_CONTRAST_BOLUS_AGENT); 415 result.Remove(DICOM_TAG_CONTRAST_BOLUS_AGENT);
350 } 416 }
351 417
352 void DicomMap::SetupFindInstanceTemplate(DicomMap& result) 418 void DicomMap::SetupFindInstanceTemplate(DicomMap& result)
353 { 419 {
354 SetupFindTemplate(result, instanceTags, sizeof(instanceTags) / sizeof(DicomTag)); 420 SetupFindTemplate(result, INSTANCE_MAIN_DICOM_TAGS, sizeof(INSTANCE_MAIN_DICOM_TAGS) / sizeof(MainDicomTag));
355 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false); 421 result.SetValue(DICOM_TAG_ACCESSION_NUMBER, "", false);
356 result.SetValue(DICOM_TAG_PATIENT_ID, "", false); 422 result.SetValue(DICOM_TAG_PATIENT_ID, "", false);
357 result.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "", false); 423 result.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "", false);
358 result.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, "", false); 424 result.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, "", false);
359 } 425 }
369 } 435 }
370 436
371 437
372 bool DicomMap::IsMainDicomTag(const DicomTag& tag, ResourceType level) 438 bool DicomMap::IsMainDicomTag(const DicomTag& tag, ResourceType level)
373 { 439 {
374 DicomTag *tags = NULL; 440 const MainDicomTag *tags = NULL;
375 size_t size; 441 size_t size;
376 442 LoadMainDicomTags(tags, size, level);
377 switch (level)
378 {
379 case ResourceType_Patient:
380 tags = patientTags;
381 size = sizeof(patientTags) / sizeof(DicomTag);
382 break;
383
384 case ResourceType_Study:
385 tags = studyTags;
386 size = sizeof(studyTags) / sizeof(DicomTag);
387 break;
388
389 case ResourceType_Series:
390 tags = seriesTags;
391 size = sizeof(seriesTags) / sizeof(DicomTag);
392 break;
393
394 case ResourceType_Instance:
395 tags = instanceTags;
396 size = sizeof(instanceTags) / sizeof(DicomTag);
397 break;
398
399 default:
400 throw OrthancException(ErrorCode_ParameterOutOfRange);
401 }
402 443
403 for (size_t i = 0; i < size; i++) 444 for (size_t i = 0; i < size; i++)
404 { 445 {
405 if (tags[i] == tag) 446 if (tags[i].tag_ == tag)
406 { 447 {
407 return true; 448 return true;
408 } 449 }
409 } 450 }
410 451
420 } 461 }
421 462
422 463
423 void DicomMap::GetMainDicomTagsInternal(std::set<DicomTag>& result, ResourceType level) 464 void DicomMap::GetMainDicomTagsInternal(std::set<DicomTag>& result, ResourceType level)
424 { 465 {
425 DicomTag *tags = NULL; 466 const MainDicomTag *tags = NULL;
426 size_t size; 467 size_t size;
427 468 LoadMainDicomTags(tags, size, level);
428 switch (level)
429 {
430 case ResourceType_Patient:
431 tags = patientTags;
432 size = sizeof(patientTags) / sizeof(DicomTag);
433 break;
434
435 case ResourceType_Study:
436 tags = studyTags;
437 size = sizeof(studyTags) / sizeof(DicomTag);
438 break;
439
440 case ResourceType_Series:
441 tags = seriesTags;
442 size = sizeof(seriesTags) / sizeof(DicomTag);
443 break;
444
445 case ResourceType_Instance:
446 tags = instanceTags;
447 size = sizeof(instanceTags) / sizeof(DicomTag);
448 break;
449
450 default:
451 throw OrthancException(ErrorCode_ParameterOutOfRange);
452 }
453 469
454 for (size_t i = 0; i < size; i++) 470 for (size_t i = 0; i < size; i++)
455 { 471 {
456 result.insert(tags[i]); 472 result.insert(tags[i].tag_);
457 } 473 }
458 } 474 }
459 475
460 476
461 void DicomMap::GetMainDicomTags(std::set<DicomTag>& result, ResourceType level) 477 void DicomMap::GetMainDicomTags(std::set<DicomTag>& result, ResourceType level)
477 493
478 void DicomMap::GetTags(std::set<DicomTag>& tags) const 494 void DicomMap::GetTags(std::set<DicomTag>& tags) const
479 { 495 {
480 tags.clear(); 496 tags.clear();
481 497
482 for (Map::const_iterator it = map_.begin(); 498 for (Content::const_iterator it = content_.begin();
483 it != map_.end(); ++it) 499 it != content_.end(); ++it)
484 { 500 {
485 tags.insert(it->first); 501 tags.insert(it->first);
486 } 502 }
487 } 503 }
488 504
1028 } 1044 }
1029 1045
1030 1046
1031 void DicomMap::Merge(const DicomMap& other) 1047 void DicomMap::Merge(const DicomMap& other)
1032 { 1048 {
1033 for (Map::const_iterator it = other.map_.begin(); 1049 for (Content::const_iterator it = other.content_.begin();
1034 it != other.map_.end(); ++it) 1050 it != other.content_.end(); ++it)
1035 { 1051 {
1036 assert(it->second != NULL); 1052 assert(it->second != NULL);
1037 1053
1038 if (map_.find(it->first) == map_.end()) 1054 if (content_.find(it->first) == content_.end())
1039 { 1055 {
1040 map_[it->first] = it->second->Clone(); 1056 content_[it->first] = it->second->Clone();
1041 } 1057 }
1042 } 1058 }
1043 } 1059 }
1044 1060
1045 1061
1046 void DicomMap::ExtractMainDicomTagsInternal(const DicomMap& other, 1062 void DicomMap::ExtractMainDicomTagsInternal(const DicomMap& other,
1047 ResourceType level) 1063 ResourceType level)
1048 { 1064 {
1049 const DicomTag* tags = NULL; 1065 const MainDicomTag* tags = NULL;
1050 size_t size = 0; 1066 size_t size = 0;
1051 1067
1052 LoadMainDicomTags(tags, size, level); 1068 LoadMainDicomTags(tags, size, level);
1053 assert(tags != NULL && size > 0); 1069 assert(tags != NULL && size > 0);
1054 1070
1055 for (size_t i = 0; i < size; i++) 1071 for (size_t i = 0; i < size; i++)
1056 { 1072 {
1057 Map::const_iterator found = other.map_.find(tags[i]); 1073 Content::const_iterator found = other.content_.find(tags[i].tag_);
1058 1074
1059 if (found != other.map_.end() && 1075 if (found != other.content_.end() &&
1060 map_.find(tags[i]) == map_.end()) 1076 content_.find(tags[i].tag_) == content_.end())
1061 { 1077 {
1062 assert(found->second != NULL); 1078 assert(found->second != NULL);
1063 map_[tags[i]] = found->second->Clone(); 1079 content_[tags[i].tag_] = found->second->Clone();
1064 } 1080 }
1065 } 1081 }
1066 } 1082 }
1067 1083
1068 1084
1081 // TODO - Speed up possible by making this std::set a global variable 1097 // TODO - Speed up possible by making this std::set a global variable
1082 1098
1083 std::set<DicomTag> mainDicomTags; 1099 std::set<DicomTag> mainDicomTags;
1084 GetMainDicomTags(mainDicomTags); 1100 GetMainDicomTags(mainDicomTags);
1085 1101
1086 for (Map::const_iterator it = map_.begin(); it != map_.end(); ++it) 1102 for (Content::const_iterator it = content_.begin(); it != content_.end(); ++it)
1087 { 1103 {
1088 if (mainDicomTags.find(it->first) == mainDicomTags.end()) 1104 if (mainDicomTags.find(it->first) == mainDicomTags.end())
1089 { 1105 {
1090 return false; 1106 return false;
1091 } 1107 }
1097 1113
1098 void DicomMap::Serialize(Json::Value& target) const 1114 void DicomMap::Serialize(Json::Value& target) const
1099 { 1115 {
1100 target = Json::objectValue; 1116 target = Json::objectValue;
1101 1117
1102 for (Map::const_iterator it = map_.begin(); it != map_.end(); ++it) 1118 for (Content::const_iterator it = content_.begin(); it != content_.end(); ++it)
1103 { 1119 {
1104 assert(it->second != NULL); 1120 assert(it->second != NULL);
1105 1121
1106 std::string tag = it->first.Format(); 1122 std::string tag = it->first.Format();
1107 1123
1127 for (size_t i = 0; i < tags.size(); i++) 1143 for (size_t i = 0; i < tags.size(); i++)
1128 { 1144 {
1129 DicomTag tag(0, 0); 1145 DicomTag tag(0, 0);
1130 1146
1131 if (!DicomTag::ParseHexadecimal(tag, tags[i].c_str()) || 1147 if (!DicomTag::ParseHexadecimal(tag, tags[i].c_str()) ||
1132 map_.find(tag) != map_.end()) 1148 content_.find(tag) != content_.end())
1133 { 1149 {
1134 throw OrthancException(ErrorCode_BadFileFormat); 1150 throw OrthancException(ErrorCode_BadFileFormat);
1135 } 1151 }
1136 1152
1137 std::auto_ptr<DicomValue> value(new DicomValue); 1153 std::auto_ptr<DicomValue> value(new DicomValue);
1138 value->Unserialize(source[tags[i]]); 1154 value->Unserialize(source[tags[i]]);
1139 1155
1140 map_[tag] = value.release(); 1156 content_[tag] = value.release();
1141 } 1157 }
1142 } 1158 }
1143 1159
1144 1160
1145 void DicomMap::FromDicomWeb(const Json::Value& source) 1161 void DicomMap::FromDicomWeb(const Json::Value& source)
1294 } 1310 }
1295 1311
1296 1312
1297 void DicomMap::RemoveBinaryTags() 1313 void DicomMap::RemoveBinaryTags()
1298 { 1314 {
1299 Map kept; 1315 Content kept;
1300 1316
1301 for (Map::iterator it = map_.begin(); it != map_.end(); ++it) 1317 for (Content::iterator it = content_.begin(); it != content_.end(); ++it)
1302 { 1318 {
1303 assert(it->second != NULL); 1319 assert(it->second != NULL);
1304 1320
1305 if (!it->second->IsBinary() && 1321 if (!it->second->IsBinary() &&
1306 !it->second->IsNull()) 1322 !it->second->IsNull())
1311 { 1327 {
1312 delete it->second; 1328 delete it->second;
1313 } 1329 }
1314 } 1330 }
1315 1331
1316 map_ = kept; 1332 content_ = kept;
1317 } 1333 }
1318 1334
1319 1335
1320 void DicomMap::DumpMainDicomTags(Json::Value& target, 1336 void DicomMap::DumpMainDicomTags(Json::Value& target,
1321 ResourceType level) const 1337 ResourceType level) const
1322 { 1338 {
1339 std::map<DicomTag, std::string> mainTags; // TODO - Create a singleton to hold this map
1340 LoadMainDicomTags(mainTags, level);
1341
1323 target = Json::objectValue; 1342 target = Json::objectValue;
1324 1343
1344 for (Content::const_iterator it = content_.begin(); it != content_.end(); ++it)
1345 {
1346 assert(it->second != NULL);
1347
1348 if (!it->second->IsBinary() &&
1349 !it->second->IsNull())
1350 {
1351 std::map<DicomTag, std::string>::const_iterator found = mainTags.find(it->first);
1352
1353 if (found != mainTags.end())
1354 {
1355 target[found->second] = it->second->GetContent();
1356 }
1357 }
1358 }
1359 }
1360
1361
1362 void DicomMap::ParseMainDicomTags(const Json::Value& source,
1363 ResourceType level)
1364 {
1365 if (source.type() != Json::objectValue)
1366 {
1367 throw OrthancException(ErrorCode_BadFileFormat);
1368 }
1325 1369
1326 } 1370 Clear();
1327 1371
1328 1372 std::map<std::string, DicomTag2> mainTags; // TODO - Create a singleton to hold this map
1329 void DicomMap::ParseMainDicomTags(Json::Value& target, 1373 LoadMainDicomTags(mainTags, level);
1330 ResourceType level) 1374
1331 { 1375 Json::Value::Members members = source.getMemberNames();
1376 for (size_t i = 0; i < members.size(); i++)
1377 {
1378 std::map<std::string, DicomTag2>::const_iterator found = mainTags.find(members[i]);
1379
1380 if (found != mainTags.end())
1381 {
1382 const Json::Value& value = source[members[i]];
1383 if (value.type() != Json::stringValue)
1384 {
1385 throw OrthancException(ErrorCode_BadFileFormat);
1386 }
1387 else
1388 {
1389 SetValue(found->second, value.asString(), false);
1390 }
1391 }
1392 }
1332 } 1393 }
1333 1394
1334 1395
1335 void DicomMap::Print(FILE* fp) const 1396 void DicomMap::Print(FILE* fp) const
1336 { 1397 {