]> Creatis software - gdcm.git/blobdiff - src/gdcmDocument.cxx
* src/gdcmValEntry.h: member voidArea type changed from char* to void*.
[gdcm.git] / src / gdcmDocument.cxx
index 7a987771e99c1aa8d9424f5c86e322bad6e752af..3b4c2d4a7c9ccef460ac9a6274d43ec550fd797e 100644 (file)
@@ -414,10 +414,9 @@ bool gdcmDocument::Write(FILE *fp, FileType type) {
 /**
  * \brief   Modifies the value of a given Header Entry (Dicom Element)
  *          when it exists. Create it with the given value when unexistant.
- * \warning Adds the Header Entry to the HTable, NOT to the chained List
  * @param   Value Value to be set
- * @param   Group Group of the Entry 
- * @param   Elem  Element of the Entry
+ * @param   Group   Group number of the Entry 
+ * @param   Elem  Element number of the Entry
  * \return  pointer to the modified/created Header Entry (NULL when creation
  *          failed).
  */
@@ -444,8 +443,8 @@ gdcmDocEntry * gdcmDocument::ReplaceOrCreateByNumber(
  * \brief Set a new value if the invoked element exists
  *        Seems to be useless !!!
  * @param Value new element value
- * @param Group   group of the Entry 
- * @param Elem element of the Entry
+ * @param Group  group number of the Entry 
+ * @param Elem element number of the Entry
  * \return  boolean 
  */
 bool gdcmDocument::ReplaceIfExistByNumber(char* Value, guint16 Group, guint16 Elem ) 
@@ -459,9 +458,8 @@ bool gdcmDocument::ReplaceIfExistByNumber(char* Value, guint16 Group, guint16 El
 // Protected
 
 /**
- * \brief   Checks if a given Dicom Element exists
- *          within the H table
- * @param   group Group   number of the searched Dicom Element 
+ * \brief   Checks if a given Dicom Element exists within the H table
+ * @param   group      Group number of the searched Dicom Element 
  * @param   element  Element number of the searched Dicom Element 
  * @return  number of occurences
  */
@@ -515,8 +513,8 @@ std::string gdcmDocument::GetEntryVRByName(std::string tagName) {
  * \brief   Searches within Header Entries (Dicom Elements) parsed with 
  *          the public and private dictionaries 
  *          for the element value representation of a given tag.
- * @param   group Group of the searched tag.
- * @param   element Element of the searched tag.
+ * @param   group Group number of the searched tag.
+ * @param   element Element number of the searched tag.
  * @return  Corresponding element value representation when it exists,
  *          and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
  */
@@ -536,8 +534,8 @@ std::string gdcmDocument::GetEntryByNumber(guint16 group, guint16 element){
  *          to convert the string typed content to caller's native type 
  *          (think of C++ vs Python). The VR is actually of a higher level
  *          of semantics than just the native C++ type.
- * @param   group Group of the searched tag.
- * @param   element Element of the searched tag.
+ * @param   group     Group number of the searched tag.
+ * @param   element Element number of the searched tag.
  * @return  Corresponding element value representation when it exists,
  *          and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
  */
@@ -552,8 +550,8 @@ std::string gdcmDocument::GetEntryVRByNumber(guint16 group, guint16 element) {
  * \brief   Searches within Header Entries (Dicom Elements) parsed with 
  *          the public and private dictionaries 
  *          for the value length of a given tag..
- * @param   group Group of the searched tag.
- * @param   element Element of the searched tag.
+ * @param   group     Group number of the searched tag.
+ * @param   element Element number of the searched tag.
  * @return  Corresponding element length; -2 if not found
  */
 int gdcmDocument::GetEntryLengthByNumber(guint16 group, guint16 element) {
@@ -582,8 +580,8 @@ bool gdcmDocument::SetEntryByName(std::string content,std::string tagName) {
  *          through it's (group, element) and modifies it's content with
  *          the given value.
  * @param   content new value to substitute with
- * @param   group   group of the Dicom Element to modify
- * @param   element element of the Dicom Element to modify
+ * @param   group     group number of the Dicom Element to modify
+ * @param   element element number of the Dicom Element to modify
  */
 bool gdcmDocument::SetEntryByNumber(std::string content, 
                                   guint16 group,
@@ -625,8 +623,8 @@ bool gdcmDocument::SetEntryByNumber(std::string content,
  *          the given value.
  * \warning Use with extreme caution.
  * @param l new length to substitute with
- * @param group   group of the Entry to modify
- * @param element element of the Entry to modify
+ * @param group     group number of the Entry to modify
+ * @param element element number of the Entry to modify
  * @return  true on success, false otherwise.
  */
 bool gdcmDocument::SetEntryLengthByNumber(guint32 l, 
@@ -645,8 +643,8 @@ bool gdcmDocument::SetEntryLengthByNumber(guint32 l,
 /**
  * \brief   Gets (from Header) the offset  of a 'non string' element value 
  *          (LoadElementValues has already be executed)
- * @param Group   group of the Entry 
- * @param Elem  element of the Entry
+ * @param Group   group number of the Entry 
+ * @param Elem  element number of the Entry
  * @return File Offset of the Element Value 
  */
 size_t gdcmDocument::GetEntryOffsetByNumber(guint16 Group, guint16 Elem) 
@@ -664,8 +662,8 @@ size_t gdcmDocument::GetEntryOffsetByNumber(guint16 Group, guint16 Elem)
 /**
  * \brief   Gets (from Header) a 'non string' element value 
  *          (LoadElementValues has already be executed)  
- * @param Group   group of the Entry 
- * @param Elem element of the Entry
+ * @param Group   group number of the Entry 
+ * @param Elem  element number of the Entry
  * @return Pointer to the 'non string' area
  */
 void * gdcmDocument::GetEntryVoidAreaByNumber(guint16 Group, guint16 Elem) 
@@ -683,8 +681,8 @@ void * gdcmDocument::GetEntryVoidAreaByNumber(guint16 Group, guint16 Elem)
 /**
  * \brief         Loads (from disk) the element content 
  *                when a string is not suitable
- * @param Group   group of the Entry 
- * @param Elem element of the Entry
+ * @param Group   group number of the Entry 
+ * @param Elem  element number of the Entry
  */
 void *gdcmDocument::LoadEntryVoidArea(guint16 Group, guint16 Elem) 
 {
@@ -713,7 +711,7 @@ void *gdcmDocument::LoadEntryVoidArea(guint16 Group, guint16 Elem)
 /**
  * \brief   Sets a 'non string' value to a given Dicom Element
  * @param   area
- * @param   group Group number of the searched Dicom Element 
+ * @param   group     Group number of the searched Dicom Element 
  * @param   element Element number of the searched Dicom Element 
  * @return  
  */
@@ -909,15 +907,23 @@ void gdcmDocument::WriteEntryValue(gdcmDocEntry *tag, FILE *_fp,FileType type)
    if (group == 0xfffe)
       // Delimiters have no associated value:
       return;
-      
+               
+               //--------------------------------
+               //
+               // FIXME
+               //
+               // -------------------------------
+               
+               
+/*     // to go on compiling 
    void *voidArea;
-  // voidArea = tag->GetVoidArea();  // to go on compiling
+   voidArea = tag->GetVoidArea();  // to go on compiling
    if (voidArea != NULL) 
    { // there is a 'non string' LUT, overlay, etc
       fwrite ( voidArea,(size_t)lgr ,(size_t)1 ,_fp); // Elem value
       return;            
    }
-      
+*/      
    if (vr == "US" || vr == "SS") 
    {
       // some 'Short integer' fields may be mulivaluated
@@ -967,17 +973,20 @@ void gdcmDocument::WriteEntryValue(gdcmDocEntry *tag, FILE *_fp,FileType type)
 bool gdcmDocument::WriteEntry(gdcmDocEntry *tag, FILE *_fp,FileType type)
 {
    guint32 length = tag->GetLength();
-
+   gdcmValEntry * Vtag = (gdcmValEntry *) tag;
+std::cout << "gdcmDocument::WriteEntry  Vtag->GetValue() " << Vtag->GetValue() << std::endl;
    // The value of a tag MUST (see the DICOM norm) be an odd number of
    // bytes. When this is not the case, pad with an additional byte:
    if(length%2==1)
    { 
-//      tag->SetValue(tag->GetValue()+"\0"); // to go on compiling
-      tag->SetLength(tag->GetReadLength()+1);
+      Vtag->SetValue(Vtag->GetValue()+"\0");
+      Vtag->SetLength(Vtag->GetReadLength()+1);
    }
 
-   WriteEntryTagVRLength(tag, _fp, type);
-   WriteEntryValue(tag, _fp, type);
+   WriteEntryTagVRLength(Vtag, _fp, type);
+       std::cout << "after WriteEntryTagVRLength " << std::endl;
+   WriteEntryValue(Vtag, _fp, type);
+       std::cout << "after WriteEntryValue " << std::endl;
    return true;
 }
 
@@ -990,7 +999,6 @@ bool gdcmDocument::WriteEntry(gdcmDocEntry *tag, FILE *_fp,FileType type)
  *           (function CheckHeaderCoherence to be written)
  * \warning DON'T try, right now, to write a DICOM image
  *           from an ACR Header (meta elements will be missing!)
- * \sa WriteEntriesDeprecated (Special temporary method for Theralys)
  * @param   type type of the File to be written 
  *          (ACR-NEMA, ExplicitVR, ImplicitVR)
  * @param   _fp already open file pointer
@@ -1002,25 +1010,33 @@ bool gdcmDocument::WriteEntries(FILE *_fp,FileType type)
 // FIXME : explore recursively the whole structure...
   
    /// \todo (?) check write failures (after *each* fwrite)
-     
+ std::cout << "--------------------- gdcmDocument::WriteEntries " << std::endl;   
    for (TagDocEntryHT::iterator tag2=tagHT.begin();
                                 tag2 != tagHT.end();
                               ++tag2)
    {
+       
+       (*tag2).second->Print();
+       
       if ( type == gdcmACR ){ 
          if ((*tag2).second->GetGroup() < 0x0008)
             // Ignore pure DICOM V3 groups
             continue;
-         if ((*tag2).second->GetElement() %2)
+         if ((*tag2).second->GetGroup() %2)
             // Ignore the "shadow" groups
             continue;
          if ((*tag2).second->GetVR() == "SQ" ) // ignore Sequences
             continue;
-         if ((*tag2).second->GetSQDepthLevel() != 0) // Not only ignore the SQ element
-            continue;      
+         //if ((*tag2).second->GetDepthLevel() != 0) // Not only ignore the SQ element
+         //   continue;            
       } 
-      if (! WriteEntry((*tag2).second,_fp,type) )
+      if (! WriteEntry((*tag2).second,_fp,type) ) {
+                  std::cout << "Write Failure " << std::endl;
          return false;
+               } else {
+                               
+               }
    }
    return true;
 }   
@@ -1096,7 +1112,7 @@ long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool
    gdcmValEntry *vl;
    gdcmBinEntry *bn;   
    gdcmSeqEntry *sq;
-   std::string vr;
+   VRKey vr;
    long l;
    int depth; 
    
@@ -1109,55 +1125,55 @@ long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool
       NewDocEntry = ReadNextDocEntry( );
       if (!NewDocEntry)
          break;
-              
-      vr = NewDocEntry->GetVR();        
+
+      vr = NewDocEntry->GetVR();
       if (vr!="SQ") {
                
-         if (vr == "AE" || vr == "AS" || vr == "DA" || vr == "PN" || 
-             vr == "UI" || vr == "TM" || vr == "SH" || vr == "LO" ||
-             vr == "CS" || vr == "IS" || vr == "LO" || vr == "LT" ||
-             vr == "SH" || vr == "ST" || vr == "DS" ||                   
-             vr == "SL" || vr == "SS" || vr == "UL" || vr == "US"
-                                                                 ) {
-      // --- ValEntry                           
+         if ( gdcmGlobal::GetVR()->IsVROfGdcmStringRepresentable(vr) )
+         {
+            /////// ValEntry
             vl= new gdcmValEntry(NewDocEntry->GetDictEntry());
-            vl->Copy(NewDocEntry);         
-           vl->SetDepthLevel(depth),
-            set->AddEntry(vl);     
-           LoadDocEntry(vl);
+            vl->Copy(NewDocEntry);
+            vl->SetDepthLevel(depth);
+            set->AddEntry(vl);
+            LoadDocEntry(vl);
             if (/*!delim_mode && */vl->isItemDelimitor())
                break;
-            if ( !delim_mode && ftell(fp)-offset >= l_max) {
+            if ( !delim_mode && ftell(fp)-offset >= l_max)
+            {
                break;
-           }        
-        } else { // BinEntry
-        
-        // Hope the following VR *do* correspond to a BinEntry 
-               
-        //AT Attribute Tag;         // 2 16-bit unsigned short integers
-        //FL Floating Point Single; // 32-bit IEEE 754:1985 float
-        //FD Floating Point Double; // 64-bit IEEE 754:1985 double
-        //UN Unknown;               // Any length of bytes
-        //UT Unlimited Text;        // At most 2^32 -1 chars
-       //OB Other Byte String;     // String of bytes (VR independant)
-        //OW Other Word String;     // String of 16-bit words (VR dependant)
-                
+            }
+         }
+         else
+         {
+            if ( ! gdcmGlobal::GetVR()->IsVROfGdcmBinaryRepresentable(vr) )
+            { 
+                ////// Neither ValEntry NOR BinEntry: should mean UNKOWN VR
+                dbg.Verbose(0, "gdcmDocument::ParseDES: neither Valentry, "
+                               "nor BinEntry. Probably unknown VR.");
+            }
+
+            ////// BinEntry or UNKOWN VR:
             bn = new gdcmBinEntry(NewDocEntry->GetDictEntry());
-           bn->Copy(NewDocEntry);
-           set->AddEntry(bn);
-           LoadDocEntry(bn);
-         }      
-          if (NewDocEntry->GetGroup()   == 0x7fe0 && 
-             NewDocEntry->GetElement() == 0x0010 ) {
-             if (NewDocEntry->GetLength()==0xffffffff)       
-             // Broke US.3405.1.dcm
-             
+            bn->Copy(NewDocEntry);
+            set->AddEntry(bn);
+            LoadDocEntry(bn);
+         }
+
+         if (NewDocEntry->GetGroup()   == 0x7fe0 && 
+             NewDocEntry->GetElement() == 0x0010 )
+         {
+             if (NewDocEntry->GetLength()==0xffffffff)
+                // Broken US.3405.1.dcm
                 Parse7FE0(); // to skip the pixels 
-                            // (multipart JPEG/RLE are trouble makers)       
-          } else {
-             SkipToNextDocEntry(NewDocEntry); // to be sure we are at the beginning 
-            l = NewDocEntry->GetFullLength(); 
-          }        
+                             // (multipart JPEG/RLE are trouble makers)
+         }
+         else
+         {
+             // to be sure we are at the beginning 
+             SkipToNextDocEntry(NewDocEntry);
+             l = NewDocEntry->GetFullLength(); 
+         }
       } else {   // VR = "SQ"
       
          l=NewDocEntry->GetReadLength();            
@@ -1166,24 +1182,26 @@ long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool
               delim_mode = true;
             else
               delim_mode = false;
-        // no other way to create it ...
-         sq = new gdcmSeqEntry(NewDocEntry->GetDictEntry(),set->GetDepthLevel());
+         // no other way to create it ...
+         sq = new gdcmSeqEntry(NewDocEntry->GetDictEntry(),
+                               set->GetDepthLevel());
          sq->Copy(NewDocEntry);
-        sq->SetDelimitorMode(delim_mode);
-        sq->SetDepthLevel(depth);
+         sq->SetDelimitorMode(delim_mode);
+         sq->SetDepthLevel(depth);
 
-        if (l != 0) {  // Don't try to parse zero-length sequences
-                        
+         if (l != 0)
+         {  // Don't try to parse zero-length sequences
             long lgt = ParseSQ( sq, 
                                 NewDocEntry->GetOffset(),
                                 l, delim_mode);
-        }       
-        // FIXME : on en fait quoi, de lgt ?
+         }
+         // FIXME : on en fait quoi, de lgt ?
          set->AddEntry(sq);
-         if ( !delim_mode && ftell(fp)-offset >= l_max) {       
+         if ( !delim_mode && ftell(fp)-offset >= l_max)
+         {
             break;
-        }
-      } 
+         }
+      }
    }
    delete NewDocEntry;   
    return l; // ?? 
@@ -1269,8 +1287,15 @@ void gdcmDocument::LoadDocEntry(gdcmDocEntry *Entry)  {
    // are not loaded. Instead we leave a short notice of the offset of
    // the element content and it's length.
    if (length > MaxSizeLoadEntry) {
-      std::ostringstream s;
-      ((gdcmValEntry *)Entry)->SetValue(s.str());
+      if (gdcmValEntry* ValEntryPtr = dynamic_cast< gdcmValEntry* >(Entry) )
+      {
+         std::ostringstream s;
+         s << "gdcm::NotLoaded.";
+         s << " Address:" << (long)Entry->GetOffset();
+         s << " Length:"  << Entry->GetLength();
+         s << " x(" << std::hex << Entry->GetLength() << ")";
+         ValEntryPtr->SetValue(s.str());
+      }
       // to be sure we are at the end of the value ...
       fseek(fp,(long)Entry->GetOffset()+(long)Entry->GetLength(),SEEK_SET);
       
@@ -2238,8 +2263,8 @@ gdcmDocEntry *gdcmDocument::NewDocEntryByName(std::string Name)
 
 /**
  * \brief   Request a new virtual dict entry to the dict set
- * @param   group  group   of the underlying DictEntry
- * @param   element  element of the underlying DictEntry
+ * @param   group     group  number of the underlying DictEntry
+ * @param   element  element number of the underlying DictEntry
  * @param   vr     VR of the underlying DictEntry
  * @param   fourth owner group
  * @param   name   english name
@@ -2256,8 +2281,8 @@ gdcmDictEntry *gdcmDocument::NewVirtualDictEntry(guint16 group, guint16 element,
  * \brief   Build a new Element Value from all the low level arguments. 
  *          Check for existence of dictionary entry, and build
  *          a default one when absent.
- * @param   Group group   of the underlying DictEntry
- * @param   Elem  element of the underlying DictEntry
+ * @param   Group group   number of the underlying DictEntry
+ * @param   Elem  element number of the underlying DictEntry
  */
 gdcmDocEntry *gdcmDocument::NewDocEntryByNumber(guint16 Group, guint16 Elem) 
 {