1 /*
2 *
3 * Copyright (C) 1998-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: DVPSReferencedImage_PList
20 *
21 */
22
23 #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
24 #include "dcmtk/dcmdata/dcdeftag.h"
25 #include "dcmtk/dcmdata/dcsequen.h"
26 #include "dcmtk/dcmpstat/dvpsril.h"
27 #include "dcmtk/dcmpstat/dvpsri.h" /* for DVPSReferencedImage */
28 #include "dcmtk/dcmpstat/dvpsrsl.h" /* DVPSReferencedSeries_PList */
29 #include "dcmtk/dcmpstat/dvpsrs.h" /* for DVPSReferencedSeries, needed by MSVC5 with STL */
30 #include "dcmtk/dcmpstat/dvpsdef.h"
31
32
DVPSReferencedImage_PList()33 DVPSReferencedImage_PList::DVPSReferencedImage_PList()
34 : list_()
35 {
36 }
37
DVPSReferencedImage_PList(const DVPSReferencedImage_PList & arg)38 DVPSReferencedImage_PList::DVPSReferencedImage_PList(const DVPSReferencedImage_PList &arg)
39 : list_()
40 {
41 OFListConstIterator(DVPSReferencedImage *) first = arg.list_.begin();
42 OFListConstIterator(DVPSReferencedImage *) last = arg.list_.end();
43 while (first != last)
44 {
45 list_.push_back((*first)->clone());
46 ++first;
47 }
48 }
49
~DVPSReferencedImage_PList()50 DVPSReferencedImage_PList::~DVPSReferencedImage_PList()
51 {
52 clear();
53 }
54
clear()55 void DVPSReferencedImage_PList::clear()
56 {
57 OFListIterator(DVPSReferencedImage *) first = list_.begin();
58 OFListIterator(DVPSReferencedImage *) last = list_.end();
59 while (first != last)
60 {
61 delete (*first);
62 first = list_.erase(first);
63 }
64 }
65
read(DcmItem & dset)66 OFCondition DVPSReferencedImage_PList::read(DcmItem &dset)
67 {
68 OFCondition result = EC_Normal;
69 DcmStack stack;
70 DVPSReferencedImage *newImage = NULL;
71 DcmSequenceOfItems *dseq=NULL;
72 DcmItem *ditem=NULL;
73
74 if (EC_Normal == dset.search(DCM_ReferencedImageSequence, stack, ESM_fromHere, OFFalse))
75 {
76 dseq=(DcmSequenceOfItems *)stack.top();
77 if (dseq)
78 {
79 unsigned long numItems = dseq->card();
80 for (unsigned int i=0; i<numItems; i++)
81 {
82 ditem = dseq->getItem(i);
83 newImage = new DVPSReferencedImage();
84 if (newImage && ditem)
85 {
86 result = newImage->read(*ditem);
87 list_.push_back(newImage);
88 } else result = EC_MemoryExhausted;
89 }
90 }
91 }
92
93 return result;
94 }
95
write(DcmItem & dset)96 OFCondition DVPSReferencedImage_PList::write(DcmItem &dset)
97 {
98 OFCondition result = EC_Normal;
99 DcmSequenceOfItems *dseq=NULL;
100 DcmItem *ditem=NULL;
101
102 dseq = new DcmSequenceOfItems(DCM_ReferencedImageSequence);
103 if (dseq)
104 {
105 OFListIterator(DVPSReferencedImage *) first = list_.begin();
106 OFListIterator(DVPSReferencedImage *) last = list_.end();
107 while (first != last)
108 {
109 if (result==EC_Normal)
110 {
111 ditem = new DcmItem();
112 if (ditem)
113 {
114 result = (*first)->write(*ditem);
115 if (result==EC_Normal) dseq->insert(ditem); else delete ditem;
116 } else result = EC_MemoryExhausted;
117 }
118 ++first;
119 }
120 if (result==EC_Normal) dset.insert(dseq, OFTrue /*replaceOld*/); else delete dseq;
121 } else result = EC_MemoryExhausted;
122 return result;
123 }
124
isValid(OFString & sopclassuid)125 OFBool DVPSReferencedImage_PList::isValid(OFString& sopclassuid)
126 {
127 if (size() == 0)
128 {
129 DCMPSTAT_WARN("referenced image SQ contains empty item in presentation state");
130 return OFFalse;
131 }
132 OFBool result = OFTrue;
133 OFListIterator(DVPSReferencedImage *) first = list_.begin();
134 OFListIterator(DVPSReferencedImage *) last = list_.end();
135 while ((result == OFTrue) && (first != last))
136 {
137 result = (*first)->validateSOPClassUID(sopclassuid);
138 ++first;
139 }
140 return result;
141 }
142
findImageReference(const char * sopinstanceuid)143 DVPSReferencedImage *DVPSReferencedImage_PList::findImageReference(const char *sopinstanceuid)
144 {
145 OFListIterator(DVPSReferencedImage *) first = list_.begin();
146 OFListIterator(DVPSReferencedImage *) last = list_.end();
147 while (first != last)
148 {
149 if ((*first)->isSOPInstanceUID(sopinstanceuid)) return *first;
150 ++first;
151 }
152 return NULL;
153 }
154
removeFrameReference(const char * sopinstanceuid,unsigned long frame,unsigned long numberOfFrames)155 void DVPSReferencedImage_PList::removeFrameReference(const char *sopinstanceuid, unsigned long frame, unsigned long numberOfFrames)
156 {
157 if ((frame<1)||(numberOfFrames<frame)) return;
158 OFListIterator(DVPSReferencedImage *) first = list_.begin();
159 OFListIterator(DVPSReferencedImage *) last = list_.end();
160 while (first != last)
161 {
162 if ((*first)->isSOPInstanceUID(sopinstanceuid))
163 {
164 (*first)->removeFrameReference(frame, numberOfFrames);
165 if ((*first)->appliesToAllFrames())
166 {
167 delete (*first);
168 first = list_.erase(first);
169 } else ++first;
170 } else ++first;
171 }
172 return;
173 }
174
removeImageReference(const char * sopinstanceuid)175 void DVPSReferencedImage_PList::removeImageReference(const char *sopinstanceuid)
176 {
177 OFListIterator(DVPSReferencedImage *) first = list_.begin();
178 OFListIterator(DVPSReferencedImage *) last = list_.end();
179 while (first != last)
180 {
181 if ((*first)->isSOPInstanceUID(sopinstanceuid))
182 {
183 delete (*first);
184 first = list_.erase(first);
185 } else ++first;
186 }
187 return;
188 }
189
addImageReference(const char * sopclassUID,const char * instanceUID,const char * frames)190 OFCondition DVPSReferencedImage_PList::addImageReference(
191 const char *sopclassUID,
192 const char *instanceUID,
193 const char *frames)
194 {
195 OFCondition result = EC_Normal;
196
197 /* make sure that we don't create two references to the same image */
198 if (findImageReference(instanceUID)) result = EC_IllegalCall;
199 else
200 {
201 DVPSReferencedImage *image = new DVPSReferencedImage();
202 if (image)
203 {
204 image->setSOPClassUID(sopclassUID);
205 image->setSOPInstanceUID(instanceUID);
206 if (frames) image->setFrameNumbers(frames);
207 list_.push_back(image);
208 } else result = EC_MemoryExhausted;
209 }
210 return result;
211 }
212
addImageReference(const char * sopclassUID,const char * instanceUID,unsigned long frame,DVPSObjectApplicability applicability)213 OFCondition DVPSReferencedImage_PList::addImageReference(
214 const char *sopclassUID,
215 const char *instanceUID,
216 unsigned long frame,
217 DVPSObjectApplicability applicability)
218 {
219 if ((sopclassUID==NULL)||(instanceUID==NULL)||(applicability==DVPSB_allImages)) return EC_IllegalCall;
220 const char *framenumber=NULL;
221 if (applicability==DVPSB_currentFrame)
222 {
223 char frameString[100];
224 sprintf(frameString, "%ld", frame);
225 framenumber = frameString;
226 }
227 return addImageReference(sopclassUID, instanceUID, framenumber);
228 }
229
230
getImageReference(size_t idx,OFString & sopclassUID,OFString & instanceUID,OFString & frames)231 OFCondition DVPSReferencedImage_PList::getImageReference(
232 size_t idx,
233 OFString& sopclassUID,
234 OFString& instanceUID,
235 OFString& frames)
236 {
237 if (size() <= idx) return EC_IllegalCall;
238 OFListIterator(DVPSReferencedImage *) first = list_.begin();
239 OFListIterator(DVPSReferencedImage *) last = list_.end();
240 while (first != last)
241 {
242 if (idx==0) return (*first)->getImageReference(sopclassUID, instanceUID, frames); else
243 {
244 idx--;
245 ++first;
246 }
247 }
248 return EC_IllegalCall;
249 }
250
removeImageReference(DVPSReferencedSeries_PList & allReferences,const char * instanceUID,unsigned long frame,unsigned long numberOfFrames,DVPSObjectApplicability applicability)251 void DVPSReferencedImage_PList::removeImageReference(
252 DVPSReferencedSeries_PList& allReferences,
253 const char *instanceUID,
254 unsigned long frame,
255 unsigned long numberOfFrames,
256 DVPSObjectApplicability applicability)
257 {
258
259 if (applicability == DVPSB_allImages)
260 {
261 clear();
262 return;
263 }
264
265 // if list of image references is empty, add all existing references
266 if (size() == 0)
267 {
268 OFString seriesUID;
269 OFString sopclassUID;
270 OFString sopinstanceUID;
271 OFString frames;
272 OFString aetitle;
273 OFString filesetID;
274 OFString filesetUID;
275 const char *cframes=NULL;
276
277 size_t numberOfReferences = allReferences.numberOfImageReferences();
278 for (size_t i=0; i<numberOfReferences; i++)
279 {
280 sopclassUID.clear();
281 sopinstanceUID.clear();
282 frames.clear();
283 if (EC_Normal == allReferences.getImageReference(i, seriesUID, sopclassUID, sopinstanceUID, frames,
284 aetitle, filesetID, filesetUID))
285 {
286 if (frames.size() > 0) cframes=frames.c_str(); else cframes=NULL;
287 addImageReference(sopclassUID.c_str(), sopinstanceUID.c_str(), cframes);
288 }
289 }
290 }
291 if (applicability == DVPSB_currentImage) removeImageReference(instanceUID);
292 else removeFrameReference(instanceUID, frame, numberOfFrames);
293 return;
294 }
295
isApplicable(const char * instanceUID,unsigned long frame)296 OFBool DVPSReferencedImage_PList::isApplicable(const char *instanceUID, unsigned long frame)
297 {
298 if (size() == 0) return OFTrue; // if no image references exist, the object is valid "globally".
299 DVPSReferencedImage *imageRef = findImageReference(instanceUID);
300 if (imageRef) return imageRef->appliesToFrame(frame);
301 return OFFalse;
302 }
303
matchesApplicability(const char * instanceUID,unsigned long frame,DVPSObjectApplicability applicability)304 OFBool DVPSReferencedImage_PList::matchesApplicability(const char *instanceUID, unsigned long frame, DVPSObjectApplicability applicability)
305 {
306 DVPSReferencedImage *imageRef = NULL;
307 switch (applicability)
308 {
309 case DVPSB_currentFrame:
310 // we match if referenced image SQ contains exactly one item
311 // referencing only the current frame of the current image
312 if (size() == 1)
313 {
314 imageRef = findImageReference(instanceUID);
315 if (imageRef) return imageRef->appliesOnlyToFrame(frame);
316 }
317 break;
318 case DVPSB_currentImage:
319 // we match if referenced image SQ contains exactly one item
320 // referencing all frames of the current image
321 if (size() == 1)
322 {
323 imageRef = findImageReference(instanceUID);
324 if (imageRef) return imageRef->appliesToAllFrames();
325 }
326 break;
327 case DVPSB_allImages:
328 // applicability matches if referenced image SQ is empty
329 if (size() == 0) return OFTrue;
330 break;
331 }
332 return OFFalse;
333 }
334