GDCM 2.2.0

- Main Page
- Related Pages
- Namespaces
- Classes
- Files
- Directories
- Examples

- File List
- File Members

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