]> Creatis software - gdcm.git/blob - src/gdcmDocEntry.cxx
- src/gdcmDocument.[cxx|h] ::ParseDES and ::ParseSQ no longer bother
[gdcm.git] / src / gdcmDocEntry.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmDocEntry.cxx,v $
5   Language:  C++
6   Date:      $Date: 2004/10/06 13:12:42 $
7   Version:   $Revision: 1.24 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See Doc/License.txt or
11   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
12                                                                                 
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*/
18
19 #include "gdcmDocEntry.h"
20 #include "gdcmTS.h"
21 #include "gdcmGlobal.h"
22 #include "gdcmUtil.h"
23
24 #include <iomanip> // for std::ios::left, ...
25
26 // CLEAN ME
27 #define MAX_SIZE_PRINT_ELEMENT_VALUE 64
28
29 //-----------------------------------------------------------------------------
30 // Constructor / Destructor
31 /**
32  * \ingroup gdcmDocEntry
33  * \brief   Constructor from a given gdcmDictEntry
34  * @param   in Pointer to existing dictionary entry
35  */
36 gdcmDocEntry::gdcmDocEntry(gdcmDictEntry* in)
37 {
38    ImplicitVR = false;
39    DictEntry  = in;
40    SetKey( in->GetKey( ) );
41    Offset     = 0 ; // To avoid further missprinting
42 }
43
44 //-----------------------------------------------------------------------------
45 // Print
46 /**
47  * \ingroup gdcmDocEntry
48  * \brief   Prints the common part of gdcmValEntry, gdcmBinEntry, gdcmSeqEntry
49  * @param   os ostream we want to print in
50  */
51 void gdcmDocEntry::Print(std::ostream& os)
52 {
53    PrintLevel = 2; // FIXME
54    
55    size_t o;
56    unsigned short int g, e;
57    char st[20];
58    TSKey v;
59    std::string d2, vr;
60    std::ostringstream s;
61    uint32_t lgth;
62
63    g  = GetGroup();
64    e  = GetElement();
65    o  = GetOffset();
66    vr = GetVR();
67
68    s << gdcmDictEntry::TranslateToKey(GetGroup(),GetElement()); 
69
70    if (PrintLevel >= 2)
71    {
72       s << " lg : ";
73       lgth = GetReadLength(); // ReadLength, as opposed to UsableLength
74       if (lgth == 0xffffffff)
75       {
76          sprintf(st,"x(ffff)");  // I said : "x(ffff)" !
77          s.setf(std::ios::left);
78          s << std::setw(10-strlen(st)) << " ";  
79          s << st << " ";
80          s.setf(std::ios::left);
81          s << std::setw(8) << "-1"; 
82       }
83       else
84       {
85          sprintf(st,"x(%x)",lgth);
86          s.setf(std::ios::left);
87          s << std::setw(10-strlen(st)) << " ";
88          s << st << " ";
89          s.setf(std::ios::left);
90          s << std::setw(8) << lgth; 
91       }
92       s << " Off.: ";
93       sprintf(st,"x(%x)",o); 
94       s << std::setw(10-strlen(st)) << " ";
95       s << st << " ";
96       s << std::setw(8) << o; 
97    }
98
99    s << "[" << vr  << "] ";
100
101    if (PrintLevel >= 1)
102    {
103       s.setf(std::ios::left);
104       s << std::setw(66-GetName().length()) << " ";
105    }
106     
107    s << "[" << GetName()<< "]";
108    os << s.str();      
109 }
110
111 /**
112  * \ingroup gdcmDocEntry
113  * \brief   Writes the common part of any gdcmValEntry, gdcmBinEntry, gdcmSeqEntry
114  * @param fp already open file pointer
115  * @param filetype type of the file to be written
116  */
117 void gdcmDocEntry::Write(FILE* fp, FileType filetype)
118 {
119    uint32_t FFFF  = 0xffffffff;
120    uint16_t group = GetGroup();
121    gdcmVRKey vr   = GetVR();
122    uint16_t el    = GetElement();
123    uint32_t lgr   = GetReadLength();
124
125    if ( group == 0xfffe && el == 0x0000 )
126    {
127      // Fix in order to make some MR PHILIPS images e-film readable
128      // see gdcmData/gdcm-MR-PHILIPS-16-Multi-Seq.dcm:
129      // we just *always* ignore spurious fffe|0000 tag !   
130       return;
131    }
132
133 //
134 // ----------- Writes the common part
135 //
136    fwrite ( &group,(size_t)2 ,(size_t)1 ,fp);  //group
137    fwrite ( &el,   (size_t)2 ,(size_t)1 ,fp);  //element
138       
139    if ( filetype == gdcmExplicitVR )
140    {
141       // Special case of delimiters:
142       if (group == 0xfffe)
143       {
144          // Delimiters have NO Value Representation
145          // Hence we skip writing the VR.
146          // In order to avoid further troubles, we choose to write them
147          // as 'no-length' Item Delimitors (we pad by writing 0xffffffff)
148          // The end of a given Item will be found when  :
149          //  - a new Item Delimitor Item is encountered (the Seq goes on)
150          //  - a Sequence Delimitor Item is encountered (the Seq just ended)
151
152        // TODO : verify if the Sequence Delimitor Item was forced during Parsing 
153
154          int ff = 0xffffffff;
155          fwrite (&ff,(size_t)4 ,(size_t)1 ,fp);
156          return;
157       }
158
159       uint16_t z = 0;
160       uint16_t shortLgr = lgr;
161
162       if (vr == "unkn")
163       {
164          // Unknown was 'written'
165          // deal with Little Endian            
166          fwrite ( &shortLgr,(size_t)2 ,(size_t)1 ,fp);
167          fwrite ( &z,       (size_t)2 ,(size_t)1 ,fp);
168       }
169       else
170       {
171          fwrite (vr.c_str(),(size_t)2 ,(size_t)1 ,fp); 
172                   
173          if ( (vr == "OB") || (vr == "OW") || (vr == "SQ") || (vr == "UN") )
174          {
175             fwrite ( &z,  (size_t)2 ,(size_t)1 ,fp);
176             if (vr == "SQ")
177             {
178                // we set SQ length to ffffffff
179                // and  we shall write a Sequence Delimitor Item 
180                // at the end of the Sequence! 
181                fwrite ( &FFFF,(size_t)4 ,(size_t)1 ,fp);
182             }
183             else
184             {
185                fwrite ( &lgr,(size_t)4 ,(size_t)1 ,fp);
186             }
187          }
188          else
189          {
190             fwrite ( &shortLgr,(size_t)2 ,(size_t)1 ,fp);
191          }
192       }
193    } 
194    else // IMPLICIT VR 
195    { 
196       if (vr == "SQ")
197       {
198          fwrite ( &FFFF,(size_t)4 ,(size_t)1 ,fp);
199       }
200       else
201       {
202          fwrite ( &lgr,(size_t)4 ,(size_t)1 ,fp);
203       }
204    }
205 }
206
207 //-----------------------------------------------------------------------------
208 // Public
209
210 /**
211  * \ingroup gdcmDocEntry
212  * \brief   Gets the full length of the elementary DocEntry (not only value
213  *          length) depending on the VR.
214  */
215 uint32_t gdcmDocEntry::GetFullLength()
216 {
217    uint32_t l = GetReadLength();
218    if ( IsImplicitVR() )
219    {
220       l = l + 8;  // 2 (gr) + 2 (el) + 4 (lgth) 
221    }
222    else
223    {
224       if ( GetVR()=="OB" || GetVR()=="OW" || GetVR()=="SQ" )
225       {
226          l = l + 12; // 2 (gr) + 2 (el) + 2 (vr) + 2 (unused) + 4 (lgth)
227       }
228       else
229       {
230          l = l + 8;  // 2 (gr) + 2 (el) + 2 (vr) + 2 (lgth)
231       }
232    }
233    return l;
234 }
235
236 /**
237  * \ingroup gdcmDocEntry
238  * \brief   Copies all the attributes from an other DocEntry 
239  */
240 void gdcmDocEntry::Copy (gdcmDocEntry* e)
241 {
242    DictEntry    = e->DictEntry;
243    UsableLength = e->UsableLength;
244    ReadLength   = e->ReadLength;
245    ImplicitVR   = e->ImplicitVR;
246    Offset       = e->Offset;
247    PrintLevel   = e->PrintLevel;
248    // TODO : remove gdcmDocEntry SQDepth
249 }
250
251 /**
252  * \ingroup gdcmDocEntry
253  * \brief   tells us if entry is the last one of a 'no length' SequenceItem 
254  *          (fffe,e00d) 
255  */
256 bool gdcmDocEntry::IsItemDelimitor()
257 {
258    return (GetGroup() == 0xfffe && GetElement() == 0xe00d);
259 }
260 /**
261  * \ingroup gdcmDocEntry
262  * \brief   tells us if entry is the last one of a 'no length' Sequence 
263  *          (fffe,e0dd) 
264  */
265 bool gdcmDocEntry::IsSequenceDelimitor()
266 {
267    return (GetGroup() == 0xfffe && GetElement() == 0xe0dd);
268 }
269
270 //-----------------------------------------------------------------------------
271 // Protected
272
273
274 //-----------------------------------------------------------------------------
275 // Private
276
277 //-----------------------------------------------------------------------------