From ea7d6b73b6e3707747332e25bcc3f4ad4cd76c9c Mon Sep 17 00:00:00 2001 From: jpr Date: Fri, 21 Mar 2003 08:52:31 +0000 Subject: [PATCH 1/1] Calcul correct (merci, Eric!) de la longueur de chaque Dicom Group --- src/gdcmElValSet.cxx | 253 +++++++++++++++++++++++++------------------ src/gdcmElValSet.h | 5 +- src/gdcmFile.cxx | 163 ++++++++++------------------ src/gdcmFile.h | 9 +- src/gdcmHeader.cxx | 22 ---- 5 files changed, 207 insertions(+), 245 deletions(-) diff --git a/src/gdcmElValSet.cxx b/src/gdcmElValSet.cxx index 871c1aeb..a0ebec2e 100644 --- a/src/gdcmElValSet.cxx +++ b/src/gdcmElValSet.cxx @@ -1,5 +1,6 @@ -// $Id: gdcmElValSet.cxx,v 1.21 2003/03/14 14:26:01 jpr Exp $ +// gdcmElValSet.cxx +#include #include "gdcmUtil.h" #include "gdcmElValSet.h" @@ -13,6 +14,26 @@ void gdcmElValSet::Add(gdcmElValue * newElValue) { NameHt[newElValue->GetName()] = newElValue; } +// TODO : faire un gdcmElValSet::ReplaceOrCreate qui remplace si ça existe, qui cree sinon + +void gdcmElValSet::ReplaceOrCreate(gdcmElValue * newElValue) { + + TagKey key = newElValue->GetKey(); + + if (tagHt.count(key) > 1) + dbg.Verbose(0, "gdcmElValSet::GetElValueByNumber", + "multiple entries for this key (FIXME) !"); + + if (tagHt.count(key)) { + tagHt.erase(key); + tagHt.erase(newElValue->GetName()); + } + + tagHt [key] = newElValue; + NameHt[newElValue->GetName()] = newElValue; +} + + void gdcmElValSet::Print(ostream & os) { for (TagElValueHT::iterator tag = tagHt.begin(); tag != tagHt.end(); @@ -20,7 +41,9 @@ void gdcmElValSet::Print(ostream & os) { os << tag->first << ": "; os << "[" << tag->second->GetValue() << "]"; os << "[" << tag->second->GetName() << "]"; - os << "[" << tag->second->GetVR() << "]" << endl; + os << "[" << tag->second->GetVR() << "]"; + os << " lgr : " << tag->second->GetLength(); + os << endl; } } @@ -118,8 +141,6 @@ int gdcmElValSet::SetElValueLengthByNumber(guint32 l, "multiple entries for this key (FIXME) !"); return (0); } - // FIXME JPR: comments in English please ! - // m à j LgrElem tagHt[key]->SetLength(l); return(1); } @@ -137,6 +158,8 @@ int gdcmElValSet::SetElValueLengthByName(guint32 l, string TagName) { return(1); } +// Sorry for the DEBUG's, but tomorow is gonna be hoter than today +#define DEBUG 0 int gdcmElValSet::Write(FILE * _fp) { @@ -149,17 +172,18 @@ int gdcmElValSet::Write(FILE * _fp) { guint32 val_uint32; gint32 val_int32; guint16 val_uint16; - gint16 val_int16; + gint16 val_int16;; vector tokens; void *ptr; char str_lgrCalcGroupe[10]; + string implicitVRTransfertSyntax = "1.2.840.10008.1.2"; // Utilisées pour le calcul Group Length - int deja = 0; + int deja = 0, prem=0; guint32 lgrCalcGroupe=0; gdcmElValue *elem, *elemZ, *elemZPrec; guint16 grCourant = 0; @@ -175,60 +199,77 @@ int gdcmElValSet::Write(FILE * _fp) { // // cf : code IdDcmWriteFile dans libido/src/dcmwrite.c - if (0) // Risque de pb dans le calcul des lgr de chaque groupe. On le saute pour le moment! +if (1) { // Risque de pb dans le calcul des lgr de chaque groupe. On le saute pour le moment! + + // On fait de l'implicit VR little Endian + // (pour moins se fairche sur processeur INTEL) + // On force le TRANSFERT SYNTAX UID + + SetElValueByNumber(implicitVRTransfertSyntax, 0x0002, 0x0010); + SetElValueLengthByNumber(18, 0x0002, 0x0010); // Le 0 de fin de chaine doit etre stocké, dans ce cas + + TagElValueHT::iterator tag = tagHt.begin(); - for (TagElValueHT::iterator tag = tagHt.begin(); + elem = tag->second; + gr = elem->GetGroup(); + el = elem->GetElement(); + + if (el != 0x0000) { + if(DEBUG)printf("ajout elem OOOO premiere fois\n"); + gdcmDictEntry * tagZ = new gdcmDictEntry(gr, 0x0000, "UL"); + elemZPrec = new gdcmElValue(tagZ); // on le cree + elemZPrec->SetLength(4); + Add(elemZPrec); // On l'accroche à sa place + } else { + elemZPrec = elem; + if(DEBUG)printf("Pas d'ajout elem OOOO premiere fois\n"); + } + lgrCalcGroupe = 0; + if(DEBUG)printf("init-1 lgr (%d) pour gr %04x\n",lgrCalcGroupe, gr); + grCourant = gr; + + for (tag = ++tagHt.begin(); tag != tagHt.end(); ++tag){ - + elem = tag->second; - printf("gr %04x el %04x lgr %d\n",elem->GetGroup(), elem->GetElement(), elem->GetLength()); - - if ( (elem->GetGroup() != grCourant) && - (elem->GetGroup() != 0xfffe) ) { // On arrive sur un nv Groupe - - printf("Nouv Groupegr %04x el %04x \n",elem->GetGroup(), elem->GetElement()); - - elemZ = elem; - - if(elemZ->GetElement() != 0x0000) { // pas d'element 'Lgr groupe' - // On crée - gdcmDictEntry * tagZ = new gdcmDictEntry(grCourant, 0x0000, "UL"); + gr = elem->GetGroup(); + el = elem->GetElement(); + + if ( (gr != grCourant) /*&& // On arrive sur un nv Groupe + (el != 0xfffe) */ ) { + + if (el != 0x0000) { + gdcmDictEntry * tagZ = new gdcmDictEntry(gr, 0x0000, "UL"); elemZ = new gdcmElValue(tagZ); // on le cree elemZ->SetLength(4); - Add(elemZ); // On l'accroche à sa place - } - - if (deja) { - //sprintf(str_lgrCalcGroupe,"%d",lgrCalcGroupe); - elemZPrec->SetValue(str_lgrCalcGroupe); - lgrCalcGroupe = 0; + Add(elemZ); // On l'accroche à sa place + if(DEBUG)printf("ajout elem OOOO pour gr %04x\n",gr); + } else { + elemZ=elem; + if(DEBUG)printf("maj elmeZ\n"); } - deja = 1; - - lgrCalcGroupe = 12; //2 + 2 + 4 + 4; // Gr + Num + Lgr + LgrGroupe - printf ("lgrCalcGroupe %d\n",lgrCalcGroupe); - elemZPrec = elemZ; - grCourant = elem->GetGroup(); - - } else { // On n'EST PAS sur un nv Groupe - - printf ("lgrCalcGroupe avant : %d LgrElem %d\n",lgrCalcGroupe,elem->GetLength()); - - lgrCalcGroupe += 2 + 2 + 4 + elem->GetLength(); // Gr + Num + Lgr + LgrElem - - printf ("lgrCalcGroupe apres %d\n",lgrCalcGroupe); + ostringstream fock; + fock << lgrCalcGroupe; + //sprintf(str_lgrCalcGroupe,"%d",lgrCalcGroupe); + elemZPrec->SetValue(fock.str()); + if(DEBUG)printf("ecriture lgr (%d, %s) pour gr %04x\n",lgrCalcGroupe, fock.str().c_str(), grCourant); + if(DEBUG)printf ("%04x %04x [%s]\n",elemZPrec->GetGroup(), elemZPrec->GetElement(),elemZPrec->GetValue().c_str()); + if(DEBUG)cout << "Addresse elemZPrec " << elemZPrec<< endl; + elemZPrec=elemZ; + lgrCalcGroupe = 0; + grCourant = gr; + if(DEBUG)printf("init-2 lgr (%d) pour gr %04x\n",lgrCalcGroupe, gr); + } else { // On n'EST PAS sur un nv Groupe + lgrCalcGroupe += 2 + 2 + 4 + elem->GetLength(); // Gr + Num + Lgr + LgrElem + if(DEBUG)printf("increment (%d) el %04x-->lgr (%d) pour gr %04x\n",elem->GetLength(), el, lgrCalcGroupe, gr); } } - // Si on fait de l'implicit VR little Endian - // (pour moins se fairche sur processeur INTEL) - // penser a forcer le TRANSFERT SYNTAX UID - - SetElValueByNumber(implicitVRTransfertSyntax, 0x0002, 0x0010); - SetElValueLengthByNumber(18, 0x0002, 0x0010); // Le 0 de fin de chaine doit etre stocké, dans ce cas - +} // fin if (1) + + // restent à tester les echecs en écriture (apres chaque fwrite) for (TagElValueHT::iterator tag2 = tagHt.begin(); @@ -240,6 +281,7 @@ int gdcmElValSet::Write(FILE * _fp) { lgr = tag2->second->GetLength(); val = tag2->second->GetValue().c_str(); vr = tag2->second->GetVR(); + if(DEBUG)printf ("%04x %04x [%s] : [%s]\n",gr, el, vr.c_str(), val); fwrite ( &gr,(size_t)2 ,(size_t)1 ,_fp); //group fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp); //element @@ -248,47 +290,28 @@ int gdcmElValSet::Write(FILE * _fp) { // si on n'est pas en IMPLICIT 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 tokens.erase(tokens.begin(),tokens.end()); Tokenize (tag2->second->GetValue(), tokens, "\\"); - //printf ("%04x %04x [%s] : [%s]\n",gr, el, vr.c_str(), val); //if (tokens.size() > 1) { printf ("size : %d\n",tokens.size());} - if (vr == "US" || vr == "SS") { - /* - val_int16 = atoi(val); - ptr = &val_int16; - fwrite ( ptr,(size_t)2 ,(size_t)1 ,_fp); - continue; - */ - for (unsigned int i=0; isecond; + gr = elem->GetGroup(); + el = elem->GetElement(); + + if (el != 0x0000) { + if(DEBUG)printf("ajout elem OOOO premiere fois\n"); + gdcmDictEntry * tagZ = new gdcmDictEntry(gr, 0x0000, "UL"); + elemZPrec = new gdcmElValue(tagZ); // on le cree + elemZPrec->SetLength(4); + Add(elemZPrec); // On l'accroche à sa place + } else { + elemZPrec = elem; + if(DEBUG)printf("Pas d'ajout elem OOOO premiere fois\n"); + } + lgrCalcGroupe = 0; + if(DEBUG)printf("init-1 lgr (%d) pour gr %04x\n",lgrCalcGroupe, gr); + grCourant = gr; + + for (tag = ++tagHt.begin(); tag != tagHt.end(); ++tag){ - + elem = tag->second; - //printf("gr %04x el %04x lgr %d\n",elem->GetGroup(), elem->GetElement(), elem->GetLength()); - - if ( (elem->GetGroup() != grCourant) && - (elem->GetGroup() != 0xfffe) ) { // On arrive sur un nv Groupe - - //printf("Nouv Groupegr %04x el %04x \n",elem->GetGroup(), elem->GetElement()); - - elemZ = elem; - - if(elemZ->GetElement() != 0x0000) { // pas d'element 'Lgr groupe' - // On crée - gdcmDictEntry * tagZ = new gdcmDictEntry(grCourant, 0x0000, "UL"); + gr = elem->GetGroup(); + el = elem->GetElement(); + + if ( (gr != grCourant) /*&& // On arrive sur un nv Groupe + (el != 0xfffe) */ ) { + + if (el != 0x0000) { + gdcmDictEntry * tagZ = new gdcmDictEntry(gr, 0x0000, "UL"); elemZ = new gdcmElValue(tagZ); // on le cree elemZ->SetLength(4); - Add(elemZ); // On l'accroche à sa place - } - - if (deja) { - //sprintf(str_lgrCalcGroupe,"%d",lgrCalcGroupe); - elemZPrec->SetValue(str_lgrCalcGroupe); - lgrCalcGroupe = 0; + Add(elemZ); // On l'accroche à sa place + if(DEBUG)printf("ajout elem OOOO pour gr %04x\n",gr); + } else { + elemZ=elem; + if(DEBUG)printf("maj elmeZ\n"); } - deja = 1; - - lgrCalcGroupe = 12; //2 + 2 + 4 + 4; // Gr + Num + Lgr + LgrGroupe - //printf ("lgrCalcGroupe %d\n",lgrCalcGroupe); - - elemZPrec = elemZ; - grCourant = elem->GetGroup(); - - } else { // On n'EST PAS sur un nv Groupe - - //printf ("lgrCalcGroupe avant : %d LgrElem %d\n",lgrCalcGroupe,elem->GetLength()); - - lgrCalcGroupe += 2 + 2 + 4 + elem->GetLength(); // Gr + Num + Lgr + LgrElem - //printf ("lgrCalcGroupe apres %d\n",lgrCalcGroupe); + ostringstream fock; + fock << lgrCalcGroupe; + //sprintf(str_lgrCalcGroupe,"%d",lgrCalcGroupe); + elemZPrec->SetValue(fock.str()); + if(DEBUG)printf("ecriture lgr (%d, %s) pour gr %04x\n",lgrCalcGroupe, fock.str().c_str(), grCourant); + if(DEBUG)printf ("%04x %04x [%s]\n",elemZPrec->GetGroup(), elemZPrec->GetElement(),elemZPrec->GetValue().c_str()); + if(DEBUG)cout << "Addresse elemZPrec " << elemZPrec<< endl; + elemZPrec=elemZ; + lgrCalcGroupe = 0; + grCourant = gr; + if(DEBUG)printf("init-2 lgr (%d) pour gr %04x\n",lgrCalcGroupe, gr); + } else { // On n'EST PAS sur un nv Groupe + lgrCalcGroupe += 2 + 2 + 4 + elem->GetLength(); // Gr + Num + Lgr + LgrElem + if(DEBUG)printf("increment (%d) el %04x-->lgr (%d) pour gr %04x\n",elem->GetLength(), el, lgrCalcGroupe, gr); } } diff --git a/src/gdcmElValSet.h b/src/gdcmElValSet.h index ba351707..696e8e44 100644 --- a/src/gdcmElValSet.h +++ b/src/gdcmElValSet.h @@ -1,4 +1,4 @@ -// $Header: /cvs/public/gdcm/src/Attic/gdcmElValSet.h,v 1.3 2003/03/12 21:33:20 frog Exp $ +// $Header: /cvs/public/gdcm/src/Attic/gdcmElValSet.h,v 1.4 2003/03/21 08:52:31 jpr Exp $ #ifndef GDCMELVALSET_H #define GDCMELVALSET_H @@ -17,7 +17,8 @@ class GDCM_EXPORT gdcmElValSet { TagElValueHT tagHt; // Both accesses with a TagKey or with a TagElValueNameHT NameHt; // the DictEntry.Name are required. public: - void Add(gdcmElValue*); + void Add(gdcmElValue*); + void ReplaceOrCreate(gdcmElValue*); void Print(ostream &); void PrintByName(ostream &); int Write(FILE *fp); diff --git a/src/gdcmFile.cxx b/src/gdcmFile.cxx index a586dc7d..e0e2c66e 100644 --- a/src/gdcmFile.cxx +++ b/src/gdcmFile.cxx @@ -70,132 +70,32 @@ size_t gdcmFile::GetImageDataSize(void) { size_t lgrTotale = nbFrames*nbLignes*nbCol*(nb/8); return (lgrTotale); - } -///////////////////////////////////////////////////////////////// -/** - * \ingroup gdcmFile - * \brief amene en mémoire les Pixels d'une image NON COMPRESSEE - * \Aucun test n'est fait pour le moment sur le caractere compresse ou non de l'image - * - * @param rien - * - * @return Pointeur sur la zone mémoire contenant les Pixels lus - */ - -/* -void * gdcmFile::GetImageData (void) { - - char* _Pixels; - - int nb, nbu, highBit, signe; - string str_nbFrames, str_nb, str_nbu, str_highBit, str_signe; - - unsigned short int mask = 0xffff; - - // 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); - - if (str_nbu == "gdcm::Unfound" ) { - nbu = nb; - } else { - nbu = atoi(str_nbu.c_str() ); - } - - // Position du Bit de Poids Fort - str_highBit=GetPubElValByNumber(0x0028,0x0102); - - if (str_highBit == "gdcm::Unfound" ) { - highBit = nb - 1; - } else { - highBit = atoi(str_highBit.c_str() ); - } - - // Signe des Pixels 0 : Unsigned - str_signe=GetPubElValByNumber(0x0028,0x0103); - - if (str_signe == "gdcm::Unfound" ) { - signe = 1; - } else { - signe = atoi(str_signe.c_str() ); - } - - // Longueur en Octets des Pixels a lire - size_t _lgrTotale = GetImageDataSize(); - - //Pixels = (char *) g_malloc(_lgrTotale); - _Pixels = (char *) malloc(_lgrTotale); - - GetPixels(lgrTotale, _Pixels); - - // On remet les Octets dans le bon ordre si besoin est - if (nb != 8) { - int _sw = GetSwapCode(); - _Swap (_Pixels, _sw, _lgrTotale, nb); - } - - // On remet les Bits des Octets dans le bon ordre si besoin est - // - // ATTENTION : Jamais confronté a des pixels stockes sur 32 bits - // avec moins de 32 bits utilises - // et dont le bit de poids fort ne serait pas la ou on l'attend ... - // --> ne marchera pas dans ce cas - if (nbu!=nb){ - mask = mask >> (nb-nbu); - int l=(int)_lgrTotale/(nb/8); - unsigned short *deb = (unsigned short *)_Pixels; - for(int i=0;i> (nbu-highBit-1)) & mask; - deb ++; - } - } - // On l'affecte à un champ du dcmFile - - Pixels = _Pixels; - lgrTotale = _lgrTotale; - - // et on le retourne - // ca fait double emploi, il faudra nettoyer ça - - return (_Pixels); -} - -*/ ///////////////////////////////////////////////////////////////// /** * \ingroup gdcmFile - * \brief amene en mémoire les Pixels d'une image NON COMPRESSEE - * \Aucun test n'est fait pour le moment sur le caractere compresse ou non de l'image + * \brief TODO + * \warning WARNING * - * @param rien + * @param * - * @return Pointeur sur la zone mémoire contenant les Pixels lus + * @return */ void * gdcmFile::GetImageData (void) { char * _Pixels; // Longueur en Octets des Pixels a lire size_t taille = GetImageDataSize();// ne faudrait-il pas la stocker? - _Pixels = (char *) malloc(taille); + _Pixels = (char *) malloc(taille); GetImageDataIntoVector(_Pixels, taille); // On l'affecte à un champ du dcmFile Pixels = _Pixels; lgrTotale = taille; - // et on le retourne // ca fait double emploi, il faudra nettoyer ça return(_Pixels); @@ -218,7 +118,7 @@ void * gdcmFile::GetImageData (void) { int gdcmFile::GetImageDataIntoVector (void* destination, size_t MaxSize) { // Question : -// dans quel cas la Maxize sert-elle a quelque chose? +// dans quel cas la MaxSize 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? @@ -380,6 +280,57 @@ if( nb == 32 ) return; } +///////////////////////////////////////////////////////////////// +/** + * \ingroup gdcmFile + * \brief TODO + * \warning WARNING doit-etre etre publique ? + * + * @param + * + * @return + */ + +int gdcmFile::SetImageData(void * Data, size_t ExpectedSize) { + + SetImageDataSize(ExpectedSize); + + Pixels = Data; + lgrTotale = ExpectedSize; + + return(1); +} + + +///////////////////////////////////////////////////////////////// +/** + * \ingroup gdcmFile + * \brief TODO + * \ + * \warning WARNING doit-etre etre publique ? + * + * @param + * + * @return + */ + +void gdcmFile::SetImageDataSize(size_t ImageDataSize) { + + string content1; + string content2; + char car[20]; + + sprintf(car,"%d",ImageDataSize); + content2=car; + SetPubElValByNumber(content2, 0x7fe0, 0x0010); + + ImageDataSize+=8; + sprintf(car,"%d",ImageDataSize); + content1=car; + SetPubElValByNumber(content1, 0x7fe0, 0x0000); +} + + ///////////////////////////////////////////////////////////////// /** * \ingroup gdcmFile diff --git a/src/gdcmFile.h b/src/gdcmFile.h index 90ec3b85..bb3074ce 100644 --- a/src/gdcmFile.h +++ b/src/gdcmFile.h @@ -69,12 +69,6 @@ public: int GetImageDataIntoVector(void* destination, size_t MaxSize ); - // Question : - // - // GetImageData et GetImageDataIntoVector - // 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. @@ -82,7 +76,8 @@ public: // Pourquoi dupliquer les pixels, alors qu'on les a deja en mémoire, // et que Data (dans le gdcmHeader) est un pointeur ? - // TODO Swig int SetImageData(void * Data, size_t ExpectedSize); + int SetImageData (void * Data, size_t ExpectedSize); + void SetImageDataSize (size_t ExpectedSize); // Push to disk. // A NE PAS OUBLIER : que fait-on en cas de Transfert Syntax (dans l'entete) diff --git a/src/gdcmHeader.cxx b/src/gdcmHeader.cxx index 10f5700d..0ccd21e5 100644 --- a/src/gdcmHeader.cxx +++ b/src/gdcmHeader.cxx @@ -768,26 +768,6 @@ void gdcmHeader::LoadElementValue(gdcmElValue * ElVal) { // pour les elements de Value Multiplicity > 1 // on aura en fait une serie d'entiers - // code original - - //if ( IsAnInteger(ElVal) ) { - // guint32 NewInt; - // if( length == 2 ) { - // NewInt = ReadInt16(); - // } else if( length == 4 ) { - // - // NewInt = ReadInt32(); - // } else - // dbg.Error(true, "LoadElementValue: Inconsistency when reading Int."); - // - // //FIXME: make the following an util fonction - // ostringstream s; - // s << NewInt; - // ElVal->SetValue(s.str()); - // return; - //} - - // modif proposee. JPR // on devrait pouvoir faire + compact (?) if ( IsAnInteger(ElVal) ) { @@ -823,8 +803,6 @@ void gdcmHeader::LoadElementValue(gdcmElValue * ElVal) { return; } - - // FIXME The exact size should be length if we move to strings or whatever char* NewValue = (char*)malloc(length+1); if( !NewValue) { -- 2.45.2