GDCM  2.2.6
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, bool readvalues = true)
87 {
88  assert( SequenceLengthField.IsUndefined() );
89  ReadPreValue<TSwap>(is);
90  return ReadValue<TSwap>(is, readvalues);
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  // throw "SIEMENS Icon thingy";
106  // Bug_Siemens_PrivateIconNoItem.dcm
107  // First thing first let's rewind
108  is.seekg(-4, std::ios::cur);
109  // FF D8 <=> Start of Image (SOI) marker
110  // FF E0 <=> APP0 Reserved for Application Use
111  if ( Table.GetTag() == Tag(0xd8ff,0xe0ff) )
112  {
113  Table = BasicOffsetTable(); // clear up stuff
114  //Table.SetByteValue( "", 0 );
115  Fragment frag;
116  if( FillFragmentWithJPEG( frag, is ) )
117  {
118  Fragments.push_back( frag );
119  }
120  return is;
121  }
122  else
123  {
124  throw "Catch me if you can";
125  //assert(0);
126  }
127  }
128  return is;
129 }
130 
131 template <typename TSwap>
132 std::istream& ReadValue(std::istream &is, bool /*readvalues*/)
133 {
134  const Tag seqDelItem(0xfffe,0xe0dd);
135  // not used for now...
136  Fragment frag;
137  try
138  {
139  while( frag.Read<TSwap>(is) && frag.GetTag() != seqDelItem )
140  {
141  //gdcmDebugMacro( "Frag: " << frag );
142  Fragments.push_back( frag );
143  }
144  assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 );
145  }
146  catch(Exception &ex)
147  {
148  (void)ex;
149 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
150  // that's ok ! In all cases the whole file was read, because
151  // Fragment::Read only fail on eof() reached 1.
152  // SIEMENS-JPEG-CorruptFrag.dcm is more difficult to deal with, we have a
153  // partial fragment, read we decide to add it anyway to the stack of
154  // fragments (eof was reached so we need to clear error bit)
155  if( frag.GetTag() == Tag(0xfffe,0xe000) )
156  {
157  gdcmWarningMacro( "Pixel Data Fragment could be corrupted. Use file at own risk" );
158  Fragments.push_back( frag );
159  is.clear(); // clear the error bit
160  }
161  // 2. GENESIS_SIGNA-JPEG-CorruptFrag.dcm
162  else if ( frag.GetTag() == Tag(0xddff,0x00e0) )
163  {
164  assert( Fragments.size() == 1 );
165  const ByteValue *bv = Fragments[0].GetByteValue();
166  assert( (unsigned char)bv->GetPointer()[ bv->GetLength() - 1 ] == 0xfe );
167  // Yes this is an extra copy, this is a bug anyway, go fix YOUR code
168  Fragments[0].SetByteValue( bv->GetPointer(), bv->GetLength() - 1 );
169  gdcmWarningMacro( "JPEG Fragment length was declared with an extra byte"
170  " at the end: stripped !" );
171  is.clear(); // clear the error bit
172  }
173  // 3. LEICA/WSI
174  else if ( (frag.GetTag().GetGroup() == 0x00ff)
175  && ((frag.GetTag().GetElement() & 0x00ff) == 0xe0) )
176  {
177  // Looks like there is a mess with offset and odd byte array
178  // We are going first to backtrack one byte back, and then use a
179  // ReadBacktrack function which in turn may backtrack up to 10 bytes
180  // backward. This appears to be working on a set of DICOM/WSI files from
181  // LEICA
182  gdcmWarningMacro( "Trying to fix the even-but-odd value length bug #1" );
183  assert( Fragments.size() );
184  const size_t lastf = Fragments.size() - 1;
185  const ByteValue *bv = Fragments[ lastf ].GetByteValue();
186  const char *a = bv->GetPointer();
187  gdcmAssertAlwaysMacro( (unsigned char)a[ bv->GetLength() - 1 ] == 0xfe );
188  Fragments[ lastf ].SetByteValue( bv->GetPointer(), bv->GetLength() - 1 );
189  is.seekg( -9, std::ios::cur );
190  assert( is.good() );
191  while( frag.ReadBacktrack<TSwap>(is) && frag.GetTag() != seqDelItem )
192  {
193  gdcmDebugMacro( "Frag: " << frag );
194  Fragments.push_back( frag );
195  }
196  assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 );
197  }
198  // 4. LEICA/WSI (bis)
199  else if ( frag.GetTag().GetGroup() == 0xe000 )
200  {
201  // Looks like there is a mess with offset and odd byte array
202  // We are going first to backtrack one byte back, and then use a
203  // ReadBacktrack function which in turn may backtrack up to 10 bytes
204  // backward. This appears to be working on a set of DICOM/WSI files from
205  // LEICA
206  gdcmWarningMacro( "Trying to fix the even-but-odd value length bug #2" );
207  assert( Fragments.size() );
208  const size_t lastf = Fragments.size() - 1;
209  const ByteValue *bv = Fragments[ lastf ].GetByteValue();
210  const char *a = bv->GetPointer();
211  gdcmAssertAlwaysMacro( (unsigned char)a[ bv->GetLength() - 2 ] == 0xfe );
212  Fragments[ lastf ].SetByteValue( bv->GetPointer(), bv->GetLength() - 2 );
213  is.seekg( -10, std::ios::cur );
214  assert( is.good() );
215  while( frag.ReadBacktrack<TSwap>(is) && frag.GetTag() != seqDelItem )
216  {
217  gdcmDebugMacro( "Frag: " << frag );
218  Fragments.push_back( frag );
219  }
220  assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 );
221  }
222  // 5. LEICA/WSI (ter)
223  else if ( (frag.GetTag().GetGroup() & 0x00ff) == 0x00e0
224  && (frag.GetTag().GetElement() & 0xff00) == 0x0000 )
225  {
226  // Looks like there is a mess with offset and odd byte array
227  // We are going first to backtrack one byte back, and then use a
228  // ReadBacktrack function which in turn may backtrack up to 10 bytes
229  // backward. This appears to be working on a set of DICOM/WSI files from
230  // LEICA
231  gdcmWarningMacro( "Trying to fix the even-but-odd value length bug #3" );
232  assert( Fragments.size() );
233  const size_t lastf = Fragments.size() - 1;
234  const ByteValue *bv = Fragments[ lastf ].GetByteValue();
235  const char *a = bv->GetPointer();
236  gdcmAssertAlwaysMacro( (unsigned char)a[ bv->GetLength() - 3 ] == 0xfe );
237  Fragments[ lastf ].SetByteValue( bv->GetPointer(), bv->GetLength() - 3 );
238  is.seekg( -11, std::ios::cur );
239  assert( is.good() );
240  while( frag.ReadBacktrack<TSwap>(is) && frag.GetTag() != seqDelItem )
241  {
242  gdcmDebugMacro( "Frag: " << frag );
243  Fragments.push_back( frag );
244  }
245  assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 );
246  }
247  else
248  {
249  // 3. gdcm-JPEG-LossLess3a.dcm: easy case, an extra tag was found
250  // instead of terminator (eof is the next char)
251  gdcmWarningMacro( "Reading failed at Tag:" << frag.GetTag() << " Index #"
252  << Fragments.size() << " Offset " << is.tellg() << ". Use file at own risk."
253  << ex.what() );
254  }
255 #endif /* GDCM_SUPPORT_BROKEN_IMPLEMENTATION */
256  }
257 
258  return is;
259 }
260 
261 template <typename TSwap>
262 std::ostream const &Write(std::ostream &os) const
263 {
264  if( !Table.Write<TSwap>(os) )
265  {
266  assert(0 && "Should not happen");
267  return os;
268  }
269  for(ConstIterator it = Begin();it != End(); ++it)
270  {
271  it->Write<TSwap>(os);
272  }
273  // seq del item is not stored, write it !
274  const Tag seqDelItem(0xfffe,0xe0dd);
275  seqDelItem.Write<TSwap>(os);
276  VL zero = 0;
277  zero.Write<TSwap>(os);
278 
279  return os;
280 }
281 
282 //#if defined(SWIGPYTHON) || defined(SWIGCSHARP) || defined(SWIGJAVA)
283  // For now leave it there, this does not make sense in the C++ layer
284  // Create a new object
286  {
287  return new SequenceOfFragments();
288  }
289 //#endif
290 
291 protected:
292 public:
293  void Print(std::ostream &os) const {
294  os << "SQ L= " << SequenceLengthField << "\n";
295  os << "Table:" << Table << "\n";
296  for(ConstIterator it = Begin();it != End(); ++it)
297  {
298  os << " " << *it << "\n";
299  }
300  assert( SequenceLengthField.IsUndefined() );
301  {
302  const Tag seqDelItem(0xfffe,0xe0dd);
303  VL zero = 0;
304  os << seqDelItem;
305  os << "\t" << zero;
306  }
307  }
308  bool operator==(const Value &val) const
309  {
310  const SequenceOfFragments &sqf = dynamic_cast<const SequenceOfFragments&>(val);
311  return Table == sqf.Table &&
312  SequenceLengthField == sqf.SequenceLengthField &&
313  Fragments == sqf.Fragments;
314  }
315 
316 private:
318  VL SequenceLengthField;
320  FragmentVector Fragments;
321 
322 private:
323  bool FillFragmentWithJPEG( Fragment & frag, std::istream & is );
324 };
325 
331 } // end namespace gdcm
332 
333 #endif //GDCMSEQUENCEOFFRAGMENTS_H
FragmentVector::size_type SizeType
Definition: gdcmSequenceOfFragments.h:36
std::istream & ReadBacktrack(std::istream &is)
Definition: gdcmFragment.h:120
std::vector< Fragment > FragmentVector
Definition: gdcmSequenceOfFragments.h:35
const BasicOffsetTable & GetTable() const
Definition: gdcmSequenceOfFragments.h:82
std::istream & ReadPreValue(std::istream &is)
Definition: gdcmSequenceOfFragments.h:94
Iterator End()
Definition: gdcmSequenceOfFragments.h:40
Class to represent the value of a Data Element.
Definition: gdcmValue.h:29
static SmartPointer< SequenceOfFragments > New()
Definition: gdcmSequenceOfFragments.h:285
VL GetLength() const
Definition: gdcmByteValue.h:76
void SetLength(VL length)
Sets the actual SQ length.
Definition: gdcmSequenceOfFragments.h:53
const VL & GetVL() const
Get VL.
Definition: gdcmDataElement.h:74
#define GDCM_EXPORT
Definition: gdcmWin32.h:34
#define gdcmWarningMacro(msg)
Warning.
Definition: gdcmTrace.h:141
Value Length.
Definition: gdcmVL.h:29
#define gdcmDebugMacro(msg)
Debug.
Definition: gdcmTrace.h:119
Class to represent a Fragment.
Definition: gdcmFragment.h:43
Iterator Begin()
Definition: gdcmSequenceOfFragments.h:39
uint16_t GetElement() const
Returns the &#39;Element number&#39; of the given Tag.
Definition: gdcmTag.h:57
Class to represent a Sequence Of Fragments.
Definition: gdcmSequenceOfFragments.h:31
#define gdcmAssertAlwaysMacro(arg)
AssertAlways.
Definition: gdcmTrace.h:223
std::istream & ReadValue(std::istream &is, bool)
Definition: gdcmSequenceOfFragments.h:132
std::istream & Read(std::istream &is, bool readvalues=true)
Definition: gdcmSequenceOfFragments.h:86
VL GetLength() const
Returns the SQ length, as read from disk.
Definition: gdcmSequenceOfFragments.h:48
BasicOffsetTable & GetTable()
Definition: gdcmSequenceOfFragments.h:83
const char * what() const
what implementation
Definition: gdcmException.h:76
const std::ostream & Write(std::ostream &os) const
Write a tag in binary rep.
Definition: gdcmTag.h:169
Class to represent binary value (array of bytes)
Definition: gdcmByteValue.h:33
const std::ostream & Write(std::ostream &os) const
Definition: gdcmVL.h:99
std::ostream const & Write(std::ostream &os) const
Definition: gdcmSequenceOfFragments.h:262
ConstIterator End() const
Definition: gdcmSequenceOfFragments.h:42
Class for Smart Pointer.
Definition: gdcmObject.h:26
SequenceOfFragments()
constructor (UndefinedLength by default)
Definition: gdcmSequenceOfFragments.h:45
std::istream & Read(std::istream &is)
Definition: gdcmFragment.h:59
const Tag & GetTag() const
Get Tag.
Definition: gdcmDataElement.h:67
Class to represent a BasicOffsetTable.
Definition: gdcmBasicOffsetTable.h:26
Table.
Definition: gdcmTable.h:28
const char * GetPointer() const
Definition: gdcmByteValue.h:138
bool operator==(const Value &val) const
Definition: gdcmSequenceOfFragments.h:308
Class to represent a DICOM Data Element (Attribute) Tag (Group, Element). Basically an uint32_t which...
Definition: gdcmTag.h:38
uint16_t GetGroup() const
Returns the &#39;Group number&#39; of the given Tag.
Definition: gdcmTag.h:55
FragmentVector::iterator Iterator
Definition: gdcmSequenceOfFragments.h:37
FragmentVector::const_iterator ConstIterator
Definition: gdcmSequenceOfFragments.h:38
void Print(std::ostream &os) const
Definition: gdcmSequenceOfFragments.h:293
Exception.
Definition: gdcmException.h:33
ConstIterator Begin() const
Definition: gdcmSequenceOfFragments.h:41

Generated on Sat Dec 21 2013 05:56:17 for GDCM by doxygen 1.8.5
SourceForge.net Logo