]> Creatis software - gdcm.git/blobdiff - src/gdcmDocument.cxx
ENH: Getting real close to having JPEG support in gdcm... jpeg offset table still...
[gdcm.git] / src / gdcmDocument.cxx
index 693d425e6ecf27530982d04c4e9ef331138f98fa..6de517611e6ae675c4ae9f2712b9e7bee9ed69ba 100644 (file)
@@ -3,8 +3,8 @@
   Program:   gdcm
   Module:    $RCSfile: gdcmDocument.cxx,v $
   Language:  C++
-  Date:      $Date: 2005/10/18 10:43:31 $
-  Version:   $Revision: 1.291 $
+  Date:      $Date: 2005/10/18 19:54:26 $
+  Version:   $Revision: 1.296 $
                                                                                 
   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
   l'Image). All rights reserved. See Doc/License.txt or
@@ -604,7 +604,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];
@@ -694,7 +695,8 @@ void Document::LoadEntryBinArea(DataEntry *entry)
 
    // Swap the data content if necessary
    uint32_t i;
-   unsigned short vrLgth = Global::GetVR()->GetAtomicElementLength(entry->GetVR());
+   unsigned short vrLgth = 
+                        Global::GetVR()->GetAtomicElementLength(entry->GetVR());
    if( entry->GetVR() == "OW" )
       vrLgth = 1;
 
@@ -871,10 +873,10 @@ void Document::SkipBytes(uint32_t nBytes)
 /**
  * \brief   Re-computes the length of a ACR-NEMA/Dicom group from a DcmHeader
  */
-int Document::ComputeGroup0002Length( /*FileType filetype*/ 
+int Document::ComputeGroup0002Length( ) 
 {
    uint16_t gr;
-   std::string vr;
+   VRKey vr;
    
    int groupLength = 0;
    bool found0002 = false;   
@@ -897,7 +899,7 @@ int Document::ComputeGroup0002Length( /*FileType filetype*/ )
  
             //if ( filetype == ExplicitVR )
             //{
-            //   if ( (vr == "OB") || (vr == "OW") || (vr == "UT") || (vr == "SQ") )
+            //if ( (vr == "OB")||(vr == "OW")||(vr == "UT")||(vr == "SQ"))
             // (no SQ, OW, UT in group 0x0002;)
                if ( vr == "OB" ) 
                {
@@ -1273,7 +1275,8 @@ DocEntry *Document::Backtrack(DocEntry *docEntry)
 void Document::LoadDocEntry(DocEntry *entry, bool forceLoad)
 {
    uint16_t group  = entry->GetGroup();
-   std::string  vr = entry->GetVR();
+   uint16_t elem  = entry->GetElement();
+   const VRKey  &vr = entry->GetVR();
    uint32_t length = entry->GetLength();
 
    Fp->seekg((long)entry->GetOffset(), std::ios::beg);
@@ -1282,7 +1285,11 @@ void Document::LoadDocEntry(DocEntry *entry, bool forceLoad)
    //          (fffe e000) tells us an Element is beginning
    //          (fffe e00d) tells us an Element just ended
    //          (fffe e0dd) tells us the current SeQuence just ended
-   if ( group == 0xfffe || vr == "SQ" )
+   //
+   //          (fffe 0000) is an 'impossible' tag value, 
+   //                                    found in MR-PHILIPS-16-Multi-Seq.dcm
+   
+   if ( (group == 0xfffe && elem != 0x0000 ) || vr == "SQ" )
    {
       // NO more value field for SQ !
       return;
@@ -1331,7 +1338,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() ) 
@@ -1472,10 +1479,10 @@ 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
@@ -1486,14 +1493,15 @@ std::string Document::FindDocEntryVR()
    // 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);
 
+   gdcmWarningMacro( "--> VR: " << vr )
    if ( !CheckDocEntryVR(vr) )
    {
+      gdcmWarningMacro( "Unknown VR '" << vr << "'" )
       Fp->seekg(positionOnEntry, std::ios::beg);
-      return GDCM_UNKNOWN;
+      return GDCM_VRUNKNOWN;
    }
    return vr;
 }
@@ -1506,12 +1514,9 @@ 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);
 }
 
 /**
@@ -1552,7 +1557,7 @@ void Document::SkipToNextDocEntry(DocEntry *currentDocEntry)
 void Document::FixDocEntryFoundLength(DocEntry *entry,
                                       uint32_t foundLength)
 {
-   entry->SetReadLength( foundLength ); // will be updated only if a bug is found        
+   entry->SetReadLength( foundLength );// will be updated only if a bug is found
    if ( foundLength == 0xffffffff)
    {
       foundLength = 0;
@@ -1563,7 +1568,7 @@ void Document::FixDocEntryFoundLength(DocEntry *entry,
      
    if ( foundLength % 2)
    {
-      gdcmWarningMacro( "Warning : Tag with uneven length " << foundLength 
+      gdcmWarningMacro( "Warning : Tag with uneven length " << foundLength
         <<  " in x(" << std::hex << gr << "," << elem <<")");
    }
       
@@ -1590,7 +1595,7 @@ void Document::FixDocEntryFoundLength(DocEntry *entry,
    else if ( gr   == 0x0009 && ( elem == 0x1113 || elem == 0x1114 ) )
    {
       foundLength = 4;
-      entry->SetReadLength(4); // a bug is to be fixed !?
+      entry->SetReadLength(4); // a bug is to be fixed !
    } 
  
    else if ( entry->GetVR() == "SQ" )
@@ -1610,7 +1615,11 @@ void Document::FixDocEntryFoundLength(DocEntry *entry,
      {
         foundLength = 0;
      }
-   }            
+     else
+     {
+        foundLength=12; // to skip the mess that follows this bugged Tag !
+     }
+   }                
    entry->SetLength(foundLength);
 }
 
@@ -1624,7 +1633,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
@@ -1828,7 +1837,7 @@ bool Document::CheckSwap()
          //  Only 0 or 4321 will be possible 
          //  (no oportunity to check for the formerly well known
          //  ACR-NEMA 'Bad Big Endian' or 'Bad Little Endian' 
-         //  if unsuccessfull (i.e. neither 0x0002 nor 0x0200 etc -3, 4, ..., 8-) 
+         //  if unsuccessfull (i.e. neither 0x0002 nor 0x0200 etc-3, 4, ..., 8-)
          //  the file IS NOT ACR-NEMA nor DICOM V3
          //  Find a trick to tell it the caller...
       
@@ -1859,7 +1868,7 @@ bool Document::CheckSwap()
                Filetype = ACR;
                return true;
             default :
-               gdcmWarningMacro("ACR/NEMA unfound swap info (Really hopeless !)");
+               gdcmWarningMacro("ACR/NEMA unfound swap info (Hopeless !)");
                Filetype = Unknown;
                return false;
          }
@@ -1940,10 +1949,11 @@ DocEntry *Document::ReadNextDocEntry()
    if ( HasDCMPreamble )
       HandleOutOfGroup0002(group, elem);
  
-   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
       {
@@ -1964,6 +1974,7 @@ DocEntry *Document::ReadNextDocEntry()
          }
       }
    }
+   gdcmWarningMacro( "Found VR: " << vr << " / Real VR: " << realVR );
 
    DocEntry *newEntry;
    if ( Global::GetVR()->IsVROfSequence(realVR) )
@@ -1974,7 +1985,7 @@ DocEntry *Document::ReadNextDocEntry()
       static_cast<DataEntry *>(newEntry)->SetState(DataEntry::STATE_NOTLOADED);
    }
 
-   if ( vr == GDCM_UNKNOWN )
+   if ( vr == GDCM_VRUNKNOWN )
    {
       if ( Filetype == ExplicitVR )
       {
@@ -1984,8 +1995,9 @@ DocEntry *Document::ReadNextDocEntry()
          { 
             std::string msg;
             int offset = Fp->tellg();
-            msg = Util::Format("Entry (%04x,%04x) at 0x(%x) should be Explicit VR\n", 
-                          newEntry->GetGroup(), newEntry->GetElement(), offset );
+            msg = Util::Format(
+                        "Entry (%04x,%04x) at x(%x) should be Explicit VR\n", 
+                        newEntry->GetGroup(), newEntry->GetElement(), offset );
             gdcmWarningMacro( msg.c_str() );
           }
       }
@@ -2016,7 +2028,8 @@ DocEntry *Document::ReadNextDocEntry()
  */
 void Document::HandleBrokenEndian(uint16_t &group, uint16_t &elem)
 {
-   // Endian reversion. Some files contain groups of tags with reversed endianess.
+   // Endian reversion. 
+   // Some files contain groups of tags with reversed endianess.
    static int reversedEndian = 0;
    // try to fix endian switching in the middle of headers
    if ((group == 0xfeff) && (elem == 0x00e0))
@@ -2041,7 +2054,7 @@ void Document::HandleBrokenEndian(uint16_t &group, uint16_t &elem)
      // Do what you want, it breaks !
      //reversedEndian--;
      //SwitchByteSwapCode();
-     gdcmWarningMacro( "Should never get here! reversed Sequence Terminator!" ); 
+     gdcmWarningMacro( "Should never get here! reversed Sequence Terminator!" );
      // fix the tag
       group = 0xfffe;
       elem  = 0xe0dd;  
@@ -2059,7 +2072,8 @@ void Document::HandleBrokenEndian(uint16_t &group, uint16_t &elem)
  */
 void Document::HandleOutOfGroup0002(uint16_t &group, uint16_t &elem)
 {
-   // Endian reversion. Some files contain groups of tags with reversed endianess.
+   // Endian reversion. 
+   // Some files contain groups of tags with reversed endianess.
    if ( !Group0002Parsed && group != 0x0002)
    {
       Group0002Parsed = true;
@@ -2073,9 +2087,11 @@ void Document::HandleOutOfGroup0002(uint16_t &group, uint16_t &elem)
          return;
       }
 
-      // Group 0002 is always 'Explicit ...' even when Transfer Syntax says 'Implicit ..." 
+      // Group 0002 is always 'Explicit ...' 
+      // even when Transfer Syntax says 'Implicit ..." 
 
-      if ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRLittleEndian )
+      if ( Global::GetTS()->GetSpecialTransferSyntax(ts) == 
+                                                    TS::ImplicitVRLittleEndian )
          {
             Filetype = ImplicitVR;
          }
@@ -2083,9 +2099,12 @@ void Document::HandleOutOfGroup0002(uint16_t &group, uint16_t &elem)
       // FIXME Strangely, this works with 
       //'Implicit VR BigEndian Transfer Syntax (GE Private)
       //
-      // --> Probabely normal, since we considered we never have to trust manufacturers.
-      // (we find very often 'Implicit VR' tag, even when Transfer Syntax tells us it's Explicit ...
-      if ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRBigEndian )
+      // --> Probabely normal, since we considered we never have 
+      // to trust manufacturers.
+      // (we find very often 'Implicit VR' tag, 
+      // even when Transfer Syntax tells us it's Explicit ...
+      if ( Global::GetTS()->GetSpecialTransferSyntax(ts) == 
+                                                       TS::ExplicitVRBigEndian )
       {
          gdcmWarningMacro("Transfer Syntax Name = [" 
                         << GetTransferSyntaxName() << "]" );