GDCM  2.2.3
gdcmFragment.h
Go to the documentation of this file.
00001 /*=========================================================================
00002 
00003   Program: GDCM (Grassroots DICOM). A DICOM library
00004 
00005   Copyright (c) 2006-2011 Mathieu Malaterre
00006   All rights reserved.
00007   See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
00008 
00009      This software is distributed WITHOUT ANY WARRANTY; without even
00010      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00011      PURPOSE.  See the above copyright notice for more information.
00012 
00013 =========================================================================*/
00014 #ifndef GDCMFRAGMENT_H
00015 #define GDCMFRAGMENT_H
00016 
00017 #include "gdcmDataElement.h"
00018 #include "gdcmByteValue.h"
00019 #include "gdcmSmartPointer.h"
00020 #include "gdcmParseException.h"
00021 
00022 namespace gdcm
00023 {
00024 
00025 // Implementation detail:
00026 // I think Fragment should be a protected sublclass of DataElement:
00027 // looking somewhat like this:
00028 /*
00029 class GDCM_EXPORT Fragment : protected DataElement
00030 {
00031 public:
00032   using DataElement::GetTag;
00033   using DataElement::GetVL;
00034   using DataElement::SetByteValue;
00035   using DataElement::GetByteValue;
00036   using DataElement::GetValue;
00037 */
00038 // Instead I am only hiding the SetTag member...
00039 
00043 class GDCM_EXPORT Fragment : public DataElement
00044 {
00045 //protected:
00046 //  void SetTag(const Tag &t);
00047 public:
00048   Fragment() : DataElement(Tag(0xfffe, 0xe000), 0) {}
00049   friend std::ostream &operator<<(std::ostream &os, const Fragment &val);
00050 
00051   VL GetLength() const {
00052     assert( !ValueLengthField.IsUndefined() );
00053     assert( !ValueField || ValueField->GetLength() == ValueLengthField );
00054     return TagField.GetLength() + ValueLengthField.GetLength()
00055       + ValueLengthField;
00056   }
00057 
00058   template <typename TSwap>
00059   std::istream &Read(std::istream &is)
00060     {
00061     ReadPreValue<TSwap>(is);
00062     return ReadValue<TSwap>(is);
00063     }
00064 
00065   template <typename TSwap>
00066   std::istream &ReadPreValue(std::istream &is)
00067     {
00068     const Tag itemStart(0xfffe, 0xe000);
00069     const Tag seqDelItem(0xfffe,0xe0dd);
00070 
00071     TagField.Read<TSwap>(is);
00072     if( !is )
00073       {
00074       //  BogusItemStartItemEnd.dcm
00075       throw Exception( "Problem #1" );
00076       return is;
00077       }
00078     if( !ValueLengthField.Read<TSwap>(is) )
00079       {
00080       // GENESIS_SIGNA-JPEG-CorruptFrag.dcm
00081       // JPEG fragment is declared to have 61902, but infact really is only 61901
00082       // so we end up reading 0xddff,0x00e0, and VL = 0x0 (1 byte)
00083       throw Exception( "Problem #2" );
00084       return is;
00085       }
00086 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
00087     if( TagField != itemStart && TagField != seqDelItem )
00088       {
00089       throw Exception( "Problem #3" );
00090       }
00091 #endif
00092     return is;
00093     }
00094 
00095   template <typename TSwap>
00096   std::istream &ReadValue(std::istream &is)
00097     {
00098     // Superclass
00099     const Tag itemStart(0xfffe, 0xe000);
00100     const Tag seqDelItem(0xfffe,0xe0dd);
00101     // Self
00102     SmartPointer<ByteValue> bv = new ByteValue;
00103     bv->SetLength(ValueLengthField);
00104     if( !bv->Read<TSwap>(is) )
00105       {
00106       // Fragment is incomplete, but is a itemStart, let's try to push it anyway...
00107       gdcmWarningMacro( "Fragment could not be read" );
00108       //bv->SetLength(is.gcount());
00109       ValueField = bv;
00110       ParseException pe;
00111       pe.SetLastElement( *this );
00112       throw pe;
00113       return is;
00114       }
00115     ValueField = bv;
00116     return is;
00117     }
00118 
00119   template <typename TSwap>
00120   std::istream &ReadBacktrack(std::istream &is)
00121     {
00122     const Tag itemStart(0xfffe, 0xe000);
00123     const Tag seqDelItem(0xfffe,0xe0dd);
00124 
00125     bool cont = true;
00126     const std::streampos start = is.tellg();
00127     const int max = 10;
00128     int offset = 0;
00129     while( cont )
00130       {
00131       TagField.Read<TSwap>(is);
00132       assert( is );
00133       if( TagField != itemStart && TagField != seqDelItem )
00134         {
00135         ++offset;
00136         is.seekg( (std::streampos)((size_t)start - offset) );
00137         gdcmWarningMacro( "Fuzzy Search, backtrack: " << (start - is.tellg()) << " Offset: " << is.tellg() );
00138         if( offset > max )
00139           {
00140           gdcmErrorMacro( "Giving up" );
00141           throw "Impossible to backtrack";
00142           return is;
00143           }
00144         }
00145       else
00146         {
00147         cont = false;
00148         }
00149       }
00150     assert( TagField == itemStart || TagField == seqDelItem );
00151     if( !ValueLengthField.Read<TSwap>(is) )
00152       {
00153       return is;
00154       }
00155 
00156     // Self
00157     SmartPointer<ByteValue> bv = new ByteValue;
00158     bv->SetLength(ValueLengthField);
00159     if( !bv->Read<TSwap>(is) )
00160       {
00161       // Fragment is incomplete, but is a itemStart, let's try to push it anyway...
00162       gdcmWarningMacro( "Fragment could not be read" );
00163       //bv->SetLength(is.gcount());
00164       ValueField = bv;
00165       ParseException pe;
00166       pe.SetLastElement( *this );
00167       throw pe;
00168       return is;
00169       }
00170     ValueField = bv;
00171     return is;
00172     }
00173 
00174 
00175   template <typename TSwap>
00176   std::ostream &Write(std::ostream &os) const {
00177     const Tag itemStart(0xfffe, 0xe000);
00178     const Tag seqDelItem(0xfffe,0xe0dd);
00179     if( !TagField.Write<TSwap>(os) )
00180       {
00181       assert(0 && "Should not happen");
00182       return os;
00183       }
00184     assert( TagField == itemStart
00185          || TagField == seqDelItem );
00186     const ByteValue *bv = GetByteValue();
00187     // VL
00188     // The following piece of code is hard to read in order to support such broken file as:
00189     // CompressedLossy.dcm
00190     if( IsEmpty() )
00191       {
00192       //assert( bv );
00193       VL zero = 0;
00194       if( !zero.Write<TSwap>(os) )
00195         {
00196         assert(0 && "Should not happen");
00197         return os;
00198         }
00199       }
00200     else
00201       {
00202       assert( ValueLengthField );
00203       if( !ValueLengthField.Write<TSwap>(os) )
00204         {
00205         assert(0 && "Should not happen");
00206         return os;
00207         }
00208       }
00209     // Value
00210     if( ValueLengthField && bv )
00211       {
00212       // Self
00213       assert( bv );
00214       assert( bv->GetLength() == ValueLengthField );
00215       if( !bv->Write<TSwap>(os) )
00216         {
00217         assert(0 && "Should not happen");
00218         return os;
00219         }
00220       }
00221     return os;
00222     }
00223 };
00224 //-----------------------------------------------------------------------------
00225 inline std::ostream &operator<<(std::ostream &os, const Fragment &val)
00226 {
00227   os << "Tag: " << val.TagField;
00228   os << "\tVL: " << val.ValueLengthField;
00229   if( val.ValueField )
00230     {
00231     os << "\t" << *(val.ValueField);
00232     }
00233 
00234   return os;
00235 }
00236 
00237 } // end namespace gdcm
00238 
00239 #endif //GDCMFRAGMENT_H

Generated on Thu Nov 28 2013 07:02:50 for GDCM by doxygen 1.7.6.1
SourceForge.net Logo