]> Creatis software - gdcm.git/blobdiff - src/gdcmDocument.cxx
ENH: Properly recompile jasper if a header/file is modified. Also fixed a compilation...
[gdcm.git] / src / gdcmDocument.cxx
index 284ea27e28f463d729f456e532f8abfd7a98c562..cf01f037d4dcac996c871677ab89b3658da04b44 100644 (file)
@@ -3,8 +3,8 @@
   Program:   gdcm
   Module:    $RCSfile: gdcmDocument.cxx,v $
   Language:  C++
-  Date:      $Date: 2005/04/26 16:18:23 $
-  Version:   $Revision: 1.237 $
+  Date:      $Date: 2005/06/07 15:31:31 $
+  Version:   $Revision: 1.244 $
                                                                                 
   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
   l'Image). All rights reserved. See Doc/License.txt or
@@ -35,8 +35,6 @@
 namespace gdcm 
 {
 //-----------------------------------------------------------------------------
-// Refer to Document::CheckSwap()
-//const unsigned int Document::HEADER_LENGTH_TO_READ = 256;
 
 // Refer to Document::SetMaxSizeLoadEntry()
 const unsigned int Document::MAX_SIZE_LOAD_ELEMENT_VALUE = 0xfff; // 4096
@@ -67,9 +65,9 @@ Document::Document()
 
 /**
  * \brief   Constructor (not to break the API) 
- * @param   filename 'Document' (File or DicomDir) to be opened for parsing
+ * @param   fileName 'Document' (File or DicomDir) to be opened for parsing
  */
-Document::Document( std::string const &filename )
+Document::Document( std::string const &fileName )
          :ElementSet(-1) 
 {
    Fp = 0;
@@ -84,7 +82,12 @@ Document::Document( std::string const &filename )
    // Load will set it to true if sucessfull
    IsDocumentAlreadyLoaded = false;
 
-   Load(filename); 
+   Load(fileName);
+
+   // Normaly (?) Fp should be already deleted by CloseFile()
+   if ( Fp != 0 ) 
+      delete Fp;
+   Fp = 0;    
 }
 /**
  * \brief   Canonical destructor.
@@ -100,23 +103,25 @@ Document::~Document ()
 
 /**
  * \brief   Loader  
- * @param   filename 'Document' (File or DicomDir) to be opened for parsing
+ * @param   fileName 'Document' (File or DicomDir) to be opened for parsing
+ * @return false if file cannot be open or no swap info was found,
+ *         or no tag was found.
  */
-void Document::Load( std::string const &filename ) 
+bool Document::Load( std::string const &fileName ) 
 {
    // We should clean out anything that already exists.
    // Check IsDocumentAlreadyLoaded to be sure.
    if( IsDocumentAlreadyLoaded )
    {
-      gdcmWarningMacro( "A file was already parsed inside this " <<
-                   "gdcm::Document (previous name was: "
-                    << Filename.c_str() << ". New name is :"
-                    << filename );
+      gdcmWarningMacro( "A file was already parsed inside this "
+                        << "gdcm::Document (previous name was: "
+                        << Filename.c_str() << ". New name is :"
+                        << fileName );
      // todo : clean out the 'Document'
      // We should call ClearEntry() on the parent object ?!?
    }
 
-   Filename = filename;
+   Filename = fileName;
 
    Fp = 0;
    if ( !OpenFile() )
@@ -125,7 +130,7 @@ void Document::Load( std::string const &filename )
       //gdcmWarningMacro( "Unable to open as an ACR/DICOM file: "
       //                 << Filename.c_str() );
       Filetype = Unknown;
-      return;
+      return false;
    }
 
    Group0002Parsed = false;
@@ -144,7 +149,7 @@ void Document::Load( std::string const &filename )
       gdcmWarningMacro( "Neither a DICOM V3 nor an ACR-NEMA file: " 
                    << Filename.c_str());
       CloseFile(); 
-      return ;      
+      return false;      
     }
 
    long beg = Fp->tellg();      // just after DICOM preamble (if any)
@@ -158,7 +163,7 @@ void Document::Load( std::string const &filename )
       gdcmWarningMacro( "No tag in internal hash table for: "
                         << Filename.c_str());
       CloseFile(); 
-      return ;
+      return false;
    }
    IsDocumentAlreadyLoaded = true;
 
@@ -224,6 +229,8 @@ void Document::Load( std::string const &filename )
          SetValEntry(rows   , 0x0028, 0x0011);
    }
    // --- End of ACR-LibIDO kludge --- 
+
+   return true;
 }
 
 /**
@@ -463,7 +470,11 @@ std::ifstream *Document::OpenFile()
    Fp = new std::ifstream(Filename.c_str(), std::ios::in | std::ios::binary);
    if( ! *Fp )
    {
-      gdcmErrorMacro( "Cannot open file: " << Filename.c_str());
+   // Don't user gdcmErrorMacro :
+   // a spurious message will appear when you use, for instance 
+   // gdcm::FileHelper *fh = new gdcm::FileHelper( outputFileName );
+   // to create outputFileName.
+      gdcmWarningMacro( "Cannot open file: " << Filename.c_str());
       delete Fp;
       Fp = 0;
       return 0;
@@ -794,9 +805,9 @@ int Document::ComputeGroup0002Length( FileType filetype )
  
             if( filetype == ExplicitVR )
             {
-               if ( (vr == "OB") || (vr == "OW") || (vr == "SQ") ) 
+               if ( (vr == "OB") || (vr == "OW") || (vr == "SQ") || (vr == "UT") 
                {
-                  // explicit VR AND OB, OW, SQ : 4 more bytes
+                  // explicit VR AND OB, OW, SQ, UT : 4 more bytes
                   groupLength +=  4;
                }
             }
@@ -934,7 +945,7 @@ void Document::ParseDES(DocEntrySet *set, long offset,
                      if ( strLgrGroup != GDCM_UNFOUND)
                      {
                         lgrGroup = atoi(strLgrGroup.c_str());
-                        Fp->seekg(lgrGroup , std::ios::cur);
+                        Fp->seekg(lgrGroup, std::ios::cur);
                         used = false;
                         continue;
                      }
@@ -1145,7 +1156,6 @@ void Document::LoadDocEntry(DocEntry *entry)
    {
       if (BinEntry *binEntryPtr = dynamic_cast< BinEntry* >(entry) )
       {  
-         //s << "gdcm::NotLoaded (BinEntry)";
          s << GDCM_NOTLOADED;
          s << " Ad.:" << (long)entry->GetOffset();
          s << " x(" << std::hex << entry->GetOffset() << ")";
@@ -1154,10 +1164,8 @@ void Document::LoadDocEntry(DocEntry *entry)
          s << " x(" << std::hex << entry->GetLength() << ")";
          binEntryPtr->SetValue(s.str());
       }
-      // Be carefull : a BinEntry IS_A ValEntry ... 
       else if (ValEntry *valEntryPtr = dynamic_cast< ValEntry* >(entry) )
       {
-        // s << "gdcm::NotLoaded. (ValEntry)";
          s << GDCM_NOTLOADED;  
          s << " Address:" << (long)entry->GetOffset();
          s << " Length:"  << entry->GetLength();
@@ -1191,7 +1199,7 @@ void Document::LoadDocEntry(DocEntry *entry)
       uint32_t NewInt;
       int nbInt;
       // When short integer(s) are expected, read and convert the following 
-      // n *two characters properly i.e. consider them as short integers as
+      // (n * 2) characters properly i.e. consider them as short integers as
       // opposed to strings.
       // Elements with Value Multiplicity > 1
       // contain a set of integers (not a single one)       
@@ -1244,7 +1252,7 @@ void Document::LoadDocEntry(DocEntry *entry)
    {
       newValue = Util::DicomString(str, length+1);
       gdcmWarningMacro("Warning: bad length: " << length <<
-                       ",For string :" <<  newValue.c_str()); 
+                       " ,For string :" <<  newValue.c_str()); 
       // Since we change the length of string update it length
       //entry->SetReadLength(length+1);
    }
@@ -1291,7 +1299,7 @@ void Document::FindDocEntryLength( DocEntry *entry )
    
    if ( Filetype == ExplicitVR && !entry->IsImplicitVR() ) 
    {
-      if ( vr == "OB" || vr == "OW" || vr == "SQ" || vr == "UN" ) 
+      if ( vr == "OB" || vr == "OW" || vr == "SQ" || vr == "UT" || vr == "UN" ) 
       {
          // The following reserved two bytes (see PS 3.5-2003, section
          // "7.1.2 Data element structure with explicit vr", p 27) must be
@@ -1646,7 +1654,7 @@ void Document::FixDocEntryFoundLength(DocEntry *entry,
    // Allthough not recent many such GE corrupted images are still present
    // on Creatis hard disks. Hence this fix shall remain when such images
    // are no longer in use (we are talking a few years, here)...
-   // Note: XMedCom probably uses such a trick since it is able to read
+   // Note: XMedCon probably uses such a trick since it is able to read
    //       those pesky GE images ...
    if ( foundLength == 13)
    {
@@ -1820,7 +1828,9 @@ bool Document::CheckSwap()
       
       // Position the file position indicator at first tag 
       // (i.e. after the file preamble and the "DICM" string).
-      Fp->seekg(0, std::ios::beg);
+
+      Fp->seekg(0, std::ios::beg); // FIXME : Is it usefull?
+
       Fp->seekg ( 132L, std::ios::beg);
       return true;
    } // ------------------------------- End of DicomV3 ----------------
@@ -1829,10 +1839,43 @@ bool Document::CheckSwap()
    // preamble. We can reset the file position indicator to where the data
    // is (i.e. the beginning of the file).
 
-   gdcmWarningMacro( "Not a DICOM Version3 file");
+   gdcmWarningMacro( "Not a Kosher DICOM Version3 file (no preamble)");
 
    Fp->seekg(0, std::ios::beg);
 
+   // Let's check 'No Preamble Dicom File' :
+   // Should start with group 0x0002
+   // and be Explicit Value Representation
+
+   s16 = *((uint16_t *)(deb));
+   SwapCode = 0;     
+   switch ( s16 )
+   {
+      case 0x0002 :
+         SwapCode = 1234;
+         entCur = deb + 4;
+         break;
+      case 0x0200 :
+         SwapCode = 4321;
+         entCur = deb + 6;
+    } 
+
+   if ( SwapCode != 0 )
+   {
+      if( memcmp(entCur, "UL", (size_t)2) == 0 ||
+          memcmp(entCur, "OB", (size_t)2) == 0 ||
+          memcmp(entCur, "UI", (size_t)2) == 0 ||
+          memcmp(entCur, "SH", (size_t)2) == 0 ||
+          memcmp(entCur, "AE", (size_t)2) == 0 ||
+          memcmp(entCur, "OB", (size_t)2) == 0 )
+         {
+            Filetype = ExplicitVR;
+            gdcmWarningMacro( "Group 0002 : Explicit Value Representation");
+            return true;
+          }
+    }
+// ------------------------------- End of 'No Preamble' DicomV3 -------------
+
    // Our next best chance would be to be considering a 'clean' ACR/NEMA file.
    // By clean we mean that the length of the first group is written down.
    // If this is the case and since the length of the first group HAS to be