GDCM  2.2.3
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" );
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  assert( (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  else
194  {
195  // 3. gdcm-JPEG-LossLess3a.dcm: easy case, an extra tag was found
196  // instead of terminator (eof is the next char)
197  gdcmWarningMacro( "Reading failed at Tag:" << frag.GetTag() << " Index #"
198  << Fragments.size() << " Offset " << is.tellg() << ". Use file at own risk."
199  << ex.what() );
200  }
201 #endif /* GDCM_SUPPORT_BROKEN_IMPLEMENTATION */
202  }
203 
204  return is;
205 }
206 
207 template <typename TSwap>
208 std::ostream const &Write(std::ostream &os) const
209 {
210  if( !Table.Write<TSwap>(os) )
211  {
212  assert(0 && "Should not happen");
213  return os;
214  }
215  for(ConstIterator it = Begin();it != End(); ++it)
216  {
217  it->Write<TSwap>(os);
218  }
219  // seq del item is not stored, write it !
220  const Tag seqDelItem(0xfffe,0xe0dd);
221  seqDelItem.Write<TSwap>(os);
222  VL zero = 0;
223  zero.Write<TSwap>(os);
224 
225  return os;
226 }
227 
228 //#if defined(SWIGPYTHON) || defined(SWIGCSHARP) || defined(SWIGJAVA)
229  // For now leave it there, this does not make sense in the C++ layer
230  // Create a new object
232  {
233  return new SequenceOfFragments();
234  }
235 //#endif
236 
237 protected:
238 public:
239  void Print(std::ostream &os) const {
240  os << "SQ L= " << SequenceLengthField << "\n";
241  os << "Table:" << Table << "\n";
242  for(ConstIterator it = Begin();it != End(); ++it)
243  {
244  os << " " << *it << "\n";
245  }
246  assert( SequenceLengthField.IsUndefined() );
247  {
248  const Tag seqDelItem(0xfffe,0xe0dd);
249  VL zero = 0;
250  os << seqDelItem;
251  os << "\t" << zero;
252  }
253  }
254  bool operator==(const Value &val) const
255  {
256  const SequenceOfFragments &sqf = dynamic_cast<const SequenceOfFragments&>(val);
257  return Table == sqf.Table &&
258  SequenceLengthField == sqf.SequenceLengthField &&
259  Fragments == sqf.Fragments;
260  }
261 
262 private:
264  VL SequenceLengthField;
266  FragmentVector Fragments;
267 };
268 
274 } // end namespace gdcm
275 
276 #endif //GDCMSEQUENCEOFFRAGMENTS_H

Generated on Tue Jul 30 2013 22:32:01 for GDCM by doxygen 1.8.4
SourceForge.net Logo