]> Creatis software - gdcm.git/blobdiff - src/gdcmDocument.cxx
ENH: This time for real. Install is ok. STYLE: some minor stuff
[gdcm.git] / src / gdcmDocument.cxx
index 0ce0c26b2d6ce554db152d489c5f5314cf323b71..8ac4b2296ae0d43209ef487b7bfed0319bf1e90c 100644 (file)
@@ -3,8 +3,8 @@
   Program:   gdcm
   Module:    $RCSfile: gdcmDocument.cxx,v $
   Language:  C++
-  Date:      $Date: 2006/02/16 20:06:14 $
-  Version:   $Revision: 1.342 $
+  Date:      $Date: 2006/05/05 22:13:55 $
+  Version:   $Revision: 1.347 $
                                                                                 
   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
   l'Image). All rights reserved. See Doc/License.txt or
@@ -695,7 +695,6 @@ void Document::WriteContent(std::ofstream *fp, FileType filetype)
       fp->write(filePreamble, 128);
       fp->write("DICM", 4);
    }
-
    /*
     * \todo rewrite later, if really usefull
     *       - 'Group Length' element is optional in DICOM
@@ -1053,11 +1052,21 @@ void Document::ParseDES(DocEntrySet *set, long offset,
    bool delim_mode_intern = delim_mode;
    bool first = true;
    gdcmDebugMacro( "Enter in ParseDES, delim-mode " <<  delim_mode
-                     << " at offset " << std::hex << "0x(" << offset << ")" ); 
+                     << " at offset " << std::hex << "0x(" << offset << ")" );    
    while (true)
    {
-   // if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max) // Once per DocEntry
    
+   ///\todo FIXME : On 64 bits processors, tellg gives unexpected results after a while ?
+   ///              Probabely a bug in gdcm code somwhere (some memory erased ?)
+
+// Uncomment to track the bug
+/*   
+   if( Debug::GetDebugFlag() )   
+      std::cout << std::dec <<"(long)(Fp->tellg()) " << (long)(Fp->tellg()) // in Debug mode
+                << std::hex << " 0x(" <<(long)(Fp->tellg()) <<  ")" << std::endl;
+*/   
+   // if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max) // Once per DocEntry   
       if ( !delim_mode ) // 'and then' doesn't exist in C++ :-(
          if ( ((long)(Fp->tellg())-offset) >= l_max) // Once per DocEntry, when no delim mode
          {
@@ -1222,7 +1231,6 @@ void Document::ParseDES(DocEntrySet *set, long offset,
                      l, delim_mode_intern);
 
             gdcmDebugMacro( "Exit from ParseSQ, delim " << delim_mode_intern);
          }
          if ( !set->AddEntry( newSeqEntry ) )
          {
@@ -1288,12 +1296,14 @@ void Document::ParseSQ( SeqEntry *seqEntry,
             break;
          }
       }
-      if ( !delim_mode ) // andthen doesn't exist in C++ :-(
+      else // ! delim_mode
+      {
          if ( ((long)(Fp->tellg())-offset) >= l_max) // Once per SQItem when no delim mode
          {
             newDocEntry->Delete();
             break;
          }
+      }
       // create the current SQItem
       SQItem *itemSQ = SQItem::New( seqEntry->GetDepthLevel() );
       unsigned int l = newDocEntry->GetReadLength();
@@ -1306,16 +1316,12 @@ void Document::ParseSQ( SeqEntry *seqEntry,
       {
          dlm_mod = false;
       }
-
-      // remove fff0,e000, created out of the SQItem
-      
-      //Fp->seekg(offsetStartCurrentSQItem, std::ios::beg); //JPRx
-      
+            
       // fill up the current SQItem, starting at the beginning of fff0,e000
-
+      
+      Fp->seekg(offsetStartCurrentSQItem, std::ios::beg);        // Once per SQItem
       ParseDES(itemSQ, offsetStartCurrentSQItem, l+8, dlm_mod);
-
-      offsetStartCurrentSQItem = Fp->tellg();  // Once per SQItem
+      offsetStartCurrentSQItem = Fp->tellg();                    // Once per SQItem
  
       seqEntry->AddSQItem( itemSQ, SQItemNumber ); 
       itemSQ->Delete();
@@ -1512,7 +1518,8 @@ void Document::FindDocEntryLength( DocEntry *entry )
      // Well ... group 0002 is always coded in 'Explicit VR Litle Endian'
      // even if Transfer Syntax is 'Implicit VR ...'
      // --> Except for 'Implicit VR Big Endian Transfer Syntax GE Private' 
-
+     //     where Group 0x0002 is *also* encoded in Implicit VR !
+      
       FixDocEntryFoundLength( entry, ReadInt32() );
       return;
    }
@@ -1584,7 +1591,9 @@ uint32_t Document::FindDocEntryLengthOBOrOW()
 VRKey Document::FindDocEntryVR()
 {
    if ( Filetype != ExplicitVR )
+   {
       return GDCM_VRUNKNOWN;
+   }
 
    // Delimiters (0xfffe), are not explicit VR ... 
    if ( CurrentGroup == 0xfffe )
@@ -1611,7 +1620,7 @@ VRKey Document::FindDocEntryVR()
    if ( !CheckDocEntryVR(vr) )
    {
 /*   
-      std::cout << "================================================================Unknown VR" 
+//      std::cout << "================================================================Unknown VR" 
                << std::hex << "0x(" 
                         << (unsigned int)vr[0] << "|" << (unsigned int)vr[1] 
                         << ")" << "for : " <<  CurrentGroup
@@ -1676,17 +1685,21 @@ void Document::SkipToNextDocEntry(DocEntry *currentDocEntry)
  *          the parser went Jabberwocky) one can hope improving things by
  *          applying some heuristics.
  * @param   entry entry to check
- * @param   foundLength first assumption about length    
+ * @param   foundLength first assumption about length (before bug fix, or set to zero if =0xffffffff)    
  */
 void Document::FixDocEntryFoundLength(DocEntry *entry,
                                       uint32_t foundLength)
 {
    entry->SetReadLength( foundLength );// will be updated only if a bug is found
+   
    if ( foundLength == 0xffffffff)
    {
-      foundLength = 0;
+      //foundLength = 0;
+      //entry->SetLength(foundLength);
+      entry->SetLength(0);
+      return;  // return ASAP; don't waist time on useless tests
    }
-   
+      
    uint16_t gr   = entry->GetGroup();
    uint16_t elem = entry->GetElement(); 
      
@@ -1716,26 +1729,37 @@ void Document::FixDocEntryFoundLength(DocEntry *entry,
    // Occurence of such images is quite low (unless one leaves close to a
    // 'Leonardo' source. Hence, one might consider commenting out the
    // following fix on efficiency reasons.
-   else if ( gr   == 0x0009 && ( elem == 0x1113 || elem == 0x1114 ) )
-   {
-      foundLength = 4;
-      entry->SetReadLength(4); // a bug is to be fixed !
-   } 
+   else if ( gr == 0x0009 && ( elem == 0x1113 || elem == 0x1114 ) )
+   { 
+   // Ideally we should check we are in Explicit and double check
+   // that VR=UL... this is done properly in gdcm2
+      if( foundLength == 6 )
+      {
+         gdcmWarningMacro( "Replacing Length from 6 into 4" );
+         foundLength = 4;
+         entry->SetReadLength(4); // a bug is to be fixed !
+      } 
+      else if ( foundLength%4 )
+      {
+        gdcmErrorMacro( "This looks like to a buggy Siemens DICOM file."
+        "The length of this tag seems to be wrong" );
+      }
+   }
+
    else if ( entry->GetVR() == "SQ" )
    {
-      foundLength = 0;      // ReadLength is unchanged 
-   } 
-    
-   //////// We encountered a 'delimiter' element i.e. a tag of the form 
+      foundLength = 0;      // ReadLength is unchanged
+   }
+
+   //////// We encountered a 'delimiter' element i.e. a tag of the form
    // "fffe|xxxx" which is just a marker. Delimiters length should not be
    // taken into account.
    else if ( gr == 0xfffe )
-   {    
+   {
      // According to the norm, fffe|0000 shouldn't exist. BUT the Philips
      // image gdcmData/gdcm-MR-PHILIPS-16-Multi-Seq.dcm happens to
      // causes extra troubles...
-     if ( entry->GetElement() != 0x0000 )
+     if ( elem != 0x0000 )
      {
         foundLength = 0;
      }
@@ -1743,7 +1767,7 @@ void Document::FixDocEntryFoundLength(DocEntry *entry,
      {
         foundLength=12; // to skip the mess that follows this bugged Tag !
      }
-   }                
+   }
    entry->SetLength(foundLength);
 }
 
@@ -2028,7 +2052,7 @@ void Document::SwitchByteSwapCode()
  * \brief  during parsing, Header Elements too long are not loaded in memory
  * @param newSize new size
  */
-void Document::SetMaxSizeLoadEntry(long newSize) 
+void Document::SetMaxSizeLoadEntry(long newSize)
 {
    if ( newSize < 0 )
    {
@@ -2047,7 +2071,7 @@ void Document::SetMaxSizeLoadEntry(long newSize)
  *          (read the 'Group Number', the 'Element Number',
  *          gets the Dict Entry
  *          gets the VR, gets the length, gets the offset value)
- * @return  On succes : the newly created DocEntry, NULL on failure.      
+ * @return  On succes : the newly created DocEntry, NULL on failure.
  */
 DocEntry *Document::ReadNextDocEntry()
 {
@@ -2058,7 +2082,7 @@ DocEntry *Document::ReadNextDocEntry()
    }
    catch ( FormatError )
    {
-      // We reached the EOF (or an error occured) therefore 
+      // We reached the EOF (or an error occured) therefore
       // header parsing has to be considered as finished.
       return 0;
    }
@@ -2070,11 +2094,10 @@ DocEntry *Document::ReadNextDocEntry()
          HandleOutOfGroup0002(CurrentGroup, CurrentElem);
       else
          // Sometimes file contains groups of tags with reversed endianess.
-         HandleBrokenEndian(CurrentGroup, CurrentElem);  
+         HandleBrokenEndian(CurrentGroup, CurrentElem);
     }
-        
+
    VRKey vr = FindDocEntryVR();
-   
    VRKey realVR = vr;
 
    if ( vr == GDCM_VRUNKNOWN )
@@ -2083,9 +2106,14 @@ DocEntry *Document::ReadNextDocEntry()
       {
          realVR = "UL";     // must be UL
       }
+      else if (CurrentGroup == 0xfffe) // Don't get DictEntry for Delimitors
+      {
+         realVR = "UL";
+      }
+
       // Commented out in order not to generate 'Shadow Groups' where some 
       // Data Elements are Explicit VR and some other ones Implicit VR
-      // (Stupid MatLab DICOM Reader couln't read gdcm-written images)
+      // (Stupid MatLab DICOM Reader couldn't read gdcm-written images)
       /*
       else if (CurrentGroup%2 == 1 &&  
                                (CurrentElem >= 0x0010 && CurrentElem <=0x00ff ))
@@ -2097,11 +2125,11 @@ DocEntry *Document::ReadNextDocEntry()
       */
       else
       {
-         DictEntry *dictEntry = GetDictEntry(CurrentGroup,CurrentElem);
+         DictEntry *dictEntry = GetDictEntry(CurrentGroup,CurrentElem);//only when ImplicitVR
          if ( dictEntry )
          {
             realVR = dictEntry->GetVR();
-            dictEntry->Unregister();
+            dictEntry->Unregister(); // GetDictEntry registered it 
          }
       }
    }
@@ -2109,8 +2137,10 @@ DocEntry *Document::ReadNextDocEntry()
    DocEntry *newEntry;
    //if ( Global::GetVR()->IsVROfSequence(realVR) )
    if (realVR == "SQ")
+   {
       newEntry = NewSeqEntry(CurrentGroup, CurrentElem);
-   else 
+   }
+   else
    {
       newEntry = NewDataEntry(CurrentGroup, CurrentElem, realVR);
       static_cast<DataEntry *>(newEntry)->SetState(DataEntry::STATE_NOTLOADED);
@@ -2122,14 +2152,14 @@ DocEntry *Document::ReadNextDocEntry()
       {
          // We thought this was explicit VR, but we end up with an
          // implicit VR tag. Let's backtrack.
-         if ( newEntry->GetGroup() != 0xfffe )
+         //if ( newEntry->GetGroup() != 0xfffe )
+         if (CurrentGroup != 0xfffe )
          { 
-            std::string msg;
             int offset = Fp->tellg();//Only when heuristic for Explicit/Implicit was wrong
-            msg = Util::Format(
-                        "Entry (%04x,%04x) at x(%x) should be Explicit VR\n", 
-                        newEntry->GetGroup(), newEntry->GetElement(), offset );
-            gdcmWarningMacro( msg.c_str() );
+
+            gdcmWarningMacro("Entry (" << newEntry->GetKey() << ") at x("
+                     <<  offset << ") should be Explicit VR");
           }
       }
       newEntry->SetImplicitVR();