]> Creatis software - gdcm.git/blob - src/gdcmElementSet.cxx
Taking into account the 'Dicom Sequences' leads up to introduce new concepts
[gdcm.git] / src / gdcmElementSet.cxx
1 // gdcmElementSet.cxx
2 //-----------------------------------------------------------------------------
3 //
4 #include "gdcmElementSet.h"
5 #include "gdcmTS.h"
6
7
8 //-----------------------------------------------------------------------------
9 // Constructor / Destructor
10 /**
11  * \ingroup gdcmElementSet
12  * \brief   Constructor from a given gdcmElementSet
13  */
14 gdcmDocEntrySet::gdcmDocEntrySet() {
15
16 }
17
18 /**
19  * \ingroup gdcmElementSet
20  * \brief   Canonical destructor.
21  */
22 gdcmElementSet::~gdcmElementSet() 
23 {
24 /*   for(tous les DocEntry)
25    {
26       delete *cc;
27    }
28    */
29 }
30
31
32 //-----------------------------------------------------------------------------
33 // Public
34
35
36 //-----------------------------------------------------------------------------
37 // Protected
38
39 //-----------------------------------------------------------------------------
40 // Private
41
42 /**
43  * \brief  Find the value Length of the passed Header Entry
44  * @param  Entry Header Entry whose length of the value shall be loaded. 
45  */
46  void gdcmElementSet::FindDocEntryLength (gdcmDocEntry *Entry) {
47    guint16 element = Entry->GetElement();
48    //guint16 group   = Entry->GetGroup(); //FIXME
49    std::string  vr = Entry->GetVR();
50    guint16 length16;
51        
52    
53    if ( (filetype == ExplicitVR) && (! Entry->IsImplicitVR()) ) 
54    {
55       if ( (vr=="OB") || (vr=="OW") || (vr=="SQ") || (vr=="UN") ) 
56       {
57          // The following reserved two bytes (see PS 3.5-2001, section
58          // 7.1.2 Data element structure with explicit vr p27) must be
59          // skipped before proceeding on reading the length on 4 bytes.
60          fseek(fp, 2L, SEEK_CUR);
61          guint32 length32 = ReadInt32();
62
63          if ( (vr == "OB") && (length32 == 0xffffffff) ) 
64          {
65             Entry->SetLength(FindHeaderEntryLengthOB());
66             return;
67          }
68          FixHeaderEntryFoundLength(Entry, length32); 
69          return;
70       }
71
72       // Length is encoded on 2 bytes.
73       length16 = ReadInt16();
74       
75       // We can tell the current file is encoded in big endian (like
76       // Data/US-RGB-8-epicard) when we find the "Transfer Syntax" tag
77       // and it's value is the one of the encoding of a big endian file.
78       // In order to deal with such big endian encoded files, we have
79       // (at least) two strategies:
80       // * when we load the "Transfer Syntax" tag with value of big endian
81       //   encoding, we raise the proper flags. Then we wait for the end
82       //   of the META group (0x0002) among which is "Transfer Syntax",
83       //   before switching the swap code to big endian. We have to postpone
84       //   the switching of the swap code since the META group is fully encoded
85       //   in little endian, and big endian coding only starts at the next
86       //   group. The corresponding code can be hard to analyse and adds
87       //   many additional unnecessary tests for regular tags.
88       // * the second strategy consists in waiting for trouble, that shall
89       //   appear when we find the first group with big endian encoding. This
90       //   is easy to detect since the length of a "Group Length" tag (the
91       //   ones with zero as element number) has to be of 4 (0x0004). When we
92       //   encounter 1024 (0x0400) chances are the encoding changed and we
93       //   found a group with big endian encoding.
94       // We shall use this second strategy. In order to make sure that we
95       // can interpret the presence of an apparently big endian encoded
96       // length of a "Group Length" without committing a big mistake, we
97       // add an additional check: we look in the already parsed elements
98       // for the presence of a "Transfer Syntax" whose value has to be "big
99       // endian encoding". When this is the case, chances are we have got our
100       // hands on a big endian encoded file: we switch the swap code to
101       // big endian and proceed...
102       if ( (element  == 0x0000) && (length16 == 0x0400) ) 
103       {
104          if ( ! IsExplicitVRBigEndianTransferSyntax() ) 
105          {
106             dbg.Verbose(0, "gdcmDocument::FindLength", "not explicit VR");
107             errno = 1;
108             return;
109          }
110          length16 = 4;
111          SwitchSwapToBigEndian();
112          // Restore the unproperly loaded values i.e. the group, the element
113          // and the dictionary entry depending on them.
114          guint16 CorrectGroup   = SwapShort(Entry->GetGroup());
115          guint16 CorrectElem    = SwapShort(Entry->GetElement());
116          gdcmDictEntry * NewTag = GetDictEntryByNumber(CorrectGroup,
117                                                        CorrectElem);
118          if (!NewTag) 
119          {
120             // This correct tag is not in the dictionary. Create a new one.
121             NewTag = NewVirtualDictEntry(CorrectGroup, CorrectElem);
122          }
123          // FIXME this can create a memory leaks on the old entry that be
124          // left unreferenced.
125          Entry->SetDictEntry(NewTag);
126       }
127        
128       // Heuristic: well some files are really ill-formed.
129       if ( length16 == 0xffff) 
130       {
131          length16 = 0;
132          //dbg.Verbose(0, "gdcmDocument::FindLength",
133          //            "Erroneous element length fixed.");
134          // Actually, length= 0xffff means that we deal with
135          // Unknown Sequence Length 
136       }
137       FixHeaderEntryFoundLength(Entry, (guint32)length16);
138       return;
139    }
140    else
141    {
142       // Either implicit VR or a non DICOM conformal (see note below) explicit
143       // VR that ommited the VR of (at least) this element. Farts happen.
144       // [Note: according to the part 5, PS 3.5-2001, section 7.1 p25
145       // on Data elements "Implicit and Explicit VR Data Elements shall
146       // not coexist in a Data Set and Data Sets nested within it".]
147       // Length is on 4 bytes.
148       
149       FixHeaderEntryFoundLength(Entry, ReadInt32());
150       return;
151    }
152 }