GDCM  2.2.4
gdcmSequenceOfFragments.h
Go to the documentation of this file.
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 #ifndef GDCMSEQUENCEOFFRAGMENTS_H
15 #define GDCMSEQUENCEOFFRAGMENTS_H
16 
17 #include "gdcmValue.h"
18 #include "gdcmVL.h"
19 #include "gdcmFragment.h"
20 #include "gdcmBasicOffsetTable.h"
21 
22 namespace gdcm
23 {
24 
25  // FIXME gdcmSequenceOfItems and gdcmSequenceOfFragments
26  // should be rethink (duplicate code)
32 {
33 public:
34  // Typdefs:
35  typedef std::vector<Fragment> FragmentVector;
36  typedef FragmentVector::size_type SizeType;
37  typedef FragmentVector::iterator Iterator;
38  typedef FragmentVector::const_iterator ConstIterator;
39  Iterator Begin() { return Fragments.begin(); }
40  Iterator End() { return Fragments.end(); }
41  ConstIterator Begin() const { return Fragments.begin(); }
42  ConstIterator End() const { return Fragments.end(); }
43 
45  SequenceOfFragments():Table(),SequenceLengthField(0xFFFFFFFF) { }
46 
48  VL GetLength() const {
49  return SequenceLengthField;
50  }
51 
53  void SetLength(VL length) {
54  SequenceLengthField = length;
55  }
56 
58  void Clear();
59 
61  void AddFragment(Fragment const &item);
62 
63  // Compute the length of all fragments (and framents only!).
64  // Basically the size of the PixelData as stored (in bytes).
65  unsigned long ComputeByteLength() const;
66 
67  // Compute the length of fragments (in bytes)+ length of tag...
68  // to be used for computation of Group Length
69  VL ComputeLength() const;
70 
71  // Get the buffer
72  bool GetBuffer(char *buffer, unsigned long length) const;
73  bool GetFragBuffer(unsigned int fragNb, char *buffer, unsigned long &length) const;
74 
75  SizeType GetNumberOfFragments() const;
76  const Fragment& GetFragment(SizeType num) const;
77 
78  // Write the buffer of each fragment (call WriteBuffer on all Fragments, which are
79  // ByteValue). No Table information is written.
80  bool WriteBuffer(std::ostream &os) const;
81 
82  const BasicOffsetTable &GetTable() const { return Table; }
84 
85 template <typename TSwap>
86 std::istream& Read(std::istream &is)
87 {
88  assert( SequenceLengthField.IsUndefined() );
89  ReadPreValue<TSwap>(is);
90  return ReadValue<TSwap>(is);
91 }
92 
93 template <typename TSwap>
94 std::istream& ReadPreValue(std::istream &is)
95 {
96  //if( SequenceLengthField.IsUndefined() )
97  // First item is the basic offset table:
98  try
99  {
100  Table.Read<TSwap>(is);
101  gdcmDebugMacro( "Table: " << Table );
102  }
103  catch(...)
104  {
105  // Bug_Siemens_PrivateIconNoItem.dcm
106  // First thing first let's rewind
107  is.seekg(-4, std::ios::cur);
108  if ( Table.GetTag() == Tag(0xd8ff,0xe0ff) )
109  {
110  Fragment frag;
111  is.seekg( 8340, std::ios::cur );
112  char dummy[8340];
113  frag.SetByteValue( dummy, 8340 - Table.GetLength() - 16 );
114  Fragments.push_back( frag );
115  return is;
116  }
117  else
118  {
119  throw "Catch me if you can";
120  //assert(0);
121  }
122  }
123  return is;
124 }
125 
126 template <typename TSwap>
127 std::istream& ReadValue(std::istream &is)
128 {
129  const Tag seqDelItem(0xfffe,0xe0dd);
130  // not used for now...
131  Fragment frag;
132  try
133  {
134  while( frag.Read<TSwap>(is) && frag.GetTag() != seqDelItem )
135  {
136  gdcmDebugMacro( "Frag: " << frag );
137  Fragments.push_back( frag );
138  }
139  assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 );
140  }
141  catch(Exception &ex)
142  {
143  (void)ex;
144 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
145  // that's ok ! In all cases the whole file was read, because
146  // Fragment::Read only fail on eof() reached 1.
147  // SIEMENS-JPEG-CorruptFrag.dcm is more difficult to deal with, we have a
148  // partial fragment, read we decide to add it anyway to the stack of
149  // fragments (eof was reached so we need to clear error bit)
150  if( frag.GetTag() == Tag(0xfffe,0xe000) )
151  {
152  gdcmWarningMacro( "Pixel Data Fragment could be corrupted. Use file at own risk" );
153  Fragments.push_back( frag );
154  is.clear(); // clear the error bit
155  }
156  // 2. GENESIS_SIGNA-JPEG-CorruptFrag.dcm
157  else if ( frag.GetTag() == Tag(0xddff,0x00e0) )
158  {
159  assert( Fragments.size() == 1 );
160  const ByteValue *bv = Fragments[0].GetByteValue();
161  assert( (unsigned char)bv->GetPointer()[ bv->GetLength() - 1 ] == 0xfe );
162  // Yes this is an extra copy, this is a bug anyway, go fix YOUR code
163  Fragments[0].SetByteValue( bv->GetPointer(), bv->GetLength() - 1 );
164  gdcmWarningMacro( "JPEG Fragment length was declared with an extra byte"
165  " at the end: stripped !" );
166  is.clear(); // clear the error bit
167  }
168  // 3. LEICA/WSI
169  else if ( (frag.GetTag().GetGroup() == 0x00ff)
170  && ((frag.GetTag().GetElement() & 0x00ff) == 0xe0) )
171  {
172  // Looks like there is a mess with offset and odd byte array
173  // We are going first to backtrack one byte back, and then use a
174  // ReadBacktrack function which in turn may backtrack up to 10 bytes
175  // backward. This appears to be working on a set of DICOM/WSI files from
176  // LEICA
177  gdcmWarningMacro( "Trying to fix the even-but-odd value length bug #1" );
178  assert( Fragments.size() );
179  const size_t lastf = Fragments.size() - 1;
180  const ByteValue *bv = Fragments[ lastf ].GetByteValue();
181  const char *a = bv->GetPointer();
182  gdcmAssertAlwaysMacro( (unsigned char)a[ bv->GetLength() - 1 ] == 0xfe );
183  Fragments[ lastf ].SetByteValue( bv->GetPointer(), bv->GetLength() - 1 );
184  is.seekg( -9, std::ios::cur );
185  assert( is.good() );
186  while( frag.ReadBacktrack<TSwap>(is) && frag.GetTag() != seqDelItem )
187  {
188  gdcmDebugMacro( "Frag: " << frag );
189  Fragments.push_back( frag );
190  }
191  assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 );
192  }
193  // 4. LEICA/WSI (bis)
194  else if ( frag.GetTag().GetGroup() == 0xe000 )
195  {
196  // Looks like there is a mess with offset and odd byte array
197  // We are going first to backtrack one byte back, and then use a
198  // ReadBacktrack function which in turn may backtrack up to 10 bytes
199  // backward. This appears to be working on a set of DICOM/WSI files from
200  // LEICA
201  gdcmWarningMacro( "Trying to fix the even-but-odd value length bug #2" );
202  assert( Fragments.size() );
203  const size_t lastf = Fragments.size() - 1;
204  const ByteValue *bv = Fragments[ lastf ].GetByteValue();
205  const char *a = bv->GetPointer();
206  gdcmAssertAlwaysMacro( (unsigned char)a[ bv->GetLength() - 2 ] == 0xfe );
207  Fragments[ lastf ].SetByteValue( bv->GetPointer(), bv->GetLength() - 2 );
208  is.seekg( -10, std::ios::cur );
209  assert( is.good() );
210  while( frag.ReadBacktrack<TSwap>(is) && frag.GetTag() != seqDelItem )
211  {
212  gdcmDebugMacro( "Frag: " << frag );
213  Fragments.push_back( frag );
214  }
215  assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 );
216  }
217  // 5. LEICA/WSI (ter)
218  else if ( (frag.GetTag().GetGroup() & 0x00ff) == 0x00e0
219  && (frag.GetTag().GetElement() & 0xff00) == 0x0000 )
220  {
221  // Looks like there is a mess with offset and odd byte array
222  // We are going first to backtrack one byte back, and then use a
223  // ReadBacktrack function which in turn may backtrack up to 10 bytes
224  // backward. This appears to be working on a set of DICOM/WSI files from
225  // LEICA
226  gdcmWarningMacro( "Trying to fix the even-but-odd value length bug #3" );
227  assert( Fragments.size() );
228  const size_t lastf = Fragments.size() - 1;
229  const ByteValue *bv = Fragments[ lastf ].GetByteValue();
230  const char *a = bv->GetPointer();
231  gdcmAssertAlwaysMacro( (unsigned char)a[ bv->GetLength() - 3 ] == 0xfe );
232  Fragments[ lastf ].SetByteValue( bv->GetPointer(), bv->GetLength() - 3 );
233  is.seekg( -11, std::ios::cur );
234  assert( is.good() );
235  while( frag.ReadBacktrack<TSwap>(is) && frag.GetTag() != seqDelItem )
236  {
237  gdcmDebugMacro( "Frag: " << frag );
238  Fragments.push_back( frag );
239  }
240  assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 );
241  }
242  else
243  {
244  // 3. gdcm-JPEG-LossLess3a.dcm: easy case, an extra tag was found
245  // instead of terminator (eof is the next char)
246  gdcmWarningMacro( "Reading failed at Tag:" << frag.GetTag() << " Index #"
247  << Fragments.size() << " Offset " << is.tellg() << ". Use file at own risk."
248  << ex.what() );
249  }
250 #endif /* GDCM_SUPPORT_BROKEN_IMPLEMENTATION */
251  }
252 
253  return is;
254 }
255 
256 template <typename TSwap>
257 std::ostream const &Write(std::ostream &os) const
258 {
259  if( !Table.Write<TSwap>(os) )
260  {
261  assert(0 && "Should not happen");
262  return os;
263  }
264  for(ConstIterator it = Begin();it != End(); ++it)
265  {
266  it->Write<TSwap>(os);
267  }
268  // seq del item is not stored, write it !
269  const Tag seqDelItem(0xfffe,0xe0dd);
270  seqDelItem.Write<TSwap>(os);
271  VL zero = 0;
272  zero.Write<TSwap>(os);
273 
274  return os;
275 }
276 
277 //#if defined(SWIGPYTHON) || defined(SWIGCSHARP) || defined(SWIGJAVA)
278  // For now leave it there, this does not make sense in the C++ layer
279  // Create a new object
281  {
282  return new SequenceOfFragments();
283  }
284 //#endif
285 
286 protected:
287 public:
288  void Print(std::ostream &os) const {
289  os << "SQ L= " << SequenceLengthField << "\n";
290  os << "Table:" << Table << "\n";
291  for(ConstIterator it = Begin();it != End(); ++it)
292  {
293  os << " " << *it << "\n";
294  }
295  assert( SequenceLengthField.IsUndefined() );
296  {
297  const Tag seqDelItem(0xfffe,0xe0dd);
298  VL zero = 0;
299  os << seqDelItem;
300  os << "\t" << zero;
301  }
302  }
303  bool operator==(const Value &val) const
304  {
305  const SequenceOfFragments &sqf = dynamic_cast<const SequenceOfFragments&>(val);
306  return Table == sqf.Table &&
307  SequenceLengthField == sqf.SequenceLengthField &&
308  Fragments == sqf.Fragments;
309  }
310 
311 private:
313  VL SequenceLengthField;
315  FragmentVector Fragments;
316 };
317 
323 } // end namespace gdcm
324 
325 #endif //GDCMSEQUENCEOFFRAGMENTS_H

Generated on Mon Sep 9 2013 14:21:56 for GDCM by doxygen 1.8.4
SourceForge.net Logo