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

Generated on Sat Dec 4 2010 08:58:44 for GDCM by doxygen 1.7.2
SourceForge.net Logo