1 /*
2 *
3 * Copyright (C) 1998-2018, 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
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/dcitem.h"
26 #include "dcmtk/dcmpstat/dvpsri.h"
27 #include "dcmtk/dcmpstat/dvpsdef.h" /* for constants and macros */
28
29 #define INCLUDE_CSTDIO
30 #include "dcmtk/ofstd/ofstdinc.h"
31
32
33 /* --------------- class DVPSReferencedImage --------------- */
34
DVPSReferencedImage()35 DVPSReferencedImage::DVPSReferencedImage()
36 : referencedSOPClassUID(DCM_ReferencedSOPClassUID)
37 , referencedSOPInstanceUID(DCM_ReferencedSOPInstanceUID)
38 , referencedFrameNumber(DCM_ReferencedFrameNumber)
39 , frameCache(NULL)
40 , frameCacheEntries(0)
41 {
42 }
43
DVPSReferencedImage(const DVPSReferencedImage & copy)44 DVPSReferencedImage::DVPSReferencedImage(const DVPSReferencedImage& copy)
45 : referencedSOPClassUID(copy.referencedSOPClassUID)
46 , referencedSOPInstanceUID(copy.referencedSOPInstanceUID)
47 , referencedFrameNumber(copy.referencedFrameNumber)
48 , frameCache(NULL) // we don't copy the frame cache
49 , frameCacheEntries(0)
50 {
51 }
52
~DVPSReferencedImage()53 DVPSReferencedImage::~DVPSReferencedImage()
54 {
55 if (frameCache) delete[] frameCache;
56 }
57
read(DcmItem & dset)58 OFCondition DVPSReferencedImage::read(DcmItem &dset)
59 {
60 OFCondition result = EC_Normal;
61 DcmStack stack;
62
63 flushCache();
64
65 READ_FROM_DATASET(DcmUniqueIdentifier, EVR_UI, referencedSOPClassUID)
66 READ_FROM_DATASET(DcmUniqueIdentifier, EVR_UI, referencedSOPInstanceUID)
67 READ_FROM_DATASET(DcmIntegerString, EVR_IS, referencedFrameNumber)
68
69 /* Now perform basic sanity checks */
70
71 if (referencedSOPClassUID.getLength() == 0)
72 {
73 result=EC_IllegalCall;
74 DCMPSTAT_WARN("presentation state contains a referenced image SQ item with referencedSOPClassUID absent or empty");
75 }
76 else if (referencedSOPClassUID.getVM() != 1)
77 {
78 result=EC_IllegalCall;
79 DCMPSTAT_WARN("presentation state contains a referenced image SQ item with referencedSOPClassUID VM != 1");
80 }
81
82 if (referencedSOPInstanceUID.getLength() == 0)
83 {
84 result=EC_IllegalCall;
85 DCMPSTAT_WARN("presentation state contains a referenced image SQ item with referencedSOPInstanceUID absent or empty");
86 }
87 else if (referencedSOPInstanceUID.getVM() != 1)
88 {
89 result=EC_IllegalCall;
90 DCMPSTAT_WARN("presentation state contains a referenced image SQ item with referencedSOPInstanceUID VM != 1");
91 }
92
93 return result;
94 }
95
write(DcmItem & dset)96 OFCondition DVPSReferencedImage::write(DcmItem &dset)
97 {
98 OFCondition result = EC_Normal;
99 DcmElement *delem=NULL;
100
101 ADD_TO_DATASET(DcmUniqueIdentifier, referencedSOPClassUID)
102 ADD_TO_DATASET(DcmUniqueIdentifier, referencedSOPInstanceUID)
103 if (referencedFrameNumber.getLength() >0) { ADD_TO_DATASET(DcmIntegerString, referencedFrameNumber) }
104
105 return result;
106 }
107
validateSOPClassUID(OFString & sopclassuid)108 OFBool DVPSReferencedImage::validateSOPClassUID(OFString& sopclassuid)
109 {
110 OFBool result = OFTrue;
111 if (sopclassuid.empty()) referencedSOPClassUID.getOFString(sopclassuid, 0);
112 else
113 {
114 OFString currentUID;
115 referencedSOPClassUID.getOFString(currentUID, 0);
116 if (currentUID != sopclassuid)
117 {
118 result = OFFalse;
119 DCMPSTAT_WARN("images of different SOP classes referenced in presentation state");
120 }
121 }
122 return result;
123 }
124
setSOPClassUID(const char * uid)125 void DVPSReferencedImage::setSOPClassUID(const char *uid)
126 {
127 if (uid) referencedSOPClassUID.putString(uid); else referencedSOPClassUID.clear();
128 return;
129 }
130
setSOPInstanceUID(const char * uid)131 void DVPSReferencedImage::setSOPInstanceUID(const char *uid)
132 {
133 if (uid) referencedSOPInstanceUID.putString(uid); else referencedSOPInstanceUID.clear();
134 return;
135 }
136
setFrameNumbers(const char * frames)137 void DVPSReferencedImage::setFrameNumbers(const char *frames)
138 {
139 if (frames) referencedFrameNumber.putString(frames); else referencedFrameNumber.clear();
140 flushCache();
141 return;
142 }
143
isSOPInstanceUID(const char * uid)144 OFBool DVPSReferencedImage::isSOPInstanceUID(const char *uid)
145 {
146 OFString aString;
147 if (uid && (EC_Normal == referencedSOPInstanceUID.getOFString(aString,0)))
148 {
149 if (aString == uid) return OFTrue;
150 }
151 return OFFalse;
152 }
153
getImageReference(OFString & sopclassUID,OFString & instanceUID,OFString & frames)154 OFCondition DVPSReferencedImage::getImageReference(
155 OFString& sopclassUID,
156 OFString& instanceUID,
157 OFString& frames)
158 {
159 OFCondition result = referencedSOPClassUID.getOFString(sopclassUID,0);
160 if (EC_Normal == result) result = referencedSOPInstanceUID.getOFString(instanceUID,0);
161 if (EC_Normal == result) result = referencedFrameNumber.getOFStringArray(frames);
162 return result;
163 }
164
flushCache()165 void DVPSReferencedImage::flushCache()
166 {
167 if (frameCache) delete[] frameCache;
168 frameCache = NULL;
169 frameCacheEntries = 0;
170 }
171
appliesToAllFrames()172 OFBool DVPSReferencedImage::appliesToAllFrames()
173 {
174 if (referencedFrameNumber.getLength() == 0) return OFTrue;
175 if (referencedFrameNumber.getVM() == 0) return OFTrue;
176 return OFFalse;
177 }
178
updateCache()179 void DVPSReferencedImage::updateCache()
180 {
181 Sint32 val=0;
182 unsigned long i;
183 if (frameCache==NULL)
184 {
185 frameCacheEntries = (Uint32) referencedFrameNumber.getVM();
186 if (frameCacheEntries > 0)
187 {
188 frameCache = new Sint32[frameCacheEntries];
189 if (frameCache)
190 {
191 for (i=0; i<frameCacheEntries; i++)
192 {
193 if (EC_Normal == referencedFrameNumber.getSint32(val, i)) frameCache[i]=val; else frameCache[i]=0;
194 }
195 } else frameCacheEntries=0; // out of memory
196 }
197 }
198 }
199
appliesToFrame(unsigned long frame)200 OFBool DVPSReferencedImage::appliesToFrame(unsigned long frame)
201 {
202 if (referencedFrameNumber.getLength()==0) return OFTrue;
203 Sint32 val=0;
204 unsigned long i;
205 updateCache();
206 if (frameCache)
207 {
208 val = (Sint32) frame;
209 for (i=0; i<frameCacheEntries; i++) if (val == frameCache[i]) return OFTrue;
210 return OFFalse;
211 }
212 return OFTrue; // referencedFrameNumber seems to contain garbage.
213 }
214
appliesOnlyToFrame(unsigned long frame)215 OFBool DVPSReferencedImage::appliesOnlyToFrame(unsigned long frame)
216 {
217 Sint32 val=0;
218 if (referencedFrameNumber.getVM() == 1)
219 {
220 if (EC_Normal == referencedFrameNumber.getSint32(val, 0))
221 {
222 if (frame == (unsigned long)val) return OFTrue;
223 }
224 }
225 return OFFalse;
226 }
227
removeFrameReference(unsigned long frame,unsigned long numberOfFrames)228 void DVPSReferencedImage::removeFrameReference(unsigned long frame, unsigned long numberOfFrames)
229 {
230 unsigned long i;
231 char str[20];
232 OFString aString;
233
234 updateCache();
235 referencedFrameNumber.clear();
236 if (frameCache)
237 {
238 for (i=0; i<frameCacheEntries; i++)
239 {
240 if (frameCache[i] != (Sint32)frame)
241 {
242 if (aString.size() ==0) sprintf(str, "%ld", (long)(frameCache[i])); else sprintf(str, "\\%ld", (long)(frameCache[i]));
243 aString += str;
244 }
245 }
246 } else {
247 for (i=1; i<=numberOfFrames; i++)
248 {
249 if (i != frame)
250 {
251 if (aString.size() ==0) sprintf(str, "%ld", i); else sprintf(str, "\\%ld", i);
252 aString += str;
253 }
254 }
255 }
256 referencedFrameNumber.putString(aString.c_str());
257 flushCache();
258 }
259