GDCM: gdcmFragment.h Source File

GDCM 3.2.10

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
43 class GDCM_EXPORT Fragment : public DataElement
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
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 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
93 SmartPointer<ByteValue> bv = new ByteValue;
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;
101 ParseException pe;
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 gdcm_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 gdcm_assert( TagField == itemStart || TagField == seqDelItem );
140 if( !ValueLengthField.Read<TSwap>(is) )
141 {
142 return is;
143 }
144
145 // Self
146 SmartPointer<ByteValue> bv = new ByteValue;
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;
154 ParseException pe;
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 gdcm_assert(0 && "Should not happen");
170 return os;
171 }
172 gdcm_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 //gdcm_assert( bv );
181 VL zero = 0;
182 if( !zero.Write<TSwap>(os) )
183 {
184 gdcm_assert(0 && "Should not happen");
185 return os;
186 }
187 }
188 else
189 {
190 gdcm_assert( ValueLengthField );
191 gdcm_assert( !ValueLengthField.IsUndefined() );
192 const VL actuallen = bv->ComputeLength();
193 gdcm_assert( actuallen == ValueLengthField || actuallen == ValueLengthField + 1 );
194 if( !actuallen.Write<TSwap>(os) )
195 {
196 gdcm_assert(0 && "Should not happen");
197 return os;
198 }
199 }
200 // Value
201 if( ValueLengthField && bv )
202 {
203 // Self
204 gdcm_assert( bv );
205 gdcm_assert( bv->GetLength() == ValueLengthField );
206 if( !bv->Write<TSwap>(os) )
207 {
208 gdcm_assert(0 && "Should not happen");
209 return os;
210 }
211 }
212 return os;
213 }
214};
215//-----------------------------------------------------------------------------
216 inline 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
gdcm::ByteValue
Class to represent binary value (array of bytes).
Definition gdcmByteValue.h:36
gdcm::ByteValue::Write
std::ostream const & Write(std::ostream &os) const
Definition gdcmByteValue.h:171
gdcm::ByteValue::ComputeLength
VL ComputeLength() const
Definition gdcmByteValue.h:83
gdcm::ByteValue::GetLength
VL GetLength() const override
Definition gdcmByteValue.h:81
gdcm::DataElement::ValueField
ValuePtr ValueField
Definition gdcmDataElement.h:250
gdcm::DataElement::GetByteValue
const ByteValue * GetByteValue() const
Definition gdcmDataElement.h:133
gdcm::DataElement::TagField
Tag TagField
Definition gdcmDataElement.h:243
gdcm::DataElement::IsEmpty
bool IsEmpty() const
Check if Data Element is empty.
Definition gdcmDataElement.h:106
gdcm::DataElement::ValueLengthField
VL ValueLengthField
Definition gdcmDataElement.h:245
gdcm::DataElement::DataElement
DataElement(const Tag &t=Tag(0), const VL &vl=0, const VR &vr=VR::INVALID)
Definition gdcmDataElement.h:61
gdcm::Exception
Exception.
Definition gdcmException.h:46
gdcm::Fragment
Class to represent a Fragment.
Definition gdcmFragment.h:44
gdcm::Fragment::operator<<
friend std::ostream & operator<<(std::ostream &os, const Fragment &val)
Definition gdcmFragment.h:216
gdcm::Fragment::ReadPreValue
std::istream & ReadPreValue(std::istream &is)
Definition gdcmFragment.h:63
gdcm::Fragment::Fragment
Fragment()
Definition gdcmFragment.h:48
gdcm::Fragment::Write
std::ostream & Write(std::ostream &os) const
Definition gdcmFragment.h:164
gdcm::Fragment::GetLength
VL GetLength() const
gdcm::Fragment::ReadBacktrack
std::istream & ReadBacktrack(std::istream &is)
Definition gdcmFragment.h:110
gdcm::Fragment::ComputeLength
VL ComputeLength() const
gdcm::Fragment::Read
std::istream & Read(std::istream &is)
Definition gdcmFragment.h:56
gdcm::Fragment::ReadValue
std::istream & ReadValue(std::istream &is)
Definition gdcmFragment.h:90
gdcm::ParseException
ParseException Standard exception handling object.
Definition gdcmParseException.h:37
gdcm::ParseException::SetLastElement
void SetLastElement(const DataElement &de)
Definition gdcmParseException.h:71
gdcm::SmartPointer
Class for Smart Pointer.
Definition gdcmSmartPointer.h:40
gdcm::Tag
Class to represent a DICOM Data Element (Attribute) Tag (Group, Element).
Definition gdcmTag.h:39
gdcm::VL
Value Length.
Definition gdcmVL.h:30
gdcm::VL::Write
const std::ostream & Write(std::ostream &os) const
Definition gdcmVL.h:99
gdcmByteValue.h
gdcmDataElement.h
gdcm_assert
#define gdcm_assert(cond)
Definition gdcmException.h:104
gdcmParseException.h
gdcmSmartPointer.h
gdcmWarningMacro
#define gdcmWarningMacro(msg)
Warning.
Definition gdcmTrace.h:142
gdcmErrorMacro
#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
GDCM_EXPORT
#define GDCM_EXPORT
Definition gdcmWin32.h:34
gdcm::operator<<
std::ostream & operator<<(std::ostream &os, const Directory &d)
Definition gdcmDirectory.h:88