]> Creatis software - gdcm.git/blobdiff - src/gdcmDocument.cxx
comment out deprecated method Load(filename), everywhere.
[gdcm.git] / src / gdcmDocument.cxx
index 94de7cae21bbd26f098d29e818042818650268c4..1a3f177c3525696ae6a6126d146b0625c3f84943 100644 (file)
@@ -3,8 +3,8 @@
   Program:   gdcm
   Module:    $RCSfile: gdcmDocument.cxx,v $
   Language:  C++
-  Date:      $Date: 2005/10/18 11:35:31 $
-  Version:   $Revision: 1.293 $
+  Date:      $Date: 2005/11/21 16:28:06 $
+  Version:   $Revision: 1.331 $
                                                                                 
   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
   l'Image). All rights reserved. See Doc/License.txt or
@@ -76,7 +76,6 @@ Document::~Document ()
 
 //-----------------------------------------------------------------------------
 // Public
-
 /**
  * \brief   Loader. use SetLoadMode(), SetFileName() before ! 
  * @return false if file cannot be open or no swap info was found,
@@ -90,18 +89,17 @@ bool Document::Load(  )
       return false;
    }
    return DoTheLoadingDocumentJob( );
-} 
-/**
- * \brief   Loader. (DEPRECATED : not to break the API)   
- * @param   fileName 'Document' (File or DicomDir) to be open for parsing
- * @return false if file cannot be open or no swap info was found,
- *         or no tag was found.
- */
+}
+
+/*
+//#ifndef GDCM_LEGACY_REMOVE 
 bool Document::Load( std::string const &fileName ) 
 {
    Filename = fileName;
    return DoTheLoadingDocumentJob( );
 }
+//#endif
+*/
 
 /**
  * \brief   Performs the Loading Job (internal use only)  
@@ -119,15 +117,13 @@ bool Document::DoTheLoadingDocumentJob(  )
    if ( !OpenFile() )
    {
       // warning already performed in OpenFile()
-      //gdcmWarningMacro( "Unable to open as an ACR/DICOM file: "
-      //                 << Filename.c_str() );
       Filetype = Unknown;
       return false;
    }
 
    Group0002Parsed = false;
 
-   gdcmWarningMacro( "Starting parsing of file: " << Filename.c_str());
+   gdcmDebugMacro( "Starting parsing of file: " << Filename.c_str());
 
    Fp->seekg(0, std::ios::end);
    long lgt = Fp->tellg();       // total length of the file
@@ -154,7 +150,7 @@ bool Document::DoTheLoadingDocumentJob(  )
 
    if ( IsEmpty() )
    { 
-      gdcmWarningMacro( "No tag in internal hash table for: "
+      gdcmErrorMacro( "No tag in internal hash table for: "
                         << Filename.c_str());
       CloseFile(); 
       return false;
@@ -174,20 +170,33 @@ bool Document::DoTheLoadingDocumentJob(  )
       LoadEntryBinArea(0x0028,0x1200);  // gray LUT
    
       /// FIXME
+      /// --> FIXME : The difference between BinEntry and DataEntry
+      /// --> no longer exists, but the alteration of Dicom Dictionary remains.
+      /// --> Old comment restored on purpose.
+      /// --> New one (replacing both BinEntry and ValEntry by DataEntry)
+      /// --> had absolutely no meaning.
+      /// --> The whole comment will be removed when the stuff is cleaned !
+      /// -->
       /// The tags refered by the three following lines used to be CORRECTLY
       /// defined as having an US Value Representation in the public
       /// dictionary. BUT the semantics implied by the three following
       /// lines state that the corresponding tag contents are in fact
-      /// the ones of a DataEntry.
+      /// the ones of a BinEntry.
       /// In order to fix things "Quick and Dirty" the dictionary was
       /// altered on PURPOSE but now contains a WRONG value.
       /// In order to fix things and restore the dictionary to its
-      /// correct value, one needs to decided of the semantics by deciding
+      /// correct value, one needs to decide of the semantics by deciding
       /// whether the following tags are either :
-      /// - multivaluated US, and hence loaded as DataEntry, but afterwards
-      ///   also used as DataEntry, which requires the proper conversion,
-      /// - OW, and hence loaded as DataEntry, but afterwards also used
-      ///   as DataEntry, which requires the proper conversion.
+      /// - multivaluated US, and hence loaded as ValEntry, but afterwards
+      ///   also used as BinEntry, which requires the proper conversion,
+      /// - OW, and hence loaded as BinEntry, but afterwards also used
+      ///   as ValEntry, which requires the proper conversion.
+      
+      // --> OB (byte aray) or OW (short int aray)
+      // The actual VR has to be deduced from other entries.
+      // Our way of loading them may fail in some cases :
+      // We must or not SwapByte depending on other field values.
+             
       LoadEntryBinArea(0x0028,0x1201);  // R    LUT
       LoadEntryBinArea(0x0028,0x1202);  // G    LUT
       LoadEntryBinArea(0x0028,0x1203);  // B    LUT
@@ -212,6 +221,8 @@ bool Document::DoTheLoadingDocumentJob(  )
          {
             if ( dataEntry->GetLength() != 0 )
             {
+               // FIXME : CTX dependent means : contexted dependant.
+               //         see upper comment.
                LoadEntryBinArea(dataEntry);    //LUT Data (CTX dependent)
             }   
         }
@@ -225,7 +236,7 @@ bool Document::DoTheLoadingDocumentJob(  )
                                it != UserForceLoadList.end();
                              ++it)
    {
-      gdcmWarningMacro( "Force Load " << std::hex 
+      gdcmDebugMacro( "Force Load " << std::hex 
                        << (*it).Group << "|" <<(*it).Elem );
   
       d = GetDocEntry( (*it).Group, (*it).Elem);
@@ -277,7 +288,7 @@ bool Document::DoTheLoadingDocumentJob(  )
  */
 void Document::AddForceLoadElement (uint16_t group, uint16_t elem) 
 { 
-   Element el;
+   DicomElement el;
    el.Group = group;
    el.Elem  = elem;
    UserForceLoadList.push_back(el); 
@@ -325,11 +336,11 @@ bool Document::SetShaDict(DictKey const &dictName)
  * @return false when we're 150 % sure it's NOT a Dicom/Acr file,
  *         true otherwise. 
  */
-bool Document::IsReadable()
+bool Document::IsParsable()
 {
    if ( Filetype == Unknown )
    {
-      gdcmWarningMacro( "Wrong filetype");
+      gdcmWarningMacro( "Wrong filetype for " << GetFileName());
       return false;
    }
 
@@ -341,6 +352,17 @@ bool Document::IsReadable()
 
    return true;
 }
+/**
+ * \brief  This predicate tells us whether or not the current Document 
+ *         was properly parsed and contains at least *one* Dicom Element
+ *         (and nothing more, sorry).
+ * @return false when we're 150 % sure it's NOT a Dicom/Acr file,
+ *         true otherwise. 
+ */
+bool Document::IsReadable()
+{
+   return IsParsable();
+}
 
 /**
  * \brief   Predicate for dicom version 3 file.
@@ -386,7 +408,8 @@ FileType Document::GetFileType()
  * \brief   Accessor to the Transfer Syntax (when present) of the
  *          current document (it internally handles reading the
  *          value from disk when only parsing occured).
- * @return  The encountered Transfer Syntax of the current document.
+ * @return  The encountered Transfer Syntax of the current document, if DICOM.
+ *          GDCM_UNKNOWN for ACR-NEMA files (or broken headers ...)
  */
 std::string Document::GetTransferSyntax()
 {
@@ -408,6 +431,7 @@ std::string Document::GetTransferSyntax()
       if  ( transfer.length() == 0 )
       {
          // for brain damaged headers
+         gdcmWarningMacro( "Transfer Syntax has length = 0.");
          return GDCM_UNKNOWN;
       }
       while ( !isdigit((unsigned char)transfer[transfer.length()-1]) )
@@ -416,6 +440,7 @@ std::string Document::GetTransferSyntax()
          if  ( transfer.length() == 0 )
          {
             // for brain damaged headers
+            gdcmWarningMacro( "Transfer Syntax contains no valid character.");
             return GDCM_UNKNOWN;
          }
       }
@@ -441,7 +466,7 @@ std::string Document::GetTransferSyntaxName()
    }
    if ( transferSyntax == GDCM_UNFOUND )
    {
-      gdcmWarningMacro( "Unfound Transfer Syntax (0002,0010)");
+      gdcmDebugMacro( "Unfound Transfer Syntax (0002,0010)");
       return "Uncompressed ACR-NEMA";
    }
 
@@ -494,12 +519,48 @@ uint32_t Document::SwapLong(uint32_t a)
          a=( ((a<< 8) & 0xff00ff00) | ((a>>8) & 0x00ff00ff)  );
       break;
       default :
-         gdcmErrorMacro( "Unset swap code:" << SwapCode );
+         gdcmErrorMacro( "Unexpected swap code:" << SwapCode );
          a = 0;
    }
    return a;
 } 
 
+/**
+ * \brief   Swaps back the bytes of 8-byte long 'double' accordingly to
+ *          processor order.
+ * @return  The properly swaped 64 bits double.
+ */
+double Document::SwapDouble(double a)
+{
+   switch (SwapCode)
+   {
+      // There were no 'double' at ACR-NEMA time.
+      // We just have to deal with 'straight Little Endian' and 
+      // 'straight Big Endian'
+      case 1234 :
+         break;
+      case 4321 :
+         {
+         char *beg = (char *)&a;
+         char *end = beg + 7;
+         char t;
+         for (unsigned int i = 0; i<7; i++)
+         {
+            t    = *beg;
+            *beg = *end;
+            *end = t;
+            beg++,
+            end--;  
+         }
+         }
+         break;   
+      default :
+         gdcmErrorMacro( "Unexpected swap code:" << SwapCode );
+         a = 0.;
+   }
+   return a;
+} 
+
 //
 // -----------------File I/O ---------------
 /**
@@ -517,7 +578,7 @@ std::ifstream *Document::OpenFile()
 
    if ( Fp )
    {
-      gdcmWarningMacro( "File already open: " << Filename.c_str());
+      gdcmDebugMacro( "File already open: " << Filename.c_str());
       CloseFile();
    }
 
@@ -528,6 +589,10 @@ std::ifstream *Document::OpenFile()
    // a spurious message will appear when you use, for instance 
    // gdcm::FileHelper *fh = new gdcm::FileHelper( outputFileName );
    // to create outputFileName.
+   
+   // FIXME : if the upper comment is still usefull 
+   //         --> the constructor is not so good ...
+   
       gdcmWarningMacro( "Cannot open file: " << Filename.c_str());
       delete Fp;
       Fp = 0;
@@ -544,7 +609,10 @@ std::ifstream *Document::OpenFile()
       return 0;
    }
  
-   //-- ACR or DICOM with no Preamble; may start with a Shadow Group --
+   //-- Broken ACR or DICOM with no Preamble; may start with a Shadow Group --
+   
+   // FIXME : We cannot be sure the preable is only zeroes..
+   //         (see ACUSON-24-YBR_FULL-RLE.dcm )
    if ( 
        zero == 0x0001 || zero == 0x0100 || zero == 0x0002 || zero == 0x0200 ||
        zero == 0x0003 || zero == 0x0300 || zero == 0x0004 || zero == 0x0400 ||
@@ -552,7 +620,8 @@ std::ifstream *Document::OpenFile()
        zero == 0x0007 || zero == 0x0700 || zero == 0x0008 || zero == 0x0800 )
    {
       std::string msg = Util::Format(
-        "ACR/DICOM starting at the beginning of the file:(%04x)\n", zero);
+        "ACR/DICOM starting by 0x(%04x) at the beginning of the file\n", zero);
+      // FIXME : is it a Warning message, or a Debug message?
       gdcmWarningMacro( msg.c_str() );
       return Fp;
    }
@@ -574,7 +643,9 @@ std::ifstream *Document::OpenFile()
 
    // -- Neither ACR/No Preamble Dicom nor DICOMV3 file
    CloseFile();
-   gdcmWarningMacro( "Neither ACR/No Preamble Dicom nor DICOMV3 file: "
+   // Don't user Warning nor Error, not to polute the output
+   // while directory recursive parsing ...
+   gdcmDebugMacro( "Neither ACR/No Preamble Dicom nor DICOMV3 file: "
                       << Filename.c_str()); 
    return 0;
 }
@@ -604,7 +675,8 @@ void Document::WriteContent(std::ofstream *fp, FileType filetype)
 {
    // Skip if user wants to write an ACR-NEMA file
 
-   if ( filetype == ImplicitVR || filetype == ExplicitVR )
+   if ( filetype == ImplicitVR || filetype == ExplicitVR ||
+        filetype == JPEG )
    {
       // writing Dicom File Preamble
       char filePreamble[128];
@@ -623,6 +695,10 @@ void Document::WriteContent(std::ofstream *fp, FileType filetype)
     *    UpdateGroupLength(false,filetype);
     * if ( filetype == ACR)
     *    UpdateGroupLength(true,ACR);
+    *
+    * --> Computing group length for groups with embeded Sequences
+    * --> was too much tricky / we were [in a hurry / too lazy]
+    * --> We don't write the element 0x0000 (group length)
     */
 
    ElementSet::WriteContent(fp, filetype); // This one is recursive
@@ -642,15 +718,15 @@ void Document::LoadEntryBinArea(uint16_t group, uint16_t elem)
    DocEntry *docEntry = GetDocEntry(group, elem);
    if ( !docEntry )
    {
-      gdcmWarningMacro(std::hex << group << "|" << elem 
-                       <<  "doesn't exist" );
+      gdcmDebugMacro(std::hex << group << "|" << elem 
+                       <<  " doesn't exist" );
       return;
    }
    DataEntry *dataEntry = dynamic_cast<DataEntry *>(docEntry);
    if ( !dataEntry )
    {
       gdcmWarningMacro(std::hex << group << "|" << elem 
-                       <<  "is NOT a DataEntry");
+                       <<  " is NOT a DataEntry");
       return;
    }
    LoadEntryBinArea(dataEntry);
@@ -659,7 +735,7 @@ void Document::LoadEntryBinArea(uint16_t group, uint16_t elem)
 /**
  * \brief Loads (from disk) the element content 
  *        when a string is not suitable
- * @param elem  Entry whose binArea is going to be loaded
+ * @param entry  Entry whose binArea is going to be loaded
  */
 void Document::LoadEntryBinArea(DataEntry *entry) 
 {
@@ -683,7 +759,7 @@ void Document::LoadEntryBinArea(DataEntry *entry)
       return;
    }
 
-   // Read the datas
+   // Read the data
    Fp->read((char*)data, l);
    if ( Fp->fail() || Fp->eof() )
    {
@@ -696,11 +772,17 @@ void Document::LoadEntryBinArea(DataEntry *entry)
    uint32_t i;
    unsigned short vrLgth = 
                         Global::GetVR()->GetAtomicElementLength(entry->GetVR());
-   if( entry->GetVR() == "OW" )
-      vrLgth = 1;
+
+// FIXME : trouble expected if we read an ... OW Entry (LUT, etc ..)
+//   if( entry->GetVR() == "OW" )
+//      vrLgth = 1;
 
    switch(vrLgth)
    {
+      case 1:
+      {
+         break;
+      }     
       case 2:
       {
          uint16_t *data16 = (uint16_t *)data;
@@ -717,10 +799,9 @@ void Document::LoadEntryBinArea(DataEntry *entry)
       }
       case 8:
       {
-         gdcmWarningMacro("Can't swap 64 bits datas");
-/*         uint64_t *data64 = (uint64_t *)data;
+         double *data64 = (double *)data;
          for(i=0;i<l/vrLgth;i++)
-            data64[i] = SwapLongLong(data64[i]);*/
+            data64[i] = SwapDouble(data64[i]);
          break;
       }
    }
@@ -860,7 +941,6 @@ uint32_t Document::ReadInt32()
 
 /**
  * \brief skips bytes inside the source file 
- * \warning NOT end user intended method !
  * @return 
  */
 void Document::SkipBytes(uint32_t nBytes)
@@ -870,12 +950,12 @@ void Document::SkipBytes(uint32_t nBytes)
 }
 
 /**
- * \brief   Re-computes the length of a ACR-NEMA/Dicom group from a DcmHeader
+ * \brief   Re-computes the length of the Dicom group 0002.
  */
 int Document::ComputeGroup0002Length( ) 
 {
    uint16_t gr;
-   std::string vr;
+   VRKey vr;
    
    int groupLength = 0;
    bool found0002 = false;   
@@ -894,18 +974,14 @@ int Document::ComputeGroup0002Length( )
          {
             vr = entry->GetVR();
 
-            // FIXME : group 0x0002 is *always* Explicit VR!
-            //if ( filetype == ExplicitVR )
-            //{
             //if ( (vr == "OB")||(vr == "OW")||(vr == "UT")||(vr == "SQ"))
             // (no SQ, OW, UT in group 0x0002;)
                if ( vr == "OB" ) 
                {
-                  // explicit VR AND OB, OW, SQ, UT : 4 more bytes
+                  // explicit VR AND (OB, OW, SQ, UT) : 4 more bytes
                   groupLength +=  4;
                }
-            //}
             groupLength += 2 + 2 + 4 + entry->GetLength();   
          }
       }
@@ -921,7 +997,6 @@ int Document::ComputeGroup0002Length( )
 // Private
 /**
  * \brief Loads all the needed Dictionaries
- * \warning NOT end user intended method !   
  */
 void Document::Initialize() 
 {
@@ -948,7 +1023,7 @@ void Document::ParseDES(DocEntrySet *set, long offset,
               // (Entry will then be deleted)
    bool delim_mode_intern = delim_mode;
    bool first = true;
-   gdcmWarningMacro( "Enter in ParseDES, delim-mode " <<  delim_mode
+   gdcmDebugMacro( "Enter in ParseDES, delim-mode " <<  delim_mode
                      << " at offset " << std::hex << offset ); 
    while (true)
    {
@@ -959,19 +1034,10 @@ void Document::ParseDES(DocEntrySet *set, long offset,
 
       newDocEntry = ReadNextDocEntry( );
 
-      // FIXME :
-      // Private tag, in IMplicit VR are defaulted as a DataEntry,
-      // Very often they are only composed of Printable characters, 
-      // and could be defaulted as a DataEntry.
-      // It's too late to do the Job
-      // (we should check the value, but we know it after LoadDocEntry ...)
-
-      // Uncoment this printf line to be able to 'follow' the DocEntries
+      // Uncoment this cerr line to be able to 'follow' the DocEntries
       // when something *very* strange happens
-
-      //printf( "%04x|%04x %s\n",newDocEntry->GetGroup(), 
-      //                     newDocEntry->GetElement(),
-      //                     newDocEntry->GetVR().c_str() );
+      if( Debug::GetDebugFlag() ) 
+         std::cerr<<newDocEntry->GetKey()<<" "<<newDocEntry->GetVR()<<std::endl;
 
       if ( !newDocEntry )
       {
@@ -983,8 +1049,9 @@ void Document::ParseDES(DocEntrySet *set, long offset,
        // but we didn't get it (private Sequence + Implicit VR)
        // we have to backtrack.
       if ( !first && newDocEntry->IsItemStarter() )
-      {
-         newDocEntry = Backtrack(newDocEntry); 
+      { 
+        // Debug message within the method !      
+        newDocEntry = Backtrack(newDocEntry); 
       }
       else
       { 
@@ -997,20 +1064,12 @@ void Document::ParseDES(DocEntrySet *set, long offset,
       if ( newDataEntry )  
       {
          //////////////////////////// DataEntry
          vr = newDocEntry->GetVR();
-         if ( Filetype == ExplicitVR && 
-               !Global::GetVR()->IsVROfBinaryRepresentable(vr) )
-         { 
-               ////// No DataEntry: should mean UNKOWN VR
-               gdcmWarningMacro( std::hex << newDocEntry->GetGroup() 
-                                 << "|" << newDocEntry->GetElement()
-                                 << " : No DataEntry." 
-                                 "Probably unknown VR.");
-         }
 
          if ( !set->AddEntry( newDataEntry ) )
          {
-            gdcmWarningMacro( "in ParseDES : cannot add a DataEntry "
+            gdcmDebugMacro( "in ParseDES : cannot add a DataEntry "
                                  << newDataEntry->GetKey()  
                                  << " (at offset : " 
                                  << newDataEntry->GetOffset() << " )" );
@@ -1018,6 +1077,7 @@ void Document::ParseDES(DocEntrySet *set, long offset,
          }
          else
          {
+            newDataEntry->Delete();
             // Load only if we can add (not a duplicate key)
             LoadDocEntry( newDataEntry );
          }
@@ -1050,7 +1110,7 @@ void Document::ParseDES(DocEntrySet *set, long offset,
                (!delim_mode && ((long)(Fp->tellg())-offset) >= l_max) )
          {
             if ( !used )
-               delete newDocEntry;
+               newDocEntry->Delete();
             break;
          }
 
@@ -1080,8 +1140,7 @@ void Document::ParseDES(DocEntrySet *set, long offset,
             if ( newDocEntry->GetGroup()%2 != 0 )
             {
                 Fp->seekg( l, std::ios::cur);
-                RemoveEntry( newDocEntry );  // Remove and delete
-                //used = false; // never used
+                newDocEntry->Delete();  // Delete, not in the set 
                 continue;  
             } 
          } 
@@ -1089,8 +1148,7 @@ void Document::ParseDES(DocEntrySet *set, long offset,
          {
            // User asked to skip *any* SeQuence
             Fp->seekg( l, std::ios::cur);
-            //used = false; // never used
-            RemoveEntry( newDocEntry );  // Remove and delete
+            newDocEntry->Delete(); // Delete, not in the set
             continue;
          }
          // delay the dynamic cast as late as possible
@@ -1103,11 +1161,9 @@ void Document::ParseDES(DocEntrySet *set, long offset,
          // is a Document, then we are building the first depth level.
          // Hence the SeqEntry we are building simply has a depth
          // level of one:
-//         SQItem *parentSQItem = dynamic_cast< SQItem* > ( set );
         if ( set == this ) // ( dynamic_cast< Document* > ( set ) )
          {
             newSeqEntry->SetDepthLevel( 1 );
-         //   newSeqEntry->SetKey( newSeqEntry->GetKey() );
          }
          // But when "set" is already a SQItem, we are building a nested
          // sequence, and hence the depth level of the new SeqEntry
@@ -1117,15 +1173,12 @@ void Document::ParseDES(DocEntrySet *set, long offset,
          else if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) )
          {
             newSeqEntry->SetDepthLevel( parentSQItem->GetDepthLevel() + 1 );
-
-          //  newSeqEntry->SetKey(  parentSQItem->GetBaseTagKey()
-          //                      + newSeqEntry->GetKey() );
          }
 
          if ( l != 0 )
          {  // Don't try to parse zero-length sequences
 
-            gdcmWarningMacro( "Entry in ParseSQ, delim " << delim_mode_intern
+            gdcmDebugMacro( "Entry in ParseSQ, delim " << delim_mode_intern
                                << " at offset " << std::hex
                                << newDocEntry->GetOffset() );
 
@@ -1133,7 +1186,7 @@ void Document::ParseDES(DocEntrySet *set, long offset,
                      newDocEntry->GetOffset(),
                      l, delim_mode_intern);
 
-            gdcmWarningMacro( "Exit from ParseSQ, delim " << delim_mode_intern);
+            gdcmDebugMacro( "Exit from ParseSQ, delim " << delim_mode_intern);
  
          }
          if ( !set->AddEntry( newSeqEntry ) )
@@ -1144,22 +1197,26 @@ void Document::ParseDES(DocEntrySet *set, long offset,
                                 << newSeqEntry->GetOffset() << " )" ); 
             used = false;
          }
+         else
+         {
+            newDocEntry->Delete();
+         }
  
          if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
          {
             if ( !used )
-               delete newDocEntry;  
-               break;
+               newDocEntry->Delete();
+            break;
          }
       }  // end SeqEntry : VR = "SQ"
 
       if ( !used )
       {
-         delete newDocEntry;
+         newDocEntry->Delete();
       }
       first = false;
    }                               // end While
-   gdcmWarningMacro( "Exit from ParseDES, delim-mode " << delim_mode );
+   gdcmDebugMacro( "Exit from ParseDES, delim-mode " << delim_mode );
 }
 
 /**
@@ -1180,7 +1237,6 @@ void Document::ParseSQ( SeqEntry *seqEntry,
 
       if ( !newDocEntry )
       {
-         // FIXME Should warn user
          gdcmWarningMacro("in ParseSQ : should never get here!");
          break;
       }
@@ -1189,16 +1245,17 @@ void Document::ParseSQ( SeqEntry *seqEntry,
          if ( newDocEntry->IsSequenceDelimitor() )
          {
             seqEntry->SetDelimitationItem( newDocEntry ); 
+            newDocEntry->Delete();
             break;
          }
       }
       if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
       {
-         delete newDocEntry;
+         newDocEntry->Delete();
          break;
       }
       // create the current SQItem
-      SQItem *itemSQ = new SQItem( seqEntry->GetDepthLevel() );
+      SQItem *itemSQ = SQItem::New( seqEntry->GetDepthLevel() );
       unsigned int l = newDocEntry->GetReadLength();
       
       if ( l == 0xffffffff )
@@ -1210,18 +1267,17 @@ void Document::ParseSQ( SeqEntry *seqEntry,
          dlm_mod = false;
       }
 
-      // Let's try :------------
       // remove fff0,e000, created out of the SQItem
-      delete newDocEntry;
       Fp->seekg(offsetStartCurrentSQItem, std::ios::beg);
       // fill up the current SQItem, starting at the beginning of fff0,e000
 
       ParseDES(itemSQ, offsetStartCurrentSQItem, l+8, dlm_mod);
 
       offsetStartCurrentSQItem = Fp->tellg();
-      // end try -----------------
  
       seqEntry->AddSQItem( itemSQ, SQItemNumber ); 
+      itemSQ->Delete();
+      newDocEntry->Delete();
       SQItemNumber++;
       if ( !delim_mode && ((long)(Fp->tellg())-offset ) >= l_max )
       {
@@ -1240,7 +1296,7 @@ DocEntry *Document::Backtrack(DocEntry *docEntry)
 {
    // delete the Item Starter, built erroneously out of any Sequence
    // it's not yet in the HTable/chained list
-   delete docEntry;
+   docEntry->Delete();
 
    // Get all info we can from PreviousDocEntry
    uint16_t group = PreviousDocEntry->GetGroup();
@@ -1248,7 +1304,7 @@ DocEntry *Document::Backtrack(DocEntry *docEntry)
    uint32_t lgt   = PreviousDocEntry->GetLength();
    long offset    = PreviousDocEntry->GetOffset();
 
-   gdcmWarningMacro( "Backtrack :" << std::hex << group 
+   gdcmDebugMacro( "Backtrack :" << std::hex << group 
                                    << "|" << elem
                                    << " at offset " << offset );
    RemoveEntry( PreviousDocEntry );
@@ -1275,7 +1331,7 @@ void Document::LoadDocEntry(DocEntry *entry, bool forceLoad)
 {
    uint16_t group  = entry->GetGroup();
    uint16_t elem  = entry->GetElement();
-   std::string  vr = entry->GetVR();
+   const VRKey  &vr = entry->GetVR();
    uint32_t length = entry->GetLength();
 
    Fp->seekg((long)entry->GetOffset(), std::ios::beg);
@@ -1308,8 +1364,7 @@ void Document::LoadDocEntry(DocEntry *entry, bool forceLoad)
    }
 
    // The elements whose length is bigger than the specified upper bound
-   // are not loaded. Instead we leave a short notice on the offset of
-   // the element content and it's length.
+   // are not loaded.
 
    std::ostringstream s;
 
@@ -1337,7 +1392,7 @@ void Document::LoadDocEntry(DocEntry *entry, bool forceLoad)
 void Document::FindDocEntryLength( DocEntry *entry )
    throw ( FormatError )
 {
-   std::string  vr  = entry->GetVR();
+   const VRKey &vr  = entry->GetVR();
    uint16_t length16;       
    
    if ( Filetype == ExplicitVR && !entry->IsImplicitVR() ) 
@@ -1408,7 +1463,8 @@ void Document::FindDocEntryLength( DocEntry *entry )
       // Length is on 4 bytes.
 
      // Well ... group 0002 is always coded in 'Explicit VR Litle Endian'
-     // even if Transfer Syntax is 'Implicit VR ...' 
+     // even if Transfer Syntax is 'Implicit VR ...'
+     // --> Except for 'Implicit VR Big Endian Transfer Syntax GE Private' 
       
       FixDocEntryFoundLength( entry, ReadInt32() );
       return;
@@ -1417,7 +1473,6 @@ void Document::FindDocEntryLength( DocEntry *entry )
 
 /**
  * \brief  Find the Length till the next sequence delimiter
- * \warning NOT end user intended method !
  * @return 
  */
 uint32_t Document::FindDocEntryLengthOBOrOW()
@@ -1478,28 +1533,33 @@ uint32_t Document::FindDocEntryLengthOBOrOW()
  * \brief     Find the Value Representation of the current Dicom Element.
  * @return    Value Representation of the current Entry
  */
-std::string Document::FindDocEntryVR()
+VRKey Document::FindDocEntryVR()
 {
    if ( Filetype != ExplicitVR )
-      return GDCM_UNKNOWN;
+      return GDCM_VRUNKNOWN;
 
    long positionOnEntry = Fp->tellg();
    // Warning: we believe this is explicit VR (Value Representation) because
-   // we used a heuristic that found "UL" in the first tag. Alas this
-   // doesn't guarantee that all the tags will be in explicit VR. In some
-   // cases (see e-film filtered files) one finds implicit VR tags mixed
-   // within an explicit VR file. Hence we make sure the present tag
-   // is in explicit VR and try to fix things if it happens not to be
-   // the case.
+   // we used a heuristic that found "UL" in the first tag and/or
+   // 'Transfer Syntax' told us it is.
+   // Alas this doesn't guarantee that all the tags will be in explicit VR. 
+   // In some cases one finds implicit VR tags mixed within an explicit VR file.
+   // Hence we make sure the present tag is in explicit VR and try to fix things
+   // if it happens not to be the case.
 
-   char vr[3];
-   Fp->read (vr, (size_t)2);
-   vr[2] = 0;
+   VRKey vr;
+   Fp->read(&(vr[0]),(size_t)2);
 
    if ( !CheckDocEntryVR(vr) )
    {
+      // Don't warn user with useless messages
+      // Often, delimiters (0xfffe), are not explicit VR ...
+      if ( CurrentGroup != 0xfffe )
+         gdcmWarningMacro( "Unknown VR " << std::hex << "0x(" 
+                        << (unsigned int)vr[0] << "|" << (unsigned int)vr[1] 
+                        << ") at offset :" << positionOnEntry );
       Fp->seekg(positionOnEntry, std::ios::beg);
-      return GDCM_UNKNOWN;
+      return GDCM_VRUNKNOWN;
    }
    return vr;
 }
@@ -1512,17 +1572,13 @@ std::string Document::FindDocEntryVR()
  * @return    false if the VR is incorrect or if the VR isn't referenced
  *            otherwise, it returns true
 */
-bool Document::CheckDocEntryVR(VRKey vr)
+bool Document::CheckDocEntryVR(const VRKey &vr)
 {
-   if ( !Global::GetVR()->IsValidVR(vr) )
-      return false;
-
-   return true; 
+   return Global::GetVR()->IsValidVR(vr);
 }
 
 /**
  * \brief   Skip a given Header Entry 
- * \warning NOT end user intended method !
  * @param   entry entry to skip
  */
 void Document::SkipDocEntry(DocEntry *entry) 
@@ -1532,7 +1588,6 @@ void Document::SkipDocEntry(DocEntry *entry)
 
 /**
  * \brief   Skips to the beginning of the next Header Entry 
- * \warning NOT end user intended method !
  * @param   currentDocEntry entry to skip
  */
 void Document::SkipToNextDocEntry(DocEntry *currentDocEntry) 
@@ -1634,7 +1689,7 @@ bool Document::IsDocEntryAnInteger(DocEntry *entry)
 {
    uint16_t elem         = entry->GetElement();
    uint16_t group        = entry->GetGroup();
-   const std::string &vr = entry->GetVR();
+   const VRKey &vr       = entry->GetVR();
    uint32_t length       = entry->GetLength();
 
    // When we have some semantics on the element we just read, and if we
@@ -1648,9 +1703,9 @@ bool Document::IsDocEntryAnInteger(DocEntry *entry)
       }
       else 
       {
-         // Allthough this should never happen, still some images have a
+         // Although this should never happen, still some images have a
          // corrupted group length [e.g. have a glance at offset x(8336) of
-         // gdcmData/gdcm-MR-PHILIPS-16-Multi-Seq.dcm].
+         // gdcmData/gdcm-MR-PHILIPS-16-Multi-Seq.dcm.
          // Since for dicom compliant and well behaved headers, the present
          // test is useless (and might even look a bit paranoid), when we
          // encounter such an ill-formed image, we simply display a warning
@@ -1696,7 +1751,7 @@ bool Document::CheckSwap()
    char *entCur = deb + 128;
    if ( memcmp(entCur, "DICM", (size_t)4) == 0 )
    {
-      gdcmWarningMacro( "Looks like DICOM Version3 (preamble + DCM)" );
+      gdcmDebugMacro( "Looks like DICOM Version3 (preamble + DCM)" );
       
       // Group 0002 should always be VR, and the first element 0000
       // Let's be carefull (so many wrong headers ...)
@@ -1728,7 +1783,7 @@ bool Document::CheckSwap()
       // instead of just checking for UL, OB and UI !? group 0000 
       {
          Filetype = ExplicitVR;
-         gdcmWarningMacro( "Group 0002 : Explicit Value Representation");
+         gdcmDebugMacro( "Group 0002 : Explicit Value Representation");
       } 
       else 
       {
@@ -1740,12 +1795,12 @@ bool Document::CheckSwap()
       if ( net2host )
       {
          SwapCode = 4321;
-         gdcmWarningMacro( "HostByteOrder != NetworkByteOrder");
+         gdcmDebugMacro( "HostByteOrder != NetworkByteOrder, SwapCode = 4321");
       }
       else 
       {
          SwapCode = 1234;
-         gdcmWarningMacro( "HostByteOrder = NetworkByteOrder");
+         gdcmDebugMacro( "HostByteOrder = NetworkByteOrder, SwapCode = 1234");
       }
       
       // Position the file position indicator at first tag 
@@ -1792,7 +1847,7 @@ bool Document::CheckSwap()
            memcmp(entCur, "OB", (size_t)2) == 0 )
          {
             Filetype = ExplicitVR;
-            gdcmWarningMacro( "Group 0002 : Explicit Value Representation");
+            gdcmDebugMacro( "Group 0002 : Explicit Value Representation");
             return true;
           }
     }
@@ -1881,8 +1936,8 @@ bool Document::CheckSwap()
  */
 void Document::SwitchByteSwapCode() 
 {
-   gdcmWarningMacro( "Switching Byte Swap code from "<< SwapCode
-                     << " at :" <<std::hex << Fp->tellg() );
+   gdcmDebugMacro( "Switching Byte Swap code from "<< SwapCode
+                     << " at: 0x" << std::hex << Fp->tellg() );
    if ( SwapCode == 1234 ) 
    {
       SwapCode = 4321;
@@ -1899,6 +1954,7 @@ void Document::SwitchByteSwapCode()
    {
       SwapCode = 3412;
    }
+   gdcmDebugMacro( " Into: "<< SwapCode );
 }
 
 /**
@@ -1928,13 +1984,10 @@ void Document::SetMaxSizeLoadEntry(long newSize)
  */
 DocEntry *Document::ReadNextDocEntry()
 {
-   uint16_t group;
-   uint16_t elem;
-
    try
    {
-      group = ReadInt16();
-      elem  = ReadInt16();
+      CurrentGroup = ReadInt16();
+      CurrentElem  = ReadInt16();
    }
    catch ( FormatError )
    {
@@ -1944,22 +1997,24 @@ DocEntry *Document::ReadNextDocEntry()
    }
 
    // Sometimes file contains groups of tags with reversed endianess.
-   HandleBrokenEndian(group, elem);
+   HandleBrokenEndian(CurrentGroup, CurrentElem);
 
    // In 'true DICOM' files Group 0002 is always little endian
    if ( HasDCMPreamble )
-      HandleOutOfGroup0002(group, elem);
+      HandleOutOfGroup0002(CurrentGroup, CurrentElem);
  
-   std::string vr = FindDocEntryVR();
-   std::string realVR = vr;
+   VRKey vr = FindDocEntryVR();
+   
+   VRKey realVR = vr;
 
-   if ( vr == GDCM_UNKNOWN )
+   if ( vr == GDCM_VRUNKNOWN )
    {
-      if ( elem == 0x0000 ) // Group Length
+      if ( CurrentElem == 0x0000 ) // Group Length
       {
          realVR = "UL";     // must be UL
       }
-      else if (group%2 == 1 &&  (elem >= 0x0010 && elem <=0x00ff ))
+      else if (CurrentGroup%2 == 1 &&  
+                               (CurrentElem >= 0x0010 && CurrentElem <=0x00ff ))
       {  
       // DICOM PS 3-5 7.8.1 a) states that those 
       // (gggg-0010->00FF where gggg is odd) attributes have to be LO
@@ -1967,24 +2022,26 @@ DocEntry *Document::ReadNextDocEntry()
       }
       else
       {
-         DictEntry *dictEntry = GetDictEntry(group,elem);
+         DictEntry *dictEntry = GetDictEntry(CurrentGroup,CurrentElem);
          if ( dictEntry )
          {
             realVR = dictEntry->GetVR();
+            dictEntry->Unregister();
          }
       }
    }
+  // gdcmDebugMacro( "Found VR: " << vr << " / Real VR: " << realVR );
 
    DocEntry *newEntry;
    if ( Global::GetVR()->IsVROfSequence(realVR) )
-      newEntry = NewSeqEntry(group, elem);
+      newEntry = NewSeqEntry(CurrentGroup, CurrentElem);
    else 
    {
-      newEntry = NewDataEntry(group, elem, realVR);
+      newEntry = NewDataEntry(CurrentGroup, CurrentElem, realVR);
       static_cast<DataEntry *>(newEntry)->SetState(DataEntry::STATE_NOTLOADED);
    }
 
-   if ( vr == GDCM_UNKNOWN )
+   if ( vr == GDCM_VRUNKNOWN )
    {
       if ( Filetype == ExplicitVR )
       {
@@ -2010,7 +2067,7 @@ DocEntry *Document::ReadNextDocEntry()
    catch ( FormatError )
    {
       // Call it quits
-      delete newEntry;
+      newEntry->Delete();
       return 0;
    }
 
@@ -2034,6 +2091,7 @@ void Document::HandleBrokenEndian(uint16_t &group, uint16_t &elem)
    if ((group == 0xfeff) && (elem == 0x00e0))
    {
      // start endian swap mark for group found
+     gdcmDebugMacro( "Start endian swap mark found." );
      reversedEndian++;
      SwitchByteSwapCode();
      // fix the tag
@@ -2043,6 +2101,7 @@ void Document::HandleBrokenEndian(uint16_t &group, uint16_t &elem)
    else if (group == 0xfffe && elem == 0xe00d && reversedEndian) 
    {
      // end of reversed endian group
+     gdcmDebugMacro( "End of reversed endian." );
      reversedEndian--;
      SwitchByteSwapCode();
    }
@@ -2060,7 +2119,7 @@ void Document::HandleBrokenEndian(uint16_t &group, uint16_t &elem)
    }
    else if (group == 0xfffe && elem == 0xe0dd) 
    {
-      gdcmWarningMacro( "Straight Sequence Terminator." );  
+      gdcmDebugMacro( "Straight Sequence Terminator." );  
    }
 }
 
@@ -2077,12 +2136,18 @@ void Document::HandleOutOfGroup0002(uint16_t &group, uint16_t &elem)
    {
       Group0002Parsed = true;
       // we just came out of group 0002
-      // if Transfer syntax is Big Endian we have to change CheckSwap
+      // if Transfer Syntax is Big Endian we have to change CheckSwap
 
       std::string ts = GetTransferSyntax();
+      if ( ts == GDCM_UNKNOWN )
+      {
+         gdcmDebugMacro("True DICOM File, with NO Transfer Syntax (?!) " );
+         return;      
+      }
       if ( !Global::GetTS()->IsTransferSyntax(ts) )
       {
-         gdcmWarningMacro("True DICOM File, with NO Tansfer Syntax: " << ts );
+         gdcmWarningMacro("True DICOM File, with illegal Transfer Syntax: [" 
+                          << ts << "]");
          return;
       }
 
@@ -2091,9 +2156,9 @@ void Document::HandleOutOfGroup0002(uint16_t &group, uint16_t &elem)
 
       if ( Global::GetTS()->GetSpecialTransferSyntax(ts) == 
                                                     TS::ImplicitVRLittleEndian )
-         {
-            Filetype = ImplicitVR;
-         }
+      {
+         Filetype = ImplicitVR;
+      }
        
       // FIXME Strangely, this works with 
       //'Implicit VR BigEndian Transfer Syntax (GE Private)
@@ -2105,7 +2170,7 @@ void Document::HandleOutOfGroup0002(uint16_t &group, uint16_t &elem)
       if ( Global::GetTS()->GetSpecialTransferSyntax(ts) == 
                                                        TS::ExplicitVRBigEndian )
       {
-         gdcmWarningMacro("Transfer Syntax Name = [" 
+         gdcmDebugMacro("Transfer Syntax Name = [" 
                         << GetTransferSyntaxName() << "]" );
          SwitchByteSwapCode();
          group = SwapShort(group);