]> Creatis software - gdcm.git/blob - src/gdcmDocEntry.cxx
ENH: Try to sync gdcm CVS and gdcm 1.2. ~2000 lines of changes, please be gentle...
[gdcm.git] / src / gdcmDocEntry.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmDocEntry.cxx,v $
5   Language:  C++
6   Date:      $Date: 2006/02/16 20:06:14 $
7   Version:   $Revision: 1.81 $
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 "gdcmDataEntry.h"
21 #include "gdcmTS.h"
22 #include "gdcmVR.h"
23 #include "gdcmGlobal.h"
24 #include "gdcmUtil.h"
25 #include "gdcmDebug.h"
26
27 #include <iomanip> // for std::ios::left, ...
28 #include <fstream>
29
30 namespace gdcm 
31 {
32 //-----------------------------------------------------------------------------
33
34 // Constructor / Destructor
35 /**
36  * \brief   Constructor from a given DictEntry
37  * @param   in Pointer to existing dictionary entry
38  */
39 DocEntry::DocEntry(DictEntry *in)
40 {
41    ImplicitVR = false;
42    DicomDict  = in;
43    Offset     = 0 ; // To avoid further missprinting
44
45    // init some variables
46    ReadLength = 0;
47    Length = 0;
48
49    gdcmAssertMacro(DicomDict);
50    DicomDict->Register();
51 }
52
53 /**
54  * \brief   Destructor from a given DictEntry
55  */
56 DocEntry::~DocEntry()
57 {
58    gdcmAssertMacro(DicomDict);
59
60    DicomDict->Unregister();
61 }
62
63 //-----------------------------------------------------------------------------
64 // Public
65 /**
66  * \brief   Writes the common part of any DataEntry, SeqEntry
67  * @param fp already open ofstream pointer
68  * @param filetype type of the file (ACR, ImplicitVR, ExplicitVR, ...)
69  */
70 void DocEntry::WriteContent(std::ofstream *fp, FileType filetype)
71 {
72    uint32_t ffff  = 0xffffffff;
73    uint16_t group = GetGroup();
74
75    ///\todo allow skipping Shadow groups 
76  
77    VRKey vr       = GetVR();
78    uint16_t elem  = GetElement();
79    uint32_t lgth  = GetLength();
80
81    if ( group == 0xfffe && elem == 0x0000 )
82    {
83      // Fix in order to make some MR PHILIPS images e-film readable
84      // see gdcmData/gdcm-MR-PHILIPS-16-Multi-Seq.dcm:
85      // we just *always* ignore spurious fffe|0000 tag !   
86       return;
87    }
88
89    //
90    // ----------- Writes the common part
91    //
92     // To avoid gdcm to propagate oddities.
93     // --> Don't forget to *write* an even length value   
94    if (lgth%2)
95       lgth ++;
96    
97  // ----------- Writes the common part : the Tag   
98    binary_write( *fp, group); //group number
99    binary_write( *fp, elem);  //element number
100
101    // Dicom V3 group 0x0002 is *always* Explicit VR !
102    if ( filetype == ExplicitVR || filetype == JPEG || group == 0x0002 )
103    {
104 // ----------- Writes the common part : the VR + the length 
105   
106       // Special case of delimiters:
107       if (group == 0xfffe)
108       {
109          // Delimiters have NO Value Representation
110          // Hence we skip writing the VR.
111          //
112          // In order to avoid further troubles, we choose to write them
113          // as 'no-length' Item Delimitors (we pad by writing 0xffffffff)
114          // We shall force the end of a given SeqItem by writting 
115          //  a Item Delimitation Item (fffe, e00d)
116
117          uint32_t ff = 0xffffffff;
118          binary_write(*fp, ff);
119          return;
120       }
121
122       uint16_t zero = 0;
123       uint16_t shortLgr = (uint16_t)lgth;
124
125       if( IsVRUnknown() )
126       {
127          // GDCM_VRUNKNOWN was stored in the Entry VR;
128          // deal with Entry as if TS were Implicit VR
129  
130          binary_write(*fp, lgth);
131       }
132       else
133       {
134          binary_write(*fp, vr.str());
135
136          // See PS 3.5-2004 page 33, 36                  
137          if ( (vr == "SQ") || (vr == "OB") || (vr == "OW") || (vr == "OF") 
138           ||  (vr == "UN") || (vr == "UT") )
139          {
140             binary_write(*fp, zero);
141             if (vr == "SQ")
142             {
143                // we set SQ length to ffffffff
144                // and  we shall write a Sequence Delimitor Item 
145                // at the end of the Sequence! 
146                binary_write(*fp, ffff);
147             }
148             else
149             {
150                binary_write(*fp, lgth);
151             }
152          }
153          else
154          {
155             binary_write(*fp, shortLgr);
156          }
157       }
158    } 
159    else // IMPLICIT VR 
160    { 
161 // ----------- Writes the common part : the VR  
162       if (vr == "SQ")
163       {
164          binary_write(*fp, ffff);
165       }
166       else
167       {
168          binary_write(*fp, lgth);
169       }
170    }
171 }
172
173 /**
174  * \brief   Gets the full length of the elementary DocEntry (not only value
175  *          length) depending on the VR.
176  */
177 uint32_t DocEntry::GetFullLength()
178 {
179    uint32_t l = GetReadLength();
180    if ( IsImplicitVR() )
181    {
182       l = l + 8;  // 2 (gr) + 2 (el) + 4 (lgth) 
183    }
184    else
185    {
186       if ( GetVR()=="OB" || GetVR()=="OW" || GetVR()=="SQ" )
187       {
188          l = l + 12; // 2 (gr) + 2 (el) + 2 (vr) + 2 (unused) + 4 (lgth)
189       }
190       else
191       {
192          l = l + 8;  // 2 (gr) + 2 (el) + 2 (vr) + 2 (lgth)
193       }
194    }
195    return l;
196 }
197
198 /**
199  * \brief   tells us if entry is the last one of a 'no length' SequenceItem 
200  *          (fffe,e00d) 
201  */
202 bool DocEntry::IsItemDelimitor()
203 {
204    return (GetGroup() == 0xfffe && GetElement() == 0xe00d);
205 }
206
207 /**
208  * \brief   tells us if entry is the first one of an Item 
209  *          (fffe,e000) 
210  */
211 bool DocEntry::IsItemStarter()
212 {
213    return (GetGroup() == 0xfffe && GetElement() == 0xe000);
214 }
215
216 /**
217  * \brief   tells us if entry is the last one of a 'no length' Sequence 
218  *          (fffe,e0dd) 
219  */
220 bool DocEntry::IsSequenceDelimitor()
221 {
222    return (GetGroup() == 0xfffe && GetElement() == 0xe0dd);
223 }
224
225 /**
226  * \brief Copies all the attributes from an other DocEntry 
227  * @param doc entry to copy from
228  */
229 void DocEntry::Copy(DocEntry *doc)
230 {
231    Length     = doc->Length;
232    ReadLength = doc->ReadLength;
233    ImplicitVR = doc->ImplicitVR;
234    Offset     = doc->Offset;
235 }
236
237 //-----------------------------------------------------------------------------
238 // Protected
239
240 //-----------------------------------------------------------------------------
241 // Private
242
243 //-----------------------------------------------------------------------------
244 // Print
245 /**
246  * \brief   Prints the common part of DataEntry, SeqEntry
247  * @param   os ostream we want to print in
248  * @param indent Indentation string to be prepended during printing
249  */
250 void DocEntry::Print(std::ostream &os, std::string const & )
251 {
252    size_t o;
253    std::string st;
254    TSKey v;
255    std::string d2;
256    VRKey vr;
257    std::ostringstream s;
258    uint32_t lgth;
259
260    o  = GetOffset();
261    vr = GetVR();
262    if ( vr == GDCM_VRUNKNOWN )
263       vr = "  ";
264
265    s << DictEntry::TranslateToKey(GetGroup(),GetElement()); 
266
267    if (PrintLevel >= 2)
268    {
269       s << " lg : ";
270       lgth = GetReadLength(); // ReadLength, as opposed to (usable) Length
271       if (lgth == 0xffffffff)
272       {
273          st = " ffff ";
274          s.setf(std::ios::left);
275          s << std::setw(4);  
276          s << "    x(ffff) ";
277          s.setf(std::ios::left);
278          s << std::setw(8) << "-1"; 
279       }
280       else
281       {
282          st = Util::Format("x(%x)",lgth); // we may keep it
283          s.setf(std::ios::left);
284          s << std::setw(11-st.size()) << " ";
285          s << st << " ";
286          s.setf(std::ios::left);
287          s << std::setw(8) << lgth; 
288       }
289       s << " Off.: ";
290       st = Util::Format("x(%x)",o);  // we may keep it
291       s << std::setw(11-st.size()) << " ";
292       s << st << " ";
293       s << std::setw(8) << o; 
294    }
295    if (PrintLevel >= 1)
296       s << " ";
297
298    s << "[" << vr  << "] ";
299
300    std::string name;
301    if ( GetElement() == 0x0000 )
302       name = "Group Length";
303    else
304       name = GetName();
305
306    if (PrintLevel >= 1)
307    {
308       s.setf(std::ios::left);
309       s << std::setw(66-name.length()) << " ";
310    }
311     
312    s << "[" << name << "]";
313    os << s.str();      
314 }
315
316 //-----------------------------------------------------------------------------
317 } // end namespace gdcm