]> Creatis software - gdcm.git/blob - src/gdcmElValSet.cxx
ajouts accesseurs
[gdcm.git] / src / gdcmElValSet.cxx
1 // gdcmElValSet.cxx
2
3 #include <sstream>
4 #include "gdcmUtil.h"
5 #include "gdcmElValSet.h"
6
7 #define DEBUG 0
8
9
10 TagElValueHT & gdcmElValSet::GetTagHt(void) {
11         return tagHt;
12 }
13
14 void gdcmElValSet::Add(gdcmElValue * newElValue) {
15         tagHt [newElValue->GetKey()]  = newElValue;
16         NameHt[newElValue->GetName()] = newElValue;
17 }
18
19 void gdcmElValSet::Print(ostream & os) {
20         for (TagElValueHT::iterator tag = tagHt.begin();
21                   tag != tagHt.end();
22                   ++tag){
23                 os << tag->first << ": ";
24                 os << "[" << tag->second->GetValue() << "]";
25                 os << "[" << tag->second->GetName()  << "]";
26                 os << "[" << tag->second->GetVR()    << "]"; 
27                 os << " lgr : " << tag->second->GetLength();
28                 os << endl;
29         }
30
31
32 void gdcmElValSet::PrintByName(ostream & os) {
33         for (TagElValueNameHT::iterator tag = NameHt.begin();
34                   tag != NameHt.end();
35                   ++tag){
36                 os << tag->first << ": ";
37                 os << "[" << tag->second->GetValue() << "]";
38                 os << "[" << tag->second->GetKey()   << "]";
39                 os << "[" << tag->second->GetVR()    << "]" << endl;
40         }
41 }
42
43 gdcmElValue* gdcmElValSet::GetElementByNumber(guint32 group, guint32 element) {
44         TagKey key = gdcmDictEntry::TranslateToKey(group, element);
45         if ( ! tagHt.count(key))
46                 return (gdcmElValue*)0;
47         if (tagHt.count(key) > 1)
48                 dbg.Verbose(0, "gdcmElValSet::GetElementByNumber",
49                             "multiple entries for this key (FIXME) !");
50         return tagHt.find(key)->second;
51 }
52
53 gdcmElValue* gdcmElValSet::GetElementByName(string TagName) {
54    if ( ! NameHt.count(TagName))
55       return (gdcmElValue*)0;
56    if (NameHt.count(TagName) > 1)
57       dbg.Verbose(0, "gdcmElValSet::GetElement",
58                   "multipe entries for this key (FIXME) !");
59    return NameHt.find(TagName)->second;
60 }
61
62 string gdcmElValSet::GetElValueByNumber(guint32 group, guint32 element) {
63         TagKey key = gdcmDictEntry::TranslateToKey(group, element);
64         if ( ! tagHt.count(key))
65                 return "gdcm::Unfound";
66         if (tagHt.count(key) > 1)
67                 dbg.Verbose(0, "gdcmElValSet::GetElValueByNumber",
68                             "multiple entries for this key (FIXME) !");
69         return tagHt.find(key)->second->GetValue();
70 }
71
72 string gdcmElValSet::GetElValueByName(string TagName) {
73         if ( ! NameHt.count(TagName))
74                 return "gdcm::Unfound";
75         if (NameHt.count(TagName) > 1)
76                 dbg.Verbose(0, "gdcmElValSet::GetElValue",
77                             "multipe entries for this key (FIXME) !");
78         return NameHt.find(TagName)->second->GetValue();
79 }
80
81
82 int gdcmElValSet::SetElValueByNumber(string content,
83                                      guint32 group, guint32 element) {
84                                      
85 // TODO : comprendre pourquoi ils sont déclares comme des guint32, alors que c'est des guint16
86
87         TagKey key = gdcmDictEntry::TranslateToKey(group, element);
88         if ( ! tagHt.count(key))
89                 return 0;
90         if (tagHt.count(key) > 1) {
91                 dbg.Verbose(0, "gdcmElValSet::SetElValueByNumber",
92                             "multiple entries for this key (FIXME) !");
93                 return (0); 
94         }
95                                                
96         tagHt[key]->SetValue(content);
97
98         // Question : m à j LgrElem ?
99         tagHt[key]->SetLength(strlen(content.c_str()));  
100
101         // FIXME should we really update the element length ?
102         tagHt[key]->SetLength(content.length());         
103
104         return(1);              
105 }
106
107 int gdcmElValSet::SetElValueByName(string content, string TagName) {
108         if ( ! NameHt.count(TagName))
109                 return 0;
110         if (NameHt.count(TagName) > 1) {
111                 dbg.Verbose(0, "gdcmElValSet::SetElValueByName",
112                             "multipe entries for this key (FIXME) !");
113                 return 0;
114         }
115         NameHt.find(TagName)->second->SetValue(content);
116         NameHt.find(TagName)->second->SetLength(strlen(content.c_str()));        
117         return(1);              
118 }
119
120 /**
121  * \ingroup  gdcmElValSet
122  * \brief    Generate a free TagKey i.e. a TagKey that is not present
123  *           in the TagHt dictionary. One of the potential usage is
124  *           to add  gdcm generated additional informartion to the ElValSet
125  *           (see gdcmHeader::AddAndDefaultElements).
126  * @param group The generated tag must belong to this group.  
127  * @return   The element of tag with given group which is fee.
128  */
129 guint32 gdcmElValSet::GenerateFreeTagKeyInGroup(guint32 group) {
130    for (guint32 elem = 0; elem < UINT32_MAX; elem++) {
131       TagKey key = gdcmDictEntry::TranslateToKey(group, elem);
132       if (tagHt.count(key) == 0)
133          return elem;
134    }
135    return UINT32_MAX;
136 }
137
138 int gdcmElValSet::SetElValueLengthByNumber(guint32 l,
139                                            guint32 group, guint32 element) {
140         TagKey key = gdcmDictEntry::TranslateToKey(group, element);
141         if ( ! tagHt.count(key))
142                 return 0;
143         tagHt[key]->SetLength(l);        
144         return 1 ;              
145 }
146
147
148 int gdcmElValSet::SetElValueLengthByName(guint32 l, string TagName) {
149         if ( ! NameHt.count(TagName))
150                 return 0;
151         NameHt.find(TagName)->second->SetLength(l);      
152         return 1 ;              
153 }
154
155 // Sorry for the DEBUG's, but tomorow is gonna be hoter than today
156
157 int gdcmElValSet::Write(FILE * _fp) {
158
159         guint16 gr, el;
160         guint32 lgr;
161         const char * val;
162         string vr;
163         guint32 val_uint32;
164         guint16 val_uint16;
165         
166         vector<string> tokens;
167         
168         void *ptr;
169         
170         string implicitVRTransfertSyntax = "1.2.840.10008.1.2";
171         
172         // Utilisées pour le calcul Group Length
173         guint32 lgrCalcGroupe=0;
174         gdcmElValue *elem, *elemZ, *elemZPrec;
175         guint16 grCourant = 0;
176         
177         // Question :
178         // Comment pourrait-on tester si on est TrueDicom ou non ,
179         // (FileType est un champ de gdcmHeader ...)
180         //
181
182         // On parcourt la table pour recalculer la longueur des 'elements 0x0000'
183         // au cas ou un tag ai été ajouté par rapport à ce qui a été lu
184         // dans l'image native
185         //
186         // cf : code IdDcmWriteFile dans libido/src/dcmwrite.c
187                                 
188         // On fait de l'implicit VR little Endian 
189         // (pour moins se fairche sur processeur INTEL)
190         // On force le TRANSFERT SYNTAX UID
191                                 
192         SetElValueByNumber(implicitVRTransfertSyntax, 0x0002, 0x0010);  
193         SetElValueLengthByNumber(18, 0x0002, 0x0010);  // Le 0 de fin de chaine doit etre stocké, dans ce cas   
194                         
195         TagElValueHT::iterator tag = tagHt.begin();
196         
197         elem = tag->second;
198         gr   = elem->GetGroup();
199         el   = elem->GetElement();
200                         
201         if (el != 0x0000) {
202                 if(DEBUG)printf("ajout elem OOOO premiere fois\n");
203                 gdcmDictEntry * tagZ = new gdcmDictEntry(gr, 0x0000, "UL");
204                 elemZPrec = new gdcmElValue(tagZ);      // on le cree
205                 elemZPrec->SetLength(4);
206                 Add(elemZPrec);                         // On l'accroche à sa place
207         } else {
208                 elemZPrec = elem;
209                 if(DEBUG)printf("Pas d'ajout elem OOOO premiere fois\n");
210         }
211         lgrCalcGroupe = 0;
212         if(DEBUG)printf("init-1 lgr (%d) pour gr %04x\n",lgrCalcGroupe, gr);
213         grCourant = gr;
214         
215         for (tag = ++tagHt.begin();
216                   tag != tagHt.end();
217                   ++tag){
218                   
219                 elem = tag->second;
220                 gr = elem->GetGroup();
221                 el = elem->GetElement();
222
223                 if ( (gr != grCourant) /*&&     // On arrive sur un nv Groupe     
224                      (el != 0xfffe) */  ) {
225                             
226                         if (el != 0x0000) {
227                                 gdcmDictEntry * tagZ = new gdcmDictEntry(gr, 0x0000, "UL");
228                                 elemZ = new gdcmElValue(tagZ); // on le cree
229                                 elemZ->SetLength(4);
230                                 Add(elemZ);                     // On l'accroche à sa place 
231                                 if(DEBUG)printf("ajout elem OOOO pour gr %04x\n",gr);
232                         } else { 
233                                 elemZ=elem;
234                                 if(DEBUG)printf("maj elemZ\n");
235                         }
236                         
237                         ostringstream f;
238                         f << lgrCalcGroupe; 
239                         //sprintf(str_lgrCalcGroupe,"%d",lgrCalcGroupe);
240                         elemZPrec->SetValue(f.str());
241                         if(DEBUG)printf("ecriture lgr (%d, %s) pour gr %04x\n",lgrCalcGroupe, f.str().c_str(), grCourant);
242                         if(DEBUG)printf ("%04x %04x [%s]\n",elemZPrec->GetGroup(), elemZPrec->GetElement(),
243                                                         elemZPrec->GetValue().c_str());
244                         if(DEBUG)cout << "Addresse elemZPrec " << elemZPrec<< endl;
245                         elemZPrec=elemZ;
246                         lgrCalcGroupe = 0;
247                         grCourant     = gr;     
248                         if(DEBUG)printf("init-2 lgr (%d) pour gr %04x\n",lgrCalcGroupe, gr);                    
249                 } else {                        // On n'EST PAS sur un nv Groupe
250                         lgrCalcGroupe += 2 + 2 + 4 + elem->GetLength();  // Gr + Num + Lgr + LgrElem
251                         if(DEBUG)printf("increment (%d) el %04x-->lgr (%d) pour gr %04x\n",
252                                                                 elem->GetLength(), el, lgrCalcGroupe, gr);
253                 }               
254         }
255         
256         // restent à tester les echecs en écriture (apres chaque fwrite)
257         
258         for (TagElValueHT::iterator tag2 = tagHt.begin();
259                   tag2 != tagHt.end();
260                   ++tag2){
261                 
262                 gr =  tag2->second->GetGroup();
263                 el =  tag2->second->GetElement();
264                 lgr = tag2->second->GetLength();
265                 val = tag2->second->GetValue().c_str();
266                 vr =  tag2->second->GetVR();
267                 if(DEBUG)printf ("%04x %04x [%s] : [%s]\n",gr, el, vr.c_str(), val);
268                         
269                 fwrite ( &gr,(size_t)2 ,(size_t)1 ,_fp);        //group
270                 fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp);        //element
271                 
272                 //fwrite ( vr,(size_t)2 ,(size_t)1 ,_fp);       //VR
273                 
274                 // si on n'est pas en IMPLICIT VR voir pb (lgr  + VR)
275                 
276                 fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp);       //lgr
277                 
278                 tokens.erase(tokens.begin(),tokens.end());
279                 Tokenize (tag2->second->GetValue(), tokens, "\\");
280                 
281                 //if (tokens.size() > 1) { printf ("size : %d\n",tokens.size());}
282                 
283                 if (vr == "US" || vr == "SS") {
284                         for (unsigned int i=0; i<tokens.size();i++) {
285                                 val_uint16 = atoi(tokens[i].c_str());           
286                                 ptr = &val_uint16;
287                                 fwrite ( ptr,(size_t)2 ,(size_t)1 ,_fp);
288                         }
289                         continue;       
290                 }
291                 if (vr == "UL" || vr == "SL") { 
292                         for (unsigned int i=0; i<tokens.size();i++) {
293                                 val_uint32 = atoi(tokens[i].c_str());           
294                                 ptr = &val_uint32;
295                                 fwrite ( ptr,(size_t)4 ,(size_t)1 ,_fp);
296                         }
297                         continue;       
298                 }       
299                 
300                 // Les pixels ne sont pas chargés dans l'element !
301                 if ((gr == 0x7fe0) && (el == 0x0010) ) break;
302
303                 fwrite ( val,(size_t)lgr ,(size_t)1 ,_fp); //valeur Elem
304         }
305                 
306         return(1);
307 }
308
309
310 int gdcmElValSet::WriteAcr(FILE * _fp) {
311 //
312 // ATTENTION : fusioner le code avec celui de gdcmElValSet::Write
313 //
314
315         guint16 gr, el;
316         guint32 lgr;
317         const char * val;
318         string vr;
319         guint32 val_uint32;
320         guint16 val_uint16;
321         
322         vector<string> tokens;
323         
324         void *ptr;
325         
326         //string implicitVRTransfertSyntax = "1.2.840.10008.1.2"; // supprime par rapport à Write
327         
328         // Utilisées pour le calcul Group Length
329
330         guint32 lgrCalcGroupe=0;
331         gdcmElValue *elem, *elemZ, *elemZPrec;
332         guint16 grCourant = 0;
333         
334         // On parcourt la table pour recalculer la longueur des 'elements 0x0000'
335         // au cas ou un tag ai été ajouté par rapport à ce qui a été lu
336         // dans l'image native
337         //
338         // cf : code IdDcmWriteFile dans libido/src/dcmwrite.c
339                                         
340         TagElValueHT::iterator tag = tagHt.begin();
341         
342         elem = tag->second;
343         gr   = elem->GetGroup();
344         el   = elem->GetElement();
345                         
346         if (el != 0x0000) {
347                 if(DEBUG)printf("ajout elem OOOO premiere fois\n");
348                 gdcmDictEntry * tagZ = new gdcmDictEntry(gr, 0x0000, "UL");
349                 elemZPrec = new gdcmElValue(tagZ);      // on le cree
350                 elemZPrec->SetLength(4);
351                 Add(elemZPrec);                         // On l'accroche à sa place
352         } else {
353                 elemZPrec = elem;
354                 if(DEBUG)printf("Pas d'ajout elem OOOO premiere fois\n");
355         }
356         lgrCalcGroupe = 0;
357         if(DEBUG)printf("init-1 lgr (%d) pour gr %04x\n",lgrCalcGroupe, gr);
358         grCourant = gr;
359         
360         for (tag = ++tagHt.begin();
361                   tag != tagHt.end();
362                   ++tag){
363                   
364                 elem = tag->second;
365                 gr = elem->GetGroup();
366                 el = elem->GetElement();
367                 vr = elem->GetVR();
368                 
369                 if (vr == "SQ") continue;       // pas SEQUENCE en ACR-NEMA
370                                                 // WARNING : risque de pb 
371                                                 // si on est descendu 'a l'interieur' des SQ    
372
373                 if ( (gr != grCourant) /*&&     // On arrive sur un nv Groupe     
374                      (el != 0xfffe) */  ) {
375                             
376                         if (el != 0x0000) {
377                                 gdcmDictEntry * tagZ = new gdcmDictEntry(gr, 0x0000, "UL");
378                                 elemZ = new gdcmElValue(tagZ); // on le cree
379                                 elemZ->SetLength(4);
380                                 Add(elemZ);                     // On l'accroche à sa place 
381                                 if(DEBUG)printf("ajout elem OOOO pour gr %04x\n",gr);
382                         } else { 
383                                 elemZ=elem;
384                                 if(DEBUG)printf("maj elmeZ\n");
385                         }
386                         
387                         ostringstream f;
388                         f << lgrCalcGroupe; 
389                         elemZPrec->SetValue(f.str());
390                         if(DEBUG)printf("ecriture lgr (%d, %s) pour gr %04x\n",lgrCalcGroupe, f.str().c_str(), grCourant);
391                         if(DEBUG)printf ("%04x %04x [%s]\n",elemZPrec->GetGroup(), elemZPrec->GetElement(),
392                                                         elemZPrec->GetValue().c_str());
393                         if(DEBUG)cout << "Addresse elemZPrec " << elemZPrec<< endl;
394                         elemZPrec=elemZ;
395                         lgrCalcGroupe = 0;
396                         grCourant     = gr;     
397                         if(DEBUG)printf("init-2 lgr (%d) pour gr %04x\n",lgrCalcGroupe, gr);                    
398                 } else {                        // On n'EST PAS sur un nv Groupe
399                         lgrCalcGroupe += 2 + 2 + 4 + elem->GetLength();  // Gr + Num + Lgr + LgrElem
400                         if(DEBUG)printf("increment (%d) el %04x-->lgr (%d) pour gr %04x\n",elem->GetLength(), el, 
401                                                         lgrCalcGroupe, gr);
402                 }               
403         }
404         
405         // Si on fait de l'implicit VR little Endian 
406         // (pour moins se fairche sur processeur INTEL)
407         // penser a forcer le TRANSFERT SYNTAX UID
408         
409         // supprime par rapport à Write         
410         //SetElValueByNumber(implicitVRTransfertSyntax, 0x0002, 0x0010);        
411         //SetElValueLengthByNumber(18, 0x0002, 0x0010);  // Le 0 de fin de chaine doit etre stocké, dans ce cas 
412                 
413         // restent à tester les echecs en écriture (apres chaque fwrite)
414         
415         for (TagElValueHT::iterator tag2 = tagHt.begin();
416                   tag2 != tagHt.end();
417                   ++tag2){
418
419                 gr =  tag2->second->GetGroup();
420                                                 // saut des groupes speciaux DICOM V3
421                 if (gr < 0x0008) continue;      // ajouté par rapport à Write
422                                                 // saut des groupes impairs
423                 if (gr %2)       continue;      // ajouté par rapport à Write
424                 
425                 el =  tag2->second->GetElement();
426                 lgr = tag2->second->GetLength();
427                 val = tag2->second->GetValue().c_str();
428                 vr =  tag2->second->GetVR();
429                         
430                 fwrite ( &gr,(size_t)2 ,(size_t)1 ,_fp);        //group
431                 fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp);        //element
432                                 
433                 // si on n'est pas en IMPLICIT VR voir pb (lgr  + VR)
434                 
435                 fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp);               //lgr
436                 
437                 tokens.erase(tokens.begin(),tokens.end());
438                 Tokenize (tag2->second->GetValue(), tokens, "\\");
439                 
440                 if (vr == "US" || vr == "SS") {
441
442                         for (unsigned int i=0; i<tokens.size();i++) {
443                                 val_uint16 = atoi(tokens[i].c_str());           
444                                 ptr = &val_uint16;
445                                 fwrite ( ptr,(size_t)2 ,(size_t)1 ,_fp);
446                         }
447                         continue;
448                         
449                 }
450                 if (vr == "UL" || vr == "SL") {
451                         for (unsigned int i=0; i<tokens.size();i++) {
452                                 val_uint32 = atoi(tokens[i].c_str());           
453                                 ptr = &val_uint32;
454                                 fwrite ( ptr,(size_t)4 ,(size_t)1 ,_fp);
455                         }
456                         continue;                               
457                         
458                 }       
459                 
460                 // Les pixels ne sont pas chargés dans l'element !
461                 if ((gr == 0x7fe0) && (el == 0x0010) ) break;
462
463                 fwrite ( val,(size_t)lgr ,(size_t)1 ,_fp); //valeur Elem
464         }
465                 
466         return(1);
467 }
468
469 // Sorry for the DEBUG's, but tomorow is gonna be hoter than today
470
471 int gdcmElValSet::WriteExplVR(FILE * _fp) {
472
473 //
474 // ATTENTION : fusioner le code avec celui de gdcmElValSet::Write
475 //
476
477         guint16 gr, el;
478         guint32 lgr;
479         const char * val;
480         string vr;
481         guint32 val_uint32;
482         guint16 val_uint16;
483         guint16 z=0, shortLgr;
484         
485         vector<string> tokens;
486         
487         void *ptr;
488
489         string explicitVRTransfertSyntax = "1.2.840.10008.1.2.1";
490         
491         // Utilisées pour le calcul Group Length
492         guint32 lgrCalcGroupe=0;
493         gdcmElValue *elem, *elemZ, *elemZPrec;
494         guint16 grCourant = 0;
495         
496         // Question :
497         // Comment pourrait-on tester si on est TrueDicom ou non ,
498         // (FileType est un champ de gdcmHeader ...)
499         //
500
501         // On parcourt la table pour recalculer la longueur des 'elements 0x0000'
502         // au cas ou un tag ai été ajouté par rapport à ce qui a été lu
503         // dans l'image native
504         //
505         // cf : code IdDcmWriteFile dans libido/src/dcmwrite.c
506                 
507                 
508         // On fait de l'Explicit VR little Endian 
509         
510                                 
511         SetElValueByNumber(explicitVRTransfertSyntax, 0x0002, 0x0010);  
512         SetElValueLengthByNumber(20, 0x0002, 0x0010);  // Le 0 de fin de chaine doit etre stocké, dans ce cas  // ???   
513                         
514         TagElValueHT::iterator tag = tagHt.begin();
515         
516         elem = tag->second;
517         gr   = elem->GetGroup();
518         el   = elem->GetElement();
519                         
520         if (el != 0x0000) {
521                 if(DEBUG)printf("ajout elem OOOO premiere fois\n");
522                 gdcmDictEntry * tagZ = new gdcmDictEntry(gr, 0x0000, "UL");
523                 elemZPrec = new gdcmElValue(tagZ);      // on le cree
524                 elemZPrec->SetLength(4);
525                 Add(elemZPrec);                         // On l'accroche à sa place
526         } else {
527                 elemZPrec = elem;
528                 if(DEBUG)printf("Pas d'ajout elem OOOO premiere fois\n");
529         }
530         lgrCalcGroupe = 0;
531         if(DEBUG)printf("init-1 lgr (%d) pour gr %04x\n",lgrCalcGroupe, gr);
532         grCourant = gr;
533         
534         for (tag = ++tagHt.begin();
535                   tag != tagHt.end();
536                   ++tag){
537                   
538                 elem = tag->second;
539                 gr = elem->GetGroup();
540                 el = elem->GetElement();
541
542                 if ( (gr != grCourant) /*&&     // On arrive sur un nv Groupe     
543                      (el != 0xfffe) */  ) {
544                             
545                         if (el != 0x0000) {
546                                 gdcmDictEntry * tagZ = new gdcmDictEntry(gr, 0x0000, "UL");
547                                 elemZ = new gdcmElValue(tagZ); // on le cree
548                                 elemZ->SetLength(4);
549                                 Add(elemZ);                     // On l'accroche à sa place 
550                                 if(DEBUG)printf("ajout elem OOOO pour gr %04x\n",gr);
551                         } else { 
552                                 elemZ=elem;
553                                 if(DEBUG)printf("maj elemZ\n");
554                         }
555                         
556                         ostringstream f;
557                         f << lgrCalcGroupe; 
558                         //sprintf(str_lgrCalcGroupe,"%d",lgrCalcGroupe);
559                         elemZPrec->SetValue(f.str());
560                         if(DEBUG)printf("ecriture lgr (%d, %s) pour gr %04x\n",lgrCalcGroupe, f.str().c_str(), grCourant);
561                         if(DEBUG)printf ("%04x %04x [%s]\n",elemZPrec->GetGroup(), elemZPrec->GetElement(),
562                                                         elemZPrec->GetValue().c_str());
563                         if(DEBUG)cout << "Addresse elemZPrec " << elemZPrec<< endl;
564                         elemZPrec=elemZ;
565                         lgrCalcGroupe = 0;
566                         grCourant     = gr;     
567                         if(DEBUG)printf("init-2 lgr (%d) pour gr %04x\n",lgrCalcGroupe, gr);                    
568                 } else {                        // On n'EST PAS sur un nv Groupe
569                         lgrCalcGroupe += 2 + 2 + 4 + elem->GetLength();  // Gr + Num + Lgr + LgrElem
570                         if(DEBUG)printf("increment (%d) el %04x-->lgr (%d) pour gr %04x\n",elem->GetLength(), 
571                                                         el, lgrCalcGroupe, gr);
572                 }               
573         }
574                 
575         // restent à tester les echecs en écriture (apres chaque fwrite)
576         
577         for (TagElValueHT::iterator tag2 = tagHt.begin();
578                   tag2 != tagHt.end();
579                   ++tag2){
580                 
581                 gr =  tag2->second->GetGroup();
582                 el =  tag2->second->GetElement();
583                 lgr = tag2->second->GetLength();
584                 val = tag2->second->GetValue().c_str();
585                 vr =  tag2->second->GetVR();
586                 if(DEBUG)printf ("%04x %04x [%s] : [%s]\n",gr, el, vr.c_str(), val);
587                         
588                 fwrite ( &gr,(size_t)2 ,(size_t)1 ,_fp);        //group
589                 fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp);        //element
590                                 
591                 // On est en EXPLICIT VR
592                 if (gr == 0x0002) {
593                         fwrite (vr.c_str(),(size_t)2 ,(size_t)1 ,_fp);
594                 
595                         if ( (vr == "OB") || (vr == "OW") || (vr == "SQ") ) {
596                                 fwrite ( &z,  (size_t)2 ,(size_t)1 ,_fp);
597                                 fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp);
598
599                         } else {
600                                 shortLgr=lgr;
601                                 fwrite ( &shortLgr,(size_t)2 ,(size_t)1 ,_fp);
602                         }
603                 } else {
604                         fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp);
605                 }
606                 
607                 tokens.erase(tokens.begin(),tokens.end());
608                 Tokenize (tag2->second->GetValue(), tokens, "\\");
609                                 
610                 if (vr == "US" || vr == "SS") {
611                         for (unsigned int i=0; i<tokens.size();i++) {
612                                 val_uint16 = atoi(tokens[i].c_str());           
613                                 ptr = &val_uint16;
614                                 fwrite ( ptr,(size_t)2 ,(size_t)1 ,_fp);
615                         }
616                         continue;       
617                 }
618                 if (vr == "UL" || vr == "SL") { 
619                         for (unsigned int i=0; i<tokens.size();i++) {
620                                 val_uint32 = atoi(tokens[i].c_str());           
621                                 ptr = &val_uint32;
622                                 fwrite ( ptr,(size_t)4 ,(size_t)1 ,_fp);
623                         }
624                         continue;       
625                 }       
626                 
627                 // Les pixels ne sont pas chargés dans l'element !
628                 if ((gr == 0x7fe0) && (el == 0x0010) ) break;
629
630                 fwrite ( val,(size_t)lgr ,(size_t)1 ,_fp); //valeur Elem
631         }
632                 
633         return(1);
634 }
635
636
637