GDCM  2.0.18
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 qnd 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 
00038   SequenceOfFragments():Table(),SequenceLengthField(0xFFFFFFFF) { }
00039 
00041   VL GetLength() const {
00042     return SequenceLengthField; }
00044   void SetLength(VL length) {
00045     SequenceLengthField = length;
00046   }
00047   void Clear();
00048 
00050   void AddFragment(Fragment const &item);
00051 
00052   // Compute the length of all fragments (and framents only!).
00053   // Basically the size of the PixelData as stored (in bytes).
00054   unsigned long ComputeByteLength() const;
00055 
00056   // Compute the length of fragments (in bytes)+ length of tag...
00057   // to be used for computation of Group Length
00058   VL ComputeLength() const;
00059 
00060   // Get the buffer
00061   bool GetBuffer(char *buffer, unsigned long length) const;
00062   bool GetFragBuffer(unsigned int fragNb, char *buffer, unsigned long &length) const;
00063   unsigned int GetNumberOfFragments() const;
00064   const Fragment& GetFragment(unsigned int num) const;
00065 
00066   // Write the buffer of each fragment (call WriteBuffer on all Fragments, which are
00067   // ByteValue). No Table information is written.
00068   bool WriteBuffer(std::ostream &os) const;
00069 
00070   const BasicOffsetTable &GetTable() const { return Table; }
00071   BasicOffsetTable &GetTable() { return Table; }
00072 
00073 
00074 template <typename TSwap>
00075 std::istream& Read(std::istream &is)
00076 {
00077   assert( SequenceLengthField.IsUndefined() );
00078   //if( SequenceLengthField.IsUndefined() )
00079     {
00080     const Tag seqDelItem(0xfffe,0xe0dd);
00081     // First item is the basic offset table:
00082     try
00083       {
00084       Table.Read<TSwap>(is);
00085       gdcmDebugMacro( "Table: " << Table );
00086       }
00087     catch(...)
00088       {
00089       // Bug_Siemens_PrivateIconNoItem.dcm
00090       // First thing first let's rewind
00091       is.seekg(-4, std::ios::cur);
00092       if ( Table.GetTag() == Tag(0xd8ff,0xe0ff) )
00093         {
00094         Fragment frag;
00095         is.seekg( 8340, std::ios::cur );
00096         char dummy[8340];
00097         frag.SetByteValue( dummy, 8340 - Table.GetLength() - 16 );
00098         Fragments.push_back( frag );
00099         return is;
00100         }
00101       else
00102         {
00103         throw "Catch me if you can";
00104         //assert(0);
00105         }
00106       }
00107     // not used for now...
00108     Fragment frag;
00109     try
00110       {
00111       while( frag.Read<TSwap>(is) && frag.GetTag() != seqDelItem )
00112         {
00113         gdcmDebugMacro( "Frag: " << frag );
00114         Fragments.push_back( frag );
00115         }
00116       assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 );
00117       }
00118     catch(Exception &ex)
00119       {
00120       (void)ex;  //to avoid unreferenced variable warning on release
00121 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
00122       // that's ok ! In all cases the whole file was read, because Fragment::Read only fail on eof() reached
00123       // 1. SIEMENS-JPEG-CorruptFrag.dcm is more difficult to deal with, we have a partial fragment, read
00124       // we decide to add it anyway to the stack of fragments (eof was reached so we need to clear error bit)
00125       if( frag.GetTag() == Tag(0xfffe,0xe000)  )
00126         {
00127         gdcmWarningMacro( "Pixel Data Fragment could be corrupted. Use file at own risk" );
00128         Fragments.push_back( frag );
00129         is.clear(); // clear the error bit
00130         }
00131       // 2. GENESIS_SIGNA-JPEG-CorruptFrag.dcm
00132       else if ( frag.GetTag() == Tag(0xddff,0x00e0) )
00133         {
00134         assert( Fragments.size() == 1 );
00135         const ByteValue *bv = Fragments[0].GetByteValue();
00136         assert( (unsigned char)bv->GetPointer()[ bv->GetLength() - 1 ] == 0xfe );
00137         // Yes this is an extra copy, this is a bug anyway, go fix YOUR code
00138         Fragments[0].SetByteValue( bv->GetPointer(), bv->GetLength() - 1 );
00139         gdcmWarningMacro( "JPEG Fragment length was declared with an extra byte at the end: stripped !" );
00140         is.clear(); // clear the error bit
00141         }
00142       else
00143         {
00144         // 3. gdcm-JPEG-LossLess3a.dcm: easy case, an extra tag was found instead of terminator (eof is the next char)
00145         gdcmWarningMacro( "Reading failed at Tag:" << frag.GetTag() << ". Use file at own risk." << ex.what() );
00146         }
00147 #else
00148       (void)ex;
00149 #endif /* GDCM_SUPPORT_BROKEN_IMPLEMENTATION */
00150       }
00151     }
00152 
00153   return is;
00154 }
00155 
00156 template <typename TSwap>
00157 std::ostream const &Write(std::ostream &os) const
00158 {
00159   if( !Table.Write<TSwap>(os) )
00160     {
00161     assert(0 && "Should not happen");
00162     return os;
00163     }
00164   SequenceOfFragments::FragmentVector::const_iterator it = Fragments.begin();
00165   for(;it != Fragments.end(); ++it)
00166     {
00167     it->Write<TSwap>(os);
00168     }
00169   // seq del item is not stored, write it !
00170   const Tag seqDelItem(0xfffe,0xe0dd);
00171   seqDelItem.Write<TSwap>(os);
00172   VL zero = 0;
00173   zero.Write<TSwap>(os);
00174 
00175   return os;
00176 }
00177 
00178 //#if defined(SWIGPYTHON) || defined(SWIGCSHARP) || defined(SWIGJAVA)
00179   // For now leave it there, this does not make sense in the C++ layer
00180   // Create a new object
00181   static SmartPointer<SequenceOfFragments> New()
00182   {
00183      return new SequenceOfFragments();
00184   }
00185 //#endif
00186 
00187 protected:
00188 public:
00189   void Print(std::ostream &os) const {
00190     os << "SQ L= " << SequenceLengthField << "\n";
00191     os << "Table:" << Table << "\n";
00192     FragmentVector::const_iterator it =
00193       Fragments.begin();
00194     for(;it != Fragments.end(); ++it)
00195       {
00196       os << "  " << *it << "\n";
00197       }
00198     assert( SequenceLengthField.IsUndefined() );
00199       {
00200       const Tag seqDelItem(0xfffe,0xe0dd);
00201       VL zero = 0;
00202       os << seqDelItem;
00203       os << "\t" << zero;
00204       }
00205   }
00206   bool operator==(const Value &val) const
00207     {
00208     const SequenceOfFragments &sqf = dynamic_cast<const SequenceOfFragments&>(val);
00209     return Table == sqf.Table &&
00210       SequenceLengthField == sqf.SequenceLengthField &&
00211       Fragments == sqf.Fragments;
00212     }
00213 
00214 private:
00215 public:
00216   BasicOffsetTable Table;
00217   VL SequenceLengthField;
00219   FragmentVector Fragments;
00220 };
00221 
00227 } // end namespace gdcm
00228 
00229 #endif //GDCMSEQUENCEOFFRAGMENTS_H

Generated on Tue Dec 6 2011 20:36:27 for GDCM by doxygen 1.7.5.1
SourceForge.net Logo