1 /*=========================================================================
2 
3   Program: GDCM (Grassroots DICOM). A DICOM library
4 
5   Copyright (c) 2006-2011 Mathieu Malaterre
6   All rights reserved.
7   See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
8 
9      This software is distributed WITHOUT ANY WARRANTY; without even
10      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11      PURPOSE.  See the above copyright notice for more information.
12 
13 =========================================================================*/
14 
15 #ifndef GDCMCP246EXPLICITDATAELEMENT_TXX
16 #define GDCMCP246EXPLICITDATAELEMENT_TXX
17 
18 #include "gdcmSequenceOfItems.h"
19 #include "gdcmSequenceOfFragments.h"
20 #include "gdcmVL.h"
21 #include "gdcmParseException.h"
22 #include "gdcmImplicitDataElement.h"
23 
24 #include "gdcmValueIO.h"
25 #include "gdcmSwapper.h"
26 
27 namespace gdcm
28 {
29 //-----------------------------------------------------------------------------
30 template <typename TSwap>
Read(std::istream & is)31 std::istream &CP246ExplicitDataElement::Read(std::istream &is)
32 {
33   ReadPreValue<TSwap>(is);
34   return ReadValue<TSwap>(is);
35 }
36 //-----------------------------------------------------------------------------
37 template <typename TSwap>
ReadPreValue(std::istream & is)38 std::istream &CP246ExplicitDataElement::ReadPreValue(std::istream &is)
39 {
40   TagField.Read<TSwap>(is);
41   // See PS 3.5, Data Element Structure With Explicit VR
42   // Read Tag
43   if( !is )
44     {
45     if( !is.eof() ) // FIXME This should not be needed
46       {
47       assert(0 && "Should not happen" );
48       }
49     return is;
50     }
51   assert( TagField != Tag(0xfffe,0xe0dd) );
52   const Tag itemDelItem(0xfffe,0xe00d);
53   if( TagField == itemDelItem )
54     {
55     if( !ValueLengthField.Read<TSwap>(is) )
56       {
57       assert(0 && "Should not happen");
58       return is;
59       }
60     if( ValueLengthField != 0 )
61       {
62       gdcmDebugMacro(
63         "Item Delimitation Item has a length different from 0" );
64       }
65     // Set pointer to NULL to avoid user error
66     ValueField = nullptr;
67     return is;
68     }
69 
70   // Read VR
71   try
72     {
73     if( !VRField.Read(is) )
74       {
75       assert(0 && "Should not happen" );
76       return is;
77       }
78     }
79   catch( std::exception & )
80     {
81     // gdcm-MR-PHILIPS-16-Multi-Seq.dcm
82     // assert( TagField == Tag(0xfffe, 0xe000) );
83     // -> For some reason VR is written as {44,0} well I guess this is a VR...
84     // Technically there is a second bug, dcmtk assume other things when reading this tag,
85     // so I need to change this tag too, if I ever want dcmtk to read this file. oh well
86     // 0019004_Baseline_IMG1.dcm
87     // -> VR is garbage also...
88     // assert( TagField == Tag(8348,0339) || TagField == Tag(b5e8,0338))
89     gdcmWarningMacro( "Assuming 16 bits VR for Tag=" <<
90       TagField << " in order to read a buggy DICOM file." );
91     VRField = VR::INVALID;
92     }
93   // Read Value Length
94   if( VR::GetLength(VRField) == 4 )
95     {
96     if( !ValueLengthField.Read<TSwap>(is) )
97       {
98       assert(0 && "Should not happen");
99       return is;
100       }
101     }
102   else
103     {
104     // 16bits only
105     if( !ValueLengthField.template Read16<TSwap>(is) )
106       {
107       //gdcmAssertAlwaysMacro(0 && "Should not happen");
108       // The following is occurs with gdcm 2.0.17 when two
109       // seq del item marker are found
110       // See UnexpectedSequenceDelimiterInFixedLengthSequence.dcm
111       throw Exception("Should not happen CP246");
112       return is;
113       }
114     }
115   return is;
116 }
117 //-----------------------------------------------------------------------------
118 template <typename TSwap>
ReadValue(std::istream & is,bool readvalues)119 std::istream &CP246ExplicitDataElement::ReadValue(std::istream &is, bool readvalues)
120 {
121   if( is.eof() ) return is;
122   if( ValueLengthField == 0 )
123     {
124     // Simple fast path
125     ValueField = nullptr;
126     return is;
127     }
128 
129   //std::cerr << "exp cur tag=" << TagField << " VR=" << VRField << " VL=" << ValueLengthField << std::endl;
130   // Read the Value
131   //assert( ValueField == 0 );
132   if( VRField == VR::SQ )
133     {
134     // Check whether or not this is an undefined length sequence
135     assert( TagField != Tag(0x7fe0,0x0010) );
136     ValueField = new SequenceOfItems;
137     }
138   else if( ValueLengthField.IsUndefined() )
139     {
140     if( VRField == VR::UN )
141       {
142       // Support cp246 conforming file:
143       // Enhanced_MR_Image_Storage_PixelSpacingNotIn_0028_0030.dcm (illegal)
144       // vs
145       // undefined_length_un_vr.dcm
146       assert( TagField != Tag(0x7fe0,0x0010) );
147       ValueField = new SequenceOfItems;
148       ValueField->SetLength(ValueLengthField); // perform realloc
149       try
150         {
151         if( !ValueIO<CP246ExplicitDataElement,TSwap>::Read(is,*ValueField,readvalues) ) // non cp246
152           {
153           assert(0);
154           }
155         }
156       catch( std::exception &)
157         {
158         // Must be one of those non-cp246 file...
159         // but for some reason seekg back to previous offset + Read
160         // as CP246Explicit does not work...
161         ParseException pe;
162         pe.SetLastElement(*this);
163         throw pe;
164         }
165       return is;
166       }
167     else
168       {
169       // Ok this is Pixel Data fragmented...
170       assert( TagField == Tag(0x7fe0,0x0010) );
171       assert( VRField & VR::OB_OW );
172       ValueField = new SequenceOfFragments;
173       }
174     }
175   else
176     {
177     //assert( TagField != Tag(0x7fe0,0x0010) );
178     ValueField = new ByteValue;
179     }
180   // We have the length we should be able to read the value
181   ValueField->SetLength(ValueLengthField); // perform realloc
182 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
183   if( TagField == Tag(0x2001,0xe05f)
184     || TagField == Tag(0x2001,0xe100)
185     || TagField == Tag(0x2005,0xe080)
186     || TagField == Tag(0x2005,0xe083)
187     || TagField == Tag(0x2005,0xe084)
188     //TagField.IsPrivate() && VRField == VR::SQ
189     //-> Does not work for 0029
190     //we really need to read item marker
191   )
192     {
193     gdcmWarningMacro( "ByteSwaping Private SQ: " << TagField );
194     assert( VRField == VR::SQ );
195     try
196       {
197       if( !ValueIO<CP246ExplicitDataElement,SwapperDoOp>::Read(is,*ValueField,readvalues) )
198         {
199         assert(0 && "Should not happen");
200         }
201       }
202     catch( std::exception & )
203       {
204       ValueLengthField = ValueField->GetLength();
205       }
206     return is;
207     }
208 #endif
209   //if( !ValueField->Read<TSwap>(is) )
210   if( !ValueIO<CP246ExplicitDataElement,TSwap>::Read(is,*ValueField,readvalues) )
211     {
212     // Might be the famous UN 16bits
213     ParseException pe;
214     pe.SetLastElement( *this );
215     throw pe;
216     return is;
217     }
218 
219   return is;
220 }
221 
222 template <typename TSwap>
ReadWithLength(std::istream & is,VL & length)223 std::istream &CP246ExplicitDataElement::ReadWithLength(std::istream &is, VL & length)
224 {
225   (void)length;
226   return Read<TSwap>(is);
227 }
228 
229 
230 } // end namespace gdcm
231 
232 #endif // GDCMCP246EXPLICITDATAELEMENT_TXX
233