]> Creatis software - gdcm.git/commitdiff
Last commit before the final(?) one, for the new version.
authorjpr <jpr>
Mon, 7 Jun 2004 14:41:35 +0000 (14:41 +0000)
committerjpr <jpr>
Mon, 7 Jun 2004 14:41:35 +0000 (14:41 +0000)
Please keep on wainting.

13 files changed:
src/gdcmBinEntry.cxx
src/gdcmDocEntry.h
src/gdcmDocEntrySet.cxx
src/gdcmDocEntrySet.h
src/gdcmDocument.cxx
src/gdcmDocument.h
src/gdcmElementSet.cxx
src/gdcmElementSet.h
src/gdcmSQItem.cxx
src/gdcmSQItem.h
src/gdcmSeqEntry.cxx
src/gdcmSeqEntry.h
src/gdcmValEntry.h

index 8478f58686a93d423d07fc1aac6e6eced8bc1e41..63260fd4c4438e1d9a4f119abc2e74eff79588da 100644 (file)
@@ -31,7 +31,7 @@ gdcmBinEntry::~gdcmBinEntry(){
  
 void gdcmBinEntry::Print(std::ostream &os = std::cout) {
    PrintCommonPart(os);
-   std::cout << "gdcmBinEntry : Print, et alors ?" <<std::endl;
+   std::cout << " gdcmBinEntry : Print, so WHAT ?" <<std::endl;
 }
 //-----------------------------------------------------------------------------
 // Public
index b48e3cb065dc97eebe7050182711e9e761b1e96a..d165fd40b437cb5b5cf0ef26b1ca287fb33a445e 100644 (file)
@@ -7,6 +7,7 @@
 #include <stdio.h>
 
 #include "gdcmDictEntry.h"
+//#include "gdcmValEntry.h"
 class gdcmHeader;
 
 //-----------------------------------------------------------------------------
@@ -18,15 +19,7 @@ class gdcmHeader;
 class GDCM_EXPORT gdcmDocEntry {
 public:
    gdcmDocEntry(gdcmDictEntry*);
-
-   /// \brief Returns the 'Value' (e.g. "Dupond Marcel") converted into a
-   /// 'string', if it's stored as an integer in the Dicom Header of the
-   /// current Dicom Header Entry 
-   /// TODO virtual?  
-   //inline std::string  GetValue(void)     { return value; };
-   // Pour continuer a compiler :-(
-   inline std::string  GetValue(void)     { return "value"; };
-      
+     
    /// Returns the Dicom Group number of the current Dicom Header Entry
    inline guint16      GetGroup(void)     { return entry->GetGroup();  };
 
@@ -124,7 +117,12 @@ public:
 
    bool isItemDelimitor();
    bool isSequenceDelimitor();   
-      
+
+   inline int GetDepthLevel(void) 
+      {return(SQDepthLevel);}
+   void SetDepthLevel(int depth) 
+      {SQDepthLevel = depth;}
+            
 private:
    // FIXME: In fact we should be more specific and use :
    // friend gdcmDocEntry * gdcmHeader::ReadNextElement(void);
index 8f54c1bfca1cdb1e4b056ce182443b68747f8200..9b7286f06a28e627fcf8d8d3e7b7879a7e7a2d42 100644 (file)
@@ -18,7 +18,8 @@
  * \ingroup gdcmDocEntrySet
  * \brief   Constructor from a given gdcmDocEntrySet
  */
-gdcmDocEntrySet::gdcmDocEntrySet() {
+gdcmDocEntrySet::gdcmDocEntrySet(int depthLevel) {
+   SQDepthLevel = depthLevel + 1;
 }
 /**
  * \brief   Canonical destructor.
index b2132bfe6b6ecd02a54bcf263b8bd391a9ed30c6..94566ad23b62ff835f2643f71e18a16ced0b19ef 100644 (file)
@@ -13,13 +13,18 @@ class GDCM_EXPORT gdcmDocEntrySet
 
 public:
 
-   gdcmDocEntrySet(void); 
+   gdcmDocEntrySet(int depth = 0); 
    ~gdcmDocEntrySet(void);
 
    virtual bool AddEntry(gdcmDocEntry *Entry) = 0; // pure virtual
    bool CheckEntryVR(gdcmDocEntry *Entry, std::string vr); 
    virtual void Print (std::ostream & os = std::cout) = 0;// pure virtual
-                                                 
+
+   inline int GetDepthLevel(void) 
+      {return(SQDepthLevel);}
+   void SetDepthLevel(int depth) 
+      {SQDepthLevel = depth;}
+         
 protected:
 
    void gdcmDocEntrySet::FindDocEntryLength (gdcmDocEntry *Entry);
@@ -28,10 +33,10 @@ protected:
     
    virtual gdcmDocEntry *NewDocEntryByNumber(guint16 group, 
                                              guint16 element)=0; // pure virtual
-   virtual gdcmDocEntry *NewDocEntryByName  (std::string Name)=0; // pure virtual  
-  
+   virtual gdcmDocEntry *NewDocEntryByName  (std::string Name)=0;// pure virtual  
 
-         
+   int SQDepthLevel;
+                                                         
 private:
     
 };
index 67a114e2e196606626c08b9f6ff49d5542557632..d5852766f98d7a059408fbb6c6f10fcb5023e140 100644 (file)
 #define UI1_2_840_10008_1_2_1    "1.2.840.10008.1.2.1"
 #define UI1_2_840_10008_1_2_2    "1.2.840.10008.1.2.2"
 #define UI1_2_840_10008_1_2_1_99 "1.2.840.10008.1.2.1.99"
+#define UI1_1_2_840_10008_1_2_5  "1.2.840.10008.1.2.5"
 
-typedef struct {
-   guint32 totalSQlength;
-   guint32 alreadyParsedlength;
-} pileElem;
+#define str2num(str, typeNum) *((typeNum *)(str))
 
 //-----------------------------------------------------------------------------
 // Refer to gdcmDocument::CheckSwap()
@@ -61,7 +59,8 @@ const unsigned int gdcmDocument::MAX_SIZE_PRINT_ELEMENT_VALUE = 64;
 gdcmDocument::gdcmDocument(const char *inFilename, 
                        bool exception_on_error,
                        bool enable_sequences,
-                       bool ignore_shadow) {
+                       bool ignore_shadow) 
+              : gdcmElementSet(-1)   {
    enableSequences=enable_sequences;
    ignoreShadow   =ignore_shadow;
    
@@ -84,12 +83,10 @@ gdcmDocument::gdcmDocument(const char *inFilename,
    long beg = ftell(fp);
    lgt -= beg;
    
-    //std::cout << "beg, lgt : " << beg << "  " << lgt << std::endl;        
-
+   SQDepthLevel=0;
+   
    long l=ParseDES( this, beg, lgt, false); // le Load sera fait a la volee
-   CloseFile();
-
- /* TO DO : uncomment when everything else is OK  
+   CloseFile(); 
   
    // --------------------------------------------------------------
    // Special Patch to allow gdcm to read ACR-LibIDO formated images
@@ -103,15 +100,13 @@ gdcmDocument::gdcmDocument(const char *inFilename,
        RecCode == "CANRME_AILIBOD1_1." )  // for brain-damaged softwares
                                           // with "little-endian strings"
    {
-         filetype = ACR_LIBIDO; 
+         filetype = gdcmACR_LIBIDO; 
          std::string rows    = GetEntryByNumber(0x0028, 0x0010);
          std::string columns = GetEntryByNumber(0x0028, 0x0011);
          SetEntryByNumber(columns, 0x0028, 0x0010);
          SetEntryByNumber(rows   , 0x0028, 0x0011);
    }
    // ----------------- End of Special Patch ---------------- 
-   */ 
-
 
    printLevel = 1;  // 'Medium' print level by default
 }
@@ -120,8 +115,9 @@ gdcmDocument::gdcmDocument(const char *inFilename,
  * \brief  constructor 
  * @param   exception_on_error
  */
-gdcmDocument::gdcmDocument(bool exception_on_error) {
-       (void)exception_on_error;
+gdcmDocument::gdcmDocument(bool exception_on_error) 
+             :gdcmElementSet(-1)    {
+   (void)exception_on_error;
    enableSequences=0;
 
    SetMaxSizeLoadEntry(MAX_SIZE_LOAD_ELEMENT_VALUE);
@@ -203,9 +199,11 @@ bool gdcmDocument::SetShaDict(DictKey dictName){
  */
 bool gdcmDocument::IsReadable(void) { 
    if(filetype==gdcmUnknown) {
+      std::cout << "wrong filetype" <<std::endl;
       return(false);
    }
-   if(listEntries.size()<=0) {    
+   if(!tagHT.empty()<=0) { 
+      std::cout << "wrong tagHT size "<< tagHT.size() <<std::endl;     
       return(false);
    }
 
@@ -223,7 +221,7 @@ bool gdcmDocument::IsImplicitVRLittleEndianTransferSyntax(void) {
       return false;
    LoadDocEntrySafe(Element);
 
-   std::string Transfer = Element->GetValue();
+   std::string Transfer = ((gdcmValEntry *)Element)->GetValue();
    if ( Transfer == UI1_2_840_10008_1_2 )
       return true;
    return false;
@@ -240,7 +238,7 @@ bool gdcmDocument::IsExplicitVRLittleEndianTransferSyntax(void) {
       return false;
    LoadDocEntrySafe(Element);
 
-   std::string Transfer = Element->GetValue();
+   std::string Transfer = ((gdcmValEntry *)Element)->GetValue();
    if ( Transfer == UI1_2_840_10008_1_2_1 )
       return true;
    return false;
@@ -257,7 +255,7 @@ bool gdcmDocument::IsDeflatedExplicitVRLittleEndianTransferSyntax(void) {
       return false;
    LoadDocEntrySafe(Element);
 
-   std::string Transfer = Element->GetValue();
+   std::string Transfer = ((gdcmValEntry *)Element)->GetValue();
    if ( Transfer == UI1_2_840_10008_1_2_1_99 )
       return true;
    return false;
@@ -274,7 +272,7 @@ bool gdcmDocument::IsExplicitVRBigEndianTransferSyntax(void) {
       return false;
    LoadDocEntrySafe(Element);
 
-   std::string Transfer = Element->GetValue();
+   std::string Transfer = ((gdcmValEntry *)Element)->GetValue();
    if ( Transfer == UI1_2_840_10008_1_2_2 )  //1.2.2 ??? A verifier !
       return true;
    return false;
@@ -354,7 +352,7 @@ bool gdcmDocument::Write(FILE *fp, FileType type) {
 ///  ==============
 ///      The stuff will have to be rewritten using the SeQuence based 
 ///       tree-like stucture instead  of the chained list .
-///      (so we shall remove the GroupHT from the gdcmDocument)
+///      (so we shall remove the Group*HT from the gdcmDocument)
 ///      To be checked
 /// =============
 
@@ -508,7 +506,7 @@ std::string gdcmDocument::GetEntryVRByName(std::string tagName) {
       return GDCM_UNFOUND;
 
    gdcmDocEntry* elem =  GetDocEntryByNumber(dictEntry->GetGroup(),
-                                                   dictEntry->GetElement());
+                                             dictEntry->GetElement());
    return elem->GetVR();
 }
 
@@ -526,7 +524,7 @@ std::string gdcmDocument::GetEntryByNumber(guint16 group, guint16 element){
    TagKey key = gdcmDictEntry::TranslateToKey(group, element);
    if ( ! tagHT.count(key))
       return GDCM_UNFOUND;
-   return tagHT.find(key)->second->GetValue();
+   return ((gdcmValEntry *)tagHT.find(key)->second)->GetValue();
 }
 
 /**
@@ -602,18 +600,8 @@ bool gdcmDocument::SetEntryByNumber(std::string content,
    }
       
    gdcmDocEntry * a;
-   IterHT p;
-   TagDocEntryHT::iterator p2;
-   // DO NOT remove the following lines : they explain the stuff   
-   //p= tagHT.equal_range(key); // get a pair of iterators first-last synonym
-   //p2=p.first;                // iterator on the first synonym 
-   //a=p2->second;              // H Table target column (2-nd col)
-    
-   // or, easier :
-   
-   // Oops ! this was for multimap, right ?
-   a = ((tagHT.equal_range(key)).first)->second; 
-       
+   a = tagHT[key];
+           
    ((gdcmValEntry*)a)->SetValue(content);
    
    std::string vr = a->GetVR();
@@ -749,7 +737,9 @@ bool gdcmDocument::SetEntryVoidAreaByNumber(void * area,
 void gdcmDocument::UpdateShaEntries(void) {
    gdcmDictEntry *entry;
    std::string vr;
-
+   
+   // TODO : if still any use (?) explore recursively the whole structure
+/*
    for(ListTag::iterator it=listEntries.begin();
        it!=listEntries.end();
        ++it)
@@ -769,15 +759,13 @@ void gdcmDocument::UpdateShaEntries(void) {
       else
          vr=(*it)->GetVR();
 
-      //(*it)->SetValue(GetDocEntryUnvalue(*it));
-      // to go on compiling
+      (*it)->SetValue(GetDocEntryUnvalue(*it));  // to go on compiling
       if(entry){
          // Set the new entry and the new value
          (*it)->SetDictEntry(entry);
          CheckDocEntryVR(*it,vr);
 
-         //(*it)->SetValue(GetDocEntryValue(*it));
-        // to go on compiling
+         (*it)->SetValue(GetDocEntryValue(*it));    // to go on compiling
         
       }
       else
@@ -786,6 +774,7 @@ void gdcmDocument::UpdateShaEntries(void) {
          (*it)->SetDictEntry(NewVirtualDictEntry((*it)->GetGroup(),(*it)->GetElement(),vr));
       }
    }
+*/   
 }
 
 /**
@@ -821,18 +810,6 @@ gdcmDocEntry* gdcmDocument::GetDocEntryByNumber(guint16 group, guint16 element)
    return tagHT.find(key)->second;
 }
 
-/**
- * \brief   retrieves the Dicom Elements (all of them) using (group, element) 
- * @param   group Group number of the searched Dicom Element.
- * @param   element Element number of the searched Dicom Element.
- * @return  a range (i.e.pair<,>) containing all elements whose key is group|element) 
- */
-IterHT gdcmDocument::GetDocEntrySameNumber(guint16 group, guint16 element){
-   TagKey key = gdcmDictEntry::TranslateToKey(group, element);
-   return (tagHT.equal_range(key));
-}
-
 /**
  * \brief         Loads the element while preserving the current
  *                underlying file position indicator as opposed to
@@ -846,116 +823,6 @@ void gdcmDocument::LoadDocEntrySafe(gdcmDocEntry * entry) {
    fseek(fp, PositionOnEntry, SEEK_SET);
 }
 
-/**
- * \brief   Re-computes the length of a ACR-NEMA/Dicom group from a DcmHeader
- * \warning : to be re-written using the chained list instead of the H table.
- * \warning : DO NOT use (doesn't work any longer because of the multimap)
- * \todo : to be re-written using the chained list instead of the H table
- * @param   SkipSequence TRUE if we don't want to write Sequences (ACR-NEMA Files)
- * @param   type Type of the File (ExplicitVR,ImplicitVR, ACR, ...) 
- */
- /* Probabely useless, now !
-void gdcmDocument::UpdateGroupLength(bool SkipSequence, FileType type) {
-   guint16 gr, el;
-   std::string vr;
-   
-   gdcmDocEntry *elem;
-   char trash[10];
-   std::string str_trash;
-   
-   GroupKey key;
-   GroupHT groupHt;  // to hold the length of each group
-   TagKey tk;
-   // remember :
-   // typedef std::map<GroupKey, int> GroupHT;
-   
-   gdcmDocEntry *elemZ;
-  
-   // for each Tag in the DCM Header
-   
-   for (TagDocEntryHT::iterator tag2 = tagHT.begin(); 
-        tag2 != tagHT.end();
-        ++tag2)
-   {
-      elem  = tag2->second;
-      gr = elem->GetGroup();
-      el = elem->GetElement();
-      vr = elem->GetVR(); 
-                 
-      sprintf(trash, "%04x", gr);
-      key = trash;   // generate 'group tag'
-      
-      // if the caller decided not to take SEQUENCEs into account 
-      // e.g : he wants to write an ACR-NEMA File 
-                
-      if (SkipSequence && vr == "SQ") 
-         continue;
-      
-      // Still unsolved problem :
-      // we cannot find the 'Sequence Delimitation Item'
-      // since it's at the end of the Hash Table
-      // (fffe,e0dd) 
-       
-      // there is SEQUENCE in ACR-NEMA
-      // WARNING : 
-      // --> la descente a l'interieur' des SQ 
-      // devrait etre faite avec une liste chainee, pas avec une HTable...
-            
-      if ( groupHt.count(key) == 0) // we just read the first elem of a given group
-      { 
-         if (el == 0x0000) // the first elem is 0x0000
-         {
-            groupHt[key] = 0;      // initialize group length 
-         } 
-         else 
-         {
-            groupHt[key] = 2 + 2 + 4 + elem->GetLength(); // non 0x0000 first group elem
-         } 
-      } 
-      else // any elem but the first
-      {   
-         if (type == ExplicitVR) 
-         {
-            if ( (vr == "OB") || (vr == "OW") || (vr == "SQ") ) 
-            {
-               groupHt[key] +=  4; // explicit VR AND OB, OW, SQ : 4 more bytes
-            }
-         }
-         groupHt[key] += 2 + 2 + 4 + elem->GetLength(); 
-      } 
-   }
-
-   unsigned short int gr_bid;
-  
-   for (GroupHT::iterator g = groupHt.begin(); // for each group we found
-        g != groupHt.end();
-        ++g)
-   { 
-      // FIXME: g++ -Wall -Wstrict-prototypes reports on following line:
-      //        warning: unsigned int format, different type arg
-      sscanf(g->first.c_str(),"%x",&gr_bid); //FIXME
-      tk = g->first + "|0000";   // generate the element full tag
-                     
-      if ( tagHT.count(tk) == 0) // if element 0x0000 not found
-      {
-         gdcmDictEntry * tagZ = new gdcmDictEntry(gr_bid, 0x0000, "UL");       
-         elemZ = new gdcmDocEntry(tagZ);
-         elemZ->SetLength(4);
-         AddEntry(elemZ);   // create it
-      } 
-      else 
-      {
-         elemZ=GetDocEntryByNumber(gr_bid, 0x0000);
-      }     
-      sprintf(trash ,"%d",g->second);
-      str_trash=trash;
-      //elemZ->SetValue(str_trash); // to go on compiling
-   }   
-}
-
-*/
 
 /**
  * \brief Writes in a file (according to the requested format)
@@ -1044,8 +911,7 @@ void gdcmDocument::WriteEntryValue(gdcmDocEntry *tag, FILE *_fp,FileType type)
       return;
       
    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
@@ -1059,7 +925,7 @@ void gdcmDocument::WriteEntryValue(gdcmDocEntry *tag, FILE *_fp,FileType type)
       // we split the string and write each value as a short int
       std::vector<std::string> tokens;
       tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
-      Tokenize (tag->GetValue(), tokens, "\\");
+      Tokenize (((gdcmValEntry *)tag)->GetValue(), tokens, "\\");
       for (unsigned int i=0; i<tokens.size();i++) 
       {
          guint16 val_uint16 = atoi(tokens[i].c_str());
@@ -1076,7 +942,7 @@ void gdcmDocument::WriteEntryValue(gdcmDocEntry *tag, FILE *_fp,FileType type)
    {
       std::vector<std::string> tokens;
       tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
-      Tokenize (tag->GetValue(), tokens, "\\");
+      Tokenize (((gdcmValEntry *)tag)->GetValue(), tokens, "\\");
       for (unsigned int i=0; i<tokens.size();i++) 
       {
          guint32 val_uint32 = atoi(tokens[i].c_str());
@@ -1086,7 +952,7 @@ void gdcmDocument::WriteEntryValue(gdcmDocEntry *tag, FILE *_fp,FileType type)
       tokens.clear();
       return;
    }           
-   fwrite (tag->GetValue().c_str(), (size_t)lgr ,(size_t)1, _fp); // Elem value
+   fwrite (((gdcmValEntry *)tag)->GetValue().c_str(), (size_t)lgr ,(size_t)1, _fp); // Elem value
 }
 
 /**
@@ -1106,8 +972,7 @@ bool gdcmDocument::WriteEntry(gdcmDocEntry *tag, FILE *_fp,FileType type)
    // 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->SetValue(tag->GetValue()+"\0"); // to go on compiling
       tag->SetLength(tag->GetReadLength()+1);
    }
 
@@ -1132,64 +997,34 @@ bool gdcmDocument::WriteEntry(gdcmDocEntry *tag, FILE *_fp,FileType type)
  */
 
 bool gdcmDocument::WriteEntries(FILE *_fp,FileType type)
-{   
+{ 
+
+// FIXME : explore recursively the whole structure...
+  
    /// \todo (?) check write failures (after *each* fwrite)
      
-   for (ListTag::iterator tag2=listEntries.begin();
-                          tag2 != listEntries.end();
-                          ++tag2)
+   for (TagDocEntryHT::iterator tag2=tagHT.begin();
+                                tag2 != tagHT.end();
+                              ++tag2)
    {
       if ( type == gdcmACR ){ 
-         if ((*tag2)->GetGroup() < 0x0008)
+         if ((*tag2).second->GetGroup() < 0x0008)
             // Ignore pure DICOM V3 groups
             continue;
-         if ((*tag2)->GetElement() %2)
+         if ((*tag2).second->GetElement() %2)
             // Ignore the "shadow" groups
             continue;
-         if ((*tag2)->GetVR() == "SQ" ) // ignore Sequences
+         if ((*tag2).second->GetVR() == "SQ" ) // ignore Sequences
             continue;
-         if ((*tag2)->GetSQDepthLevel() != 0) // Not only ignore the SQ element
+         if ((*tag2).second->GetSQDepthLevel() != 0) // Not only ignore the SQ element
             continue;      
       } 
-      if (! WriteEntry(*tag2,_fp,type) )
+      if (! WriteEntry((*tag2).second,_fp,type) )
          return false;
    }
    return true;
 }   
 
-/**
- * \brief   writes on disc according to the requested format
- *          (ACR-NEMA, ExplicitVR, ImplicitVR) the image,
- *          using only the last synonym of each mutimap H Table post.
- * \warning Uses the H Table, instead of the Chained List
- *          in order to be compliant with the old way to proceed
- *         (added elements taken in to account)
- *         Only THERALYS, during a transitory phase is supposed
- *         to use this method !!!
- * \warning DON'T try, right now, to write a DICOM image
- *           from an ACR Header (meta elements will be missing!)
- * \sa WriteEntries
- * @param   _fp already open file pointer
- * @param   type type of the File to be written 
- *          (ACR-NEMA, ExplicitVR, ImplicitVR)
- */
-void gdcmDocument::WriteEntriesDeprecated(FILE *_fp,FileType type) {
-
-   // restent a tester les echecs en ecriture (apres chaque fwrite)
-
-   for (TagDocEntryHT::iterator tag2=tagHT.begin();
-        tag2 != tagHT.end();
-        ++tag2){
-      if ( type == gdcmACR ){ 
-         if ((*tag2->second).GetGroup() < 0x0008)    continue; // ignore pure DICOM V3 groups
-         if ((*tag2->second).GetElement() %2)        continue; // ignore shadow groups
-         if ((*tag2->second).GetVR() == "SQ" )       continue; // ignore Sequences
-         if ((*tag2->second).GetSQDepthLevel() != 0) continue; // Not only ignore the SQ element          
-      }
-      if ( ! WriteEntry(tag2->second,_fp,type))
-         break;
-   }
-}
 
 /**
  * \brief   Swaps back the bytes of 4-byte long integer accordingly to
@@ -1250,8 +1085,6 @@ guint16 gdcmDocument::UnswapShort(guint16 a) {
 //-----------------------------------------------------------------------------
 // Private
 
-
-
 /**
  * \brief   Parses a DocEntrySet (Zero-level DocEntries or SQ Item DocEntries)
  * @return  false if file is not ACR-NEMA / PAPYRUS / DICOM 
@@ -1265,27 +1098,17 @@ long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool
    gdcmSeqEntry *sq;
    string vr;
    long l;
-   cout << hex << "offset " << offset 
-        << " l_max "<< l_max 
-        << " ftell a l'entree " << ftell(fp)
-       << endl;         
+   int depth; 
+   
+   depth = set->GetDepthLevel();     
    while (true) { 
+   
+      if ( !delim_mode && ftell(fp)-offset >= l_max) { 
+         break;  
+      }
       NewDocEntry = ReadNextDocEntry( );
       if (!NewDocEntry)
          break;
-        
-      std::cout << hex 
-               << " gr " 
-               << NewDocEntry->GetGroup() 
-               << " el "
-              << NewDocEntry->GetElement() 
-              << " vr "
-              << NewDocEntry->GetVR()
-              << " lgt "
-              << NewDocEntry->GetReadLength()
-              << " off "
-              << NewDocEntry->GetOffset()             
-              << std::endl;
               
       vr = NewDocEntry->GetVR();        
       if (vr!="SQ") {
@@ -1293,24 +1116,20 @@ long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool
          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 == "SH" || vr == "ST" || vr == "DS" ||                   
              vr == "SL" || vr == "SS" || vr == "UL" || vr == "US"
                                                                  ) {
       // --- ValEntry                           
             vl= new gdcmValEntry(NewDocEntry->GetDictEntry());
-            vl->Copy(NewDocEntry);
-            set->AddEntry(vl);
+            vl->Copy(NewDocEntry);         
+           vl->SetDepthLevel(depth),
+            set->AddEntry(vl);     
            LoadDocEntry(vl);
-           std::cout << "value [" << vl->GetValue() << "]" << std::endl;
             if (/*!delim_mode && */vl->isItemDelimitor())
                break;
-           cout << hex
-                << " l_max = "<< l_max
-                << " offset = " << offset
-                << " ftell(fp) = " << ftell(fp)
-                << endl;
-            if ( !delim_mode && ftell(fp)-offset >= l_max)
-               break;       
+            if ( !delim_mode && ftell(fp)-offset >= l_max) {
+               break;
+           }        
         } else { // BinEntry
         
         // Hope the following VR *do* correspond to a BinEntry 
@@ -1325,44 +1144,47 @@ long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool
                 
             bn = new gdcmBinEntry(NewDocEntry->GetDictEntry());
            bn->Copy(NewDocEntry);
+           set->AddEntry(bn);
            LoadDocEntry(bn);
-            std::cout << "value [" << "Bin Entry, in voidArea" << "]" << std::endl;                     
          }      
-
-          SkipToNextDocEntry(NewDocEntry); // to be sure we are at the beginning 
-         l = NewDocEntry->GetFullLength(); 
-           
+          if (NewDocEntry->GetGroup()   == 0x7fe0 && 
+             NewDocEntry->GetElement() == 0x0010 ) {
+             if (NewDocEntry->GetLength()==0xffffffff)       
+             // Broke 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(); 
+          }        
       } else {   // VR = "SQ"
-            
-         std::cout << "gdcmDocument::ParseDES : SQ found " << std::endl;
-         l=NewDocEntry->GetReadLength();
-        
-         if (l == 0xffffffff)
-           delim_mode = true;
-         else
-           delim_mode = false;
-          
-         sq = new gdcmSeqEntry(NewDocEntry->GetDictEntry());
+      
+         l=NewDocEntry->GetReadLength();            
+         if (l != 0) // don't mess the delim_mode for zero-length sequence
+            if (l == 0xffffffff)
+              delim_mode = true;
+            else
+              delim_mode = false;
+        // no other way to create it ...
+         sq = new gdcmSeqEntry(NewDocEntry->GetDictEntry(),set->GetDepthLevel());
          sq->Copy(NewDocEntry);
         sq->SetDelimitorMode(delim_mode);
+        sq->SetDepthLevel(depth);
 
-        if (l != 0) {  // Don't try to parse zero-length sequences              
-            long lgt = ParseSQ((gdcmDocEntrySet *)sq, 
-                                //NewDocEntry->GetOffset(),
-                               offset, // marche pour DICOMDIR, plante sur 3...dcm
+        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 ?
          set->AddEntry(sq);
-        cout << " l_max = " << l_max
-             << " offset = " << offset
-             << "ftell(fp) = " << ftell(fp)
-             << endl;
-         if ( !delim_mode && ftell(fp)-offset >= l_max)
+         if ( !delim_mode && ftell(fp)-offset >= l_max) {       
             break;
+        }
       } 
    }
-   cout << endl; 
    delete NewDocEntry;   
    return l; // ?? 
 }
@@ -1371,125 +1193,47 @@ long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool
  * \brief   Parses a Sequence ( SeqEntry after SeqEntry)
  * @return  parsed length for this level
  */ 
-long gdcmDocument::ParseSQ(gdcmDocEntrySet *set, long offset, long l_max, bool delim_mode) {
-
-   cout << "=================== gdcmDocument::ParseSQ on entre ds une Sequence"
-        << hex
-        << " offset " << offset
-       << " l_max " << l_max
-       << " delim_mode " << delim_mode
-        <<endl;
+long gdcmDocument::ParseSQ(gdcmSeqEntry *set, long offset, long l_max, bool delim_mode) {
    int SQItemNumber = 0;
    gdcmDocEntry *NewDocEntry = (gdcmDocEntry *)0;
    gdcmSQItem *itemSQ;
    bool dlm_mod;
    int lgr, l, lgth;
-   
+   int depth = set->GetDepthLevel();
    while (true) {
-      std::cout << " ===== gdcmDocument::ParseSQ on itere "
-                << "sur les SQ Items : num " 
-                 << SQItemNumber << std::endl;
       
-      NewDocEntry = ReadNextDocEntry();
-cout << "=============================== isSequenceDelimitor " 
-     << NewDocEntry->isSequenceDelimitor() 
-     << endl;     
+      NewDocEntry = ReadNextDocEntry();   
       if(delim_mode) {   
           if (NewDocEntry->isSequenceDelimitor()) {
-            cout << " SequenceDelimitationItem found" << endl;
-         //                    add the Sequence Delimitor  // TODO : find the trick to put it proprerly !
-         //   ((gdcmSeqEntry *)set)->SetSequenceDelimitationItem(NewDocEntry);
+         //add the Sequence Delimitor  // TODO : find the trick to put it properly !
+            set->SetSequenceDelimitationItem(NewDocEntry);
             break;
           }         
       }             
       if (!delim_mode && (ftell(fp)-offset) >= l_max) {
-             cout << hex
-                  << " offset " << offset
-                 << " l_max " << l_max
-                 << " ftell " << ftell(fp)
-                  << endl;              
-             cout << "depasse ou atteint : on sort " << endl;    
              break;
-      }                
-      itemSQ = new gdcmSQItem();
+      }
+      itemSQ = new gdcmSQItem(set->GetDepthLevel());
       itemSQ->AddEntry(NewDocEntry); // no value, no voidArea. Think of it while printing !
       l= NewDocEntry->GetReadLength();
-      cout << "NewDocEntry->GetReadLength() " << l << endl;
+      
       if (l ==0xffffffff)
          dlm_mod = true;
       else
          dlm_mod=false;
-cout << "================================ appel ParseDES :dlm_mod = " << dlm_mod <<endl;      
+      
       lgr=ParseDES(itemSQ, NewDocEntry->GetOffset(), l, dlm_mod);
-      ((gdcmSeqEntry *)set)->AddEntry(itemSQ);  
-cout << "================================ sortie ParseDES " << endl;
-      SQItemNumber ++;
+      
+      set->AddEntry(itemSQ);    
+      SQItemNumber ++; // a voir
+      if (!delim_mode && (ftell(fp)-offset) >= l_max) {
+         break;
+      }       
    }
-   //Update(lgth); 
    lgth = ftell(fp) - offset;
-   cout << "=============== lgr Sequence :" << lgth <<endl;
    return(lgth);
 }
 
-
-/**
- * \brief   Parses the header of the file and load element values.
- * @return  false if file is not ACR-NEMA / PAPYRUS / DICOM 
- */
-
-/* =======================================================================
-// Replaced by ParseSQ
-  
-bool gdcmDocument::LoadHeaderEntries(bool exception_on_error) throw(gdcmFormatError) {
-   (void)exception_on_error;
-   rewind(fp);
-   if (!CheckSwap())
-      return false;
-      
-   gdcmDocEntry *newDocEntry = (gdcmDocEntry *)0;   
-   while ( (newDocEntry = ReadNextDocEntry()) ) {
-     SkipDocEntry(newDocEntry);
-     if ( (ignoreShadow==0) || (newDocEntry->GetGroup()%2) == 0) { 
-        AddEntry(newDocEntry); 
-     }     
-   }   
-   rewind(fp);
-   // Be carefull : merging this two loops may cause troubles ...
-   for (ListTag::iterator i = GetListEntry().begin();                           
-        i != GetListEntry().end();                                                
-        ++i)                                                                      
-   {                                                                            
-      LoadDocEntry(*i);                                                      
-   }                                                                            
-   rewind(fp);                                                                     
-   
-   // Load 'non string' values
-   
-   // --------------------------------------------------------------
-   // Special Patch to allow gdcm to read ACR-LibIDO formated images
-   //
-   // if recognition code tells us we deal with a LibIDO image
-   // we switch lineNumber and columnNumber
-   //
-   std::string RecCode;
-   RecCode = GetEntryByNumber(0x0008, 0x0010); // recognition code
-   if (RecCode == "ACRNEMA_LIBIDO_1.1" ||
-       RecCode == "CANRME_AILIBOD1_1." )  // for brain-damaged softwares
-                                          // with "little-endian strings"
-   {
-         filetype = ACR_LIBIDO; 
-         std::string rows    = GetEntryByNumber(0x0028, 0x0010);
-         std::string columns = GetEntryByNumber(0x0028, 0x0011);
-         SetEntryByNumber(columns, 0x0028, 0x0010);
-         SetEntryByNumber(rows   , 0x0028, 0x0011);
-   }
-   // ----------------- End of Special Patch ----------------   
-   return true;
-}
-======================================================================= */
-
-
 /**
  * \brief         Loads the element content if its length doesn't exceed
  *                the value specified with gdcmDocument::SetMaxSizeLoadEntry()
@@ -1526,11 +1270,10 @@ void gdcmDocument::LoadDocEntry(gdcmDocEntry *Entry)  {
    // the element content and it's length.
    if (length > MaxSizeLoadEntry) {
       std::ostringstream s;
-      s << "gdcm::NotLoaded.";
-      s << " Address:" << (long)Entry->GetOffset();
-      s << " Length:"  << Entry->GetLength();
-      s << " x(" << std::hex << Entry->GetLength() << ")";
       ((gdcmValEntry *)Entry)->SetValue(s.str());
+      // to be sure we are at the end of the value ...
+      fseek(fp,(long)Entry->GetOffset()+(long)Entry->GetLength(),SEEK_SET);
+      
       return;
    }
     
@@ -1825,7 +1568,7 @@ std::string gdcmDocument::GetDocEntryValue(gdcmDocEntry *Entry)
 {
    if ( (IsDocEntryAnInteger(Entry)) && (Entry->IsImplicitVR()) )
    {
-      std::string val=Entry->GetValue();
+      std::string val=((gdcmValEntry *)Entry)->GetValue();
       std::string vr=Entry->GetVR();
       guint32 length = Entry->GetLength();
       std::ostringstream s;
@@ -1880,7 +1623,7 @@ std::string gdcmDocument::GetDocEntryValue(gdcmDocEntry *Entry)
       return(s.str());
    }
 
-   return(Entry->GetValue());
+   return(((gdcmValEntry *)Entry)->GetValue());
 }
 
 /**
@@ -1904,7 +1647,7 @@ std::string gdcmDocument::GetDocEntryUnvalue(gdcmDocEntry *Entry)
          guint16 NewInt16;
 
          tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
-         Tokenize (Entry->GetValue(), tokens, "\\");
+         Tokenize (((gdcmValEntry *)Entry)->GetValue(), tokens, "\\");
          for (unsigned int i=0; i<tokens.size();i++) 
          {
             NewInt16 = atoi(tokens[i].c_str());
@@ -1917,7 +1660,7 @@ std::string gdcmDocument::GetDocEntryUnvalue(gdcmDocEntry *Entry)
          guint32 NewInt32;
 
          tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
-         Tokenize (Entry->GetValue(), tokens, "\\");
+         Tokenize (((gdcmValEntry *)Entry)->GetValue(), tokens, "\\");
          for (unsigned int i=0; i<tokens.size();i++) 
          {
             NewInt32 = atoi(tokens[i].c_str());
@@ -1933,7 +1676,7 @@ std::string gdcmDocument::GetDocEntryUnvalue(gdcmDocEntry *Entry)
       return(s.str());
    }
 
-   return(Entry->GetValue());
+   return(((gdcmValEntry *)Entry)->GetValue());
 }
 
 /**
@@ -2647,5 +2390,212 @@ gdcmDictEntry *gdcmDocument::GetDictEntryByNumber(guint16 group,guint16 element)
 }
 
 
+/**
+ * \ingroup gdcmDocument
+ * \brief   Parse pixel data from disk for multi-fragment Jpeg/Rle files
+ * \        No other way so 'skip' the Data
+ *
+ */
+void gdcmDocument::Parse7FE0 (void) {
+
+   gdcmDocEntry* Element = GetDocEntryByNumber(0x0002, 0x0010);
+   if ( !Element )
+      return;
+      
+   std::string Transfer = ((gdcmValEntry *)Element)->GetValue();
+   if (Transfer == UI1_2_840_10008_1_2 )
+      return;  
+   if ( Transfer == UI1_2_840_10008_1_2_1 )
+      return;
+   if ( Transfer == UI1_2_840_10008_1_2_2 )  //1.2.2 ??? A verifier !
+      return;         
+   if ( Transfer == UI1_2_840_10008_1_2_1_99 )
+      return;
+      
+   int nb;
+   std::string str_nb=GetEntryByNumber(0x0028,0x0100);
+   if (str_nb == GDCM_UNFOUND ) {
+      nb = 16;
+   } else {
+      nb = atoi(str_nb.c_str() );
+      if (nb == 12) nb =16;
+   }
+      
+   guint16 ItemTagGr,ItemTagEl; 
+   int ln;
+   long ftellRes;
+
+  // -------------------- for Parsing : Position on begining of Jpeg/RLE Pixels 
+
+   if ( Transfer != UI1_1_2_840_10008_1_2_5 ) { // !RLELossLessTransferSyntax 
+      // JPEG Image
+      ftellRes=ftell(fp);
+      fread(&ItemTagGr,2,1,fp);  //Reading (fffe):Basic Offset Table Item Tag Gr
+      fread(&ItemTagEl,2,1,fp);  //Reading (e000):Basic Offset Table Item Tag El
+      if(GetSwapCode()) {
+         ItemTagGr=SwapShort(ItemTagGr); 
+         ItemTagEl=SwapShort(ItemTagEl);            
+      }
+      printf ("at %x : ItemTag (should be fffe,e000): %04x,%04x\n",
+                (unsigned)ftellRes,ItemTagGr,ItemTagEl );
+      ftellRes=ftell(fp);
+      fread(&ln,4,1,fp); 
+      if(GetSwapCode()) 
+         ln=SwapLong(ln);    // Basic Offset Table Item Length
+      printf("at %x : Basic Offset Table Item Length (\?\?) %d x(%08x)\n",
+            (unsigned)ftellRes,ln,ln);
+      if (ln != 0) {
+         // What is it used for ??
+         char * BasicOffsetTableItemValue= new char[ln+1];
+         fread(BasicOffsetTableItemValue,ln,1,fp); 
+         guint32 a;
+         for (int i=0;i<ln;i+=4){
+            a=str2num(&BasicOffsetTableItemValue[i],guint32);
+            printf("      x(%08x)  %d\n",a,a);
+         }              
+      }
+      
+      ftellRes=ftell(fp);
+      fread(&ItemTagGr,2,1,fp);  // Reading (fffe) : Item Tag Gr
+      fread(&ItemTagEl,2,1,fp);  // Reading (e000) : Item Tag El
+      if(GetSwapCode()) {
+         ItemTagGr=SwapShort(ItemTagGr); 
+         ItemTagEl=SwapShort(ItemTagEl);            
+      }  
+      printf ("at %x : ItemTag (should be fffe,e000 or e0dd): %04x,%04x\n",
+            (unsigned)ftellRes,ItemTagGr,ItemTagEl );
+      
+      while ( ( ItemTagGr==0xfffe) && (ItemTagEl!=0xe0dd) ) { // Parse fragments
+      
+         ftellRes=ftell(fp);
+         fread(&ln,4,1,fp); 
+         if(GetSwapCode()) 
+            ln=SwapLong(ln);    // length
+         printf("      at %x : fragment length %d x(%08x)\n",
+                (unsigned)ftellRes, ln,ln);
+
+         // ------------------------                                     
+         fseek(fp,ln,SEEK_CUR); // skipping (not reading) fragment pixels    
+         // ------------------------              
+     
+         ftellRes=ftell(fp);
+         fread(&ItemTagGr,2,1,fp);  // Reading (fffe) : Item Tag Gr
+         fread(&ItemTagEl,2,1,fp);  // Reading (e000) : Item Tag El
+         if(GetSwapCode()) {
+            ItemTagGr=SwapShort(ItemTagGr); 
+            ItemTagEl=SwapShort(ItemTagEl);            
+         }
+         printf ("at %x : ItemTag (should be fffe,e000 or e0dd): %04x,%04x\n",
+               (unsigned)ftellRes,ItemTagGr,ItemTagEl );
+      } 
+
+   } else {
+
+      // RLE Image
+      long RleSegmentLength[15],fragmentLength;
+      guint32 nbRleSegments;
+      guint32 RleSegmentOffsetTable[15];
+      ftellRes=ftell(fp);
+      // Basic Offset Table with Item Value
+         // Item Tag
+      fread(&ItemTagGr,2,1,fp);  //Reading (fffe):Basic Offset Table Item Tag Gr
+      fread(&ItemTagEl,2,1,fp);  //Reading (e000):Basic Offset Table Item Tag El
+      if(GetSwapCode()) {
+         ItemTagGr=SwapShort(ItemTagGr); 
+         ItemTagEl=SwapShort(ItemTagEl);            
+      }
+      printf ("at %x : ItemTag (should be fffe,e000): %04x,%04x\n",
+                (unsigned)ftellRes,ItemTagGr,ItemTagEl );
+         // Item Length
+      ftellRes=ftell(fp);
+      fread(&ln,4,1,fp); 
+      if(GetSwapCode()) 
+         ln=SwapLong(ln);    // Basic Offset Table Item Length
+      printf("at %x : Basic Offset Table Item Length (\?\?) %d x(%08x)\n",
+            (unsigned)ftellRes,ln,ln);
+      if (ln != 0) {
+         // What is it used for ??
+         char * BasicOffsetTableItemValue= new char[ln+1];
+         fread(BasicOffsetTableItemValue,ln,1,fp); 
+         guint32 a;
+         for (int i=0;i<ln;i+=4){
+            a=str2num(&BasicOffsetTableItemValue[i],guint32);
+            printf("      x(%08x)  %d\n",a,a);
+         }              
+      }
+
+      ftellRes=ftell(fp);
+      fread(&ItemTagGr,2,1,fp);  // Reading (fffe) : Item Tag Gr
+      fread(&ItemTagEl,2,1,fp);  // Reading (e000) : Item Tag El
+      if(GetSwapCode()) {
+         ItemTagGr=SwapShort(ItemTagGr); 
+         ItemTagEl=SwapShort(ItemTagEl);            
+      }  
+      printf ("at %x : ItemTag (should be fffe,e000 or e0dd): %04x,%04x\n",
+            (unsigned)ftellRes,ItemTagGr,ItemTagEl );
+
+      // while 'Sequence Delimiter Item' (fffe,e0dd) not found
+      while (  ( ItemTagGr == 0xfffe) && (ItemTagEl != 0xe0dd) ) { 
+      // Parse fragments of the current Fragment (Frame)    
+         ftellRes=ftell(fp);
+         fread(&fragmentLength,4,1,fp); 
+         if(GetSwapCode()) 
+            fragmentLength=SwapLong(fragmentLength);    // length
+         printf("      at %x : 'fragment' length %d x(%08x)\n",
+                (unsigned)ftellRes, (unsigned)fragmentLength,(unsigned)fragmentLength);
+                       
+          //------------------ scanning (not reading) fragment pixels
+         fread(&nbRleSegments,4,1,fp);  // Reading : Number of RLE Segments
+         if(GetSwapCode()) 
+            nbRleSegments=SwapLong(nbRleSegments);
+            printf("   Nb of RLE Segments : %d\n",nbRleSegments);
+         for(int k=1; k<=15; k++) { // Reading RLE Segments Offset Table
+            ftellRes=ftell(fp);
+            fread(&RleSegmentOffsetTable[k],4,1,fp);
+            if(GetSwapCode())
+               RleSegmentOffsetTable[k]=SwapLong(RleSegmentOffsetTable[k]);
+            printf("        at : %x Offset Segment %d : %d (%x)\n",
+                    (unsigned)ftellRes,k,RleSegmentOffsetTable[k],
+                    RleSegmentOffsetTable[k]);
+         }
+
+          if (nbRleSegments>1) { // skipping (not reading) RLE Segments
+             for(unsigned int k=1; k<=nbRleSegments-1; k++) { 
+                RleSegmentLength[k]=   RleSegmentOffsetTable[k+1]
+                                     - RleSegmentOffsetTable[k];
+                ftellRes=ftell(fp);
+                printf ("  Segment %d : Length = %d x(%x) Start at %x\n",
+                           k,(unsigned)RleSegmentLength[k],(unsigned)RleSegmentLength[k], (unsigned)ftellRes);
+                fseek(fp,RleSegmentLength[k],SEEK_CUR);    
+             }
+          }
+          RleSegmentLength[nbRleSegments]= fragmentLength 
+                                         - RleSegmentOffsetTable[nbRleSegments];
+          ftellRes=ftell(fp);
+          printf ("  Segment %d : Length = %d x(%x) Start at %x\n",
+                           nbRleSegments,(unsigned)RleSegmentLength[nbRleSegments],
+                           (unsigned)RleSegmentLength[nbRleSegments],(unsigned)ftellRes);
+
+          fseek(fp,RleSegmentLength[nbRleSegments],SEEK_CUR); 
+            
+         // ------------------ end of scanning fragment pixels        
+      
+         ftellRes=ftell(fp);
+         fread(&ItemTagGr,2,1,fp);  // Reading (fffe) : Item Tag Gr
+         fread(&ItemTagEl,2,1,fp);  // Reading (e000) : Item Tag El
+         if(GetSwapCode()) {
+            ItemTagGr=SwapShort(ItemTagGr); 
+            ItemTagEl=SwapShort(ItemTagEl);            
+         }
+         printf ("at %x : ItemTag (should be fffe,e000 or e0dd): %04x,%04x\n",
+               (unsigned)ftellRes,ItemTagGr,ItemTagEl );
+      } 
+   }
+   return;            
+}
+
+
 
 //-----------------------------------------------------------------------------
index a8f7cb19a285287824828d26fd290580cbd6bac1..bebde32a0ea132420d47553c968ea1c943dca359 100644 (file)
@@ -10,6 +10,8 @@
 #include "gdcmException.h"
 #include "gdcmDictSet.h"
 #include "gdcmDocEntry.h"
+//#include "gdcmSeqEntry.h"
+class gdcmSeqEntry;
 #include "gdcmDocEntrySet.h"
 #include "gdcmElementSet.h"
 
 #include <list>
 
 
-
 //-----------------------------------------------------------------------------
 typedef std::string VRKey;
 typedef std::string VRAtr;
 typedef std::map<VRKey, VRAtr> VRHT;    // Value Representation Hash Table
 
 typedef std::map<TagKey, gdcmDocEntry *> TagDocEntryHT;
-typedef std::pair<TagKey, gdcmDocEntry *> PairHT;
-typedef std::pair<TagDocEntryHT::iterator,TagDocEntryHT::iterator> IterHT; 
-/// for linking together the Elements
-typedef std::list<gdcmDocEntry *> ListTag;
-
-typedef std::string GroupKey;
-typedef std::map<GroupKey, int> GroupHT;
 
 //-----------------------------------------------------------------------------
 /**
@@ -59,9 +53,7 @@ private:
    /// \brief Size threshold above which an element value will NOT be *printed*
    /// in order no to polute the screen output. By default, this upper bound
    /// is fixed to 64 bytes.
-   guint32 MaxSizePrintEntry;
-   
-   
+   guint32 MaxSizePrintEntry;   
 
 protected:
    /// Refering underlying filename.
@@ -92,12 +84,6 @@ protected:
    ///       \ref gdcmDocument::SetMaxSizePrintEntry()
    static const unsigned int MAX_SIZE_PRINT_ELEMENT_VALUE;
 
-   /// Hash Table (multimap), to provide fast access
-   TagDocEntryHT tagHT; 
-
-   /// Chained list, to keep the 'spacial' ordering
-   ListTag listEntries; 
-
    /// Will be set 1 if user asks to 'go inside' the 'sequences' (VR = "SQ")
    int enableSequences;
 
@@ -146,7 +132,6 @@ public:
    virtual void WriteEntryValue(gdcmDocEntry *tag,FILE *_fp,FileType type);
    virtual bool WriteEntry(gdcmDocEntry *tag,FILE *_fp,FileType type);
    virtual bool WriteEntries(FILE *_fp,FileType type);
-   void WriteEntriesDeprecated(FILE *_fp,FileType type); // JPR
 
    gdcmDocEntry * ReplaceOrCreateByNumber(std::string Value,
                                              guint16 Group, guint16 Elem);
@@ -171,6 +156,8 @@ protected:
               bool  enable_sequences   = false,
              bool  ignore_shadow      = false);
    virtual ~gdcmDocument(void);
+   
+   void gdcmDocument::Parse7FE0 (void);   
 // Entry
    int CheckIfEntryExistByNumber(guint16 Group, guint16 Elem ); // int !
    virtual std::string GetEntryByName    (std::string tagName);
@@ -194,8 +181,6 @@ protected:
 // Header entry
    gdcmDocEntry *GetDocEntryByNumber  (guint16 group, guint16 element); 
    gdcmDocEntry *GetDocEntryByName    (std::string Name);
-   IterHT           GetDocEntrySameNumber(guint16 group, guint16 element); 
-// IterHT           GetDocEntrySameName  (std::string Name); 
 
    void LoadDocEntrySafe(gdcmDocEntry *);
 
@@ -213,8 +198,8 @@ private:
    // What about exception_on_error ?
    
    long ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool delim_mode);
-   long ParseSQ(gdcmDocEntrySet *set, long offset, long l_max, bool delim_mode);
-   
+  // long ParseSQ(gdcmDocEntrySet *set, long offset, long l_max, bool delim_mode);
+  long ParseSQ(gdcmSeqEntry *seq, long offset, long l_max, bool delim_mode); 
    
    void LoadDocEntry      (gdcmDocEntry *);
    void FindDocEntryLength(gdcmDocEntry *);
@@ -281,7 +266,7 @@ public:
    inline TagDocEntryHT &GetEntry(void) { return tagHT; };
 
    /// Accessor to \ref gdcmDocument::listEntries
-   inline ListTag &GetListEntry(void) { return listEntries; };
+   //inline ListTag &GetListEntry(void) { return listEntries; };
 
    /// 'Swap code' accessor (see \ref sw )
    inline int GetSwapCode(void) { return sw; }
index 8dbeb6d3cd664c8d5b99234ad6e070a14981e5f9..d357da30055e3b69dfafb6d79522b14c7b0a1069 100644 (file)
  * \ingroup gdcmElementSet
  * \brief   Constructor from a given gdcmElementSet
  */
-gdcmElementSet::gdcmElementSet() {
-   //TagDocEntryHT tagHT est un champ de gdcmElementSet.
-   // inutile de faire new ?
-      
+gdcmElementSet::gdcmElementSet(int depthLevel) 
+              : gdcmDocEntrySet(depthLevel) {
 }
 
 /**
@@ -57,13 +55,15 @@ void gdcmElementSet::Print(std::ostream & os) {
 //-----------------------------------------------------------------------------
 // Protected
 
+//-----------------------------------------------------------------------------
+
 //-----------------------------------------------------------------------------
 // Private
 
 
 /**
  * \brief   add a new Dicom Element pointer to the H Table
- * @param   newDocEntry entry to add
+ * @param   NewEntry entry to add
  */
 bool gdcmElementSet::AddEntry( gdcmDocEntry *NewEntry) {
    TagKey key;
index cca674552782e46cfb93a18930b906dafe26d31c..258e58dd243ed9186c423be40d56a6c1e0ed8a05 100644 (file)
@@ -16,7 +16,7 @@ typedef std::map<TagKey, gdcmDocEntry *> TagDocEntryHT;
 class GDCM_EXPORT gdcmElementSet : public gdcmDocEntrySet 
 {
 public:
-   gdcmElementSet(void);
+   gdcmElementSet(int);
    ~gdcmElementSet(void);
    virtual bool AddEntry(gdcmDocEntry *Entry); // add to the H Table
 
@@ -24,12 +24,12 @@ public:
     
 protected:
 
-private:
-
 // Variables
 
    /// Hash Table (map), to provide fast access
-   TagDocEntryHT tagHT;   
+   TagDocEntryHT tagHT; 
+     
+private:
    
 };
 
index 79debf624bf0f825536c0595ff9ec313fa6a9415..ce080c6072c2dc2538d6669691b2ee9cd50ee196 100644 (file)
@@ -4,6 +4,7 @@
 #include "gdcmSQItem.h"
 #include "gdcmGlobal.h"
 #include "gdcmUtil.h"
+#include "gdcmValEntry.h"
 
 
 //-----------------------------------------------------------------------------
@@ -12,8 +13,9 @@
  * \ingroup gdcmSQItem
  * \brief   Constructor from a given gdcmSQItem
  */
-gdcmSQItem::gdcmSQItem( ) 
-          : gdcmDocEntrySet() {
+gdcmSQItem::gdcmSQItem(int depthLevel ) 
+          : gdcmDocEntrySet(depthLevel) {
+   SQDepthLevel = depthLevel +1;
 }
 
 /**
@@ -38,7 +40,11 @@ gdcmSQItem::~gdcmSQItem()
  */
  void gdcmSQItem::Print(std::ostream & os) {
    std::ostringstream s;
-   s << "   | " ;
+
+   if (SQDepthLevel>0) {
+      for (int i=0;i<SQDepthLevel;i++)
+         s << "   | " ;
+   }
    for (ListDocEntry::iterator i = docEntries.begin();  
         i != docEntries.end();
         ++i)
@@ -54,19 +60,67 @@ gdcmSQItem::~gdcmSQItem()
 // Public
 
 bool gdcmSQItem::AddEntry(gdcmDocEntry *entry) {
-   std::cout << "    === entree ds gdcmSQItem::AddEntry " 
-             << hex << entry->GetGroup()
-             << " "
-             << entry->GetElement() 
-            << " lgt "
-             << entry->GetReadLength()      
-             << std::endl; 
-            
    docEntries.push_back(entry);
    //TODO : check if it worked
    return true;
 }   
-                                 
+
+
+/**
+ * \brief   Sets Entry (Dicom Element) value of an element,
+ *          specified by it's tag (Group, Number) 
+ *          and the length, too ...  inside a SQ Item
+ *          If the Element is not found, it's just created !
+ * \warning we suppose, right now, the element belongs to a Public Group
+ *          (NOT a shadow one)       
+ * @param   val string value to set
+ * @param   group Group of the searched tag.
+ * @param   element Element of the searched tag.
+ * @return  true if element was found or created successfully
+ */
+ bool gdcmSQItem::SetEntryByNumber(std::string val,guint16 group, 
+                                                  guint16 element) {
+
+   for(ListDocEntry::iterator i=docEntries.begin();i!=docEntries.end();++i) { 
+      if ( (*i)->GetGroup() == 0xfffe && (*i)->GetElement() == 0xe000 ) 
+         continue;
+      if ( group   < (*i)->GetGroup() || 
+           (group == (*i)->GetGroup() && element < (*i)->GetElement()) ){
+        // instead of ReplaceOrCreateByNumber 
+        // that is a method of gdcmDocument :-( 
+         gdcmDocEntry *Entry;
+         TagKey key = gdcmDictEntry::TranslateToKey(group, element);
+         if ( ! ptagHT->count(key)) {
+          // we assume a Public Dictionnary *is* loaded
+           gdcmDict *PubDict         = gdcmGlobal::GetDicts()->GetDefaultPubDict();
+           // if the invoked (group,elem) doesn't exist inside the Dictionary
+          // we create a VirtualDictEntry
+           gdcmDictEntry *DictEntry  = PubDict->GetDictEntryByNumber(group, element);
+          if (DictEntry == NULL) {
+             DictEntry=gdcmGlobal::GetDicts()->NewVirtualDictEntry(group,element,"UN","??","??");
+          } 
+           // we assume the constructor didn't fail
+           Entry = new gdcmDocEntry(DictEntry);
+          /// \todo
+          /// ----
+          /// better we don't assume too much !
+          /// gdcmSQItem is now used to describe any DICOMDIR related object
+          ///
+         } else {
+            Entry = ptagHT->find(key)->second;
+         }
+         ((gdcmValEntry*)Entry)->SetValue(val); 
+         Entry->SetLength(val.length());
+         docEntries.insert(i,Entry); 
+        return true;
+      }           
+      if (group == (*i)->GetGroup() && element == (*i)->GetElement() ) {
+         ((gdcmValEntry*)(*i))->SetValue(val);         
+         (*i)->SetLength(val.length()); 
+         return true;    
+      }   
+   }                                               
+}                                
 //-----------------------------------------------------------------------------
 // Protected
 
@@ -77,13 +131,73 @@ bool gdcmSQItem::AddEntry(gdcmDocEntry *entry) {
 gdcmDocEntry *gdcmSQItem::NewDocEntryByNumber(guint16 group,
                                               guint16 element) {
 // TODO                                  
-   gdcmDocEntry *a;   
+   gdcmDocEntry *a;
+   std::cout << " gdcmSQItem::NewDocEntryByNumber : TODO" <<std::endl; 
    return a;                             
 }
 
 gdcmDocEntry *gdcmSQItem::NewDocEntryByName  (std::string Name) {
-// TODO        :                         
-   gdcmDocEntry *a;   
-   return a;                             
+// TODO                                  
+   gdcmDocEntry *a;
+   std::cout << " gdcmSQItem::NewDocEntryByName : TODO" <<std::endl; 
+   return a;                                     
+}
+
+/*
+ * \ingroup gdcmSQItem
+ * \brief   Gets a Dicom Element inside a SQ Item Entry, by name
+ * @return
+ */
+ gdcmDocEntry *gdcmSQItem::GetDocEntryByName(std::string name) {
+   gdcmDict *PubDict=gdcmGlobal::GetDicts()->GetDefaultPubDict();
+   gdcmDictEntry *dictEntry = (*PubDict).GetDictEntryByName(name);
+   if( dictEntry == NULL)
+      return NULL;
+   return GetDocEntryByNumber(dictEntry->GetGroup(),dictEntry->GetElement());      
 }
+
+/*
+ * \ingroup gdcmSQItem
+ * \brief   Gets a Dicom Element inside a SQ Item Entry, by number
+ * @return
+ */
+gdcmDocEntry *gdcmSQItem::GetDocEntryByNumber(guint16 group, guint16 element) {                                     
+   for(ListDocEntry::iterator i=docEntries.begin();i!=docEntries.end();++i) {
+      if ( (*i)->GetGroup()==group && (*i)->GetElement()==element)
+         return (*i);
+   }   
+   return NULL;                                          
+}
+
+/*
+ * \ingroup gdcmSQItem
+ * \brief   Get the value of a Dicom Element inside a SQ Item Entry, by number
+ * @return
+ */ 
+
+std::string gdcmSQItem::GetEntryByNumber(guint16 group, guint16 element) { 
+   for(ListDocEntry::iterator i=docEntries.begin();i!=docEntries.end();++i) {
+      if ( (*i)->GetGroup()==group && (*i)->GetElement()==element) {
+         return ((gdcmValEntry *)(*i))->GetValue();
+      }
+   }   
+   return GDCM_UNFOUND;
+}
+
+/**
+ * \ingroup gdcmSQItem
+ * \brief   Get the value of a Dicom Element inside a SQ Item Entry, by name
+ * @param   name : name of the searched element.
+ * @return
+ */ 
+
+std::string gdcmSQItem::GetEntryByName(TagName name)  {
+   gdcmDict *PubDict=gdcmGlobal::GetDicts()->GetDefaultPubDict();
+   gdcmDictEntry *dictEntry = (*PubDict).GetDictEntryByName(name); 
+
+   if( dictEntry == NULL)
+      return GDCM_UNFOUND;
+   return GetEntryByNumber(dictEntry->GetGroup(),dictEntry->GetElement()); 
+}
+
 //-----------------------------------------------------------------------------
index d5bd12c6e137454761f79f46f9d9b1316c3a43a0..fa5f2559343da3b55123c91893b5d7e75be79606 100644 (file)
@@ -7,14 +7,14 @@
 
 #include "gdcmDocEntry.h"
 #include "gdcmDocEntrySet.h"
-
+#include "gdcmDocument.h"
 //-----------------------------------------------------------------------------
 typedef std::list<gdcmDocEntry *> ListDocEntry;
 //-----------------------------------------------------------------------------
 class GDCM_EXPORT gdcmSQItem : public gdcmDocEntrySet
 {
 public:
-   gdcmSQItem(void);
+   gdcmSQItem(int);
    ~gdcmSQItem(void);
 
    virtual void Print(std::ostream &os = std::cout); 
@@ -28,23 +28,42 @@ public:
       {docEntries.push_back(e);};         
 
    virtual bool AddEntry(gdcmDocEntry *Entry); // add to the List
-               
+  
+   gdcmDocEntry *GetDocEntryByNumber(guint16 group, 
+                                     guint16 element);
+   gdcmDocEntry *GetDocEntryByName  (std::string Name);
+   
+   bool SetEntryByNumber(std::string val,guint16 group,
+                                         guint16 element);                   
+    
+   std::string GetEntryByNumber(guint16 group, guint16 element);
+   std::string GetEntryByName(TagName name);
+      
 protected:
 
-private:
-
    // DocEntry related utilities 
          
    virtual gdcmDocEntry *NewDocEntryByNumber(guint16 group,
-                                             guint16 element);
-   virtual gdcmDocEntry *NewDocEntryByName  (std::string Name); 
+                                             guint16 element); // TODO
+   virtual gdcmDocEntry *NewDocEntryByName  (std::string Name); //TODO 
 
 // Variables
 
 /// \brief chained list of (Elementary) Doc Entries
   ListDocEntry docEntries;
+  
 /// \brief SQ Item ordinal number 
   int SQItemNumber;
+
+/**
+* \brief pointer to the HTable of the gdcmDocument,
+*        (because we don't know it within any gdcmObject nor any gdcmSQItem) 
+*/
+  TagDocEntryHT *ptagHT;
+       
+private:
+
+
 };
 
 
index 0955a1b4601b21ceb171b319b6b392d32aaa6d48..70e96f2bde4fd17cdda35a6cd013a811eb7beedf 100644 (file)
  * \ingroup gdcmSeqEntry
  * \brief   Constructor from a given gdcmSeqEntry
  */
-gdcmSeqEntry::gdcmSeqEntry(gdcmDictEntry* e) 
+gdcmSeqEntry::gdcmSeqEntry(gdcmDictEntry* e, int depth
              : gdcmDocEntry(e)
 {
    delimitor_mode = false;
-   seq_term  = NULL;   
+   seq_term  = NULL;
+   SQDepthLevel = depth; // +1; // ??
 }
 
 /**
@@ -43,7 +44,7 @@ gdcmSeqEntry::~gdcmSeqEntry() {
  */
 void gdcmSeqEntry::Print(std::ostream &os){
 
-   std::ostringstream s;
+   std::ostringstream s,s2;
    string vr;
    unsigned short int g, e;
    long lgth;
@@ -51,69 +52,30 @@ void gdcmSeqEntry::Print(std::ostream &os){
    char greltag[10];  //group element tag
    char st[20]; 
 
-
+   // First, Print the Dicom Element itself.
    SetPrintLevel(2);   
-//   PrintCommonPart(os); // FIXME : why doesn't it work ?
-     
-   // First, Print the Dicom Element itself. 
-   g  = GetGroup();
-   e  = GetElement();   
-   o  = GetOffset();
-   vr = GetVR();
-   sprintf(greltag,"%04x|%04x ",g,e);           
-   s << greltag ;
-   if (GetPrintLevel()>=2) { 
-      s << "lg : ";
-      lgth = GetReadLength(); // ReadLength, as opposed to UsableLength
-      if (lgth == 0xffffffff) {
-         sprintf(st,"x(ffff)");  // I said : "x(ffff)" !
-         s.setf(std::ios::left);
-         s << std::setw(10-strlen(st)) << " ";  
-         s << st << " ";
-         s.setf(std::ios::left);
-         s << std::setw(8) << "-1";      
-      } else {
-         sprintf(st,"x(%x)",lgth);
-         s.setf(std::ios::left);
-         s << std::setw(10-strlen(st)) << " ";  
-         s << st << " ";
-         s.setf(std::ios::left);
-         s << std::setw(8) << lgth; 
-      }
-      s << " Off.: ";
-      sprintf(st,"x(%x)",o); 
-      s << std::setw(10-strlen(st)) << " ";
-      s << st << " ";
-      s << std::setw(8) << o; 
-   }
-
-   s << "[" << vr  << "] ";
-   if (GetPrintLevel()>=1) {      
-      s.setf(std::ios::left);
-      s << std::setw(66-GetName().length()) << " ";
-   }
-    
-   s << "[" << GetName()<< "]";
-
+   PrintCommonPart(os);
    s << std::endl;
-   os << s.str();
-
+   os << s.str();   
  
     // Then, Print each SQ Item   
      for(ListSQItem::iterator cc = items.begin();cc != items.end();++cc)
-   {
+   { 
       //(*cc)->SetPrintLevel(GetPrintLevel()); aurait-ce un sens ?
-      (*cc)->Print(os);
+      (*cc)->Print(os);   
    }
    // at end, print the sequence terminator item, if any
-   /*
-   if (delimitor_mode) {  // TODO : find the trick to print it properly
-      s << "   | " ;   
-      os << s.str();
-      if (seq_term = NULL)
-         seq_term->Print(os);      
-   }        
-  */             
+
+   if (delimitor_mode) {
+      s2 << "   | " ;   
+      os << s2.str();
+      if (seq_term != NULL) {
+         seq_term->Print(os);
+      }         
+      else 
+         std::cout << "      -------------- should have a sequence terminator item"
+                  << std::endl;      
+   }                    
  }
 
 //-----------------------------------------------------------------------------
@@ -123,6 +85,11 @@ void gdcmSeqEntry::Print(std::ostream &os){
 void gdcmSeqEntry::AddEntry(gdcmSQItem *sqItem) {
    items.push_back(sqItem);
 }
+
+
+void gdcmSeqEntry::SetDepthLevel(int depth) {
+   SQDepthLevel = depth;
+}
 //-----------------------------------------------------------------------------
 // Protected
 
@@ -131,6 +98,7 @@ void gdcmSeqEntry::AddEntry(gdcmSQItem *sqItem) {
 // Private
 
 // end-user intended : the guy *wants* to create his own SeQuence ?!?
+
 gdcmDocEntry *gdcmSeqEntry::NewDocEntryByNumber(guint16 group,
                                                 guint16 element) {
 // TODO                                  
@@ -141,6 +109,13 @@ gdcmDocEntry *gdcmSeqEntry::NewDocEntryByNumber(guint16 group,
 gdcmDocEntry *gdcmSeqEntry::NewDocEntryByName  (std::string Name) {
 // TODO        :                         
    gdcmDocEntry *a;   
-   return a;
+   return a;   
+}
+
+gdcmDocEntry *gdcmSeqEntry::GetDocEntryByNumber(guint16 group,
+                                                guint16 element) {
+// TODO                                  
+   gdcmDocEntry *a;   
+   return a;                             
 }      
 //-----------------------------------------------------------------------------
index 6456a57211eb46d3e60fb93023e9c8f9da7e0402..9b9e60762a88e77e7b49faedd0ac46cd0f50f7cc 100644 (file)
@@ -15,7 +15,7 @@ typedef std::list<gdcmSQItem *> ListSQItem;
 class GDCM_EXPORT gdcmSeqEntry : public gdcmDocEntry 
 {
 public:
-   gdcmSeqEntry(gdcmDictEntry* e);
+   gdcmSeqEntry(gdcmDictEntry* e, int depth);
    ~gdcmSeqEntry(void);
    
    virtual void Print(std::ostream &os = std::cout); 
@@ -39,7 +39,10 @@ public:
     
    gdcmDocEntry *NewDocEntryByNumber(guint16 group, guint16 element);    
    gdcmDocEntry *NewDocEntryByName  (std::string Name); 
-     
+   gdcmDocEntry *GetDocEntryByNumber(guint16 group, guint16 element);
+
+   void SetDepthLevel(int depth);
+         
 protected:
 
 private:
@@ -55,6 +58,8 @@ private:
 /// \brief sequence terminator item 
    gdcmDocEntry *seq_term;
 
+   //int SQDepthLevel;
+
 };
 
 
index 1c87450beea781ca97b4a5d555842b7b6a458338..6721b8d88c19adabca26e3a85e33bc4aa2fde8c0 100644 (file)
@@ -7,12 +7,12 @@
 #include <stdio.h>
 
 #include "gdcmDocEntry.h"
+
 //-----------------------------------------------------------------------------
 /**
- * \ingroup gdcmBinEntry
+ * \ingroup gdcmValEntry
  * \brief   The dicom header of a Dicom file contains a set of such entries
  *          (when successfuly parsed against a given Dicom dictionary)
- *          This one contains a 'non string' value
  */
 class GDCM_EXPORT gdcmValEntry  : public gdcmDocEntry {
 
@@ -22,11 +22,11 @@ public:
    ~gdcmValEntry(void);
 
    /// \brief Returns the 'Value' (e.g. "Dupond Marcel") converted into a
-   /// 'string', if it's stored as an integer in the Dicom Header of the
-   /// current Dicom Header Entry
+   /// 'string', if it's stored as an integer in the header of the
+   /// current Dicom Document Entry
    inline std::string  GetValue(void)     { return value; };
     
-   /// Sets the value (string) of the current Dicom Header Entry
+   /// Sets the value (string) of the current Dicom Document Entry
    inline void SetValue(std::string val)  { value = val;  };
    
    virtual void Print(std::ostream &os = std::cout); 
@@ -39,13 +39,10 @@ private:
 
 // Variables
   
-   /// \brief Header Entry value, stored as a std::string (VR will be used,
+   /// \brief Document Entry value, stored as a std::string (VR will be used,
    /// later, to decode)
    
    std::string  value;
-   
-
-
 
 };