GDCM  2.4.5
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_ns
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 
53  VL ComputeLength() const;
54 
55  template <typename TSwap>
56  std::istream &Read(std::istream &is)
57  {
58  ReadPreValue<TSwap>(is);
59  return ReadValue<TSwap>(is);
60  }
61 
62  template <typename TSwap>
63  std::istream &ReadPreValue(std::istream &is)
64  {
65  const Tag itemStart(0xfffe, 0xe000);
66  const Tag seqDelItem(0xfffe,0xe0dd);
67 
68  TagField.Read<TSwap>(is);
69  if( !is )
70  {
71  // BogusItemStartItemEnd.dcm
72  throw Exception( "Problem #1" );
73  return is;
74  }
75  if( !ValueLengthField.Read<TSwap>(is) )
76  {
77  // GENESIS_SIGNA-JPEG-CorruptFrag.dcm
78  // JPEG fragment is declared to have 61902, but infact really is only 61901
79  // so we end up reading 0xddff,0x00e0, and VL = 0x0 (1 byte)
80  throw Exception( "Problem #2" );
81  return is;
82  }
83 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
84  if( TagField != itemStart && TagField != seqDelItem )
85  {
86  throw Exception( "Problem #3" );
87  }
88 #endif
89  return is;
90  }
91 
92  template <typename TSwap>
93  std::istream &ReadValue(std::istream &is)
94  {
95  // Superclass
96  const Tag itemStart(0xfffe, 0xe000);
97  const Tag seqDelItem(0xfffe,0xe0dd);
98  // Self
100  bv->SetLength(ValueLengthField);
101  if( !bv->Read<TSwap>(is) )
102  {
103  // Fragment is incomplete, but is a itemStart, let's try to push it anyway...
104  gdcmWarningMacro( "Fragment could not be read" );
105  //bv->SetLength(is.gcount());
106  ValueField = bv;
107  ParseException pe;
108  pe.SetLastElement( *this );
109  throw pe;
110  return is;
111  }
112  ValueField = bv;
113  return is;
114  }
115 
116  template <typename TSwap>
117  std::istream &ReadBacktrack(std::istream &is)
118  {
119  const Tag itemStart(0xfffe, 0xe000);
120  const Tag seqDelItem(0xfffe,0xe0dd);
121 
122  bool cont = true;
123  const std::streampos start = is.tellg();
124  const int max = 10;
125  int offset = 0;
126  while( cont )
127  {
128  TagField.Read<TSwap>(is);
129  assert( is );
130  if( TagField != itemStart && TagField != seqDelItem )
131  {
132  ++offset;
133  is.seekg( (std::streampos)((size_t)start - offset) );
134  gdcmWarningMacro( "Fuzzy Search, backtrack: " << (start - is.tellg()) << " Offset: " << is.tellg() );
135  if( offset > max )
136  {
137  gdcmErrorMacro( "Giving up" );
138  throw "Impossible to backtrack";
139  return is;
140  }
141  }
142  else
143  {
144  cont = false;
145  }
146  }
147  assert( TagField == itemStart || TagField == seqDelItem );
148  if( !ValueLengthField.Read<TSwap>(is) )
149  {
150  return is;
151  }
152 
153  // Self
155  bv->SetLength(ValueLengthField);
156  if( !bv->Read<TSwap>(is) )
157  {
158  // Fragment is incomplete, but is a itemStart, let's try to push it anyway...
159  gdcmWarningMacro( "Fragment could not be read" );
160  //bv->SetLength(is.gcount());
161  ValueField = bv;
162  ParseException pe;
163  pe.SetLastElement( *this );
164  throw pe;
165  return is;
166  }
167  ValueField = bv;
168  return is;
169  }
170 
171 
172  template <typename TSwap>
173  std::ostream &Write(std::ostream &os) const {
174  const Tag itemStart(0xfffe, 0xe000);
175  const Tag seqDelItem(0xfffe,0xe0dd);
176  if( !TagField.Write<TSwap>(os) )
177  {
178  assert(0 && "Should not happen");
179  return os;
180  }
181  assert( TagField == itemStart
182  || TagField == seqDelItem );
183  const ByteValue *bv = GetByteValue();
184  // VL
185  // The following piece of code is hard to read in order to support such broken file as:
186  // CompressedLossy.dcm
187  if( IsEmpty() )
188  {
189  //assert( bv );
190  VL zero = 0;
191  if( !zero.Write<TSwap>(os) )
192  {
193  assert(0 && "Should not happen");
194  return os;
195  }
196  }
197  else
198  {
199  assert( ValueLengthField );
200  assert( !ValueLengthField.IsUndefined() );
201  const VL actuallen = bv->ComputeLength();
202  assert( actuallen == ValueLengthField || actuallen == ValueLengthField + 1 );
203  if( !actuallen.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_ns
238 
239 #endif //GDCMFRAGMENT_H
std::istream & ReadBacktrack(std::istream &is)
Definition: gdcmFragment.h:117
std::ostream & operator<<(std::ostream &os, const Fragment &val)
Definition: gdcmFragment.h:225
VL GetLength() const
Definition: gdcmByteValue.h:78
std::ostream const & Write(std::ostream &os) const
Definition: gdcmByteValue.h:159
#define GDCM_EXPORT
Definition: gdcmWin32.h:34
#define gdcmWarningMacro(msg)
Warning.
Definition: gdcmTrace.h:141
void SetLastElement(DataElement &de)
Definition: gdcmParseException.h:70
Value Length.
Definition: gdcmVL.h:29
Class to represent a Fragment.
Definition: gdcmFragment.h:43
ParseException Standard exception handling object.
Definition: gdcmParseException.h:36
VL ValueLengthField
Definition: gdcmDataElement.h:248
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:35
std::istream & ReadPreValue(std::istream &is)
Definition: gdcmFragment.h:63
VL ComputeLength() const
Definition: gdcmByteValue.h:80
const std::ostream & Write(std::ostream &os) const
Definition: gdcmVL.h:99
Class for Smart Pointer.
Definition: gdcmObject.h:26
std::istream & Read(std::istream &is)
Definition: gdcmFragment.h:56
std::istream & ReadValue(std::istream &is)
Definition: gdcmFragment.h:93
ValuePtr ValueField
Definition: gdcmDataElement.h:253
#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:246
std::ostream & Write(std::ostream &os) const
Definition: gdcmFragment.h:173
Exception.
Definition: gdcmException.h:43
Fragment()
Definition: gdcmFragment.h:48

Generated on Fri Sep 25 2015 17:58:23 for GDCM by doxygen 1.8.9.1
SourceForge.net Logo