GDCM  2.2.0
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 
00086 template <typename TSwap>
00087 std::istream& Read(std::istream &is)
00088 {
00089   assert( SequenceLengthField.IsUndefined() );
00090   //if( SequenceLengthField.IsUndefined() )
00091     {
00092     const Tag seqDelItem(0xfffe,0xe0dd);
00093     // First item is the basic offset table:
00094     try
00095       {
00096       Table.Read<TSwap>(is);
00097       gdcmDebugMacro( "Table: " << Table );
00098       }
00099     catch(...)
00100       {
00101       // Bug_Siemens_PrivateIconNoItem.dcm
00102       // First thing first let's rewind
00103       is.seekg(-4, std::ios::cur);
00104       if ( Table.GetTag() == Tag(0xd8ff,0xe0ff) )
00105         {
00106         Fragment frag;
00107         is.seekg( 8340, std::ios::cur );
00108         char dummy[8340];
00109         frag.SetByteValue( dummy, 8340 - Table.GetLength() - 16 );
00110         Fragments.push_back( frag );
00111         return is;
00112         }
00113       else
00114         {
00115         throw "Catch me if you can";
00116         //assert(0);
00117         }
00118       }
00119     // not used for now...
00120     Fragment frag;
00121     try
00122       {
00123       while( frag.Read<TSwap>(is) && frag.GetTag() != seqDelItem )
00124         {
00125         gdcmDebugMacro( "Frag: " << frag );
00126         Fragments.push_back( frag );
00127         }
00128       assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 );
00129       }
00130     catch(Exception &ex)
00131       {
00132       (void)ex;  //to avoid unreferenced variable warning on release
00133 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
00134       // that's ok ! In all cases the whole file was read, because
00135       // Fragment::Read only fail on eof() reached 1.
00136       // SIEMENS-JPEG-CorruptFrag.dcm is more difficult to deal with, we have a
00137       // partial fragment, read we decide to add it anyway to the stack of
00138       // fragments (eof was reached so we need to clear error bit)
00139       if( frag.GetTag() == Tag(0xfffe,0xe000)  )
00140         {
00141         gdcmWarningMacro( "Pixel Data Fragment could be corrupted. Use file at own risk" );
00142         Fragments.push_back( frag );
00143         is.clear(); // clear the error bit
00144         }
00145       // 2. GENESIS_SIGNA-JPEG-CorruptFrag.dcm
00146       else if ( frag.GetTag() == Tag(0xddff,0x00e0) )
00147         {
00148         assert( Fragments.size() == 1 );
00149         const ByteValue *bv = Fragments[0].GetByteValue();
00150         assert( (unsigned char)bv->GetPointer()[ bv->GetLength() - 1 ] == 0xfe );
00151         // Yes this is an extra copy, this is a bug anyway, go fix YOUR code
00152         Fragments[0].SetByteValue( bv->GetPointer(), bv->GetLength() - 1 );
00153         gdcmWarningMacro( "JPEG Fragment length was declared with an extra byte"
00154           " at the end: stripped !" );
00155         is.clear(); // clear the error bit
00156         }
00157       else
00158         {
00159         // 3. gdcm-JPEG-LossLess3a.dcm: easy case, an extra tag was found
00160         // instead of terminator (eof is the next char)
00161         gdcmWarningMacro( "Reading failed at Tag:" << frag.GetTag() <<
00162           ". Use file at own risk." << ex.what() );
00163         }
00164 #else
00165       (void)ex;
00166 #endif /* GDCM_SUPPORT_BROKEN_IMPLEMENTATION */
00167       }
00168     }
00169 
00170   return is;
00171 }
00172 
00173 template <typename TSwap>
00174 std::ostream const &Write(std::ostream &os) const
00175 {
00176   if( !Table.Write<TSwap>(os) )
00177     {
00178     assert(0 && "Should not happen");
00179     return os;
00180     }
00181   for(ConstIterator it = Begin();it != End(); ++it)
00182     {
00183     it->Write<TSwap>(os);
00184     }
00185   // seq del item is not stored, write it !
00186   const Tag seqDelItem(0xfffe,0xe0dd);
00187   seqDelItem.Write<TSwap>(os);
00188   VL zero = 0;
00189   zero.Write<TSwap>(os);
00190 
00191   return os;
00192 }
00193 
00194 //#if defined(SWIGPYTHON) || defined(SWIGCSHARP) || defined(SWIGJAVA)
00195   // For now leave it there, this does not make sense in the C++ layer
00196   // Create a new object
00197   static SmartPointer<SequenceOfFragments> New()
00198   {
00199      return new SequenceOfFragments();
00200   }
00201 //#endif
00202 
00203 protected:
00204 public:
00205   void Print(std::ostream &os) const {
00206     os << "SQ L= " << SequenceLengthField << "\n";
00207     os << "Table:" << Table << "\n";
00208     for(ConstIterator it = Begin();it != End(); ++it)
00209       {
00210       os << "  " << *it << "\n";
00211       }
00212     assert( SequenceLengthField.IsUndefined() );
00213       {
00214       const Tag seqDelItem(0xfffe,0xe0dd);
00215       VL zero = 0;
00216       os << seqDelItem;
00217       os << "\t" << zero;
00218       }
00219   }
00220   bool operator==(const Value &val) const
00221     {
00222     const SequenceOfFragments &sqf = dynamic_cast<const SequenceOfFragments&>(val);
00223     return Table == sqf.Table &&
00224       SequenceLengthField == sqf.SequenceLengthField &&
00225       Fragments == sqf.Fragments;
00226     }
00227 
00228 private:
00229   BasicOffsetTable Table;
00230   VL SequenceLengthField;
00232   FragmentVector Fragments;
00233 };
00234 
00240 } // end namespace gdcm
00241 
00242 #endif //GDCMSEQUENCEOFFRAGMENTS_H

Generated on Sun Jun 3 2012 15:26:50 for GDCM by doxygen 1.8.0
SourceForge.net Logo