GDCM  2.2.1
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 
86 template <typename TSwap>
87 std::istream& Read(std::istream &is)
88 {
89  assert( SequenceLengthField.IsUndefined() );
90  //if( SequenceLengthField.IsUndefined() )
91  {
92  const Tag seqDelItem(0xfffe,0xe0dd);
93  // First item is the basic offset table:
94  try
95  {
96  Table.Read<TSwap>(is);
97  gdcmDebugMacro( "Table: " << Table );
98  }
99  catch(...)
100  {
101  // Bug_Siemens_PrivateIconNoItem.dcm
102  // First thing first let's rewind
103  is.seekg(-4, std::ios::cur);
104  if ( Table.GetTag() == Tag(0xd8ff,0xe0ff) )
105  {
106  Fragment frag;
107  is.seekg( 8340, std::ios::cur );
108  char dummy[8340];
109  frag.SetByteValue( dummy, 8340 - Table.GetLength() - 16 );
110  Fragments.push_back( frag );
111  return is;
112  }
113  else
114  {
115  throw "Catch me if you can";
116  //assert(0);
117  }
118  }
119  // not used for now...
120  Fragment frag;
121  try
122  {
123  while( frag.Read<TSwap>(is) && frag.GetTag() != seqDelItem )
124  {
125  gdcmDebugMacro( "Frag: " << frag );
126  Fragments.push_back( frag );
127  }
128  assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 );
129  }
130  catch(Exception &ex)
131  {
132  (void)ex;
133 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
134  // that's ok ! In all cases the whole file was read, because
135  // Fragment::Read only fail on eof() reached 1.
136  // SIEMENS-JPEG-CorruptFrag.dcm is more difficult to deal with, we have a
137  // partial fragment, read we decide to add it anyway to the stack of
138  // fragments (eof was reached so we need to clear error bit)
139  if( frag.GetTag() == Tag(0xfffe,0xe000) )
140  {
141  gdcmWarningMacro( "Pixel Data Fragment could be corrupted. Use file at own risk" );
142  Fragments.push_back( frag );
143  is.clear(); // clear the error bit
144  }
145  // 2. GENESIS_SIGNA-JPEG-CorruptFrag.dcm
146  else if ( frag.GetTag() == Tag(0xddff,0x00e0) )
147  {
148  assert( Fragments.size() == 1 );
149  const ByteValue *bv = Fragments[0].GetByteValue();
150  assert( (unsigned char)bv->GetPointer()[ bv->GetLength() - 1 ] == 0xfe );
151  // Yes this is an extra copy, this is a bug anyway, go fix YOUR code
152  Fragments[0].SetByteValue( bv->GetPointer(), bv->GetLength() - 1 );
153  gdcmWarningMacro( "JPEG Fragment length was declared with an extra byte"
154  " at the end: stripped !" );
155  is.clear(); // clear the error bit
156  }
157  else
158  {
159  // 3. gdcm-JPEG-LossLess3a.dcm: easy case, an extra tag was found
160  // instead of terminator (eof is the next char)
161  gdcmWarningMacro( "Reading failed at Tag:" << frag.GetTag() <<
162  ". Use file at own risk." << ex.what() );
163  }
164 #endif /* GDCM_SUPPORT_BROKEN_IMPLEMENTATION */
165  }
166  }
167 
168  return is;
169 }
170 
171 template <typename TSwap>
172 std::ostream const &Write(std::ostream &os) const
173 {
174  if( !Table.Write<TSwap>(os) )
175  {
176  assert(0 && "Should not happen");
177  return os;
178  }
179  for(ConstIterator it = Begin();it != End(); ++it)
180  {
181  it->Write<TSwap>(os);
182  }
183  // seq del item is not stored, write it !
184  const Tag seqDelItem(0xfffe,0xe0dd);
185  seqDelItem.Write<TSwap>(os);
186  VL zero = 0;
187  zero.Write<TSwap>(os);
188 
189  return os;
190 }
191 
192 //#if defined(SWIGPYTHON) || defined(SWIGCSHARP) || defined(SWIGJAVA)
193  // For now leave it there, this does not make sense in the C++ layer
194  // Create a new object
196  {
197  return new SequenceOfFragments();
198  }
199 //#endif
200 
201 protected:
202 public:
203  void Print(std::ostream &os) const {
204  os << "SQ L= " << SequenceLengthField << "\n";
205  os << "Table:" << Table << "\n";
206  for(ConstIterator it = Begin();it != End(); ++it)
207  {
208  os << " " << *it << "\n";
209  }
210  assert( SequenceLengthField.IsUndefined() );
211  {
212  const Tag seqDelItem(0xfffe,0xe0dd);
213  VL zero = 0;
214  os << seqDelItem;
215  os << "\t" << zero;
216  }
217  }
218  bool operator==(const Value &val) const
219  {
220  const SequenceOfFragments &sqf = dynamic_cast<const SequenceOfFragments&>(val);
221  return Table == sqf.Table &&
222  SequenceLengthField == sqf.SequenceLengthField &&
223  Fragments == sqf.Fragments;
224  }
225 
226 private:
228  VL SequenceLengthField;
230  FragmentVector Fragments;
231 };
232 
238 } // end namespace gdcm
239 
240 #endif //GDCMSEQUENCEOFFRAGMENTS_H

Generated on Wed Apr 10 2013 04:43:10 for GDCM by doxygen 1.8.2
SourceForge.net Logo