From 55f3727f18aa712ea6d349de40b6a22ba2b6516d Mon Sep 17 00:00:00 2001 From: jpr Date: Tue, 14 Jan 2003 13:23:48 +0000 Subject: [PATCH] Ajout fonctions int AddNewEntry (gdcmDictEntry* NewEntry); int ReplaceEntry(gdcmDictEntry* NewEntry); int RemoveEntry (TagKey k); int RemoveEntry (guint16 group, guint16 element); --- src/gdcm.h | 71 +++++++++++++++++-------------- src/gdcmDict.cxx | 62 +++++++++++++++++++++++++++ src/gdcmDictEntry.cxx | 12 +++--- src/gdcmElValSet.cxx | 40 ++++++++++++++--- src/gdcmElValue.cxx | 5 ++- src/gdcmFile.cxx | 99 ++++++++++++++----------------------------- 6 files changed, 175 insertions(+), 114 deletions(-) diff --git a/src/gdcm.h b/src/gdcm.h index 36ddb3df..457920c4 100644 --- a/src/gdcm.h +++ b/src/gdcm.h @@ -52,7 +52,6 @@ using namespace std; // string type lives in the std namespace on VC++ // exporter des images lisibles par les consoles cliniques // et pas seulement importables dans e-film. - #ifdef __GNUC__ #include #define guint16 uint16_t @@ -70,7 +69,6 @@ typedef unsigned int guint32; #define GDCM_EXPORT #endif - // // ---------------------------------------------------- gdcmDictEntry // @@ -133,6 +131,7 @@ public: guint16 GetElement(void){return element;}; string GetVR(void) {return vr; }; void SetVR(string); + void SetKey(string k){ key = k; } bool IsVrUnknown(void); string GetFourth(void) {return fourth;}; string GetName(void) {return name; }; @@ -154,8 +153,6 @@ public: typedef map TagHT; // Table de Hachage : (group,Elem) --> pointeur vers une ligne du Dictionnaire Dicom -typedef map TagHT; - class GDCM_EXPORT gdcmDict { string name; string filename; @@ -164,10 +161,11 @@ public: // rempli le Dictionnaire Dicom à partir d'un fichier texte gdcmDict(const char* FileName); // Read Dict from disk - // QUESTION : - // Ca doit ajouter une nouvelle entrée 'a la fin', ou 'a sa place' ? - // - // TODO Swig int AppendEntry(gdcmDictEntry* NewEntry); + int AddNewEntry (gdcmDictEntry* NewEntry); + int ReplaceEntry(gdcmDictEntry* NewEntry); + int RemoveEntry (TagKey k); + int RemoveEntry (guint16 group, guint16 element); + // renvoie une ligne de Dictionnaire Dicom à partir de (numGroup, numElement) gdcmDictEntry * GetTag(guint32 group, guint32 element); @@ -253,25 +251,36 @@ private: public: string value; // used to be char * valeurElem size_t Offset; // Offset from the begining of file for direct user access + ElValue(gdcmDictEntry*); void SetDictEntry(gdcmDictEntry *NewEntry) { entry = NewEntry; }; - bool IsVrUnknown(void) { return entry->IsVrUnknown(); }; - - void SetLength(guint32 l){ LgrElem = l; }; - void SetValue(string val){ value = val; }; - void SetOffset(size_t of){ Offset = of; }; void SetImplicitVr(void) { ImplicitVr = true; }; bool IsImplicitVr(void) { return ImplicitVr; }; - void SetVR(string); - string GetVR(void); - string GetValue(void) { return value; }; - guint32 GetLength(void) { return LgrElem; }; - size_t GetOffset(void) { return Offset; }; - guint16 GetGroup(void) { return entry->GetGroup(); }; + + guint16 GetGroup(void) { return entry->GetGroup(); }; guint16 GetElement(void) { return entry->GetElement(); }; string GetKey(void) { return entry->GetKey(); }; string GetName(void) { return entry->GetName(); }; + + string GetVR(void) { return entry->GetVR(); }; + + void SetVR(string v) { entry->SetVR(v); }; + + // Question : + // Un champ privé, accessible en consultation et en modif (sans restriction) + // interet par rapport à un champ public ? + // --> pouvoir en changer la définition sans toucher à l'API + + void SetLength(guint32 l){ LgrElem = l; }; + guint32 GetLength(void) { return LgrElem; }; + + void SetValue(string val){ value = val; }; + string GetValue(void) { return value; }; + + void SetOffset(size_t of){ Offset = of; }; + size_t GetOffset(void) { return Offset; }; + }; @@ -300,7 +309,8 @@ public: ElValue* GetElementByName (string); string GetElValueByNumber(guint32 group, guint32 element); string GetElValueByName (string); - TagElValueHT & GetTagHt(void); + + TagElValueHT & GetTagHt(void); int SetElValueByNumber(string content, guint32 group, guint32 element); int SetElValueByName(string content, string TagName); @@ -328,24 +338,17 @@ public: // (Swig limitations for as Has_a dependency between gdcmFile and gdcmHeader) -typedef string VRKey; // Ne devrait-elle pas etre utilisee dans la definition de VRHT ? +typedef string VRKey; typedef string VRAtr; -typedef map VRHT; // Value Representation Hash Table - // Cette Table de Hachage ne devrait servir qu'a determiner - // si deux caractères correspondent à une VR existante ? +typedef map VRHT; // Value Representation Hash Table + class GDCM_EXPORT gdcmHeader { void SkipBytes(guint32); private: static VRHT *dicom_vr; // Dictionaries of data elements: - - // Question : - // Pourquoi mettre un pointeur statique vers le container des dictionnaires - // (qui est une H-table de pointeurs vers des dictionnaires) - // en plus des pointeurs vers chacun des dictionnaires ? - // Ces derniers n'auraient-ils pas suffit ? - // + static gdcmDictSet* Dicts; // global dictionary container gdcmDict* RefPubDict; // public dictionary gdcmDict* RefShaDict; // shadow dictionary (optional) @@ -560,6 +563,12 @@ public: int PutImageDataHere(void* destination, size_t MaxSize ); + // Question : + // + // GetImageData et PutImageDataHere + // Get et Put pour 2 fonctions qui font presque la meme chose :-( + // + // Allocates ExpectedSize bytes of memory at this->Data and copies the // pointed data to it. diff --git a/src/gdcmDict.cxx b/src/gdcmDict.cxx index 32cc1246..da9423b8 100644 --- a/src/gdcmDict.cxx +++ b/src/gdcmDict.cxx @@ -50,3 +50,65 @@ gdcmDictEntry * gdcmDict::GetTag(guint32 group, guint32 element) { "multiple entries for this key (FIXME) !"); return entries.find(key)->second; } + + +int gdcmDict::ReplaceEntry(gdcmDictEntry* NewEntry) { + + // au cas ou la NewEntry serait incomplete + // Question : cela peut-il se produire ? + // + TagKey key; + key = NewEntry->GetKey(); + if (key =="") { + NewEntry->gdcmDictEntry::SetKey( + gdcmDictEntry::TranslateToKey(NewEntry->GetGroup(), NewEntry->GetElement()) + ); + } + + entries.erase (NewEntry->gdcmDictEntry::GetKey()); + entries[ NewEntry->GetKey()] = NewEntry; + return (1); + // Question : Dans quel cas ça peut planter ? +} + + +int gdcmDict::AddNewEntry(gdcmDictEntry* NewEntry) { + + // au cas ou la NewEntry serait incomplete + // Question : cela peut-il se produire ? + // + + TagKey key; + key = NewEntry->GetKey(); + if (key =="") { + NewEntry->SetKey( + gdcmDictEntry::TranslateToKey(NewEntry->GetGroup(), NewEntry->GetElement()) + ); + } + + if(entries.count(key) >= 1) { + printf("gdcmDict::AddNewEntry %s deja present\n", key.c_str()); + return(0); + } else { + entries[NewEntry->GetKey()] = NewEntry; + return(1); + } + } + + +int gdcmDict::RemoveEntry(TagKey key) { + if(entries.count(key) == 1) { + entries.erase(key); + return (1); + } else { + printf("gdcmDict::RemoveEntry %s non trouve\n", key.c_str()); + return (0); + } +} + + +int gdcmDict::RemoveEntry (guint16 group, guint16 element) { + + return( RemoveEntry(gdcmDictEntry::TranslateToKey(group, element)) ); +} + diff --git a/src/gdcmDictEntry.cxx b/src/gdcmDictEntry.cxx index c9b1ca0c..3e9b109e 100644 --- a/src/gdcmDictEntry.cxx +++ b/src/gdcmDictEntry.cxx @@ -6,12 +6,12 @@ gdcmDictEntry::gdcmDictEntry(guint16 InGroup, guint16 InElement, string InVr, string InFourth, string InName) { - group = InGroup; - element = InElement; - vr = InVr; - fourth = InFourth; - name = InName; - key = TranslateToKey(group, element); + group = InGroup; + element = InElement; + vr = InVr; + fourth = InFourth; + name = InName; + key = TranslateToKey(group, element); } TagKey gdcmDictEntry::TranslateToKey(guint16 group, guint16 element) { diff --git a/src/gdcmElValSet.cxx b/src/gdcmElValSet.cxx index 70f21fc1..6cdcc310 100644 --- a/src/gdcmElValSet.cxx +++ b/src/gdcmElValSet.cxx @@ -22,14 +22,32 @@ void ElValSet::Print(ostream & os) { os << "[" << tag->second->GetVR() << "]" << endl; } } - + int ElValSet::Write(FILE * _fp) { +// ATTENTION : fonction non terminée (commitée a titre de precaution) + guint16 gr, el; guint32 lgr; const char * val; - // restent à tester les echecs en écriture + + // A FAIRE : + // parcourir la table pour recalculer la longueur des 'elements 0x0000' + // au cas ou un tag ai été ajouté par rapport à ce qui a été lu + // dans l'image native + // + // cf : code IdDcmWriteFile + +/* + for (TagElValueHT::iterator tag = tagHt.begin(); + tag != tagHt.end(); + ++tag){ + + + } +*/ + // resteront à tester les echecs en écriture for (TagElValueHT::iterator tag = tagHt.begin(); tag != tagHt.end(); ++tag){ @@ -38,29 +56,37 @@ int ElValSet::Write(FILE * _fp) { // peut-on se passer des affectations? // - passer l'adresse du resultat d'une fonction (???) // - acceder au champ sans passer par un accesseur ? - gr = tag->second->GetGroup(); - el = tag->second->GetElement(); + gr = tag->second->GetGroup(); + el = tag->second->GetElement(); lgr = tag->second->GetLength(); val = tag->second->GetValue().c_str(); fwrite ( &gr,(size_t)2 ,(size_t)1 ,_fp); //group fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp); //element - //fwrite ( tag->second->GetVR(),(size_t)2 ,(size_t)1 ,_fp); //VR + //fwrite ( tag->second->GetVR(),(size_t)2 ,(size_t)1 ,_fp); //VR // voir pb lgr + VR - fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp); //lgr + + fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp); //lgr + + // ATTENTION // voir pb des int16 et int32 : les identifier, les convertir, modifier la longueur + // ou alors stocker la valeur 16 ou 32 bits, + un indicateur : char, int16, int32 + fwrite ( val,(size_t)lgr ,(size_t)1 ,_fp); //valeur Elem } return(1); } + + + void ElValSet::PrintByName(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->GetKey() << "]"; os << "[" << tag->second->GetVR() << "]" << endl; } } diff --git a/src/gdcmElValue.cxx b/src/gdcmElValue.cxx index 060ffb99..33906902 100644 --- a/src/gdcmElValue.cxx +++ b/src/gdcmElValue.cxx @@ -2,10 +2,11 @@ #include "gdcm.h" -void ElValue::SetVR(string ValRep) { entry->SetVR(ValRep); } -string ElValue::GetVR(void) { return entry->GetVR(); } + // void ElValue::SetVR(string v) { entry->SetVR(v); }; ElValue::ElValue(gdcmDictEntry* in) { ImplicitVr = false; entry = in; } + + diff --git a/src/gdcmFile.cxx b/src/gdcmFile.cxx index 11f9b015..89c872f3 100644 --- a/src/gdcmFile.cxx +++ b/src/gdcmFile.cxx @@ -24,10 +24,9 @@ static void _Swap(void* im, int swap, int lgr, int nb); * @return */ -gdcmFile::gdcmFile(string & filename) - :gdcmHeader(filename.c_str()) +gdcmFile::gdcmFile(string & filename) + :gdcmHeader(filename.c_str()) { - if (DEBUG) printf("On a echappe a gdcmHeader !\n"); } @@ -52,10 +51,6 @@ size_t gdcmFile::GetImageDataSize(void) { // Nombre de Colonnes nbCol =atoi(gdcmHeader::GetPubElValByNumber(0x0028,0x0011).c_str()); -printf("nbCol %d\n",nbCol); -printf("nbLig %d\n",nbLignes); - - // Nombre de Frames str_nbFrames=gdcmHeader::GetPubElValByNumber(0x0028,0x0008); @@ -64,7 +59,6 @@ printf("nbLig %d\n",nbLignes); } else { nbFrames = atoi(str_nbFrames.c_str() ); } -printf("nbFrames %d\n",nbFrames); // Nombre de Bits Alloues pour le stockage d'un Pixel str_nb=gdcmHeader::GetPubElValByNumber(0x0028,0x0100); @@ -75,8 +69,6 @@ printf("nbFrames %d\n",nbFrames); nb = atoi(str_nb.c_str() ); } -printf("nb %d\n",nb); - size_t lgrTotale = nbFrames*nbLignes*nbCol*(nb/8); return (lgrTotale); @@ -96,37 +88,21 @@ printf("nb %d\n",nb); void * gdcmFile::GetImageData (void) { char* _Pixels; - int nbLignes, nbCol; - int nbFrames, nb, nbu, highBit, signe; + int nb, nbu, highBit, signe; string str_nbFrames, str_nb, str_nbu, str_highBit, str_signe; unsigned short int mask = 0xffff; - - // Nombre de Lignes - nbLignes=atoi(GetPubElValByNumber(0x0028,0x0010).c_str()); - // Nombre de Colonnes - nbCol =atoi(GetPubElValByNumber(0x0028,0x0011).c_str()); - - // Nombre de Frames - str_nbFrames=GetPubElValByNumber(0x0028,0x0008); - - if (str_nbFrames == "gdcm::Unfound" ) { - nbFrames = 1; - } else { - nbFrames = atoi(str_nbFrames.c_str() ); - } - - // Nombre de Bits Alloues - str_nb=GetPubElValByNumber(0x0028,0x0100); + // Nombre de Bits Alloues pour le stockage d'un Pixel + str_nb=gdcmHeader::GetPubElValByNumber(0x0028,0x0100); if (str_nb == "gdcm::Unfound" ) { nb = 16; } else { nb = atoi(str_nb.c_str() ); } - + // Nombre de Bits Utilises str_nbu=GetPubElValByNumber(0x0028,0x0101); @@ -155,7 +131,7 @@ void * gdcmFile::GetImageData (void) { } // Longueur en Octets des Pixels a lire - size_t _lgrTotale = nbFrames*nbLignes*nbCol*(nb/8); + size_t _lgrTotale = GetImageDataSize(); //Pixels = (char *) g_malloc(_lgrTotale); _Pixels = (char *) malloc(_lgrTotale); @@ -212,32 +188,33 @@ void * gdcmFile::GetImageData (void) { */ int gdcmFile::PutImageDataHere (void* destination, size_t MaxSize) { + +// Question : +// dans quel cas la Maxize sert-elle a quelque chose? +// que fait-on si la taille de l'image est + gde que Maxize? +// que fait-on si la taille de l'image est + petite que Maxize? + void * Pixels = destination; // pour garder le code identique avec GetImageData - int nbLignes, nbCol; - int nbFrames, nb, nbu, highBit, signe; + int nb, nbu, highBit, signe; string str_nbFrames, str_nb, str_nbu, str_highBit, str_signe; unsigned short int mask = 0xffff; - - // Nombre de Lignes - nbLignes=atoi(GetPubElValByNumber(0x0028,0x0010).c_str()); - // Nombre de Colonnes - nbCol =atoi(GetPubElValByNumber(0x0028,0x0011).c_str()); - - // Nombre de Frames - str_nbFrames=GetPubElValByNumber(0x0028,0x0008); - - if (str_nbFrames == "gdcm::Unfound" ) { - nbFrames = 1; - } else { - nbFrames = atoi(str_nbFrames.c_str() ); - } + // Longueur en Octets des Pixels a lire + size_t _lgrTotale = GetImageDataSize(); // ne faudrait-il pas la stocker? + + // si lgrTotale < MaxSize ==> Gros pb . A VOIR + + lgrTotale = MaxSize; // pour garder le code identique avec GetImageData + //Pixels = (char *) malloc(lgrTotale); // pour garder le code identique avec GetImageData - // Nombre de Bits Alloues - str_nb=GetPubElValByNumber(0x0028,0x0100); + GetPixels(lgrTotale, Pixels); + + + // Nombre de Bits Alloues pour le stockage d'un Pixel + str_nb=gdcmHeader::GetPubElValByNumber(0x0028,0x0100); if (str_nb == "gdcm::Unfound" ) { nb = 16; @@ -271,16 +248,7 @@ int gdcmFile::PutImageDataHere (void* destination, size_t MaxSize) { } else { signe = atoi(str_signe.c_str() ); } - - // Longueur en Octets des Pixels a lire - size_t lgrTotale = nbFrames*nbLignes*nbCol*(nb/8); - - // si lgrTotale < MaxSize ==> Gros pb . A VOIR - - lgrTotale = MaxSize; // pour garder le code identique avec GetImageData - //Pixels = (char *) malloc(lgrTotale); // pour garder le code identique avec GetImageData - - GetPixels(lgrTotale, Pixels); + // On remet les Octets dans le bon ordre si besoin est if (nb != 8) { @@ -304,9 +272,7 @@ int gdcmFile::PutImageDataHere (void* destination, size_t MaxSize) { deb ++; } } - - printf ("on est sorti\n"); - + // VOIR s'il ne faudrait pas l'affecter à un champ du dcmHeader //return (Pixels); // pour garder le code identique avec GetImageData @@ -388,9 +354,6 @@ if( nb == 32 ) return; } - - - ///////////////////////////////////////////////////////////////// /** * \ingroup gdcmFile @@ -425,8 +388,8 @@ int gdcmFile::WriteRawData (string nomFichier) { * \ingroup gdcmFile * \brief Ecrit sur disque UNE image Dicom * \Aucun test n'est fait sur l'"Endiannerie" du processeur. - * \Ca sera à l'utilisateur d'appeler son Reader correctement - * \ Equivalent a IdDcmWrite) + * \Ca sera à l'utilisateur d'appeler son Reader correctement. + * \ (Equivalent a IdDcmWrite) * * @param * @@ -447,13 +410,13 @@ int gdcmFile::WriteDcm (string nomFichier) { } // Ecriture Dicom File Preamble - //filePreamble=(char*)g_malloc0(128); // voir pourquoi ca ne passe pas a la compile filePreamble=(char*)calloc(128,1); fwrite(filePreamble,128,1,fp1); fwrite("DICM",4,1,fp1); if(DEBUG) printf("Ecriture File Preamble\n"); // un accesseur de + est obligatoire ??? + GetPubElVals().Write(fp1); fclose (fp1); -- 2.48.1