# gdcmFragment.h

Go to the documentation of this file.

    00001 /*=========================================================================
    00002
    00003   Program: GDCM (Grassroots DICOM). A DICOM library
    00004   Module:  $URL$
    00005
    00006   Copyright (c) 2006-2010 Mathieu Malaterre
    00007   All rights reserved.
    00008   See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
    00009
    00010      This software is distributed WITHOUT ANY WARRANTY; without even
    00011      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
    00012      PURPOSE.  See the above copyright notice for more information.
    00013
    00014 =========================================================================*/
    00015 #ifndef GDCMFRAGMENT_H
    00016 #define GDCMFRAGMENT_H
    00017
    00018 #include "gdcmDataElement.h"
    00019 #include "gdcmByteValue.h"
    00020 #include "gdcmSmartPointer.h"
    00021 #include "gdcmParseException.h"
    00022
    00023 namespace gdcm
    00024 {
    00025
    00026 // Implementation detail:
    00027 // I think Fragment should be a protected sublclass of DataElement:
    00028 // looking somewhat like this:
    00029 /*
    00030 class GDCM_EXPORT Fragment : protected DataElement
    00031 {
    00032 public:
    00033   using DataElement::GetTag;
    00034   using DataElement::GetVL;
    00035   using DataElement::SetByteValue;
    00036   using DataElement::GetByteValue;
    00037   using DataElement::GetValue;
    00038 */
    00039 // Instead I am only hiding the SetTag member...
    00040
    00044 class GDCM_EXPORT Fragment : public DataElement
    00045 {
    00046 //protected:
    00047 //  void SetTag(const Tag &t);
    00048 public:
    00049   Fragment() : DataElement(Tag(0xfffe, 0xe000), 0) {}
    00050   friend std::ostream &operator<<(std::ostream &os, const Fragment &val);
    00051
    00052   VL GetLength() const {
    00053     assert( !ValueLengthField.IsUndefined() );
    00054     assert( !ValueField || ValueField->GetLength() == ValueLengthField );
    00055     return TagField.GetLength() + ValueLengthField.GetLength()
    00056       + ValueLengthField;
    00057   }
    00058
    00059   template <typename TSwap>
    00060   std::istream &Read(std::istream &is)
    00061     {
    00062     // Superclass
    00063     const Tag itemStart(0xfffe, 0xe000);
    00064     const Tag seqDelItem(0xfffe,0xe0dd);
    00065     if( !TagField.Read<TSwap>(is) )
    00066       {
    00067       //  BogusItemStartItemEnd.dcm
    00068       throw Exception( "Problem" );
    00069       return is;
    00070       }
    00071     if( !ValueLengthField.Read<TSwap>(is) )
    00072       {
    00073       // GENESIS_SIGNA-JPEG-CorruptFrag.dcm
    00074       // JPEG fragment is declared to have 61902, but infact really is only 61901
    00075       // so we end up reading 0xddff,0x00e0, and VL = 0x0 (1 byte)
    00076       throw Exception( "Problem" );
    00077       return is;
    00078       }
    00079 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
    00080     if( TagField != itemStart && TagField != seqDelItem )
    00081       {
    00082       throw Exception( "Problem" );
    00083       }
    00084 #endif
    00085     // Self
    00086     SmartPointer<ByteValue> bv = new ByteValue;
    00087     bv->SetLength(ValueLengthField);
    00088     if( !bv->Read<TSwap>(is) )
    00089       {
    00090       // Fragment is incomplete, but is a itemStart, let's try to push it anyway...
    00091       gdcmWarningMacro( "Fragment could not be read" );
    00092       //bv->SetLength(is.gcount());
    00093       ValueField = bv;
    00094       ParseException pe;
    00095       pe.SetLastElement( *this );
    00096       throw pe;
    00097       return is;
    00098       }
    00099     ValueField = bv;
    00100     return is;
    00101     }
    00102
    00103
    00104   template <typename TSwap>
    00105   std::ostream &Write(std::ostream &os) const {
    00106     const Tag itemStart(0xfffe, 0xe000);
    00107     const Tag seqDelItem(0xfffe,0xe0dd);
    00108     if( !TagField.Write<TSwap>(os) )
    00109       {
    00110       assert(0 && "Should not happen");
    00111       return os;
    00112       }
    00113     assert( TagField == itemStart
    00114          || TagField == seqDelItem );
    00115     const ByteValue *bv = GetByteValue();
    00116     // VL
    00117     // The following piece of code is hard to read in order to support such broken file as:
    00118     // CompressedLossy.dcm
    00119     if( IsEmpty() )
    00120       {
    00121       //assert( bv );
    00122       VL zero = 0;
    00123       if( !zero.Write<TSwap>(os) )
    00124         {
    00125         assert(0 && "Should not happen");
    00126         return os;
    00127         }
    00128       }
    00129     else
    00130       {
    00131       assert( ValueLengthField );
    00132       if( !ValueLengthField.Write<TSwap>(os) )
    00133         {
    00134         assert(0 && "Should not happen");
    00135         return os;
    00136         }
    00137       }
    00138     // Value
    00139     if( ValueLengthField && bv )
    00140       {
    00141       // Self
    00142       assert( bv );
    00143       assert( bv->GetLength() == ValueLengthField );
    00144       if( !bv->Write<TSwap>(os) )
    00145         {
    00146         assert(0 && "Should not happen");
    00147         return os;
    00148         }
    00149       }
    00150     return os;
    00151     }
    00152 };
    00153 //-----------------------------------------------------------------------------
    00154 inline std::ostream &operator<<(std::ostream &os, const Fragment &val)
    00155 {
    00156   os << "Tag: " << val.TagField;
    00157   os << "\tVL: " << val.ValueLengthField;
    00158   if( val.ValueField )
    00159     {
    00160     os << "\t" << *(val.ValueField);
    00161     }
    00162
    00163   return os;
    00164 }
    00165
    00166
    00167 } // end namespace gdcm
    00168
    00169 #endif //GDCMFRAGMENT_H