]> Creatis software - gdcm.git/commitdiff
src/gdcmHeader.cxx many addons of low level methods -- Frog
authorfrog <frog>
Wed, 9 Oct 2002 22:27:14 +0000 (22:27 +0000)
committerfrog <frog>
Wed, 9 Oct 2002 22:27:14 +0000 (22:27 +0000)
ChangeLog
TODO
src/.cvsignore [new file with mode: 0644]
src/Makefile
src/gdcmElValue.cxx [new file with mode: 0644]
src/gdcmHeader.cxx
src/gdcmlib.h

index 66dcea839570189ca3d117be3359b493ab194cdf..50d0273cc527da1fba4a9199acfca669bb730a04 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+2002-10-10 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * src/gdcmHeader.cxx many addons of low level methods
+
 2002-10-07 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
       * src/gdcmHeader now contains_IdDcmCheckSwap, _IdDcmRecupLgr,
         and _IdDcmSWAP_LONG.
diff --git a/TODO b/TODO
index 9fc1484d0be19209fa4fc32e092467be1b1b5bf7..4461948f2a862940990672c4ea7981623a6a4d60 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,8 +1,14 @@
 GetPubElValByNumber doit faire la difference entre chaine vide 
 et chaine pas touve''. Eventuellement raiser une exception ?
 
-gdcmHeader::_IdDcmRecupLgr : le d'elements dans la table de type DICOM_VR
-  est hard code' (a 26). FIX ME.
+gdcmHeader::ReadNextElement: retarder le stockage en mem des gros elements
+ * etablir une taille limite sur les elements a ramener en memoire
+   (parametrisable en public dans la classe)
+ * ne pas ramener les elements au dela de ce seuil, mais les flaguer
+   comme a charger plus tard
+ * a l'acces (pour le groupe des pixels par exemple) retourner au fichier
+   pour trouver la bonne valeur (GetPixelData).
+   
 
 grep str2num *.c: c'est une macro sans doute proprifiable
 
diff --git a/src/.cvsignore b/src/.cvsignore
new file mode 100644 (file)
index 0000000..5761abc
--- /dev/null
@@ -0,0 +1 @@
+*.o
index f47fa5c09df3d913182d567de86812b208be71dd..64faab30341086b0cd8a19c5307d281fc24a49e1 100644 (file)
@@ -9,14 +9,14 @@ PYTHON_PREFIX  =`$(PYTHON) -c "import sys; print sys.exec_prefix"`
 PYTHON_VERSION =`$(PYTHON) -c "import sys; print sys.version[:3]"`
 PYTHON_INCLUDES="-I$(PYTHON_PREFIX)/include/python$(PYTHON_VERSION)"
 
-CXXFLAGS=$(PYTHON_INCLUDES) `glib-config --cflags`
+CXXFLAGS=`glib-config --cflags`
 
 %.o : %.cxx
        $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $< -o $@
 %_wrap.cxx : %.i
        $(SWIG) $(SWIGFLAGS) $(PYTHON_INCLUDES) -o $@ $<
 
-all: gdcmHeader.o dcm_wrap.o
+all: gdcmHeader.o gdcmElValue.o dcm_wrap.o
 
 test: gdcmHeader.o
 
diff --git a/src/gdcmElValue.cxx b/src/gdcmElValue.cxx
new file mode 100644 (file)
index 0000000..20a75e8
--- /dev/null
@@ -0,0 +1,14 @@
+#include "gdcmlib.h"
+#define DEBUG 1
+
+void ElValue::SetVR(string ValRep) {
+       if (!entry && DEBUG) {
+               printf ("ElValue::SetVR: no known entry\n");
+               return;
+       }
+       entry->SetVR(ValRep);
+}
+
+void ElValue::SetLgrLue(guint32 lgr) {
+       LgrLueElem = lgr;
+}
index 6899e505b07794f68160c6c6f4b8c995733f406c..363a3260ed66a0786ec57c308e032eb252ed8c78 100644 (file)
@@ -9,6 +9,7 @@ extern "C" {
 #else
 #include <netinet/in.h>
 #endif
+#include <map>
 
 #define LGR_ENTETE_A_LIRE 256 // on ne lit plus que le debut
 #define DEBUG 1
@@ -16,6 +17,51 @@ extern "C" {
 //FIXME: this looks dirty to me...
 #define str2num(str, typeNum) *((typeNum *)(str))
 
+VRHT * gdcmHeader::dicom_vr = (VRHT*)0;
+
+gdcmHeader::gdcmHeader () {
+       if (!gdcmHeader::dicom_vr)
+               InitVRDict();
+       bool grPixelTrouve = false;
+       PixelPosition = (size_t)0;
+       PixelsTrouves = false;
+}
+
+void gdcmHeader::InitVRDict (void) {
+       if (dicom_vr && DEBUG) {
+               printf ("InitVRDict : VR dictionary allready set\n");
+               return;
+       }
+       VRHT *vr = new VRHT;
+       (*vr)["AE"] = "Application Entity";       // 16 car max
+       (*vr)["AS"] = "Age String";               // 4 car fixe
+       (*vr)["AT"] = "Attribute Tag";            // 2 unsigned short int
+       (*vr)["CS"] = "Code String";              // 16 car max
+       (*vr)["DA"] = "Date";                     // 8 car fixe
+       (*vr)["DS"] = "Decimal String";           // Decimal codé Binaire 16 max
+       (*vr)["DT"] = "Date Time";                // 26 car max
+       (*vr)["FL"] = "Floating Point Single";    // 4 octets IEEE 754:1985
+       (*vr)["FD"] = "Floating Point Double";    // 8 octets IEEE 754:1985
+       (*vr)["IS"] = "Integer String";           // en format externe 12 max
+       (*vr)["LO"] = "Long String";              // 64 octets max
+       (*vr)["LT"] = "Long Text";                // 10240 max
+       (*vr)["OB"] = "Other Byte String";
+       (*vr)["OW"] = "Other Word String";
+       (*vr)["PN"] = "Person Name";
+       (*vr)["SH"] = "Short String";             // 16 car max
+       (*vr)["SL"] = "Signed Long";
+       (*vr)["SQ"] = "Sequence of Items";        // Not Applicable
+       (*vr)["SS"] = "Signed Short";             // 2 octets
+       (*vr)["ST"] = "Short Text";               // 1024 car max
+       (*vr)["TM"] = "Time";                     // 16 car max
+       (*vr)["UI"] = "Unique Identifier";        // 64 car max
+       (*vr)["UN"] = "Unknown";
+       (*vr)["UT"] = "Unlimited Text";           //  2 puissance 32 -1 car max
+       (*vr)["UL"] = "Unsigned Long ";           // 4 octets fixe
+       (*vr)["US"] = "Unsigned Short ";          // 2 octets fixe
+   dicom_vr = vr;      
+}
+
 /**
  * \ingroup gdcmHeader
  * \brief   La seule maniere sure que l'on aie pour determiner 
@@ -208,11 +254,12 @@ void gdcmHeader::setAcrLibido() {
 
 // FIXME sw n'est plus un argument necessaire
 long int gdcmHeader::RecupLgr(
-       _ID_DCM_ELEM *pleCourant, int sw, int *skippedLength, int *longueurLue)
+       ElValue *pleCourant,
+       int *skippedLength)
 {
        guint32 l_gr; 
        unsigned short int l_gr_2;
-       int i, trouve;
+       int i;
        char VR[5];
        int lgrLue;
        
@@ -226,19 +273,20 @@ long int gdcmHeader::RecupLgr(
                lgrLue=fread (&VR, (size_t)2,(size_t)1, fp);
                VR[2]=0;
                
-               // ATTENTION :
-               // Ce n'est pas parce qu'on a trouve UL la premiere fois qu'on respecte 
-               // Explicit VR tout le temps (cf e=film ...)
-               
-               for(i=0,trouve=0;i<nbCode;i++) {
-                       if(memcmp(_ID_dicom_vr[i].dicom_VR,VR,(size_t)2)==0) {
-                               (pleCourant)->VR=_ID_dicom_vr[i].dicom_VR;
-                               trouve=1;
-                               break;
-                       }
-               }
-               
-               if ( trouve == 0) {
+               // Warning: we believe this is explicit VR (Value Representation) because
+               // we used a heuristic that found "UL" in the first tag. Alas this
+               // doesn't guarantee that all the tags will be in explicit VR. In some
+               // cases (see e-film filtered files) one finds implicit VR tags mixed
+               // within an explicit VR file. Hence we make sure the present tag
+               // is in explicit VR and try to fix things if it happens not to be
+               // the case.
+
+               // FIXME There should be only one occurence returned. Avoid the
+               // first extraction by calling proper method.
+               VRAtr FoundVR = dicom_vr->find(string(VR))->first;
+               if (FoundVR.empty()) {
+                       pleCourant->SetVR(FoundVR);
+               } else {
                        
                        // On est mal : implicit VR repere
                        // mais ce n'est pas un code connu ...
@@ -255,7 +303,7 @@ long int gdcmHeader::RecupLgr(
                        if(DEBUG)
                                printf("IdDcmRecupLgr : lgr deduite : %08x , %d\n",l_gr,l_gr);
                        
-                       *longueurLue=l_gr;
+                       pleCourant->SetLgrLue(l_gr);
                        if ( (int)l_gr == -1)
                                l_gr=0;
                         
@@ -291,9 +339,9 @@ long int gdcmHeader::RecupLgr(
                        //on lit la lgr sur DEUX octets
                        lgrLue=fread (&l_gr_2, (size_t)2,(size_t)1, fp);
                        
-                       if(sw) l_gr_2 = _IdDcmSWAP_SHORT((unsigned short)l_gr_2,sw);
+                       if(sw) l_gr_2 = SWAP_SHORT((unsigned short)l_gr_2);
                        
-                       *longueurLue=l_gr_2;
+                       pleCourant->SetLgrLue(l_gr_2);
                        
                        
                        if ( l_gr_2 == 0xffff) {
@@ -313,7 +361,7 @@ long int gdcmHeader::RecupLgr(
                *skippedLength = 4;
        }
        
-       *longueurLue=l_gr;
+       pleCourant->SetLgrLue(l_gr);
        
        // Traitement des curiosites sur la longueur
        
@@ -336,7 +384,6 @@ long int gdcmHeader::RecupLgr(
 
  * @return  longueur retenue pour le champ 
  */
-
 guint32 gdcmHeader::SWAP_LONG(guint32 a) {
        // FIXME: il pourrait y avoir un pb pour les entiers negatifs ...
        switch (sw) {
@@ -358,3 +405,273 @@ guint32 gdcmHeader::SWAP_LONG(guint32 a) {
        }
        return(a);
 }
+
+/**
+ * \ingroup gdcmHeader
+ * \brief   remet les octets dans un ordre compatible avec celui du processeur
+
+ * @return  longueur retenue pour le champ 
+ */
+short int gdcmHeader::SWAP_SHORT(short int a) {
+       if ( (sw==4321)  || (sw==2143) )
+               a =(((a<<8) & 0x0ff00) | ((a>>8)&0x00ff));
+       return (a);
+}
+
+/**
+ * \ingroup       gdcmHeader
+ * \brief         lit le dicom_element suivant.
+ *                     (le fichier doit deja avoir ete ouvert,
+ *                      _IdAcrCheckSwap(ID_DCM_HDR *e) avoir ete appele)
+ * @param e      ID_DCM_HDR  dans lequel effectuer la recherche.
+ * @param sw           code swap.
+ * @return             En cas de succes, 1 
+ *                     0 en cas d'echec.
+ */
+
+ElValue * gdcmHeader::ReadNextElement(void) {
+       unsigned short g;
+       unsigned short n;
+       guint32 l;
+       long int posFich;
+       int skL;
+       size_t lgrLue;
+       //CLEANME DICOM_ELEMENTS *t;
+       ElValue * nouvDcmElem;
+       
+       if (DEBUG) printf(" ===> entree ds _IdDcmReadNextElement\n");
+               
+       // FIXME la probabilte pour depasser sans s'en rendre compte
+       // est grande avec le test d'egalite' suivant !
+       if(offsetCourant == taille_fich) { // On a atteint la fin du fichier
+               if (DEBUG) printf(" On a atteint la fin du fichier\n");
+               return(NULL);
+       } else {
+               if (DEBUG) {
+                       posFich = ftell(fp);
+                       printf("lgrFich %f positionDsFich %f offset courant %f\n", 
+                       (float)taille_fich,
+                       (float)posFich,
+                       (float)offsetCourant);
+               }
+       } 
+       
+       // ------------------------- Lecture Num group : g
+       lgrLue=fread (&g, (size_t)2,(size_t)1, fp);
+       
+       if (feof(fp))  {
+               if (DEBUG) printf("_IdDcmReadNextElement : eof trouve\n");
+               return (NULL);
+       }
+       if (ferror(fp)){
+               if (DEBUG) printf(" IdDcmReadNextElement : echec lecture NumGr\n");
+               return (NULL);
+       }
+       
+       if (DEBUG) printf("_IdDcmReadNextElement : gr  %04x\n",g );
+       
+       if (sw) g= SWAP_SHORT(((short)g));
+       
+       //CLEANME nouvDcmElem->Gr=g;
+       //FIXME this might be usefull for detecting at parse time that
+       //something is screwy in the file
+       //e->__NumeroGroupePrecedent =g;
+       
+
+       // ------------------------- Lecture Num Elem : n
+       lgrLue=fread (&n, (size_t)2,(size_t)1, fp);
+       
+       if (feof(fp))  {
+               if (DEBUG) printf("_IdDcmReadNextElement : eof trouve\n");
+               return (NULL);
+       }
+       if (ferror(fp)){
+               if (DEBUG) printf(" IdDcmReadNextElement : echec lecture NumElem\n");
+               return (NULL);
+       }
+       
+       if (DEBUG) printf("_IdDcmReadNextElement :  num %04x\n",n );
+       
+       if(sw) n= SWAP_SHORT(((short)n));
+       //CLEANMEnouvDcmElem->Num=n;
+
+       // Find out if the tag we encountered is in the dictionaries:
+       DictEntry * NewTag = IsInDicts(g, n);
+       if (!NewTag)
+               NewTag = new DictEntry(g, n, "Unknown", "Unknown");
+
+       nouvDcmElem = new ElValue(NewTag);
+       if (!nouvDcmElem) {
+               printf("Echec alloc ElValue *nouvDcmElem\n");
+               return(NULL);
+       }
+
+       // ------------------------- Lecture longueur element : l
+       
+       l = RecupLgr(nouvDcmElem, &skL);
+       
+       if(g==0xfffe) l=0;  // pour sauter les indicateurs de 'SQ'
+       
+       nouvDcmElem->LgrElem=l;
+       
+       if (DEBUG)
+               if (n!=0)
+                       printf("_IdDcmReadNextElement : "
+                              " gr %04x\tnum %04x\tlong %08x (%d)\n", g,n,l,l);
+
+       // ------------------------- Lecture Valeur element 
+       
+       // FIXME The exact size should be l if we move to strings or whatever
+       // CLEAN ME NEWValue used to be nouvDcmElem->valeurElem
+       char* NewValue = (char*)g_malloc(l+1);
+       if(NewValue) {
+               NewValue[l]= 0;
+       } else {
+               if (DEBUG)
+                        printf(" IdDcmReadNextElement : echec Alloc valeurElem lgr : %d\n",l);
+               return (NULL);
+       }
+       
+       // FIXME les elements trop long (seuil a fixer a la main) ne devraient
+       // pas etre charge's !!!! Voir TODO.
+       lgrLue=fread (NewValue, (size_t)l,(size_t)1, fp);
+       
+       offsetCourant +=  2 + 2 + skL; // gr +  num + lgr
+       nouvDcmElem->Offset = offsetCourant;
+       offsetCourant += l;            // debut elem suivant
+
+       // ------------------------- Doit-on le Swapper ?
+       
+       if ((n==0) && sw)  {  // n=0 : lgr du groupe : guint32
+               *(guint32 *) NewValue = SWAP_LONG ((*(guint32 *) NewValue));  
+       } else {
+               if(sw) {
+                       if ( (g/2)*2-g==0) { /* on ne teste pas les groupes impairs */
+                               
+                               if ((l==4)||(l==2)) {  // pour eviter de swapper les chaines 
+                                                           // de lgr 2 ou 4
+                                       if (DEBUG) 
+                                               printf("Consultation Dictionary DICOM g %04x n %0xx l %d\n",
+                                                       g,n,l);
+                                       
+                                       // FIXME make reference to nouvDcmElem->GetTag
+                                       string VR = NewTag->GetVR();
+                                       if (   (VR == "UL") || (VR == "US")
+                                           || (VR == "SL") || (VR == "SS")
+                                           || (g == 0x0028 && ( n == 0x0005 || n == 0x0200) )) {
+                                               // seuls (28,5) de vr RET et (28,200) sont des entiers
+                                               // ... jusqu'a preuve du contraire
+                                               
+                                               if(l==4) { 
+                                                       *(guint32 *) NewValue =
+                                                           SWAP_LONG  ((*(guint32 *) NewValue)); 
+                                               } else {
+                                                       if(l==2) 
+                                                   *(unsigned short *) NewValue =
+                                                       SWAP_SHORT ((*(unsigned short *)NewValue));
+                                                }
+                                       }
+                               } /* fin if l==2 ==4 */
+                       } /* fin if g pair */
+               } /* fin sw */  
+       }
+       nouvDcmElem->value = NewValue;
+       SetAsidePixelData(nouvDcmElem);
+       return nouvDcmElem;
+}
+
+/**
+ * \ingroup gdcmHeader
+ * \brief   If we encountered the offset of the pixels in the file
+ *          (Pixel Data) then keep the info aside.
+ */
+void gdcmHeader::SetAsidePixelData(ElValue* elem) {
+         /// FIXME this wall process is bizarre:
+         // on peut pas lire pixel data et pixel location puis
+         // a la fin de la lecture aller interpreter ce qui existe ?
+         // penser a nettoyer les variables globales associes genre
+         // PixelsTrouve ou grPixelTrouve...
+         //
+       // They are two cases :
+       // * the pixel data (i.e. the image or the volume) is pointed by it's
+       //   default official tag (0x7fe0,0x0010),
+       // * the writer of this file decided to put the image "address" (i.e the
+       //   offset from the begining of the file) at a different tag.
+       //   Then the "Pixel Data" offset might be found by indirection through
+       //   the "Image Location" tag (0x0028,  0x0200). In other terms the Image
+       //   Location tag contains the group where the "Pixel Data" offset is and
+       //   inside this group the element is conventionally at element 0x0010
+       //   (when the norm is respected).
+       // 
+       // Hence getting our hands on the Pixel Data is a two stage process:
+       //  1/ * find if the "Pixel Data" tag exists.
+       //     * if it does not exist, look for the "Pixel Location" tag.
+       //  2/ look at the proper tag ("Pixel Data" or "Pixel Location" when
+       //     it exists) what the offset it.
+       guint16 g;
+       guint16 n;
+       g = elem->GetGroup();
+       n = elem->GetElement();
+       if (!grPixelTrouve) {   // on n a pas encore trouve les pixels
+               if (g > 0x0028) {
+                       if (n > 0x0200 || g == 0x7FE0 ) {  // on a depasse (28,200)
+                               grPixel  = 0x7FE0;
+                               numPixel = 0x0010;
+                               grPixelTrouve = true;
+                               if (DEBUG)
+                                       printf("------------------------grPixel %04x numPixel %04x\n",
+                                              grPixel,numPixel);
+                       }
+               } else {         // on est sur (28,200)
+                       if (g == 0x0028) {
+                               if (n == 0x0200) {
+                                       grPixelTrouve = 1;
+                                       char* NewValue = (char*)g_malloc(elem->GetLgrElem()+1);
+                                       // FIXME: not very elegant conversion
+                                       for(int i=0;i<4;i++)
+                                               *((char*)(&grPixel)+i) = *(NewValue+i); 
+                                       elem->SetValue(NewValue);
+                                       
+                                       if (DEBUG)
+                                               printf("------------------------GrPixel %04x\n", grPixel);
+                                       
+                                       if (grPixel != 0x7FE0)   // Vieux pb Philips
+                                               numPixel = 0x1010;    // encore utile ??
+                                       else
+                                               numPixel = 0x0010;
+                                       if (DEBUG)
+                                               printf("------------------------grPixel %04x numPixel %04x\n",
+                                                      grPixel,numPixel);
+                               }
+                       }
+               }
+       } else {     // on vient de trouver les pixels
+               if (g == grPixel) {
+                       if (n == numPixel) {
+                               PixelPosition = elem->Offset; 
+                               PixelsTrouves = true;
+                       if (DEBUG)
+                               printf(" \t===> Pixels Trouves\n");
+                       }
+               }
+       }
+}
+
+DictEntry * gdcmHeader::IsInDicts(guint32 group, guint32 element) {
+       DictEntry * found = (DictEntry*)0;
+       if (!RefPubDict && !RefShaDict) {
+               //FIXME build a default dictionary !
+               printf("FIXME in gdcmHeader::IsInDicts\n");
+       }
+       if (RefPubDict) {
+               found = RefPubDict->GetTag(group, element);
+               if (found)
+                       return found;
+       }
+       if (RefShaDict) {
+               found = RefShaDict->GetTag(group, element);
+               if (found)
+                       return found;
+       }
+       return found;
+}
index beb8530ca46f96eec22cd166b8e596e8e14fa5cd..a923f4c8a8fac2d1b0a082e9d08534281d3fecb6 100644 (file)
@@ -39,12 +39,12 @@ private:
 //////           and the element within a DictEntry. What is the point
 //////           of storing the equivalent of a TagKey within the information
 //////           accessed through that TagKey !?
-       guint16 group;          // e.g. 0x0010
-       guint16 element;        // e.g. 0x0010
-       string  name;           // e.g. "Patient_Name"
-       string  ValRep; // Value Representation i.e. some clue about the nature
-                                                       // of the data represented e.g. "FD" short for
-                                                       // "Floating Point Double"
+       guint16 group;    // e.g. 0x0010
+       guint16 element;  // e.g. 0x0010
+       string  name;     // e.g. "Patient_Name"
+       string  ValRep;   // Value Representation i.e. some clue about the nature
+                         // of the data represented e.g. "FD" short for
+                         // "Floating Point Double"
        // DCMTK has many fields for handling a DictEntry (see below). What are the
        // relevant ones for gdcmlib ?
        //      struct DBI_SimpleEntry {
@@ -63,6 +63,10 @@ private:
 public:
        DictEntry();
        DictEntry(guint16 group, guint16 element, string  name, string  VR);
+       void   SetVR(string);
+       string GetVR(void);
+       guint16 GetGroup(void)   { return group;};
+       guint16 GetElement(void) {return element;};
 };
 
 // A single DICOM dictionary i.e. a container for a collection of dictionary
@@ -75,8 +79,9 @@ class Dict {
        TagHT entries;
 public:
        Dict();
-       Dict(string filename);  // Read Dict from disk
+       Dict(string filename);   // Read Dict from disk
        int AppendEntry(DictEntry* NewEntry);
+       DictEntry * GetTag(guint32, guint32);  // Is this tag in this Dict ?
 };
 
 // Container for managing a set of loaded dictionaries. Sharing dictionaries
@@ -89,7 +94,7 @@ private:
        map<DictId, Dict*> dicts;
        int AppendDict(Dict* NewDict);
 public:
-       DictSet();              // Default constructor loads THE DICOM v3 dictionary
+       DictSet();    // Default constructor loads THE DICOM v3 dictionary
        int LoadDictFromFile(string filename);
 ///// QUESTION: the following function might not be thread safe !? Maybe
 /////           we need some mutex here, to avoid concurent creation of
@@ -103,8 +108,22 @@ public:
 // The dicom header of a Dicom file contains a set of such ELement VALUES
 // (when successfuly parsed against a given Dicom dictionary)
 class ElValue {
-       DictEntry entry;
-       string  value;
+private:
+       DictEntry *entry;
+       guint32 LgrLueElem; // Longueur Lue
+       // Might prove of some interest (see _ID_DCM_ELEM)
+       // int Swap;
+public:
+       guint32 LgrElem;   // FIXME probably for bad reasons at parse time !
+       string  value;     // used to be char * valeurElem
+       size_t Offset;     // Offset from the begining of file for direct user access
+       ElValue(DictEntry*);
+       void SetVR(string);
+       void SetLgrLue(guint32);
+       guint16 GetGroup(void)   { return entry->GetGroup(); };
+       guint16 GetElement(void) { return entry->GetElement(); };
+       guint32 GetLgrElem(void) { return LgrElem; };
+       void SetValue(string val) { value = val; };
 };
 
 // Container for a set of succefully parsed ElValues.
@@ -118,6 +137,12 @@ public:
        int Add(ElValue);
 };
 
+// The various entries of the explicit value representation (VR) shall
+// be managed within a dictionary. 
+typedef string VRKey;
+typedef string VRAtr;
+typedef map<TagKey, VRAtr> VRHT;    // Value Representation Hash Table
+
 // The typical usage of objects of this class is to classify a set of
 // dicom files according to header information e.g. to create a file hierachy
 // reflecting the Patient/Study/Serie informations, or extracting a given
@@ -126,7 +151,6 @@ public:
 // Notes:
 // * the gdcmHeader::Set*Tag* family members cannot be defined as protected
 //   (Swig limitations for as Has_a dependency between gdcmFile and gdcmHeader)
-typedef int _ID_DCM_ELEM;
 class gdcmHeader {     
        //enum EndianType {
                //LittleEndian, 
@@ -141,20 +165,37 @@ class gdcmHeader {
                ACR,
                ACR_LIBIDO};
 private:
+       // All instances share the same valur representation dictionary
+       static VRHT *dicom_vr;
        static DictSet* Dicts;  // Global dictionary container
        Dict* RefPubDict;       // Public Dictionary
        Dict* RefShaDict;       // Shadow Dictionary (optional)
        ElValSet PubElVals;     // Element Values parsed with Public Dictionary
        ElValSet ShaElVals;     // Element Values parsed with Shadow Dictionary
        FileType filetype;
+       // In order to inspect/navigate through the file
+       size_t taille_fich;
        FILE * fp;
-       long int offsetCourant;
+       size_t offsetCourant;
+       // The tag Image Location ((0028,0200) containing the adress of
+       // the pixels) is not allways present. When we store this information
+       // FIXME
+       // outside of the elements:
+       guint16 grPixel;
+       guint16 numPixel;
+       bool PixelsTrouves;
+       bool grPixelTrouve;
+       size_t PixelPosition;
        int sw;
        void CheckSwap(void);
        void setAcrLibido(void);
-       long int RecupLgr(_ID_DCM_ELEM *pleCourant, int sw,
-                         int *skippedLength, int *longueurLue);
+       long int RecupLgr(ElValue *, int *);
        guint32 SWAP_LONG(guint32);
+       short int SWAP_SHORT(short int);
+       void InitVRDict(void);
+       ElValue * ReadNextElement(void);
+       DictEntry * IsInDicts(guint32, guint32);
+       void SetAsidePixelData(ElValue*);
 protected:
 ///// QUESTION: Maybe Print is a better name than write !?
        int write(ostream&);