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/dvpspll.h"
25 #include "dcmtk/dcmpstat/dvpspl.h"      /* for DVPSImageBoxContent */
26 #include "dcmtk/dcmpstat/dvpshlp.h"     /* for class DVPSHelper */
27 #include "dcmtk/dcmpstat/dvpsibl.h"     /* for class DVPSImageBoxContent_PList */
28 #include "dcmtk/dcmimgle/diluptab.h"    /* for class DiLookupTable */
29 #include "dcmtk/dcmpstat/dvpsdef.h"
30 #include "dcmtk/dcmpstat/dvpsib.h"      /* for DVPSImageBoxContent, needed by MSVC5 with STL */
31 
32 /* --------------- class DVPSImageBoxContent_PList --------------- */
33 
DVPSPresentationLUT_PList()34 DVPSPresentationLUT_PList::DVPSPresentationLUT_PList()
35 : list_()
36 {
37 }
38 
DVPSPresentationLUT_PList(const DVPSPresentationLUT_PList & arg)39 DVPSPresentationLUT_PList::DVPSPresentationLUT_PList(const DVPSPresentationLUT_PList &arg)
40 : list_()
41 {
42   OFListConstIterator(DVPSPresentationLUT *) first = arg.list_.begin();
43   OFListConstIterator(DVPSPresentationLUT *) last = arg.list_.end();
44   while (first != last)
45   {
46     list_.push_back((*first)->clone());
47     ++first;
48   }
49 }
50 
~DVPSPresentationLUT_PList()51 DVPSPresentationLUT_PList::~DVPSPresentationLUT_PList()
52 {
53   clear();
54 }
55 
clear()56 void DVPSPresentationLUT_PList::clear()
57 {
58   OFListIterator(DVPSPresentationLUT *) first = list_.begin();
59   OFListIterator(DVPSPresentationLUT *) last = list_.end();
60   while (first != last)
61   {
62     delete (*first);
63     first = list_.erase(first);
64   }
65 }
66 
read(DcmItem & dset)67 OFCondition DVPSPresentationLUT_PList::read(DcmItem &dset)
68 {
69   OFCondition result = EC_Normal;
70   DcmStack stack;
71   DVPSPresentationLUT *newLUT = NULL;
72   DcmSequenceOfItems *dseq=NULL;
73   DcmItem *ditem=NULL;
74 
75   if (EC_Normal == dset.search(DCM_RETIRED_PresentationLUTContentSequence, stack, ESM_fromHere, OFFalse))
76   {
77     dseq=(DcmSequenceOfItems *)stack.top();
78     if (dseq)
79     {
80       unsigned long numItems = dseq->card();
81       for (unsigned int i=0; i<numItems; i++)
82       {
83         ditem = dseq->getItem(i);
84         newLUT = new DVPSPresentationLUT();
85         if (newLUT && ditem)
86         {
87           result = newLUT->read(*ditem, OFTrue);
88           list_.push_back(newLUT);
89         } else result = EC_MemoryExhausted;
90       }
91     }
92   }
93 
94   return result;
95 }
96 
write(DcmItem & dset)97 OFCondition DVPSPresentationLUT_PList::write(DcmItem &dset)
98 {
99   if (size()==0) return EC_Normal; // don't write if sequence is empty
100 
101   OFCondition result = EC_Normal;
102   DcmSequenceOfItems *dseq=NULL;
103   DcmItem *ditem=NULL;
104 
105   dseq = new DcmSequenceOfItems(DCM_RETIRED_PresentationLUTContentSequence);
106   if (dseq)
107   {
108     OFListIterator(DVPSPresentationLUT *) first = list_.begin();
109     OFListIterator(DVPSPresentationLUT *) last = list_.end();
110     while (first != last)
111     {
112       if (result==EC_Normal)
113       {
114         ditem = new DcmItem();
115         if (ditem)
116         {
117           result = (*first)->write(*ditem, OFTrue);
118           if (result==EC_Normal) dseq->insert(ditem); else delete ditem;
119         } else result = EC_MemoryExhausted;
120       }
121       ++first;
122     }
123     if (result==EC_Normal) dset.insert(dseq, OFTrue /*replaceOld*/); else delete dseq;
124   } else result = EC_MemoryExhausted;
125   return result;
126 }
127 
cleanup(const char * filmBox,DVPSImageBoxContent_PList & imageBoxes)128 void DVPSPresentationLUT_PList::cleanup(const char *filmBox, DVPSImageBoxContent_PList& imageBoxes)
129 {
130   OFString aFilmbox;
131   if (filmBox) aFilmbox = filmBox;
132   const char *uid;
133   OFListIterator(DVPSPresentationLUT *) first = list_.begin();
134   OFListIterator(DVPSPresentationLUT *) last = list_.end();
135   while (first != last)
136   {
137     uid = (*first)->getSOPInstanceUID();
138     if (uid && ((aFilmbox == uid)||(imageBoxes.presentationLUTInstanceUIDisUsed(uid)))) ++first;
139     else
140     {
141       delete (*first);
142       first = list_.erase(first);
143     }
144   }
145   return;
146 }
147 
findPresentationLUT(const char * instanceUID)148 DVPSPresentationLUT *DVPSPresentationLUT_PList::findPresentationLUT(const char *instanceUID)
149 {
150   if (instanceUID==NULL) return NULL;
151   OFString instance(instanceUID);
152   OFListIterator(DVPSPresentationLUT *) first = list_.begin();
153   OFListIterator(DVPSPresentationLUT *) last = list_.end();
154   const char *c;
155   while (first != last)
156   {
157     c = (*first)->getSOPInstanceUID();
158     if (c && (instance == c)) return (*first);
159     ++first;
160   }
161   return NULL;
162 }
163 
addPresentationLUT(DVPSPresentationLUT * newLUT,OFBool inversePLUT)164 const char *DVPSPresentationLUT_PList::addPresentationLUT(DVPSPresentationLUT *newLUT, OFBool inversePLUT)
165 {
166   if (newLUT == NULL) return NULL;
167 
168   DiLookupTable *diLUT = NULL;
169   const char *result = NULL;
170 
171   // 'INVERSE' LUT shape is undefined for Print and has already
172   // been rendered into the bitmap at this stage.
173   DVPSPresentationLUTType lutType = newLUT->getType();
174   if (lutType == DVPSP_inverse) lutType = DVPSP_identity;
175 
176   DVPSPresentationLUT *myLUT = newLUT->clone();
177   if (myLUT)
178   {
179     // make sure that we don't copy an inverse LUT shape
180     if (myLUT->getType() == DVPSP_inverse) myLUT->setType(DVPSP_identity);
181     if (lutType == DVPSP_table)
182     {
183       if (inversePLUT) myLUT->invert();
184       diLUT = myLUT->createDiLookupTable();
185     }
186   } else return NULL;
187 
188   // see if myLUT is already somewhere in the list
189   OFListIterator(DVPSPresentationLUT *) first = list_.begin();
190   OFListIterator(DVPSPresentationLUT *) last = list_.end();
191   while (first != last)
192   {
193     if ((*first)->getType() == lutType)
194     {
195       if (lutType == DVPSP_table)
196       {
197    	if ((*first)->compareDiLookupTable(diLUT))
198       	{
199       	  result = (*first)->getSOPInstanceUID();
200       	  break;
201         }
202       } else {
203         result = (*first)->getSOPInstanceUID();
204         break;
205       }
206     }
207     ++first;
208   }
209   delete diLUT;
210 
211   if (result)
212   {
213     delete myLUT;
214     return result;
215   }
216 
217   // no match, store new LUT
218   char uid[100];
219   dcmGenerateUniqueIdentifier(uid);
220   myLUT->setSOPInstanceUID(uid);
221   list_.push_back(myLUT);
222   result = myLUT->getSOPInstanceUID();
223 
224   return result;
225 }
226 
227 
printSCPDelete(T_DIMSE_Message & rq,T_DIMSE_Message & rsp)228 void DVPSPresentationLUT_PList::printSCPDelete(T_DIMSE_Message& rq, T_DIMSE_Message& rsp)
229 {
230   OFListIterator(DVPSPresentationLUT *) first = list_.begin();
231   OFListIterator(DVPSPresentationLUT *) last = list_.end();
232   OFBool found = OFFalse;
233   OFString theUID(rq.msg.NDeleteRQ.RequestedSOPInstanceUID);
234   while ((first != last) && (!found))
235   {
236     if (theUID == (*first)->getSOPInstanceUID()) found = OFTrue;
237     else ++first;
238   }
239 
240   if (found)
241   {
242     delete (*first);
243     list_.erase(first);
244   } else {
245     // presentation LUT does not exist or wrong instance UID
246     DCMPSTAT_WARN("cannot delete presentation LUT with instance UID '" << rq.msg.NDeleteRQ.RequestedSOPInstanceUID << "': object does not exist.");
247     rsp.msg.NDeleteRSP.DimseStatus = STATUS_N_NoSuchObjectInstance;
248   }
249 }
250