# 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     TagField.Read<TSwap>(is);
    00063     return ReadValue<TSwap>(is);
    00064     }
    00065
    00066   template <typename TSwap>
    00067   std::istream &ReadValue(std::istream &is)
    00068     {
    00069     // Superclass
    00070     const Tag itemStart(0xfffe, 0xe000);
    00071     const Tag seqDelItem(0xfffe,0xe0dd);
    00072     if( !is )
    00073       {
    00074       //  BogusItemStartItemEnd.dcm
    00075       throw Exception( "Problem" );
    00076       return is;
    00077       }
    00078     if( !ValueLengthField.Read<TSwap>(is) )
    00079       {
    00080       // GENESIS_SIGNA-JPEG-CorruptFrag.dcm
    00081       // JPEG fragment is declared to have 61902, but infact really is only 61901
    00082       // so we end up reading 0xddff,0x00e0, and VL = 0x0 (1 byte)
    00083       throw Exception( "Problem" );
    00084       return is;
    00085       }
    00086 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
    00087     if( TagField != itemStart && TagField != seqDelItem )
    00088       {
    00089       throw Exception( "Problem" );
    00090       }
    00091 #endif
    00092     // Self
    00093     SmartPointer<ByteValue> bv = new ByteValue;
    00094     bv->SetLength(ValueLengthField);
    00095     if( !bv->Read<TSwap>(is) )
    00096       {
    00097       // Fragment is incomplete, but is a itemStart, let's try to push it anyway...
    00098       gdcmWarningMacro( "Fragment could not be read" );
    00099       //bv->SetLength(is.gcount());
    00100       ValueField = bv;
    00101       ParseException pe;
    00102       pe.SetLastElement( *this );
    00103       throw pe;
    00104       return is;
    00105       }
    00106     ValueField = bv;
    00107     return is;
    00108     }
    00109
    00110
    00111   template <typename TSwap>
    00112   std::ostream &Write(std::ostream &os) const {
    00113     const Tag itemStart(0xfffe, 0xe000);
    00114     const Tag seqDelItem(0xfffe,0xe0dd);
    00115     if( !TagField.Write<TSwap>(os) )
    00116       {
    00117       assert(0 && "Should not happen");
    00118       return os;
    00119       }
    00120     assert( TagField == itemStart
    00121          || TagField == seqDelItem );
    00122     const ByteValue *bv = GetByteValue();
    00123     // VL
    00124     // The following piece of code is hard to read in order to support such broken file as:
    00125     // CompressedLossy.dcm
    00126     if( IsEmpty() )
    00127       {
    00128       //assert( bv );
    00129       VL zero = 0;
    00130       if( !zero.Write<TSwap>(os) )
    00131         {
    00132         assert(0 && "Should not happen");
    00133         return os;
    00134         }
    00135       }
    00136     else
    00137       {
    00138       assert( ValueLengthField );
    00139       if( !ValueLengthField.Write<TSwap>(os) )
    00140         {
    00141         assert(0 && "Should not happen");
    00142         return os;
    00143         }
    00144       }
    00145     // Value
    00146     if( ValueLengthField && bv )
    00147       {
    00148       // Self
    00149       assert( bv );
    00150       assert( bv->GetLength() == ValueLengthField );
    00151       if( !bv->Write<TSwap>(os) )
    00152         {
    00153         assert(0 && "Should not happen");
    00154         return os;
    00155         }
    00156       }
    00157     return os;
    00158     }
    00159 };
    00160 //-----------------------------------------------------------------------------
    00161 inline std::ostream &operator<<(std::ostream &os, const Fragment &val)
    00162 {
    00163   os << "Tag: " << val.TagField;
    00164   os << "\tVL: " << val.ValueLengthField;
    00165   if( val.ValueField )
    00166     {
    00167     os << "\t" << *(val.ValueField);
    00168     }
    00169
    00170   return os;
    00171 }
    00172
    00173
    00174 } // end namespace gdcm
    00175
    00176 #endif //GDCMFRAGMENT_H