GDCM  2.2.6
gdcmFragment.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 GDCMFRAGMENT_H
15 #define GDCMFRAGMENT_H
16 
17 #include "gdcmDataElement.h"
18 #include "gdcmByteValue.h"
19 #include "gdcmSmartPointer.h"
20 #include "gdcmParseException.h"
21 
22 namespace gdcm
23 {
24 
25 // Implementation detail:
26 // I think Fragment should be a protected subclass of DataElement:
27 // looking somewhat like this:
28 /*
29 class GDCM_EXPORT Fragment : protected DataElement
30 {
31 public:
32  using DataElement::GetTag;
33  using DataElement::GetVL;
34  using DataElement::SetByteValue;
35  using DataElement::GetByteValue;
36  using DataElement::GetValue;
37 */
38 // Instead I am only hiding the SetTag member...
39 
44 {
45 //protected:
46 // void SetTag(const Tag &t);
47 public:
48  Fragment() : DataElement(Tag(0xfffe, 0xe000), 0) {}
49  friend std::ostream &operator<<(std::ostream &os, const Fragment &val);
50 
51  VL GetLength() const {
52  assert( !ValueLengthField.IsUndefined() );
53  assert( !ValueField || ValueField->GetLength() == ValueLengthField );
54  return TagField.GetLength() + ValueLengthField.GetLength()
55  + ValueLengthField;
56  }
57 
58  template <typename TSwap>
59  std::istream &Read(std::istream &is)
60  {
61  ReadPreValue<TSwap>(is);
62  return ReadValue<TSwap>(is);
63  }
64 
65  template <typename TSwap>
66  std::istream &ReadPreValue(std::istream &is)
67  {
68  const Tag itemStart(0xfffe, 0xe000);
69  const Tag seqDelItem(0xfffe,0xe0dd);
70 
71  TagField.Read<TSwap>(is);
72  if( !is )
73  {
74  // BogusItemStartItemEnd.dcm
75  throw Exception( "Problem #1" );
76  return is;
77  }
78  if( !ValueLengthField.Read<TSwap>(is) )
79  {
80  // GENESIS_SIGNA-JPEG-CorruptFrag.dcm
81  // JPEG fragment is declared to have 61902, but infact really is only 61901
82  // so we end up reading 0xddff,0x00e0, and VL = 0x0 (1 byte)
83  throw Exception( "Problem #2" );
84  return is;
85  }
86 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
87  if( TagField != itemStart && TagField != seqDelItem )
88  {
89  throw Exception( "Problem #3" );
90  }
91 #endif
92  return is;
93  }
94 
95  template <typename TSwap>
96  std::istream &ReadValue(std::istream &is)
97  {
98  // Superclass
99  const Tag itemStart(0xfffe, 0xe000);
100  const Tag seqDelItem(0xfffe,0xe0dd);
101  // Self
103  bv->SetLength(ValueLengthField);
104  if( !bv->Read<TSwap>(is) )
105  {
106  // Fragment is incomplete, but is a itemStart, let's try to push it anyway...
107  gdcmWarningMacro( "Fragment could not be read" );
108  //bv->SetLength(is.gcount());
109  ValueField = bv;
110  ParseException pe;
111  pe.SetLastElement( *this );
112  throw pe;
113  return is;
114  }
115  ValueField = bv;
116  return is;
117  }
118 
119  template <typename TSwap>
120  std::istream &ReadBacktrack(std::istream &is)
121  {
122  const Tag itemStart(0xfffe, 0xe000);
123  const Tag seqDelItem(0xfffe,0xe0dd);
124 
125  bool cont = true;
126  const std::streampos start = is.tellg();
127  const int max = 10;
128  int offset = 0;
129  while( cont )
130  {
131  TagField.Read<TSwap>(is);
132  assert( is );
133  if( TagField != itemStart && TagField != seqDelItem )
134  {
135  ++offset;
136  is.seekg( (std::streampos)((size_t)start - offset) );
137  gdcmWarningMacro( "Fuzzy Search, backtrack: " << (start - is.tellg()) << " Offset: " << is.tellg() );
138  if( offset > max )
139  {
140  gdcmErrorMacro( "Giving up" );
141  throw "Impossible to backtrack";
142  return is;
143  }
144  }
145  else
146  {
147  cont = false;
148  }
149  }
150  assert( TagField == itemStart || TagField == seqDelItem );
151  if( !ValueLengthField.Read<TSwap>(is) )
152  {
153  return is;
154  }
155 
156  // Self
158  bv->SetLength(ValueLengthField);
159  if( !bv->Read<TSwap>(is) )
160  {
161  // Fragment is incomplete, but is a itemStart, let's try to push it anyway...
162  gdcmWarningMacro( "Fragment could not be read" );
163  //bv->SetLength(is.gcount());
164  ValueField = bv;
165  ParseException pe;
166  pe.SetLastElement( *this );
167  throw pe;
168  return is;
169  }
170  ValueField = bv;
171  return is;
172  }
173 
174 
175  template <typename TSwap>
176  std::ostream &Write(std::ostream &os) const {
177  const Tag itemStart(0xfffe, 0xe000);
178  const Tag seqDelItem(0xfffe,0xe0dd);
179  if( !TagField.Write<TSwap>(os) )
180  {
181  assert(0 && "Should not happen");
182  return os;
183  }
184  assert( TagField == itemStart
185  || TagField == seqDelItem );
186  const ByteValue *bv = GetByteValue();
187  // VL
188  // The following piece of code is hard to read in order to support such broken file as:
189  // CompressedLossy.dcm
190  if( IsEmpty() )
191  {
192  //assert( bv );
193  VL zero = 0;
194  if( !zero.Write<TSwap>(os) )
195  {
196  assert(0 && "Should not happen");
197  return os;
198  }
199  }
200  else
201  {
202  assert( ValueLengthField );
203  if( !ValueLengthField.Write<TSwap>(os) )
204  {
205  assert(0 && "Should not happen");
206  return os;
207  }
208  }
209  // Value
210  if( ValueLengthField && bv )
211  {
212  // Self
213  assert( bv );
214  assert( bv->GetLength() == ValueLengthField );
215  if( !bv->Write<TSwap>(os) )
216  {
217  assert(0 && "Should not happen");
218  return os;
219  }
220  }
221  return os;
222  }
223 };
224 //-----------------------------------------------------------------------------
225 inline std::ostream &operator<<(std::ostream &os, const Fragment &val)
226 {
227  os << "Tag: " << val.TagField;
228  os << "\tVL: " << val.ValueLengthField;
229  if( val.ValueField )
230  {
231  os << "\t" << *(val.ValueField);
232  }
233 
234  return os;
235 }
236 
237 } // end namespace gdcm
238 
239 #endif //GDCMFRAGMENT_H
VL GetLength() const
Definition: gdcmVL.h:68
std::istream & ReadBacktrack(std::istream &is)
Definition: gdcmFragment.h:120
VL GetLength() const
Definition: gdcmByteValue.h:76
std::ostream const & Write(std::ostream &os) const
Definition: gdcmByteValue.h:186
#define GDCM_EXPORT
Definition: gdcmWin32.h:34
#define gdcmWarningMacro(msg)
Warning.
Definition: gdcmTrace.h:141
void SetLastElement(DataElement &de)
Definition: gdcmParseException.h:60
Value Length.
Definition: gdcmVL.h:29
Class to represent a Fragment.
Definition: gdcmFragment.h:43
ParseException Standard exception handling object.
Definition: gdcmParseException.h:26
std::ostream & operator<<(std::ostream &os, const Directory &d)
Definition: gdcmDirectory.h:92
VL ValueLengthField
Definition: gdcmDataElement.h:259
Class to represent a Data Element either Implicit or Explicit.
Definition: gdcmDataElement.h:58
Class to represent binary value (array of bytes)
Definition: gdcmByteValue.h:33
std::istream & ReadPreValue(std::istream &is)
Definition: gdcmFragment.h:66
const std::ostream & Write(std::ostream &os) const
Definition: gdcmVL.h:99
Class for Smart Pointer.
Definition: gdcmObject.h:26
VL GetLength() const
Definition: gdcmFragment.h:51
std::istream & Read(std::istream &is)
Definition: gdcmFragment.h:59
std::istream & ReadValue(std::istream &is)
Definition: gdcmFragment.h:96
ValuePtr ValueField
Definition: gdcmDataElement.h:264
#define gdcmErrorMacro(msg)
Error this is pretty bad, more than just warning It could mean lost of data, something not handle...
Definition: gdcmTrace.h:163
Class to represent a DICOM Data Element (Attribute) Tag (Group, Element). Basically an uint32_t which...
Definition: gdcmTag.h:38
Tag TagField
Definition: gdcmDataElement.h:257
std::ostream & Write(std::ostream &os) const
Definition: gdcmFragment.h:176
Exception.
Definition: gdcmException.h:33
Fragment()
Definition: gdcmFragment.h:48

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