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