GDCM 3.0.24
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"
21
22namespace gdcm_ns
23{
24
25 // FIXME gdcmSequenceOfItems and gdcmSequenceOfFragments
26 // should be rethink (duplicate code)
32{
33public:
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 override {
49 return SequenceLengthField;
50 }
51
53 void SetLength(VL length) override {
54 SequenceLengthField = length;
55 }
56
58 void Clear() override;
59
61 void AddFragment(Fragment const &item);
62
63 // Compute the length of all fragments (and fragments 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
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
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
85template <typename TSwap>
86std::istream& Read(std::istream &is, bool readvalues = true)
87{
88 assert( SequenceLengthField.IsUndefined() );
89 ReadPreValue<TSwap>(is);
90 return ReadValue<TSwap>(is, readvalues);
91}
92
93template <typename TSwap>
94std::istream& ReadPreValue(std::istream &is)
95{
96 // First item is the basic offset table:
97#if 0
98 try
99 {
100 Table.Read<TSwap>(is);
101 gdcmDebugMacro( "Table: " << Table );
102 }
103 catch(...)
104 {
105 // throw "SIEMENS Icon thingy";
106 // Bug_Siemens_PrivateIconNoItem.dcm
107 // First thing first let's rewind
108 is.seekg(-4, std::ios::cur);
109 // FF D8 <=> Start of Image (SOI) marker
110 // FF E0 <=> APP0 Reserved for Application Use
111 if ( Table.GetTag() == Tag(0xd8ff,0xe0ff) )
112 {
113 Table = BasicOffsetTable(); // clear up stuff
114 //Table.SetByteValue( "", 0 );
115 Fragment frag;
116 if( FillFragmentWithJPEG( frag, is ) )
117 {
118 Fragments.push_back( frag );
119 }
120 return is;
121 }
122 else
123 {
124 throw "Catch me if you can";
125 //assert(0);
126 }
127 }
128#else
129 Table.Read<TSwap>(is);
130 gdcmDebugMacro( "Table: " << Table );
131#endif
132 return is;
133}
134
135template <typename TSwap>
136std::istream& ReadValue(std::istream &is, bool /*readvalues*/)
137{
138 const Tag seqDelItem(0xfffe,0xe0dd);
139 // not used for now...
140 Fragment frag;
141 try
142 {
143 while( frag.Read<TSwap>(is) && frag.GetTag() != seqDelItem )
144 {
145 //gdcmDebugMacro( "Frag: " << frag );
146 Fragments.push_back( frag );
147 }
148 assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 );
149 }
150 catch(Exception &ex)
151 {
152 (void)ex;
153#ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
154 // that's ok ! In all cases the whole file was read, because
155 // Fragment::Read only fail on eof() reached 1.
156 // SIEMENS-JPEG-CorruptFrag.dcm is more difficult to deal with, we have a
157 // partial fragment, read we decide to add it anyway to the stack of
158 // fragments (eof was reached so we need to clear error bit)
159 if( frag.GetTag() == Tag(0xfffe,0xe000) )
160 {
161 gdcmWarningMacro( "Pixel Data Fragment could be corrupted. Use file at own risk" );
162 Fragments.push_back( frag );
163 is.clear(); // clear the error bit
164 }
165 // 2. GENESIS_SIGNA-JPEG-CorruptFrag.dcm
166 else if ( frag.GetTag() == Tag(0xddff,0x00e0) )
167 {
168 assert( Fragments.size() == 1 );
169 const ByteValue *bv = Fragments[0].GetByteValue();
170 assert( (unsigned char)bv->GetPointer()[ bv->GetLength() - 1 ] == 0xfe );
171 // Yes this is an extra copy, this is a bug anyway, go fix YOUR code
172 Fragments[0].SetByteValue( bv->GetPointer(), bv->GetLength() - 1 );
173 gdcmWarningMacro( "JPEG Fragment length was declared with an extra byte"
174 " at the end: stripped !" );
175 is.clear(); // clear the error bit
176 }
177 // 3. LEICA/WSI
178 else if ( (frag.GetTag().GetGroup() == 0x00ff)
179 && ((frag.GetTag().GetElement() & 0x00ff) == 0xe0) )
180 {
181 // Looks like there is a mess with offset and odd byte array
182 // We are going first to backtrack one byte back, and then use a
183 // ReadBacktrack function which in turn may backtrack up to 10 bytes
184 // backward. This appears to be working on a set of DICOM/WSI files from
185 // LEICA
186 gdcmWarningMacro( "Trying to fix the even-but-odd value length bug #1" );
187 assert( Fragments.size() );
188 const size_t lastf = Fragments.size() - 1;
189 const ByteValue *bv = Fragments[ lastf ].GetByteValue();
190 const char *a = bv->GetPointer();
191 gdcmAssertAlwaysMacro( (unsigned char)a[ bv->GetLength() - 1 ] == 0xfe );
192 Fragments[ lastf ].SetByteValue( bv->GetPointer(), bv->GetLength() - 1 );
193 is.seekg( -9, std::ios::cur );
194 assert( is.good() );
195 while( frag.ReadBacktrack<TSwap>(is) && frag.GetTag() != seqDelItem )
196 {
197 gdcmDebugMacro( "Frag: " << frag );
198 Fragments.push_back( frag );
199 }
200 assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 );
201 }
202 // 4. LEICA/WSI (bis)
203 else if ( frag.GetTag().GetGroup() == 0xe000 )
204 {
205 // Looks like there is a mess with offset and odd byte array
206 // We are going first to backtrack one byte back, and then use a
207 // ReadBacktrack function which in turn may backtrack up to 10 bytes
208 // backward. This appears to be working on a set of DICOM/WSI files from
209 // LEICA
210 gdcmWarningMacro( "Trying to fix the even-but-odd value length bug #2" );
211 assert( Fragments.size() );
212 const size_t lastf = Fragments.size() - 1;
213 const ByteValue *bv = Fragments[ lastf ].GetByteValue();
214 const char *a = bv->GetPointer();
215 gdcmAssertAlwaysMacro( (unsigned char)a[ bv->GetLength() - 2 ] == 0xfe );
216 Fragments[ lastf ].SetByteValue( bv->GetPointer(), bv->GetLength() - 2 );
217 is.seekg( -10, std::ios::cur );
218 assert( is.good() );
219 while( frag.ReadBacktrack<TSwap>(is) && frag.GetTag() != seqDelItem )
220 {
221 gdcmDebugMacro( "Frag: " << frag );
222 Fragments.push_back( frag );
223 }
224 assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 );
225 }
226 // 5. LEICA/WSI (ter)
227 else if ( (frag.GetTag().GetGroup() & 0x00ff) == 0x00e0
228 && (frag.GetTag().GetElement() & 0xff00) == 0x0000 )
229 {
230 // Looks like there is a mess with offset and odd byte array
231 // We are going first to backtrack one byte back, and then use a
232 // ReadBacktrack function which in turn may backtrack up to 10 bytes
233 // backward. This appears to be working on a set of DICOM/WSI files from
234 // LEICA
235 gdcmWarningMacro( "Trying to fix the even-but-odd value length bug #3" );
236 assert( Fragments.size() );
237 const size_t lastf = Fragments.size() - 1;
238 const ByteValue *bv = Fragments[ lastf ].GetByteValue();
239 const char *a = bv->GetPointer();
240 gdcmAssertAlwaysMacro( (unsigned char)a[ bv->GetLength() - 3 ] == 0xfe );
241 Fragments[ lastf ].SetByteValue( bv->GetPointer(), bv->GetLength() - 3 );
242 is.seekg( -11, std::ios::cur );
243 assert( is.good() );
244 while( frag.ReadBacktrack<TSwap>(is) && frag.GetTag() != seqDelItem )
245 {
246 gdcmDebugMacro( "Frag: " << frag );
247 Fragments.push_back( frag );
248 }
249 assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 );
250 }
251 else
252 {
253 // 3. gdcm-JPEG-LossLess3a.dcm: easy case, an extra tag was found
254 // instead of terminator (eof is the next char)
255 gdcmWarningMacro( "Reading failed at Tag:" << frag.GetTag() << " Index #"
256 << Fragments.size() << " Offset " << is.tellg() << ". Use file at own risk."
257 << ex.what() );
258 }
259#endif /* GDCM_SUPPORT_BROKEN_IMPLEMENTATION */
260 }
261
262 return is;
263}
264
265template <typename TSwap>
266std::ostream const &Write(std::ostream &os) const
267{
268 if( !Table.Write<TSwap>(os) )
269 {
270 assert(0 && "Should not happen");
271 return os;
272 }
273 for(ConstIterator it = Begin();it != End(); ++it)
274 {
275 it->Write<TSwap>(os);
276 }
277 // seq del item is not stored, write it !
278 const Tag seqDelItem(0xfffe,0xe0dd);
279 seqDelItem.Write<TSwap>(os);
280 VL zero = 0;
281 zero.Write<TSwap>(os);
282
283 return os;
284}
285
286//#if defined(SWIGPYTHON) || defined(SWIGCSHARP) || defined(SWIGJAVA)
287 // For now leave it there, this does not make sense in the C++ layer
288 // Create a new object
290 {
291 return new SequenceOfFragments();
292 }
293//#endif
294
295protected:
296public:
297 void Print(std::ostream &os) const override {
298 os << "SQ L= " << SequenceLengthField << "\n";
299 os << "Table:" << Table << "\n";
300 for(ConstIterator it = Begin();it != End(); ++it)
301 {
302 os << " " << *it << "\n";
303 }
304 assert( SequenceLengthField.IsUndefined() );
305 {
306 const Tag seqDelItem(0xfffe,0xe0dd);
307 VL zero = 0;
308 os << seqDelItem;
309 os << "\t" << zero;
310 }
311 }
312 bool operator==(const Value &val) const override
313 {
314 const SequenceOfFragments &sqf = dynamic_cast<const SequenceOfFragments&>(val);
315 return Table == sqf.Table &&
316 SequenceLengthField == sqf.SequenceLengthField &&
317 Fragments == sqf.Fragments;
318 }
319
320private:
322 VL SequenceLengthField;
324 FragmentVector Fragments;
325
326private:
327 bool FillFragmentWithJPEG( Fragment & frag, std::istream & is );
328};
329
335} // end namespace gdcm_ns
336
337#endif //GDCMSEQUENCEOFFRAGMENTS_H
Class to represent a BasicOffsetTable.
Definition gdcmBasicOffsetTable.h:27
Class to represent binary value (array of bytes)
Definition gdcmByteValue.h:35
const char * GetPointer() const
Definition gdcmByteValue.h:110
VL GetLength() const override
Definition gdcmByteValue.h:77
const VL & GetVL() const
Get VL.
Definition gdcmDataElement.h:74
const Tag & GetTag() const
Get Tag.
Definition gdcmDataElement.h:67
Exception.
Definition gdcmException.h:44
const char * what() const override
what implementation
Definition gdcmException.h:86
Class to represent a Fragment.
Definition gdcmFragment.h:44
std::istream & ReadBacktrack(std::istream &is)
Definition gdcmFragment.h:110
std::istream & Read(std::istream &is)
Definition gdcmFragment.h:56
Class to represent a Sequence Of Fragments.
Definition gdcmSequenceOfFragments.h:32
bool operator==(const Value &val) const override
Definition gdcmSequenceOfFragments.h:312
std::istream & Read(std::istream &is, bool readvalues=true)
Definition gdcmSequenceOfFragments.h:86
void SetLength(VL length) override
Sets the actual SQ length.
Definition gdcmSequenceOfFragments.h:53
void AddFragment(Fragment const &item)
Appends a Fragment to the already added ones.
bool WriteBuffer(std::ostream &os) const
FragmentVector::iterator Iterator
Definition gdcmSequenceOfFragments.h:37
Iterator Begin()
Definition gdcmSequenceOfFragments.h:39
BasicOffsetTable & GetTable()
Definition gdcmSequenceOfFragments.h:83
std::istream & ReadPreValue(std::istream &is)
Definition gdcmSequenceOfFragments.h:94
bool GetFragBuffer(unsigned int fragNb, char *buffer, unsigned long &length) const
VL GetLength() const override
Returns the SQ length, as read from disk.
Definition gdcmSequenceOfFragments.h:48
const Fragment & GetFragment(SizeType num) const
ConstIterator Begin() const
Definition gdcmSequenceOfFragments.h:41
ConstIterator End() const
Definition gdcmSequenceOfFragments.h:42
void Print(std::ostream &os) const override
Definition gdcmSequenceOfFragments.h:297
unsigned long ComputeByteLength() const
SizeType GetNumberOfFragments() const
void Clear() override
Clear.
static SmartPointer< SequenceOfFragments > New()
Definition gdcmSequenceOfFragments.h:289
Iterator End()
Definition gdcmSequenceOfFragments.h:40
FragmentVector::size_type SizeType
Definition gdcmSequenceOfFragments.h:36
std::istream & ReadValue(std::istream &is, bool)
Definition gdcmSequenceOfFragments.h:136
const BasicOffsetTable & GetTable() const
Definition gdcmSequenceOfFragments.h:82
FragmentVector::const_iterator ConstIterator
Definition gdcmSequenceOfFragments.h:38
SequenceOfFragments()
constructor (UndefinedLength by default)
Definition gdcmSequenceOfFragments.h:45
std::ostream const & Write(std::ostream &os) const
Definition gdcmSequenceOfFragments.h:266
std::vector< Fragment > FragmentVector
Definition gdcmSequenceOfFragments.h:35
bool GetBuffer(char *buffer, unsigned long length) const
Class for Smart Pointer.
Definition gdcmSmartPointer.h:40
Table.
Definition gdcmTable.h:29
Class to represent a DICOM Data Element (Attribute) Tag (Group, Element).
Definition gdcmTag.h:39
uint16_t GetGroup() const
Returns the 'Group number' of the given Tag.
Definition gdcmTag.h:55
const std::ostream & Write(std::ostream &os) const
Write a tag in binary rep.
Definition gdcmTag.h:169
uint16_t GetElement() const
Returns the 'Element number' of the given Tag.
Definition gdcmTag.h:57
Value Length.
Definition gdcmVL.h:30
const std::ostream & Write(std::ostream &os) const
Definition gdcmVL.h:99
Class to represent the value of a Data Element.
Definition gdcmValue.h:32
#define gdcmAssertAlwaysMacro(arg)
AssertAlways.
Definition gdcmTrace.h:228
#define gdcmWarningMacro(msg)
Warning.
Definition gdcmTrace.h:142
#define gdcmDebugMacro(msg)
Debug.
Definition gdcmTrace.h:119
#define GDCM_EXPORT
Definition gdcmWin32.h:34