]> Creatis software - gdcm.git/blobdiff - src/gdcmElValSet.cxx
*FIX: Use carnaught table to reduce boolean expr !
[gdcm.git] / src / gdcmElValSet.cxx
index a672453712cd52d6536a706c37142c6d6bce7657..634237d2da097a174b036a7afeb4431165ba2c99 100644 (file)
@@ -1,18 +1,15 @@
 // gdcmElValSet.cxx
 
-#ifdef _MSC_VER
-// 'identifier' : class 'type' needs to have dll-interface to be used by
-// clients of class 'type2'
-#pragma warning ( disable : 4251 )
-// 'identifier' : identifier was truncated to 'number' characters in the
-// debug information
-#pragma warning ( disable : 4786 )
-#endif //_MSC_VER
-
-#include <sstream>
 #include "gdcmUtil.h"
 #include "gdcmElValSet.h"
 #include "gdcmTS.h"
+#ifdef GDCM_NO_ANSI_STRING_STREAM
+#  include <strstream>
+#  define  ostringstream ostrstream
+# else
+#  include <sstream>
+#endif
+
 
 gdcmElValSet::~gdcmElValSet() {
    for (TagElValueHT::iterator tag = tagHt.begin(); tag != tagHt.end(); ++tag) {
@@ -27,10 +24,6 @@ gdcmElValSet::~gdcmElValSet() {
    NameHt.clear();
 }
 
-TagElValueHT & gdcmElValSet::GetTagHt(void) {
-       return tagHt;
-}
-
 /**
  * \ingroup gdcmElValSet
  * \brief   
@@ -40,6 +33,11 @@ TagElValueHT & gdcmElValSet::GetTagHt(void) {
 void gdcmElValSet::Add(gdcmElValue * newElValue) {
        tagHt [newElValue->GetKey()]  = newElValue;
        NameHt[newElValue->GetName()] = newElValue;
+       
+// WARNING : push_bash in listElem ONLY during ParseHeader
+// TODO : something to allow further Elements addition 
+// position to be taken care of !      
+       listElem.push_back(newElValue); 
 }
 
 /**
@@ -59,14 +57,16 @@ int gdcmElValSet::CheckIfExistByNumber(guint16 Group, guint16 Elem ) {
  * \ingroup gdcmElValSet
  * \brief   
  */
-void gdcmElValSet::Print(ostream & os) {
+void gdcmElValSet::Print(std::ostream & os) {
 
    size_t o;
-   short int g, e;
+   unsigned short int g, e;
    TSKey v;
    std::string d2;
    gdcmTS * ts = gdcmGlobal::GetTS();
    
+   std::cout << "------------- using tagHt ---------------------" << std::endl;
+   
    for (TagElValueHT::iterator tag = tagHt.begin();
           tag != tagHt.end();
           ++tag){
@@ -79,7 +79,7 @@ void gdcmElValSet::Print(ostream & os) {
       os << tag->first << ": ";
       os << " lgr : " << tag->second->GetLength();
       os << ", Offset : " << o;
-      os << " x(" << hex << o << dec << ") ";
+      os << " x(" << std::hex << o << std::dec << ") ";
       os << "\t[" << tag->second->GetVR()    << "]";
       os << "\t[" << tag->second->GetName()  << "]";       
       os << "\t[" << d2 << "]";
@@ -94,22 +94,61 @@ void gdcmElValSet::Print(ostream & os) {
                os << "  ==>\t[" << ts->GetValue(v) << "]"; 
          }
       }              
-      os << endl;
+      os << std::endl;
    }
+   
+   std::cout << "------------ using listElem -------------------" << std::endl;
+      
+  guint32 lgth;
+  char greltag[10];  //group element tag
+   
+  for (ListTag::iterator i = listElem.begin();  
+          i != listElem.end();
+          ++i){
+      g = (*i)->GetGroup();
+      e = (*i)->GetElement();
+      v = (*i)->GetValue();
+      o = (*i)->GetOffset();
+      sprintf(greltag,"%04x|%04x",g,e);           
+      d2 = _CreateCleanString(v);  // replace non printable characters by '.'
+      os << greltag << ": lgth : ";
+      lgth = (*i)->GetReadLength();
+      if ( lgth == 0xffffffff) 
+         os << std::hex << lgth << std::dec ;
+      else
+         os << lgth;
+      os << ", Offset : " << o;
+      os << " x(" << std::hex << o << std::dec << ") ";
+      os << "\t[" << (*i)->GetVR()    << "]";
+      os << "\t[" << (*i)->GetName()  << "]";       
+      os << "\t[" << d2 << "]";
+      
+      // Display the UID value (instead of displaying the rough code)  
+      if (g == 0x0002) {  // Any more to be displayed ?
+         if ( (e == 0x0010) || (e == 0x0002) )            
+            os << "  ==>\t[" << ts->GetValue(v) << "]";   
+      } else {
+         if (g == 0x0008) {
+            if ( (e == 0x0016) || (e == 0x1150)  )        
+               os << "  ==>\t[" << ts->GetValue(v) << "]"; 
+         }
+      }              
+      os << std::endl;
+   }      
 } 
 
 /**
  * \ingroup gdcmElValSet
  * \brief   
  */
-void gdcmElValSet::PrintByName(ostream & os) {
+void gdcmElValSet::PrintByName(std::ostream & os) {
    for (TagElValueNameHT::iterator tag = NameHt.begin();
           tag != NameHt.end();
           ++tag){
       os << tag->first << ": ";
       os << "[" << tag->second->GetValue() << "]";
       os << "[" << tag->second->GetKey()   << "]";
-      os << "[" << tag->second->GetVR()    << "]" << endl;
+      os << "[" << tag->second->GetVR()    << "]" << std::endl;
    }
 }
 
@@ -176,7 +215,13 @@ int gdcmElValSet::SetElValueByNumber(std::string content,
    TagKey key = gdcmDictEntry::TranslateToKey(group, element);
    if ( ! tagHt.count(key))
       return 0;
-   tagHt[key]->SetValue(content);      
+   int l = content.length();
+   if(l%2) {  // Odd length are padded with a space (020H).
+      l++;
+      content = content + '\0';
+   }
+   tagHt[key]->SetValue(content);
+
    std::string vr = tagHt[key]->GetVR();
    guint32 lgr;
 
@@ -185,7 +230,7 @@ int gdcmElValSet::SetElValueByNumber(std::string content,
    else if( (vr == "UL") || (vr == "SL") )
       lgr = 4;
    else
-      lgr = content.length();     
+      lgr = l;    
    tagHt[key]->SetLength(lgr); 
    return 1;
 }
@@ -200,7 +245,16 @@ int gdcmElValSet::SetElValueByNumber(std::string content,
 int gdcmElValSet::SetElValueByName(std::string content, std::string TagName) {
    if ( ! NameHt.count(TagName))
       return 0;
+   int l = content.length();
+   if(l%2) {  // Odd length are padded with a space (020H).
+      l++;
+      // Well. I know that '/0' is NOT a space
+      // but it doesn't work with a space. 
+      // Use hexedit and see 0002|0010 value (Transfer Syntax UID)
+      content = content + '\0';
+   }
    NameHt[TagName]->SetValue(content);
+
    std::string vr = NameHt[TagName]->GetVR();
    guint32 lgr;
 
@@ -265,6 +319,7 @@ int gdcmElValSet::SetElValueLengthByNumber(guint32 length,
    TagKey key = gdcmDictEntry::TranslateToKey(group, element);
    if ( ! tagHt.count(key))
       return 0;
+   if (length%2) length++; // length must be even
    tagHt[key]->SetLength(length);       
    return 1 ;          
 }
@@ -278,6 +333,7 @@ int gdcmElValSet::SetElValueLengthByNumber(guint32 length,
 int gdcmElValSet::SetElValueLengthByName(guint32 length, std::string TagName) {
    if ( ! NameHt.count(TagName))
       return 0;
+   if (length%2) length++; // length must be even
    NameHt.find(TagName)->second->SetLength(length);     
    return 1 ;          
 }
@@ -375,9 +431,14 @@ void gdcmElValSet::UpdateGroupLength(bool SkipSequence, FileType type) {
 
 /**
  * \ingroup gdcmElValSet
- * \brief   
- * @param   type
- * @param   _fp 
+ * \brief   writes on disc according to the requested format
+ * \        (ACR-NEMA, DICOM, RAW) the image
+ * \ warning does NOT add the missing elements in the header :
+ * \         it's up to the user doing it !
+ * \         (function CheckHeaderCoherence to be written)
+ * @param   type type of the File to be written 
+ *          (ACR-NEMA, DICOM, RAW)
+ * @param   _fp already open file pointer
  * @return  
  */
 void gdcmElValSet::WriteElements(FileType type, FILE * _fp) {
@@ -388,12 +449,16 @@ void gdcmElValSet::WriteElements(FileType type, FILE * _fp) {
    guint32 val_uint32;
    guint16 val_uint16;
    
-   vector<std::string> tokens;
+   std::vector<std::string> tokens;
+   
+   // TODO : use listElem to iterate, not TagHt!
+   //        pb : gdcmElValSet.Add does NOT update listElem
+   //        find a trick in STL to do it, at low cost !
 
    void *ptr;
 
    // Tout ceci ne marche QUE parce qu'on est sur un proc Little Endian 
-   // restent à tester les echecs en écriture (apres chaque fwrite)
+   // restent a tester les echecs en ecriture (apres chaque fwrite)
 
    for (TagElValueHT::iterator tag2=tagHt.begin();
         tag2 != tagHt.end();
@@ -405,7 +470,7 @@ void gdcmElValSet::WriteElements(FileType type, FILE * _fp) {
       val = tag2->second->GetValue().c_str();
       vr =  tag2->second->GetVR();
       
-     // cout << "Tag "<< hex << gr << " " << el << "\n";
+     // std::cout << "Tag "<< std::hex << gr << " " << el << std::endl;
 
       if ( type == ACR ) { 
          if (gr < 0x0008)   continue; // ignore pure DICOM V3 groups
@@ -472,28 +537,13 @@ void gdcmElValSet::WriteElements(FileType type, FILE * _fp) {
  */
 int gdcmElValSet::Write(FILE * _fp, FileType type) {
 
-   if (type == ImplicitVR) {
-      std::string implicitVRTransfertSyntax = "1.2.840.10008.1.2";
-      SetElValueByNumber(implicitVRTransfertSyntax, 0x0002, 0x0010);
-      
-      //FIXME Refer to standards on page 21, chapter 6.2 "Value representation":
-      //      values with a VR of UI shall be padded with a single trailing null
-      //      Dans le cas suivant on doit pader manuellement avec un 0
-      
-      SetElValueLengthByNumber(18, 0x0002, 0x0010);
-   }  
        // Question :
-       // Comment pourrait-on savoir si le DcmHeader vient d'un fichier DicomV3 ou non ,
+       // Comment pourrait-on savoir si le DcmHeader vient d'un fichier DicomV3 ou non
        // (FileType est un champ de gdcmHeader ...)
        // WARNING : Si on veut ecrire du DICOM V3 a partir d'un DcmHeader ACR-NEMA
-       // no way
-       
-   if (type == ExplicitVR) {
-      std::string explicitVRTransfertSyntax = "1.2.840.10008.1.2.1";
-      SetElValueByNumber(explicitVRTransfertSyntax, 0x0002, 0x0010);
-      // See above comment 
-      SetElValueLengthByNumber(20, 0x0002, 0x0010);
-   }
+       // no way 
+        // a moins de se livrer a un tres complique ajout des champs manquants.
+        // faire un CheckAndCorrectHeader (?)
 
    if ( (type == ImplicitVR) || (type == ExplicitVR) )
       UpdateGroupLength(false,type);