]> Creatis software - gdcm.git/blob - src/gdcmDocEntry.cxx
2004-06-22 Jean-Pierre Roux
[gdcm.git] / src / gdcmDocEntry.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmDocEntry.cxx,v $
5   Language:  C++
6   Date:      $Date: 2004/06/22 13:47:33 $
7   Version:   $Revision: 1.8 $
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.htm 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    ImplicitVR = false;
38    entry = in;
39 }
40
41 /**
42  * \ingroup gdcmDocEntry
43  * \brief   Canonical Printer
44  * @param   os ostream we want to print in
45  */
46 void gdcmDocEntry::Print(std::ostream & os) {
47    std::ostringstream s;
48    s << std::endl;
49    PrintCommonPart(os);
50    os << s.str();
51 }
52
53 //-----------------------------------------------------------------------------
54 // Print
55 /**
56  * \ingroup gdcmDocEntry
57  * \brief   Prints the common part of gdcmValEntry, gdcmBinEntry, gdcmSeqEntry
58  */
59 void gdcmDocEntry::PrintCommonPart(std::ostream & os) {
60
61    printLevel=2; // FIXME
62    
63    size_t o;
64    unsigned short int g, e;
65    char st[20];
66    TSKey v;
67    std::string d2, vr;
68    std::ostringstream s;
69    guint32 lgth;
70    char greltag[10];  //group element tag
71
72    g  = GetGroup();
73    e  = GetElement();
74    o  = GetOffset();
75    vr = GetVR();
76    sprintf(greltag,"%04x|%04x ",g,e);           
77    s << greltag ;
78        
79    if (printLevel>=2) { 
80       s << "lg : ";
81       lgth = GetReadLength(); // ReadLength, as opposed to UsableLength
82       if (lgth == 0xffffffff) {
83          sprintf(st,"x(ffff)");  // I said : "x(ffff)" !
84          s.setf(std::ios::left);
85          s << std::setw(10-strlen(st)) << " ";  
86          s << st << " ";
87          s.setf(std::ios::left);
88          s << std::setw(8) << "-1";      
89       } else {
90          sprintf(st,"x(%x)",lgth);
91          s.setf(std::ios::left);
92          s << std::setw(10-strlen(st)) << " ";  
93          s << st << " ";
94          s.setf(std::ios::left);
95          s << std::setw(8) << lgth; 
96       }
97       s << " Off.: ";
98       sprintf(st,"x(%x)",o); 
99       s << std::setw(10-strlen(st)) << " ";
100       s << st << " ";
101       s << std::setw(8) << o; 
102    }
103
104    s << "[" << vr  << "] ";
105
106    if (printLevel>=1) {      
107       s.setf(std::ios::left);
108       s << std::setw(66-GetName().length()) << " ";
109    }
110     
111    s << "[" << GetName()<< "]";
112    os << s.str();      
113 }
114
115 /**
116  * \ingroup gdcmDocEntry
117  * \brief   Writes the common part of any gdcmValEntry, gdcmBinEntry, gdcmSeqEntry
118  */
119 void gdcmDocEntry::Write(FILE *fp, FileType filetype) {
120    std::cout << "gdcmDocEntry::Write : Is that what you wanted to do ? " << std::endl;
121    WriteCommonPart(fp, filetype);
122 }
123
124 /**
125  * \ingroup gdcmDocEntry
126  * \brief   Writes the common part of any gdcmValEntry, gdcmBinEntry, gdcmSeqEntry
127  */
128 void gdcmDocEntry::WriteCommonPart(FILE *fp, FileType filetype) {
129
130    guint16 group  = GetGroup();
131    VRKey   vr     = GetVR();
132    guint16 el     = GetElement();
133    guint32 lgr    = GetReadLength();
134
135    if ( (group == 0xfffe) && (el == 0x0000) ) 
136      // Fix in order to make some MR PHILIPS images e-film readable
137      // see gdcmData/gdcm-MR-PHILIPS-16-Multi-Seq.dcm:
138      // we just *always* ignore spurious fffe|0000 tag !   
139       return; 
140
141 //
142 // ----------- Writes the common part
143 //
144    fwrite ( &group,(size_t)2 ,(size_t)1 ,fp);  //group
145    fwrite ( &el,   (size_t)2 ,(size_t)1 ,fp);  //element
146       
147    if ( filetype == gdcmExplicitVR ) {
148
149       // Special case of delimiters:
150       if (group == 0xfffe) {
151          // Delimiters have NO Value Representation
152          // Hence we skip writing the VR.
153          // In order to avoid further troubles, we choose to write them
154          // as 'no-length' Item Delimitors (we pad by writing 0xffffffff)
155          // The end of a given Item will be found when  :
156          //  - a new Item Delimitor Item is encountered (the Seq goes on)
157          //  - a Sequence Delimitor Item is encountered (the Seq just ended)
158
159        // TODO : verify if the Sequence Delimitor Item was forced during Parsing 
160
161          int ff=0xffffffff;
162          fwrite (&ff,(size_t)4 ,(size_t)1 ,fp);
163          return;
164       }
165
166       guint16 z=0;
167       guint16 shortLgr = lgr;
168       if (vr == "unkn") {     // Unknown was 'written'
169          // deal with Little Endian            
170          fwrite ( &shortLgr,(size_t)2 ,(size_t)1 ,fp);
171          fwrite ( &z,  (size_t)2 ,(size_t)1 ,fp);
172       } else {
173          fwrite (vr.c_str(),(size_t)2 ,(size_t)1 ,fp); 
174
175 // TODO : better we set SQ length to ffffffff
176 //      and write a Sequence Delimitor Item at the end of the Sequence!                    
177          if ( (vr == "OB") || (vr == "OW") || (vr == "SQ") )
178          {
179             fwrite ( &z,  (size_t)2 ,(size_t)1 ,fp);
180             fwrite ( &lgr,(size_t)4 ,(size_t)1 ,fp);
181          } else {
182             fwrite ( &shortLgr,(size_t)2 ,(size_t)1 ,fp);
183          }
184       }
185    } 
186    else // IMPLICIT VR 
187    { 
188       fwrite ( &lgr,(size_t)4 ,(size_t)1 ,fp);
189    }
190 }
191
192 //-----------------------------------------------------------------------------
193 // Public
194
195 /**
196  * \ingroup gdcmDocEntry
197  * \brief   Gets the full length of the elementary DocEntry (not only value length)
198  */
199 guint32 gdcmDocEntry::GetFullLength(void) {
200    guint32 l;
201    l = GetReadLength();
202    if ( IsImplicitVR() ) 
203       l = l + 8;  // 2 (gr) + 2 (el) + 4 (lgth) 
204    else    
205       if ( GetVR()=="OB" || GetVR()=="OW" || GetVR()=="SQ" )
206          l = l + 12; // 2 (gr) + 2 (el) + 2 (vr) + 2 (unused) + 4 (lgth)
207       else
208          l = l + 8;  // 2 (gr) + 2 (el) + 2 (vr) + 2 (lgth)
209    return(l);
210 }
211
212 /**
213  * \ingroup gdcmDocEntry
214  * \brief   Copies all the attributes from an other DocEntry 
215  */
216 void gdcmDocEntry::Copy (gdcmDocEntry* e) {
217    this->entry        = e->entry;
218    this->UsableLength = e->UsableLength;
219    this->ReadLength   = e->ReadLength;
220    this->ImplicitVR   = e->ImplicitVR;
221    this->Offset       = e->Offset;
222    this->printLevel   = e->printLevel;
223    // TODO : remove gdcmDocEntry SQDepth
224 }
225
226 /**
227  * \ingroup gdcmDocEntry
228  * \brief   tells us if entry is the first one of a Sequence Item (fffe,e00d) 
229  */
230 bool gdcmDocEntry::isItemDelimitor() {
231    if ( (GetGroup() == 0xfffe) && (GetElement() == 0xe00d) )
232       return true;
233    else
234       return false;      
235 }
236 /**
237  * \ingroup gdcmDocEntry
238  * \brief   tells us if entry is the last one of a 'no length' Sequence fffe,e0dd) 
239  */
240 bool gdcmDocEntry::isSequenceDelimitor() {
241    if (GetGroup() == 0xfffe && GetElement() == 0xe0dd)
242       return true;
243    else
244       return false; 
245 }
246
247 //-----------------------------------------------------------------------------
248 // Protected
249
250
251 //-----------------------------------------------------------------------------
252 // Private
253
254 //-----------------------------------------------------------------------------