gdcmItem.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-2009 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 
00016 #ifndef __gdcmItem_h
00017 #define __gdcmItem_h
00018 
00019 #include "gdcmDataElement.h"
00020 #include "gdcmDataSet.h"
00021 #include "gdcmParseException.h"
00022 #include "gdcmSwapper.h"
00023 
00024 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
00025 #include "gdcmByteSwapFilter.h"
00026 #endif
00027 
00028 namespace gdcm
00029 {
00030 
00031 class DataSet;
00045 class GDCM_EXPORT Item : public DataElement
00046 {
00047 public:
00048   Item() : DataElement(Tag(0xfffe, 0xe000), 0xFFFFFFFF), NestedDataSet() {}
00049   friend std::ostream& operator<< (std::ostream &os, const Item &val);
00050 
00051   void Clear() {
00052     NestedDataSet.Clear();
00053     }
00054 
00055   template <typename TDE>
00056   VL GetLength() const;
00057 
00058   void InsertDataElement(const DataElement & de) {
00059     NestedDataSet.Insert(de);
00060     // Update the length
00061     if( !IsUndefinedLength() )
00062       {
00063       assert( 0 && "InsertDataElement" );
00064       //ValueLengthField += de.GetLength();
00065       }
00066     }
00067   const DataElement& GetDataElement(const Tag& t) const
00068     {
00069     return NestedDataSet.GetDataElement(t);
00070     }
00071 
00072   // Completely defines it with the nested dataset
00073   // destroy anything present
00074   void SetNestedDataSet(const DataSet& nested)
00075     {
00076     NestedDataSet = nested;
00077     }
00078   // Return a const ref to the Nested Data Set
00079   const DataSet &GetNestedDataSet() const
00080     {
00081     return NestedDataSet;
00082     }
00083   DataSet &GetNestedDataSet()
00084     {
00085     return NestedDataSet;
00086     }
00087 
00088   //Value const & GetValue() const { return *NestedDataSet; }
00089 
00090   Item(Item const &val):DataElement(val)
00091     {
00092     NestedDataSet = val.NestedDataSet;
00093     }
00094 
00095   template <typename TDE, typename TSwap>
00096   std::istream &Read(std::istream &is) {
00097     // Superclass
00098     {
00099         DataSet &nested = NestedDataSet;
00100         nested.Clear();
00101         assert( nested.IsEmpty() );
00102     }
00103     if( !TagField.Read<TSwap>(is) )
00104       {
00105       throw Exception("Should not happen (item)");
00106       return is;
00107       }
00108 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
00109     // MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm
00110     if( TagField == Tag(0xfeff, 0x00e0)
00111       || TagField == Tag(0xfeff, 0xdde0) )
00112       {
00113       gdcmWarningMacro( "ByteSwaping Private SQ: " << TagField );
00114       // Invert previously read TagField since wrong endianess:
00115       TagField = Tag( SwapperDoOp::Swap( TagField.GetGroup() ), SwapperDoOp::Swap( TagField.GetElement() ) );
00116       assert ( TagField == Tag(0xfffe, 0xe000)
00117         || TagField == Tag(0xfffe, 0xe0dd) );
00118 
00119       if( !ValueLengthField.Read<SwapperDoOp>(is) )
00120         {
00121         assert(0 && "Should not happen");
00122         return is;
00123         }
00124       // Self
00125       // Some file written by GDCM 1.0 we writting 0xFFFFFFFF instead of 0x0
00126       if( TagField == Tag(0xfffe,0xe0dd) )
00127         {
00128         if( ValueLengthField )
00129           {
00130           gdcmErrorMacro( "ValueLengthField is not 0" );
00131           }
00132         }
00133       //else if( ValueLengthField == 0 )
00134       //  {
00135       //  //assert( TagField == Tag( 0xfffe, 0xe0dd) );
00136       //  if( TagField != Tag( 0xfffe, 0xe0dd) )
00137       //    {
00138       //    gdcmErrorMacro( "SQ: " << TagField << " has a length of 0" );
00139       //    }
00140       //  }
00141       else if( ValueLengthField.IsUndefined() )
00142         {
00143         DataSet &nested = NestedDataSet;
00144         nested.Clear();
00145         assert( nested.IsEmpty() );
00146         std::streampos start = is.tellg();
00147         try
00148           {
00149           nested.template ReadNested<TDE,SwapperDoOp>(is);
00150           ByteSwapFilter bsf(nested);
00151           bsf.ByteSwap();
00152           }
00153         catch(ParseException &pe)
00154           {
00155           (void)pe;
00156           // MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm
00157           // You have to byteswap the length but not the tag...sigh
00158           gdcmWarningMacro( "Attempt to read nested Item without byteswapping the Value Length." );
00159           start -= is.tellg();
00160           assert( start < 0 );
00161           is.seekg( start, std::ios::cur );
00162           nested.Clear();
00163           nested.template ReadNested<TDE,SwapperNoOp>(is);
00164           ByteSwapFilter bsf(nested);
00165           // Tag are read in big endian, need to byteswap them back...
00166           bsf.SetByteSwapTag(true);
00167           bsf.ByteSwap();
00168           }
00169         catch(Exception &e)
00170           {
00171           // MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm
00172           throw e;
00173           }
00174         catch(...)
00175           {
00176           assert(0);
00177           }
00178         }
00179       else /* if( ValueLengthField.IsUndefined() ) */
00180         {
00181         DataSet &nested = NestedDataSet;
00182         nested.Clear();
00183         assert( nested.IsEmpty() );
00184         nested.template ReadWithLength<TDE,SwapperDoOp>(is, ValueLengthField);
00185         ByteSwapFilter bsf(nested);
00186         bsf.ByteSwap();
00187         }
00188       return is;
00189       }
00190     // http://groups.google.com/group/comp.protocols.dicom/msg/c07efcf5e759fc83
00191     // Bug_Philips_ItemTag_3F3F.dcm
00192     if( TagField == Tag(0x3f3f, 0x3f00) )
00193       {
00194       //TagField = Tag(0xfffe, 0xe000);
00195       }
00196 #endif
00197     if( TagField != Tag(0xfffe, 0xe000) && TagField != Tag(0xfffe, 0xe0dd) )
00198       {
00199       gdcmDebugMacro( "Invalid Item, found tag: " << TagField);
00200       throw Exception( "Not a valid Item" );
00201       }
00202     assert( TagField == Tag(0xfffe, 0xe000) || TagField == Tag(0xfffe, 0xe0dd) );
00203 
00204     if( !ValueLengthField.Read<TSwap>(is) )
00205       {
00206       assert(0 && "Should not happen");
00207       return is;
00208       }
00209     // Self
00210     if( TagField == Tag(0xfffe,0xe0dd) )
00211       {
00212       // Some file written by GDCM 1.0 were written with 0xFFFFFFFF instead of 0x0
00213       if( ValueLengthField )
00214         {
00215         gdcmDebugMacro( "ValueLengthField is not 0 but " << ValueLengthField );
00216         }
00217       }
00218     else if( ValueLengthField.IsUndefined() )
00219       {
00220       DataSet &nested = NestedDataSet;
00221       nested.Clear();
00222       assert( nested.IsEmpty() );
00223       nested.template ReadNested<TDE,TSwap>(is);
00224       }
00225     else /* if( ValueLengthField.IsUndefined() ) */
00226       {
00227       assert( !ValueLengthField.IsUndefined() );
00228       DataSet &nested = NestedDataSet;
00229       nested.Clear();
00230       assert( nested.IsEmpty() );
00231       nested.template ReadWithLength<TDE,TSwap>(is, ValueLengthField);
00232       }
00233 
00234     return is;
00235   }
00236 
00237   template <typename TDE, typename TSwap>
00238   const std::ostream &Write(std::ostream &os) const {
00239 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
00240     if( TagField == Tag(0x3f3f,0x3f00) && false )
00241       {
00242       Tag t(0xfffe, 0xe000);
00243       t.Write<TSwap>(os);
00244       }
00245     else
00246 #endif
00247       {
00248       assert ( TagField == Tag(0xfffe, 0xe000)
00249         || TagField == Tag(0xfffe, 0xe0dd) );
00250       // Not sure how this happen
00251       if( TagField == Tag(0xfffe, 0xe0dd) )
00252         {
00253         gdcmWarningMacro( "SegDelItem found in defined length Sequence" );
00254         assert( ValueLengthField == 0 );
00255         assert( NestedDataSet.Size() == 0 );
00256         }
00257       if( !TagField.Write<TSwap>(os) )
00258         {
00259         assert(0 && "Should not happen");
00260         return os;
00261         }
00262       }
00263     if( ValueLengthField.IsUndefined() )
00264       {
00265       if( !ValueLengthField.Write<TSwap>(os) )
00266         {
00267         assert(0 && "Should not happen");
00268         return os;
00269         }
00270       }
00271     else
00272       {
00273       VL dummy = NestedDataSet.GetLength<TDE>();
00274       //assert( ValueLengthField == dummy );
00275       if( !dummy.Write<TSwap>(os) )
00276         {
00277         assert(0 && "Should not happen");
00278         return os;
00279         }
00280       }
00281     // Self
00282     NestedDataSet.Write<TDE,TSwap>(os);
00283     if( ValueLengthField.IsUndefined() )
00284       {
00285       const Tag itemDelItem(0xfffe,0xe00d);
00286       itemDelItem.Write<TSwap>(os);
00287       VL zero = 0;
00288       zero.Write<TSwap>(os);
00289       }
00290 
00291     return os;
00292   }
00293 
00294 /*
00295 There are three special SQ related Data Elements that are not ruled by the VR encoding rules conveyed
00296 by the Transfer Syntax. They shall be encoded as Implicit VR. These special Data Elements are Item
00297 (FFFE,E000), Item Delimitation Item (FFFE,E00D), and Sequence Delimitation Item (FFFE,E0DD).
00298 However, the Data Set within the Value Field of the Data Element Item (FFFE,E000) shall be encoded
00299 according to the rules conveyed by the Transfer Syntax.
00300 */
00301   bool FindDataElement(const Tag &t) const {
00302     return NestedDataSet.FindDataElement( t );
00303   }
00304 
00305 private:
00306   /* NESTED DATA SET  a Data Set contained within a Data Element of an other Data Set.
00307    * May be nested recursively.
00308    * Only Data Elements with VR = SQ  may, themselves, contain Data Sets
00309    */
00310   DataSet NestedDataSet;
00311 };
00312 //-----------------------------------------------------------------------------
00313 inline std::ostream& operator<<(std::ostream& os, const Item &val)
00314 {
00315   os << val.TagField;
00316   os << "\t" << val.ValueLengthField << "\n";
00317   val.NestedDataSet.Print( os, "\t" );
00318 
00319   return os;
00320 }
00321 
00322 
00323 } // end namespace gdcm
00324 
00325 #include "gdcmItem.txx"
00326 
00327 #endif //__gdcmItem_h

Generated on Wed Jun 30 13:49:14 2010 for GDCM by doxygen 1.6.3
SourceForge.net Logo