1 /*
2 *
3 * Copyright (C) 1999-2010, OFFIS e.V.
4 * All rights reserved. See COPYRIGHT file for details.
5 *
6 * This software and supporting documentation were developed by
7 *
8 * OFFIS e.V.
9 * R&D Division Health
10 * Escherweg 2
11 * D-26121 Oldenburg, Germany
12 *
13 *
14 * Module: dcmpstat
15 *
16 * Author: Marco Eichelberg
17 *
18 * Purpose:
19 * classes: DVPSImageBoxContent_PList
20 *
21 */
22
23 #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
24 #include "dcmtk/dcmpstat/dvpsibl.h"
25 #include "dcmtk/dcmpstat/dvpsib.h" /* for DVPSImageBoxContent */
26 #include "dcmtk/dcmpstat/dvpshlp.h" /* for class DVPSHelper */
27
28 /* --------------- class DVPSImageBoxContent_PList --------------- */
29
DVPSImageBoxContent_PList()30 DVPSImageBoxContent_PList::DVPSImageBoxContent_PList()
31 : list_()
32 {
33 }
34
DVPSImageBoxContent_PList(const DVPSImageBoxContent_PList & arg)35 DVPSImageBoxContent_PList::DVPSImageBoxContent_PList(const DVPSImageBoxContent_PList &arg)
36 : list_()
37 {
38 OFListConstIterator(DVPSImageBoxContent *) first = arg.list_.begin();
39 OFListConstIterator(DVPSImageBoxContent *) last = arg.list_.end();
40 while (first != last)
41 {
42 list_.push_back((*first)->clone());
43 ++first;
44 }
45 }
46
~DVPSImageBoxContent_PList()47 DVPSImageBoxContent_PList::~DVPSImageBoxContent_PList()
48 {
49 clear();
50 }
51
clear()52 void DVPSImageBoxContent_PList::clear()
53 {
54 OFListIterator(DVPSImageBoxContent *) first = list_.begin();
55 OFListIterator(DVPSImageBoxContent *) last = list_.end();
56 while (first != last)
57 {
58 delete (*first);
59 first = list_.erase(first);
60 }
61 }
62
read(DcmItem & dset,DVPSPresentationLUT_PList & presentationLUTList)63 OFCondition DVPSImageBoxContent_PList::read(DcmItem &dset, DVPSPresentationLUT_PList& presentationLUTList)
64 {
65 OFCondition result = EC_Normal;
66 DcmStack stack;
67 DVPSImageBoxContent *newImage = NULL;
68 DcmSequenceOfItems *dseq=NULL;
69 DcmItem *ditem=NULL;
70
71 if (EC_Normal == dset.search(DCM_RETIRED_ImageBoxContentSequence, stack, ESM_fromHere, OFFalse))
72 {
73 dseq=(DcmSequenceOfItems *)stack.top();
74 if (dseq)
75 {
76 unsigned long numItems = dseq->card();
77 for (unsigned int i=0; i<numItems; i++)
78 {
79 ditem = dseq->getItem(i);
80 newImage = new DVPSImageBoxContent();
81 if (newImage && ditem)
82 {
83 result = newImage->read(*ditem, presentationLUTList);
84 list_.push_back(newImage);
85 } else result = EC_MemoryExhausted;
86 }
87 }
88 }
89
90 return result;
91 }
92
write(DcmItem & dset,OFBool writeRequestedImageSize,size_t numItems,OFBool ignoreEmptyImages,OFBool writeReferencedPLUTSQ)93 OFCondition DVPSImageBoxContent_PList::write(
94 DcmItem &dset,
95 OFBool writeRequestedImageSize,
96 size_t numItems,
97 OFBool ignoreEmptyImages,
98 OFBool writeReferencedPLUTSQ)
99 {
100 if (size()==0) return EC_IllegalCall; // can't write if sequence is empty
101
102 OFCondition result = EC_Normal;
103 DcmSequenceOfItems *dseq=NULL;
104 DcmItem *ditem=NULL;
105 OFBool working = OFTrue;
106 unsigned long numWritten = 0;
107
108 dseq = new DcmSequenceOfItems(DCM_RETIRED_ImageBoxContentSequence);
109 if (dseq)
110 {
111 OFListIterator(DVPSImageBoxContent *) first = list_.begin();
112 OFListIterator(DVPSImageBoxContent *) last = list_.end();
113 while ((first != last) && working)
114 {
115 if ((result==EC_Normal) && ((! ignoreEmptyImages)||((*first)->getImageBoxPosition() > 0)))
116 {
117 ditem = new DcmItem();
118 if (ditem)
119 {
120 result = (*first)->write(*ditem, writeRequestedImageSize, writeReferencedPLUTSQ);
121 if (result==EC_Normal)
122 {
123 dseq->insert(ditem);
124 numWritten++;
125 } else delete ditem;
126 } else result = EC_MemoryExhausted;
127 }
128 ++first;
129 if (numItems && (--numItems==0)) working=OFFalse;
130 }
131 // we're not allowed to store SP objects with empty image box list sequence
132 if ((result==EC_Normal) && (numWritten > 0)) dset.insert(dseq, OFTrue /*replaceOld*/); else delete dseq;
133 } else result = EC_MemoryExhausted;
134 return result;
135 }
136
createDefaultValues(OFBool renumber,OFBool ignoreEmptyImages)137 OFCondition DVPSImageBoxContent_PList::createDefaultValues(OFBool renumber, OFBool ignoreEmptyImages)
138 {
139 if (size()==0) return EC_IllegalCall; // can't write if sequence is empty
140 OFCondition result = EC_Normal;
141 unsigned long counter = 1;
142
143 OFListIterator(DVPSImageBoxContent *) first = list_.begin();
144 OFListIterator(DVPSImageBoxContent *) last = list_.end();
145 while ((first != last)&&(EC_Normal == result))
146 {
147 result = (*first)->createDefaultValues(renumber, counter++, ignoreEmptyImages);
148 ++first;
149 }
150 return result;
151 }
152
addImageSOPClasses(DcmSequenceOfItems & seq,size_t numItems)153 OFCondition DVPSImageBoxContent_PList::addImageSOPClasses(DcmSequenceOfItems& seq, size_t numItems)
154 {
155 OFCondition result = EC_Normal;
156 OFBool working = OFTrue;
157 const char *c = NULL;
158 OFListIterator(DVPSImageBoxContent *) first = list_.begin();
159 OFListIterator(DVPSImageBoxContent *) last = list_.end();
160 while ((first != last) && working)
161 {
162 if (EC_Normal == result)
163 {
164 c = (*first)->getSOPClassUID();
165 if (c && (! DVPSHelper::haveReferencedUIDItem(seq, c))) result = DVPSHelper::addReferencedUIDItem(seq, c);
166 }
167 ++first;
168 if (numItems && (--numItems==0)) working=OFFalse;
169 }
170 return result;
171 }
172
addImageBox(const char * instanceuid,const char * retrieveaetitle,const char * refstudyuid,const char * refseriesuid,const char * refsopclassuid,const char * refsopinstanceuid,const char * requestedimagesize,const char * patientid,const char * presentationlutuid)173 OFCondition DVPSImageBoxContent_PList::addImageBox(
174 const char *instanceuid,
175 const char *retrieveaetitle,
176 const char *refstudyuid,
177 const char *refseriesuid,
178 const char *refsopclassuid,
179 const char *refsopinstanceuid,
180 const char *requestedimagesize,
181 const char *patientid,
182 const char *presentationlutuid)
183 {
184 OFCondition result = EC_Normal;
185 DVPSImageBoxContent *newImage = new DVPSImageBoxContent();
186 if (newImage)
187 {
188 result = newImage->setContent(instanceuid, retrieveaetitle, refstudyuid,
189 refseriesuid, refsopclassuid, refsopinstanceuid,
190 requestedimagesize, patientid, presentationlutuid);
191 if (EC_Normal == result) list_.push_back(newImage); else delete newImage;
192 } else result = EC_MemoryExhausted;
193 return result;
194 }
195
addImageBox(DVPSImageBoxContent * box)196 OFCondition DVPSImageBoxContent_PList::addImageBox(DVPSImageBoxContent * box)
197 {
198 list_.push_back(box);
199 return(EC_Normal);
200 }
201
setRequestedDecimateCropBehaviour(DVPSDecimateCropBehaviour value)202 OFCondition DVPSImageBoxContent_PList::setRequestedDecimateCropBehaviour(DVPSDecimateCropBehaviour value)
203 {
204 OFCondition result=EC_Normal;
205 OFListIterator(DVPSImageBoxContent *) first = list_.begin();
206 OFListIterator(DVPSImageBoxContent *) last = list_.end();
207 while (first != last)
208 {
209 result = (*first)->setRequestedDecimateCropBehaviour(value);
210 if (EC_Normal != result) return result;
211 ++first;
212 }
213 return result;
214 }
215
deleteImage(size_t idx)216 OFCondition DVPSImageBoxContent_PList::deleteImage(size_t idx)
217 {
218 OFListIterator(DVPSImageBoxContent *) first = list_.begin();
219 OFListIterator(DVPSImageBoxContent *) last = list_.end();
220 while ((first != last)&&(idx--)) ++first;
221 if (first != last)
222 {
223 delete (*first);
224 list_.erase(first);
225 return EC_Normal;
226 }
227 return EC_IllegalCall;
228 }
229
deleteMultipleImages(size_t number)230 OFCondition DVPSImageBoxContent_PList::deleteMultipleImages(size_t number)
231 {
232 OFListIterator(DVPSImageBoxContent *) first = list_.begin();
233 OFListIterator(DVPSImageBoxContent *) last = list_.end();
234 while ((first != last)&&(number--))
235 {
236 delete (*first);
237 first = list_.erase(first);
238 }
239 return EC_Normal;
240 }
241
getImageBox(size_t idx)242 DVPSImageBoxContent *DVPSImageBoxContent_PList::getImageBox(size_t idx)
243 {
244 OFListIterator(DVPSImageBoxContent *) first = list_.begin();
245 OFListIterator(DVPSImageBoxContent *) last = list_.end();
246 while (first != last)
247 {
248 if (idx==0) return *first;
249 idx--;
250 ++first;
251 }
252 return NULL;
253 }
254
imageHasAdditionalSettings(size_t idx)255 OFBool DVPSImageBoxContent_PList::imageHasAdditionalSettings(size_t idx)
256 {
257 DVPSImageBoxContent *box = getImageBox(idx);
258 if (box) return box->hasAdditionalSettings();
259 return OFFalse;
260 }
261
setImagePolarity(size_t idx,const char * value)262 OFCondition DVPSImageBoxContent_PList::setImagePolarity(size_t idx, const char *value)
263 {
264 DVPSImageBoxContent *box = getImageBox(idx);
265 if (box) return box->setPolarity(value);
266 return EC_IllegalCall;
267 }
268
setImageRequestedSize(size_t idx,const char * value)269 OFCondition DVPSImageBoxContent_PList::setImageRequestedSize(size_t idx, const char *value)
270 {
271 DVPSImageBoxContent *box = getImageBox(idx);
272 if (box) return box->setRequestedImageSize(value);
273 return EC_IllegalCall;
274 }
275
setImageMagnificationType(size_t idx,const char * value)276 OFCondition DVPSImageBoxContent_PList::setImageMagnificationType(size_t idx, const char *value)
277 {
278 DVPSImageBoxContent *box = getImageBox(idx);
279 if (box) return box->setMagnificationType(value);
280 return EC_IllegalCall;
281 }
282
setImageSmoothingType(size_t idx,const char * value)283 OFCondition DVPSImageBoxContent_PList::setImageSmoothingType(size_t idx, const char *value)
284 {
285 DVPSImageBoxContent *box = getImageBox(idx);
286 if (box) return box->setSmoothingType(value);
287 return EC_IllegalCall;
288 }
289
setImageConfigurationInformation(size_t idx,const char * value)290 OFCondition DVPSImageBoxContent_PList::setImageConfigurationInformation(size_t idx, const char *value)
291 {
292 DVPSImageBoxContent *box = getImageBox(idx);
293 if (box) return box->setConfigurationInformation(value);
294 return EC_IllegalCall;
295 }
296
setImageSOPInstanceUID(size_t idx,const char * value)297 OFCondition DVPSImageBoxContent_PList::setImageSOPInstanceUID(size_t idx, const char *value)
298 {
299 DVPSImageBoxContent *box = getImageBox(idx);
300 if (box) return box->setSOPInstanceUID(value);
301 return EC_IllegalCall;
302 }
303
getImagePolarity(size_t idx)304 const char *DVPSImageBoxContent_PList::getImagePolarity(size_t idx)
305 {
306 DVPSImageBoxContent *box = getImageBox(idx);
307 if (box) return box->getPolarity();
308 return NULL;
309 }
310
getImageRequestedSize(size_t idx)311 const char *DVPSImageBoxContent_PList::getImageRequestedSize(size_t idx)
312 {
313 DVPSImageBoxContent *box = getImageBox(idx);
314 if (box) return box->getRequestedImageSize();
315 return NULL;
316 }
317
getImageMagnificationType(size_t idx)318 const char *DVPSImageBoxContent_PList::getImageMagnificationType(size_t idx)
319 {
320 DVPSImageBoxContent *box = getImageBox(idx);
321 if (box) return box->getMagnificationType();
322 return NULL;
323 }
324
getImageSmoothingType(size_t idx)325 const char *DVPSImageBoxContent_PList::getImageSmoothingType(size_t idx)
326 {
327 DVPSImageBoxContent *box = getImageBox(idx);
328 if (box) return box->getSmoothingType();
329 return NULL;
330 }
331
getImageConfigurationInformation(size_t idx)332 const char *DVPSImageBoxContent_PList::getImageConfigurationInformation(size_t idx)
333 {
334 DVPSImageBoxContent *box = getImageBox(idx);
335 if (box) return box->getConfigurationInformation();
336 return NULL;
337 }
338
getSOPInstanceUID(size_t idx)339 const char *DVPSImageBoxContent_PList::getSOPInstanceUID(size_t idx)
340 {
341 DVPSImageBoxContent *box = getImageBox(idx);
342 if (box) return box->getSOPInstanceUID();
343 return NULL;
344 }
345
getReferencedPresentationLUTInstanceUID(size_t idx)346 const char *DVPSImageBoxContent_PList::getReferencedPresentationLUTInstanceUID(size_t idx)
347 {
348 DVPSImageBoxContent *box = getImageBox(idx);
349 if (box) return box->getReferencedPresentationLUTInstanceUID();
350 return NULL;
351 }
352
setAllImagesToDefault()353 OFCondition DVPSImageBoxContent_PList::setAllImagesToDefault()
354 {
355 OFCondition result = EC_Normal;
356 OFListIterator(DVPSImageBoxContent *) first = list_.begin();
357 OFListIterator(DVPSImageBoxContent *) last = list_.end();
358 while (first != last)
359 {
360 result = (*first)->setDefault();
361 ++first;
362 if (EC_Normal != result) return result;
363 }
364 return result;
365 }
366
getImageReference(size_t idx,const char * & studyUID,const char * & seriesUID,const char * & instanceUID)367 OFCondition DVPSImageBoxContent_PList::getImageReference(size_t idx, const char *&studyUID, const char *&seriesUID, const char *&instanceUID)
368 {
369 DVPSImageBoxContent *box = getImageBox(idx);
370 if (box) return box->getImageReference(studyUID, seriesUID, instanceUID);
371 return EC_IllegalCall;
372 }
373
prepareBasicImageBox(size_t idx,DcmItem & dset)374 OFCondition DVPSImageBoxContent_PList::prepareBasicImageBox(size_t idx, DcmItem &dset)
375 {
376 DVPSImageBoxContent *box = getImageBox(idx);
377 if (box) return box->prepareBasicImageBox(dset);
378 return EC_IllegalCall;
379 }
380
presentationLUTInstanceUIDisUsed(const char * uid)381 OFBool DVPSImageBoxContent_PList::presentationLUTInstanceUIDisUsed(const char *uid)
382 {
383 OFString uidS;
384 if (uid) uidS = uid;
385 const char *c;
386
387 OFListIterator(DVPSImageBoxContent *) first = list_.begin();
388 OFListIterator(DVPSImageBoxContent *) last = list_.end();
389 while (first != last)
390 {
391 c = (*first)->getReferencedPresentationLUTInstanceUID();
392 if (c && (uidS == c)) return OFTrue;
393 ++first;
394 }
395 return OFFalse;
396 }
397
haveSinglePresentationLUTUsed(const char * filmBox)398 const char *DVPSImageBoxContent_PList::haveSinglePresentationLUTUsed(const char *filmBox)
399 {
400 OFList<char *> uidList;
401 if (filmBox==NULL) filmBox = "";
402 const char *c;
403 OFString aString;
404 OFBool found;
405 OFListIterator(char *) uidfirst;
406 OFListIterator(char *) uidlast;
407
408 OFListIterator(DVPSImageBoxContent *) first = list_.begin();
409 OFListIterator(DVPSImageBoxContent *) last = list_.end();
410 while (first != last)
411 {
412 c = (*first)->getReferencedPresentationLUTInstanceUID();
413 if ((c == NULL)||(strlen(c)==0)) c = filmBox;
414 aString = c; // aString now contains the UID of the P-LUT to be used for this image, if any.
415 uidfirst = uidList.begin();
416 uidlast = uidList.end();
417 found = OFFalse;
418 while (uidfirst != uidlast)
419 {
420 if (aString == (*uidfirst))
421 {
422 found = OFTrue;
423 break;
424 }
425 ++uidfirst;
426 }
427 if (!found) uidList.push_back((char *)c);
428 ++first;
429 }
430
431 if (uidList.size()==1) return *(uidList.begin()); // if there is only one LUT, return it
432 return NULL;
433 }
434
435
printSCPCreate(unsigned long numBoxes,DcmUniqueIdentifier & studyUID,DcmUniqueIdentifier & seriesUID,const char * aetitle)436 OFBool DVPSImageBoxContent_PList::printSCPCreate(
437 unsigned long numBoxes,
438 DcmUniqueIdentifier& studyUID,
439 DcmUniqueIdentifier& seriesUID,
440 const char *aetitle)
441 {
442 clear();
443 DVPSImageBoxContent *box = NULL;
444 char uid[100];
445 for (unsigned long i=0; i<numBoxes; i++)
446 {
447 box = new DVPSImageBoxContent();
448 if (box)
449 {
450 if ((EC_Normal == box->setSOPInstanceUID(dcmGenerateUniqueIdentifier(uid))) &&
451 (EC_Normal == box->setUIDsAndAETitle(studyUID, seriesUID, aetitle)))
452 {
453 list_.push_back(box);
454 }
455 else
456 {
457 delete box;
458 return OFFalse;
459 }
460 } else return OFFalse;
461 }
462 return OFTrue;
463 }
464
465
writeReferencedImageBoxSQ(DcmItem & dset)466 OFCondition DVPSImageBoxContent_PList::writeReferencedImageBoxSQ(DcmItem &dset)
467 {
468 if (size()==0) return EC_IllegalCall; // can't write if sequence is empty
469
470 OFCondition result = EC_Normal;
471 DcmSequenceOfItems *dseq=NULL;
472 DcmItem *ditem=NULL;
473 DcmUniqueIdentifier *uid=NULL;
474 const char *instanceUID=NULL;
475
476 dseq = new DcmSequenceOfItems(DCM_ReferencedImageBoxSequence);
477 if (dseq)
478 {
479 OFListIterator(DVPSImageBoxContent *) first = list_.begin();
480 OFListIterator(DVPSImageBoxContent *) last = list_.end();
481 while (first != last)
482 {
483 if (result==EC_Normal)
484 {
485 ditem = new DcmItem();
486 if (ditem)
487 {
488 uid = new DcmUniqueIdentifier(DCM_ReferencedSOPClassUID);
489 if (uid) result = uid->putString(UID_BasicGrayscaleImageBoxSOPClass); else result = EC_MemoryExhausted;
490 if (EC_Normal == result) result = ditem->insert(uid, OFTrue /*replaceOld*/); else delete uid;
491
492 uid = new DcmUniqueIdentifier(DCM_ReferencedSOPInstanceUID);
493 instanceUID = (*first)->getSOPInstanceUID();
494 if (uid && instanceUID) result = uid->putString(instanceUID); else result = EC_MemoryExhausted;
495 if (EC_Normal == result) result = ditem->insert(uid, OFTrue /*replaceOld*/); else delete uid;
496
497 if (result==EC_Normal) dseq->insert(ditem); else delete ditem;
498 } else result = EC_MemoryExhausted;
499 }
500 ++first;
501 }
502 if (result==EC_Normal) dset.insert(dseq, OFTrue /*replaceOld*/); else delete dseq;
503 } else result = EC_MemoryExhausted;
504 return result;
505 }
506
507
matchesPresentationLUT(DVPSPrintPresentationLUTAlignment align) const508 OFBool DVPSImageBoxContent_PList::matchesPresentationLUT(DVPSPrintPresentationLUTAlignment align) const
509 {
510 OFBool result = OFTrue;
511 OFListConstIterator(DVPSImageBoxContent *) first = list_.begin();
512 OFListConstIterator(DVPSImageBoxContent *) last = list_.end();
513 while (first != last)
514 {
515 result = result && (*first)->matchesPresentationLUT(align);
516 ++first;
517 }
518 return result;
519 }
520
521
duplicateImageBox(const char * uid)522 DVPSImageBoxContent *DVPSImageBoxContent_PList::duplicateImageBox(const char *uid)
523 {
524 if (uid == NULL) return NULL;
525
526 OFString aString(uid);
527 OFListIterator(DVPSImageBoxContent *) first = list_.begin();
528 OFListIterator(DVPSImageBoxContent *) last = list_.end();
529 while (first != last)
530 {
531 if (aString == (*first)->getSOPInstanceUID()) return (*first)->clone();
532 ++first;
533 }
534 return NULL;
535 }
536
haveImagePositionClash(const char * uid,Uint16 position)537 OFBool DVPSImageBoxContent_PList::haveImagePositionClash(const char *uid, Uint16 position)
538 {
539 if (uid == NULL) return OFFalse;
540
541 OFString aString(uid);
542 OFListIterator(DVPSImageBoxContent *) first = list_.begin();
543 OFListIterator(DVPSImageBoxContent *) last = list_.end();
544 while (first != last)
545 {
546 if (((*first)->getImageBoxPosition() == position)&&(aString != (*first)->getSOPInstanceUID())) return OFTrue; //clash
547 ++first;
548 }
549 return OFFalse;
550 }
551
552
replace(DVPSImageBoxContent * newImageBox)553 void DVPSImageBoxContent_PList::replace(DVPSImageBoxContent *newImageBox)
554 {
555 if (! newImageBox) return;
556
557 OFString aString(newImageBox->getSOPInstanceUID());
558 OFListIterator(DVPSImageBoxContent *) first = list_.begin();
559 OFListIterator(DVPSImageBoxContent *) last = list_.end();
560 while (first != last)
561 {
562 if (aString == (*first)->getSOPInstanceUID())
563 {
564 delete (*first);
565 first = list_.erase(first);
566 }
567 else ++first;
568 }
569 list_.push_back(newImageBox);
570 }
571
emptyPageWarning()572 OFBool DVPSImageBoxContent_PList::emptyPageWarning()
573 {
574 OFListIterator(DVPSImageBoxContent *) first = list_.begin();
575 OFListIterator(DVPSImageBoxContent *) last = list_.end();
576 while (first != last)
577 {
578 if ((*first)->getImageBoxPosition() > 0) return OFFalse;
579 ++first;
580 }
581 return OFTrue;
582 }
583