]> Creatis software - gdcm.git/blob - src/gdcmElValSet.cxx
Update for writting DCM files
[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(),elemZPrec->GetValue().c_str());
243                         if(DEBUG)cout << "Addresse elemZPrec " << elemZPrec<< endl;
244                         elemZPrec=elemZ;
245                         lgrCalcGroupe = 0;
246                         grCourant     = gr;     
247                         if(DEBUG)printf("init-2 lgr (%d) pour gr %04x\n",lgrCalcGroupe, gr);                    
248                 } else {                        // On n'EST PAS sur un nv Groupe
249                         lgrCalcGroupe += 2 + 2 + 4 + elem->GetLength();  // Gr + Num + Lgr + LgrElem
250                         if(DEBUG)printf("increment (%d) el %04x-->lgr (%d) pour gr %04x\n",elem->GetLength(), el, lgrCalcGroupe, gr);
251                 }               
252         }
253         
254         // restent à tester les echecs en écriture (apres chaque fwrite)
255         
256         for (TagElValueHT::iterator tag2 = tagHt.begin();
257                   tag2 != tagHt.end();
258                   ++tag2){
259                 
260                 gr =  tag2->second->GetGroup();
261                 el =  tag2->second->GetElement();
262                 lgr = tag2->second->GetLength();
263                 val = tag2->second->GetValue().c_str();
264                 vr =  tag2->second->GetVR();
265                 if(DEBUG)printf ("%04x %04x [%s] : [%s]\n",gr, el, vr.c_str(), val);
266                         
267                 fwrite ( &gr,(size_t)2 ,(size_t)1 ,_fp);        //group
268                 fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp);        //element
269                 
270                 //fwrite ( vr,(size_t)2 ,(size_t)1 ,_fp);       //VR
271                 
272                 // si on n'est pas en IMPLICIT VR voir pb (lgr  + VR)
273                 
274                 fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp);       //lgr
275                 
276                 tokens.erase(tokens.begin(),tokens.end());
277                 Tokenize (tag2->second->GetValue(), tokens, "\\");
278                 
279                 //if (tokens.size() > 1) { printf ("size : %d\n",tokens.size());}
280                 
281                 if (vr == "US" || vr == "SS") {
282                         for (unsigned int i=0; i<tokens.size();i++) {
283                                 val_uint16 = atoi(tokens[i].c_str());           
284                                 ptr = &val_uint16;
285                                 fwrite ( ptr,(size_t)2 ,(size_t)1 ,_fp);
286                         }
287                         continue;       
288                 }
289                 if (vr == "UL" || vr == "SL") { 
290                         for (unsigned int i=0; i<tokens.size();i++) {
291                                 val_uint32 = atoi(tokens[i].c_str());           
292                                 ptr = &val_uint32;
293                                 fwrite ( ptr,(size_t)4 ,(size_t)1 ,_fp);
294                         }
295                         continue;       
296                 }       
297                 
298                 // Les pixels ne sont pas chargés dans l'element !
299                 if ((gr == 0x7fe0) && (el == 0x0010) ) break;
300
301                 fwrite ( val,(size_t)lgr ,(size_t)1 ,_fp); //valeur Elem
302         }
303                 
304         return(1);
305 }
306
307
308 int gdcmElValSet::WriteAcr(FILE * _fp) {
309 //
310 // ATTENTION : fusioner le code avec celui de gdcmElValSet::Write
311 //
312
313         guint16 gr, el;
314         guint32 lgr;
315         const char * val;
316         string vr;
317         guint32 val_uint32;
318         guint16 val_uint16;
319         
320         vector<string> tokens;
321         
322         void *ptr;
323         
324         //string implicitVRTransfertSyntax = "1.2.840.10008.1.2"; // supprime par rapport à Write
325         
326         // Utilisées pour le calcul Group Length
327
328         guint32 lgrCalcGroupe=0;
329         gdcmElValue *elem, *elemZ, *elemZPrec;
330         guint16 grCourant = 0;
331         
332         // On parcourt la table pour recalculer la longueur des 'elements 0x0000'
333         // au cas ou un tag ai été ajouté par rapport à ce qui a été lu
334         // dans l'image native
335         //
336         // cf : code IdDcmWriteFile dans libido/src/dcmwrite.c
337                                         
338         TagElValueHT::iterator tag = tagHt.begin();
339         
340         elem = tag->second;
341         gr   = elem->GetGroup();
342         el   = elem->GetElement();
343                         
344         if (el != 0x0000) {
345                 if(DEBUG)printf("ajout elem OOOO premiere fois\n");
346                 gdcmDictEntry * tagZ = new gdcmDictEntry(gr, 0x0000, "UL");
347                 elemZPrec = new gdcmElValue(tagZ);      // on le cree
348                 elemZPrec->SetLength(4);
349                 Add(elemZPrec);                         // On l'accroche à sa place
350         } else {
351                 elemZPrec = elem;
352                 if(DEBUG)printf("Pas d'ajout elem OOOO premiere fois\n");
353         }
354         lgrCalcGroupe = 0;
355         if(DEBUG)printf("init-1 lgr (%d) pour gr %04x\n",lgrCalcGroupe, gr);
356         grCourant = gr;
357         
358         for (tag = ++tagHt.begin();
359                   tag != tagHt.end();
360                   ++tag){
361                   
362                 elem = tag->second;
363                 gr = elem->GetGroup();
364                 el = elem->GetElement();
365                 vr = elem->GetVR();
366                 
367                 if (vr == "SQ") continue;       // pas SEQUENCE en ACR-NEMA
368                                                 // WARNING : risque de pb 
369                                                 // si on est descendu 'a l'interieur' des SQ    
370
371                 if ( (gr != grCourant) /*&&     // On arrive sur un nv Groupe     
372                      (el != 0xfffe) */  ) {
373                             
374                         if (el != 0x0000) {
375                                 gdcmDictEntry * tagZ = new gdcmDictEntry(gr, 0x0000, "UL");
376                                 elemZ = new gdcmElValue(tagZ); // on le cree
377                                 elemZ->SetLength(4);
378                                 Add(elemZ);                     // On l'accroche à sa place 
379                                 if(DEBUG)printf("ajout elem OOOO pour gr %04x\n",gr);
380                         } else { 
381                                 elemZ=elem;
382                                 if(DEBUG)printf("maj elmeZ\n");
383                         }
384                         
385                         ostringstream f;
386                         f << lgrCalcGroupe; 
387                         elemZPrec->SetValue(f.str());
388                         if(DEBUG)printf("ecriture lgr (%d, %s) pour gr %04x\n",lgrCalcGroupe, f.str().c_str(), grCourant);
389                         if(DEBUG)printf ("%04x %04x [%s]\n",elemZPrec->GetGroup(), elemZPrec->GetElement(),elemZPrec->GetValue().c_str());
390                         if(DEBUG)cout << "Addresse elemZPrec " << elemZPrec<< endl;
391                         elemZPrec=elemZ;
392                         lgrCalcGroupe = 0;
393                         grCourant     = gr;     
394                         if(DEBUG)printf("init-2 lgr (%d) pour gr %04x\n",lgrCalcGroupe, gr);                    
395                 } else {                        // On n'EST PAS sur un nv Groupe
396                         lgrCalcGroupe += 2 + 2 + 4 + elem->GetLength();  // Gr + Num + Lgr + LgrElem
397                         if(DEBUG)printf("increment (%d) el %04x-->lgr (%d) pour gr %04x\n",elem->GetLength(), el, lgrCalcGroupe, gr);
398                 }               
399         }
400         
401         // Si on fait de l'implicit VR little Endian 
402         // (pour moins se fairche sur processeur INTEL)
403         // penser a forcer le TRANSFERT SYNTAX UID
404         
405         // supprime par rapport à Write         
406         //SetElValueByNumber(implicitVRTransfertSyntax, 0x0002, 0x0010);        
407         //SetElValueLengthByNumber(18, 0x0002, 0x0010);  // Le 0 de fin de chaine doit etre stocké, dans ce cas 
408                 
409         // restent à tester les echecs en écriture (apres chaque fwrite)
410         
411         for (TagElValueHT::iterator tag2 = tagHt.begin();
412                   tag2 != tagHt.end();
413                   ++tag2){
414
415                 gr =  tag2->second->GetGroup();
416                                                 // saut des groupes speciaux DICOM V3
417                 if (gr < 0x0008) continue;      // ajouté par rapport à Write
418                                                 // saut des groupes impairs
419                 if (gr %2)       continue;      // ajouté par rapport à Write
420                 
421                 el =  tag2->second->GetElement();
422                 lgr = tag2->second->GetLength();
423                 val = tag2->second->GetValue().c_str();
424                 vr =  tag2->second->GetVR();
425                         
426                 fwrite ( &gr,(size_t)2 ,(size_t)1 ,_fp);        //group
427                 fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp);        //element
428                                 
429                 // si on n'est pas en IMPLICIT VR voir pb (lgr  + VR)
430                 
431                 fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp);               //lgr
432                 
433                 tokens.erase(tokens.begin(),tokens.end());
434                 Tokenize (tag2->second->GetValue(), tokens, "\\");
435                 
436                 if (vr == "US" || vr == "SS") {
437
438                         for (unsigned int i=0; i<tokens.size();i++) {
439                                 val_uint16 = atoi(tokens[i].c_str());           
440                                 ptr = &val_uint16;
441                                 fwrite ( ptr,(size_t)2 ,(size_t)1 ,_fp);
442                         }
443                         continue;
444                         
445                 }
446                 if (vr == "UL" || vr == "SL") {
447                         for (unsigned int i=0; i<tokens.size();i++) {
448                                 val_uint32 = atoi(tokens[i].c_str());           
449                                 ptr = &val_uint32;
450                                 fwrite ( ptr,(size_t)4 ,(size_t)1 ,_fp);
451                         }
452                         continue;                               
453                         
454                 }       
455                 
456                 // Les pixels ne sont pas chargés dans l'element !
457                 if ((gr == 0x7fe0) && (el == 0x0010) ) break;
458
459                 fwrite ( val,(size_t)lgr ,(size_t)1 ,_fp); //valeur Elem
460         }
461                 
462         return(1);
463 }
464
465 // Sorry for the DEBUG's, but tomorow is gonna be hoter than today
466
467 int gdcmElValSet::WriteExplVR(FILE * _fp) {
468
469 //
470 // ATTENTION : fusioner le code avec celui de gdcmElValSet::Write
471 //
472
473         guint16 gr, el;
474         guint32 lgr;
475         const char * val;
476         string vr;
477         guint32 val_uint32;
478         guint16 val_uint16;
479         guint16 z=0, shortLgr;
480         
481         vector<string> tokens;
482         
483         void *ptr;
484
485         string explicitVRTransfertSyntax = "1.2.840.10008.1.2.1";
486         
487         // Utilisées pour le calcul Group Length
488         guint32 lgrCalcGroupe=0;
489         gdcmElValue *elem, *elemZ, *elemZPrec;
490         guint16 grCourant = 0;
491         
492         // Question :
493         // Comment pourrait-on tester si on est TrueDicom ou non ,
494         // (FileType est un champ de gdcmHeader ...)
495         //
496
497         // On parcourt la table pour recalculer la longueur des 'elements 0x0000'
498         // au cas ou un tag ai été ajouté par rapport à ce qui a été lu
499         // dans l'image native
500         //
501         // cf : code IdDcmWriteFile dans libido/src/dcmwrite.c
502                 
503                 
504         // On fait de l'Explicit VR little Endian 
505         
506                                 
507         SetElValueByNumber(explicitVRTransfertSyntax, 0x0002, 0x0010);  
508         SetElValueLengthByNumber(20, 0x0002, 0x0010);  // Le 0 de fin de chaine doit etre stocké, dans ce cas  // ???   
509                         
510         TagElValueHT::iterator tag = tagHt.begin();
511         
512         elem = tag->second;
513         gr   = elem->GetGroup();
514         el   = elem->GetElement();
515                         
516         if (el != 0x0000) {
517                 if(DEBUG)printf("ajout elem OOOO premiere fois\n");
518                 gdcmDictEntry * tagZ = new gdcmDictEntry(gr, 0x0000, "UL");
519                 elemZPrec = new gdcmElValue(tagZ);      // on le cree
520                 elemZPrec->SetLength(4);
521                 Add(elemZPrec);                         // On l'accroche à sa place
522         } else {
523                 elemZPrec = elem;
524                 if(DEBUG)printf("Pas d'ajout elem OOOO premiere fois\n");
525         }
526         lgrCalcGroupe = 0;
527         if(DEBUG)printf("init-1 lgr (%d) pour gr %04x\n",lgrCalcGroupe, gr);
528         grCourant = gr;
529         
530         for (tag = ++tagHt.begin();
531                   tag != tagHt.end();
532                   ++tag){
533                   
534                 elem = tag->second;
535                 gr = elem->GetGroup();
536                 el = elem->GetElement();
537
538                 if ( (gr != grCourant) /*&&     // On arrive sur un nv Groupe     
539                      (el != 0xfffe) */  ) {
540                             
541                         if (el != 0x0000) {
542                                 gdcmDictEntry * tagZ = new gdcmDictEntry(gr, 0x0000, "UL");
543                                 elemZ = new gdcmElValue(tagZ); // on le cree
544                                 elemZ->SetLength(4);
545                                 Add(elemZ);                     // On l'accroche à sa place 
546                                 if(DEBUG)printf("ajout elem OOOO pour gr %04x\n",gr);
547                         } else { 
548                                 elemZ=elem;
549                                 if(DEBUG)printf("maj elemZ\n");
550                         }
551                         
552                         ostringstream f;
553                         f << lgrCalcGroupe; 
554                         //sprintf(str_lgrCalcGroupe,"%d",lgrCalcGroupe);
555                         elemZPrec->SetValue(f.str());
556                         if(DEBUG)printf("ecriture lgr (%d, %s) pour gr %04x\n",lgrCalcGroupe, f.str().c_str(), grCourant);
557                         if(DEBUG)printf ("%04x %04x [%s]\n",elemZPrec->GetGroup(), elemZPrec->GetElement(),elemZPrec->GetValue().c_str());
558                         if(DEBUG)cout << "Addresse elemZPrec " << elemZPrec<< endl;
559                         elemZPrec=elemZ;
560                         lgrCalcGroupe = 0;
561                         grCourant     = gr;     
562                         if(DEBUG)printf("init-2 lgr (%d) pour gr %04x\n",lgrCalcGroupe, gr);                    
563                 } else {                        // On n'EST PAS sur un nv Groupe
564                         lgrCalcGroupe += 2 + 2 + 4 + elem->GetLength();  // Gr + Num + Lgr + LgrElem
565                         if(DEBUG)printf("increment (%d) el %04x-->lgr (%d) pour gr %04x\n",elem->GetLength(), el, lgrCalcGroupe, gr);
566                 }               
567         }
568                 
569         // restent à tester les echecs en écriture (apres chaque fwrite)
570         
571         for (TagElValueHT::iterator tag2 = tagHt.begin();
572                   tag2 != tagHt.end();
573                   ++tag2){
574                 
575                 gr =  tag2->second->GetGroup();
576                 el =  tag2->second->GetElement();
577                 lgr = tag2->second->GetLength();
578                 val = tag2->second->GetValue().c_str();
579                 vr =  tag2->second->GetVR();
580                 if(DEBUG)printf ("%04x %04x [%s] : [%s]\n",gr, el, vr.c_str(), val);
581                         
582                 fwrite ( &gr,(size_t)2 ,(size_t)1 ,_fp);        //group
583                 fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp);        //element
584                                 
585                 // On est en EXPLICIT VR
586                 if (gr == 0x0002) {
587                         fwrite (vr.c_str(),(size_t)2 ,(size_t)1 ,_fp);
588                 
589                         if ( (vr == "OB") || (vr == "OW") || (vr == "SQ") ) {
590                                 fwrite ( &z,  (size_t)2 ,(size_t)1 ,_fp);
591                                 fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp);
592
593                         } else {
594                                 shortLgr=lgr;
595                                 fwrite ( &shortLgr,(size_t)2 ,(size_t)1 ,_fp);
596                         }
597                 } else {
598                         fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp);
599                 }
600                 
601                 tokens.erase(tokens.begin(),tokens.end());
602                 Tokenize (tag2->second->GetValue(), tokens, "\\");
603                                 
604                 if (vr == "US" || vr == "SS") {
605                         for (unsigned int i=0; i<tokens.size();i++) {
606                                 val_uint16 = atoi(tokens[i].c_str());           
607                                 ptr = &val_uint16;
608                                 fwrite ( ptr,(size_t)2 ,(size_t)1 ,_fp);
609                         }
610                         continue;       
611                 }
612                 if (vr == "UL" || vr == "SL") { 
613                         for (unsigned int i=0; i<tokens.size();i++) {
614                                 val_uint32 = atoi(tokens[i].c_str());           
615                                 ptr = &val_uint32;
616                                 fwrite ( ptr,(size_t)4 ,(size_t)1 ,_fp);
617                         }
618                         continue;       
619                 }       
620                 
621                 // Les pixels ne sont pas chargés dans l'element !
622                 if ((gr == 0x7fe0) && (el == 0x0010) ) break;
623
624                 fwrite ( val,(size_t)lgr ,(size_t)1 ,_fp); //valeur Elem
625         }
626                 
627         return(1);
628 }
629
630
631