GDCM  2.2.3
gdcmSequenceOfFragments.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 GDCMSEQUENCEOFFRAGMENTS_H
00015 #define GDCMSEQUENCEOFFRAGMENTS_H
00016 
00017 #include "gdcmValue.h"
00018 #include "gdcmVL.h"
00019 #include "gdcmFragment.h"
00020 #include "gdcmBasicOffsetTable.h"
00021 
00022 namespace gdcm
00023 {
00024 
00025   // FIXME gdcmSequenceOfItems and gdcmSequenceOfFragments
00026   // should be rethink (duplicate code)
00031 class GDCM_EXPORT SequenceOfFragments : public Value
00032 {
00033 public:
00034   // Typdefs:
00035   typedef std::vector<Fragment> FragmentVector;
00036   typedef FragmentVector::size_type SizeType;
00037   typedef FragmentVector::iterator Iterator;
00038   typedef FragmentVector::const_iterator ConstIterator;
00039   Iterator Begin() { return Fragments.begin(); }
00040   Iterator End() { return Fragments.end(); }
00041   ConstIterator Begin() const { return Fragments.begin(); }
00042   ConstIterator End() const { return Fragments.end(); }
00043 
00045   SequenceOfFragments():Table(),SequenceLengthField(0xFFFFFFFF) { }
00046 
00048   VL GetLength() const {
00049     return SequenceLengthField;
00050   }
00051 
00053   void SetLength(VL length) {
00054     SequenceLengthField = length;
00055   }
00056 
00058   void Clear();
00059 
00061   void AddFragment(Fragment const &item);
00062 
00063   // Compute the length of all fragments (and framents only!).
00064   // Basically the size of the PixelData as stored (in bytes).
00065   unsigned long ComputeByteLength() const;
00066 
00067   // Compute the length of fragments (in bytes)+ length of tag...
00068   // to be used for computation of Group Length
00069   VL ComputeLength() const;
00070 
00071   // Get the buffer
00072   bool GetBuffer(char *buffer, unsigned long length) const;
00073   bool GetFragBuffer(unsigned int fragNb, char *buffer, unsigned long &length) const;
00074 
00075   SizeType GetNumberOfFragments() const;
00076   const Fragment& GetFragment(SizeType num) const;
00077 
00078   // Write the buffer of each fragment (call WriteBuffer on all Fragments, which are
00079   // ByteValue). No Table information is written.
00080   bool WriteBuffer(std::ostream &os) const;
00081 
00082   const BasicOffsetTable &GetTable() const { return Table; }
00083   BasicOffsetTable &GetTable() { return Table; }
00084 
00085 template <typename TSwap>
00086 std::istream& Read(std::istream &is)
00087 {
00088   assert( SequenceLengthField.IsUndefined() );
00089   ReadPreValue<TSwap>(is);
00090   return ReadValue<TSwap>(is);
00091 }
00092 
00093 template <typename TSwap>
00094 std::istream& ReadPreValue(std::istream &is)
00095 {
00096   //if( SequenceLengthField.IsUndefined() )
00097   // First item is the basic offset table:
00098   try
00099     {
00100     Table.Read<TSwap>(is);
00101     gdcmDebugMacro( "Table: " << Table );
00102     }
00103   catch(...)
00104     {
00105     // Bug_Siemens_PrivateIconNoItem.dcm
00106     // First thing first let's rewind
00107     is.seekg(-4, std::ios::cur);
00108     if ( Table.GetTag() == Tag(0xd8ff,0xe0ff) )
00109       {
00110       Fragment frag;
00111       is.seekg( 8340, std::ios::cur );
00112       char dummy[8340];
00113       frag.SetByteValue( dummy, 8340 - Table.GetLength() - 16 );
00114       Fragments.push_back( frag );
00115       return is;
00116       }
00117     else
00118       {
00119       throw "Catch me if you can";
00120       //assert(0);
00121       }
00122     }
00123   return is;
00124 }
00125 
00126 template <typename TSwap>
00127 std::istream& ReadValue(std::istream &is)
00128 {
00129   const Tag seqDelItem(0xfffe,0xe0dd);
00130   // not used for now...
00131   Fragment frag;
00132   try
00133     {
00134     while( frag.Read<TSwap>(is) && frag.GetTag() != seqDelItem )
00135       {
00136       gdcmDebugMacro( "Frag: " << frag );
00137       Fragments.push_back( frag );
00138       }
00139     assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 );
00140     }
00141   catch(Exception &ex)
00142     {
00143     (void)ex;
00144 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
00145     // that's ok ! In all cases the whole file was read, because
00146     // Fragment::Read only fail on eof() reached 1.
00147     // SIEMENS-JPEG-CorruptFrag.dcm is more difficult to deal with, we have a
00148     // partial fragment, read we decide to add it anyway to the stack of
00149     // fragments (eof was reached so we need to clear error bit)
00150     if( frag.GetTag() == Tag(0xfffe,0xe000)  )
00151       {
00152       gdcmWarningMacro( "Pixel Data Fragment could be corrupted. Use file at own risk" );
00153       Fragments.push_back( frag );
00154       is.clear(); // clear the error bit
00155       }
00156     // 2. GENESIS_SIGNA-JPEG-CorruptFrag.dcm
00157     else if ( frag.GetTag() == Tag(0xddff,0x00e0) )
00158       {
00159       assert( Fragments.size() == 1 );
00160       const ByteValue *bv = Fragments[0].GetByteValue();
00161       assert( (unsigned char)bv->GetPointer()[ bv->GetLength() - 1 ] == 0xfe );
00162       // Yes this is an extra copy, this is a bug anyway, go fix YOUR code
00163       Fragments[0].SetByteValue( bv->GetPointer(), bv->GetLength() - 1 );
00164       gdcmWarningMacro( "JPEG Fragment length was declared with an extra byte"
00165         " at the end: stripped !" );
00166       is.clear(); // clear the error bit
00167       }
00168     // 3. LEICA/WSI
00169     else if ( (frag.GetTag().GetGroup() == 0x00ff)
00170       && ((frag.GetTag().GetElement() & 0x00ff) == 0xe0) )
00171       {
00172       // Looks like there is a mess with offset and odd byte array
00173       // We are going first to backtrack one byte back, and then use a
00174       // ReadBacktrack function which in turn may backtrack up to 10 bytes
00175       // backward. This appears to be working on a set of DICOM/WSI files from
00176       // LEICA
00177       gdcmWarningMacro( "Trying to fix the even-but-odd value length bug" );
00178       assert( Fragments.size() );
00179       const size_t lastf = Fragments.size() - 1;
00180       const ByteValue *bv = Fragments[ lastf ].GetByteValue();
00181       const char *a = bv->GetPointer();
00182       assert( (unsigned char)a[ bv->GetLength() - 1 ] == 0xfe );
00183       Fragments[ lastf ].SetByteValue( bv->GetPointer(), bv->GetLength() - 1 );
00184       is.seekg( -9, std::ios::cur );
00185       assert( is.good() );
00186       while( frag.ReadBacktrack<TSwap>(is) && frag.GetTag() != seqDelItem )
00187         {
00188         gdcmDebugMacro( "Frag: " << frag );
00189         Fragments.push_back( frag );
00190         }
00191       assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 );
00192       }
00193     else
00194       {
00195       // 3. gdcm-JPEG-LossLess3a.dcm: easy case, an extra tag was found
00196       // instead of terminator (eof is the next char)
00197       gdcmWarningMacro( "Reading failed at Tag:" << frag.GetTag() << " Index #"
00198         << Fragments.size() << " Offset " << is.tellg() << ". Use file at own risk."
00199         << ex.what() );
00200       }
00201 #endif /* GDCM_SUPPORT_BROKEN_IMPLEMENTATION */
00202     }
00203 
00204   return is;
00205 }
00206 
00207 template <typename TSwap>
00208 std::ostream const &Write(std::ostream &os) const
00209 {
00210   if( !Table.Write<TSwap>(os) )
00211     {
00212     assert(0 && "Should not happen");
00213     return os;
00214     }
00215   for(ConstIterator it = Begin();it != End(); ++it)
00216     {
00217     it->Write<TSwap>(os);
00218     }
00219   // seq del item is not stored, write it !
00220   const Tag seqDelItem(0xfffe,0xe0dd);
00221   seqDelItem.Write<TSwap>(os);
00222   VL zero = 0;
00223   zero.Write<TSwap>(os);
00224 
00225   return os;
00226 }
00227 
00228 //#if defined(SWIGPYTHON) || defined(SWIGCSHARP) || defined(SWIGJAVA)
00229   // For now leave it there, this does not make sense in the C++ layer
00230   // Create a new object
00231   static SmartPointer<SequenceOfFragments> New()
00232   {
00233      return new SequenceOfFragments();
00234   }
00235 //#endif
00236 
00237 protected:
00238 public:
00239   void Print(std::ostream &os) const {
00240     os << "SQ L= " << SequenceLengthField << "\n";
00241     os << "Table:" << Table << "\n";
00242     for(ConstIterator it = Begin();it != End(); ++it)
00243       {
00244       os << "  " << *it << "\n";
00245       }
00246     assert( SequenceLengthField.IsUndefined() );
00247       {
00248       const Tag seqDelItem(0xfffe,0xe0dd);
00249       VL zero = 0;
00250       os << seqDelItem;
00251       os << "\t" << zero;
00252       }
00253   }
00254   bool operator==(const Value &val) const
00255     {
00256     const SequenceOfFragments &sqf = dynamic_cast<const SequenceOfFragments&>(val);
00257     return Table == sqf.Table &&
00258       SequenceLengthField == sqf.SequenceLengthField &&
00259       Fragments == sqf.Fragments;
00260     }
00261 
00262 private:
00263   BasicOffsetTable Table;
00264   VL SequenceLengthField;
00266   FragmentVector Fragments;
00267 };
00268 
00274 } // end namespace gdcm
00275 
00276 #endif //GDCMSEQUENCEOFFRAGMENTS_H

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