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: DVPSDisplayedArea_PList
20 *
21 */
22
23 #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
24 #include "dcmtk/dcmpstat/dvpsdal.h"
25 #include "dcmtk/dcmpstat/dvpsda.h" /* for DVPSDisplayedArea */
26 #include "dcmtk/dcmpstat/dvpsri.h" /* for DVPSReferencedImage, needed by MSVC5 with STL */
27
28
DVPSDisplayedArea_PList()29 DVPSDisplayedArea_PList::DVPSDisplayedArea_PList()
30 : list_()
31 {
32 }
33
DVPSDisplayedArea_PList(const DVPSDisplayedArea_PList & arg)34 DVPSDisplayedArea_PList::DVPSDisplayedArea_PList(const DVPSDisplayedArea_PList &arg)
35 : list_()
36 {
37 OFListConstIterator(DVPSDisplayedArea *) first = arg.list_.begin();
38 OFListConstIterator(DVPSDisplayedArea *) last = arg.list_.end();
39 while (first != last)
40 {
41 list_.push_back((*first)->clone());
42 ++first;
43 }
44 }
45
~DVPSDisplayedArea_PList()46 DVPSDisplayedArea_PList::~DVPSDisplayedArea_PList()
47 {
48 clear();
49 }
50
clear()51 void DVPSDisplayedArea_PList::clear()
52 {
53 OFListIterator(DVPSDisplayedArea *) first = list_.begin();
54 OFListIterator(DVPSDisplayedArea *) last = list_.end();
55 while (first != last)
56 {
57 delete (*first);
58 first = list_.erase(first);
59 }
60 }
61
read(DcmItem & dset)62 OFCondition DVPSDisplayedArea_PList::read(DcmItem &dset)
63 {
64 OFCondition result = EC_Normal;
65 DcmStack stack;
66 DVPSDisplayedArea *newImage = NULL;
67 DcmSequenceOfItems *dseq=NULL;
68 DcmItem *ditem=NULL;
69
70 if (EC_Normal == dset.search(DCM_DisplayedAreaSelectionSequence, stack, ESM_fromHere, OFFalse))
71 {
72 dseq=(DcmSequenceOfItems *)stack.top();
73 if (dseq)
74 {
75 unsigned long numItems = dseq->card();
76 for (unsigned int i=0; i<numItems; i++)
77 {
78 ditem = dseq->getItem(i);
79 newImage = new DVPSDisplayedArea();
80 if (newImage && ditem)
81 {
82 result = newImage->read(*ditem);
83 list_.push_back(newImage);
84 } else result = EC_MemoryExhausted;
85 }
86 }
87 }
88
89 return result;
90 }
91
write(DcmItem & dset)92 OFCondition DVPSDisplayedArea_PList::write(DcmItem &dset)
93 {
94 OFCondition result = EC_Normal;
95 DcmSequenceOfItems *dseq=NULL;
96 DcmItem *ditem=NULL;
97
98 dseq = new DcmSequenceOfItems(DCM_DisplayedAreaSelectionSequence);
99 if (dseq)
100 {
101 OFListIterator(DVPSDisplayedArea *) first = list_.begin();
102 OFListIterator(DVPSDisplayedArea *) last = list_.end();
103 while (first != last)
104 {
105 if (result==EC_Normal)
106 {
107 ditem = new DcmItem();
108 if (ditem)
109 {
110 result = (*first)->write(*ditem);
111 if (result==EC_Normal) dseq->insert(ditem); else delete ditem;
112 } else result = EC_MemoryExhausted;
113 }
114 ++first;
115 }
116 if (result==EC_Normal) dset.insert(dseq, OFTrue /*replaceOld*/); else delete dseq;
117 } else result = EC_MemoryExhausted;
118 return result;
119 }
120
findDisplayedArea(const char * instanceUID,unsigned long frame)121 DVPSDisplayedArea *DVPSDisplayedArea_PList::findDisplayedArea(const char *instanceUID, unsigned long frame)
122 {
123 OFListIterator(DVPSDisplayedArea *) first = list_.begin();
124 OFListIterator(DVPSDisplayedArea *) last = list_.end();
125 while (first != last)
126 {
127 if ((*first)->isApplicable(instanceUID, frame)) return (*first);
128 ++first;
129 }
130 return NULL;
131 }
132
rotateAndFlip(DVPSRotationType rotationFrom,OFBool isFlippedFrom,DVPSRotationType rotationTo,OFBool isFlippedTo)133 void DVPSDisplayedArea_PList::rotateAndFlip(
134 DVPSRotationType rotationFrom,
135 OFBool isFlippedFrom,
136 DVPSRotationType rotationTo,
137 OFBool isFlippedTo)
138 {
139 OFListIterator(DVPSDisplayedArea *) first = list_.begin();
140 OFListIterator(DVPSDisplayedArea *) last = list_.end();
141 while (first != last)
142 {
143 (*first)->rotateAndFlip(rotationFrom, isFlippedFrom, rotationTo, isFlippedTo);
144 ++first;
145 }
146 }
147
createDisplayedArea(DVPSReferencedSeries_PList & allReferences,const char * sopclassUID,const char * instanceUID,unsigned long frame,unsigned long numberOfFrames,DVPSObjectApplicability applicability)148 DVPSDisplayedArea *DVPSDisplayedArea_PList::createDisplayedArea(
149 DVPSReferencedSeries_PList& allReferences,
150 const char *sopclassUID,
151 const char *instanceUID,
152 unsigned long frame,
153 unsigned long numberOfFrames,
154 DVPSObjectApplicability applicability)
155 {
156
157 DVPSDisplayedArea *oldArea = findDisplayedArea(instanceUID, frame);
158 DVPSDisplayedArea *newArea = NULL;
159 if (oldArea == NULL) newArea = new DVPSDisplayedArea();
160 else
161 {
162 // Check if the existing displayed area selection happens to match the new
163 // applicability. If yes, we only need to return the existing item.
164 if (oldArea->matchesApplicability(instanceUID, frame, applicability)) return oldArea;
165
166 // the applicability has changed. Rework the complete sequence.
167 newArea = new DVPSDisplayedArea(*oldArea); // create copy
168 if (newArea) newArea->clearImageReferences();
169
170 OFListIterator(DVPSDisplayedArea *) first = list_.begin();
171 OFListIterator(DVPSDisplayedArea *) last = list_.end();
172 switch (applicability)
173 {
174 case DVPSB_currentFrame:
175 case DVPSB_currentImage:
176 while (first != last)
177 {
178 (*first)->removeImageReference(allReferences, instanceUID, frame, numberOfFrames, applicability);
179 if ((*first)->imageReferencesEmpty())
180 {
181 delete (*first);
182 first = list_.erase(first);
183 } else ++first;
184 }
185 break;
186 case DVPSB_allImages:
187 clear(); // delete all area selections
188 break;
189 }
190 }
191
192 if (newArea)
193 {
194 if (applicability != DVPSB_allImages) newArea->addImageReference(sopclassUID, instanceUID, frame, applicability);
195 list_.push_back(newArea);
196 }
197 return newArea;
198 }
199