]> Creatis software - gdcm.git/blob - src/gdcmElValSet.cxx
fin sac de noeuds avec #include <string>
[gdcm.git] / src / gdcmElValSet.cxx
1 // $Id: gdcmElValSet.cxx,v 1.19 2003/03/13 15:56:26 jpr Exp $
2
3 #include "gdcmUtil.h"
4 #include "gdcmElValSet.h"
5
6 <<<<<<< gdcmElValSet.cxx
7
8 #include <vector>
9 static void Tokenize (const string& str, vector<string>& tokens, const string& delimiters);
10
11
12
13 TagElValueHT & gdcmElValSet::GetTagHt(void) {
14         return tagHt;
15 }
16
17 void gdcmElValSet::Add(gdcmElValue * newElValue) {
18         tagHt [newElValue->GetKey()]  = newElValue;
19         NameHt[newElValue->GetName()] = newElValue;
20 }
21
22 void gdcmElValSet::Print(ostream & os) {
23         for (TagElValueHT::iterator tag = tagHt.begin();
24                   tag != tagHt.end();
25                   ++tag){
26                 os << tag->first << ": ";
27                 os << "[" << tag->second->GetValue() << "]";
28                 os << "[" << tag->second->GetName()  << "]";
29                 os << "[" << tag->second->GetVR()    << "]" << endl;
30         }
31
32
33 void gdcmElValSet::PrintByName(ostream & os) {
34         for (TagElValueNameHT::iterator tag = NameHt.begin();
35                   tag != NameHt.end();
36                   ++tag){
37                 os << tag->first << ": ";
38                 os << "[" << tag->second->GetValue() << "]";
39                 os << "[" << tag->second->GetKey()   << "]";
40                 os << "[" << tag->second->GetVR()    << "]" << endl;
41         }
42 }
43
44 gdcmElValue* gdcmElValSet::GetElementByNumber(guint32 group, guint32 element) {
45         TagKey key = gdcmDictEntry::TranslateToKey(group, element);
46         if ( ! tagHt.count(key))
47                 return (gdcmElValue*)0;
48         if (tagHt.count(key) > 1)
49                 dbg.Verbose(0, "gdcmElValSet::GetElementByNumber",
50                             "multiple entries for this key (FIXME) !");
51         return tagHt.find(key)->second;
52 }
53
54 gdcmElValue* gdcmElValSet::GetElementByName(string TagName) {
55    if ( ! NameHt.count(TagName))
56       return (gdcmElValue*)0;
57    if (NameHt.count(TagName) > 1)
58       dbg.Verbose(0, "gdcmElValSet::GetElement",
59                   "multipe entries for this key (FIXME) !");
60    return NameHt.find(TagName)->second;
61 }
62
63 string gdcmElValSet::GetElValueByNumber(guint32 group, guint32 element) {
64         TagKey key = gdcmDictEntry::TranslateToKey(group, element);
65         if ( ! tagHt.count(key))
66                 return "gdcm::Unfound";
67         if (tagHt.count(key) > 1)
68                 dbg.Verbose(0, "gdcmElValSet::GetElValueByNumber",
69                             "multiple entries for this key (FIXME) !");
70         return tagHt.find(key)->second->GetValue();
71 }
72
73 string gdcmElValSet::GetElValueByName(string TagName) {
74         if ( ! NameHt.count(TagName))
75                 return "gdcm::Unfound";
76         if (NameHt.count(TagName) > 1)
77                 dbg.Verbose(0, "gdcmElValSet::GetElValue",
78                             "multipe entries for this key (FIXME) !");
79         return NameHt.find(TagName)->second->GetValue();
80 }
81
82 int gdcmElValSet::SetElValueByNumber(string content,
83                                      guint32 group, guint32 element) {
84         TagKey key = gdcmDictEntry::TranslateToKey(group, element);
85         if ( ! tagHt.count(key))
86                 return 0;
87         if (tagHt.count(key) > 1) {
88                 dbg.Verbose(0, "gdcmElValSet::SetElValueByNumber",
89                             "multiple entries for this key (FIXME) !");
90                 return (0); 
91         }                                      
92         tagHt[key]->SetValue(content);
93
94         // Question : m à j LgrElem ?
95         tagHt[key]->SetLength(strlen(content.c_str()));  
96
97         // FIXME should we really update the element length ?
98         tagHt[key]->SetLength(content.length());         
99
100         return(1);              
101 }
102
103 int gdcmElValSet::SetElValueByName(string content, string TagName) {
104         if ( ! NameHt.count(TagName))
105                 return 0;
106         if (NameHt.count(TagName) > 1) {
107                 dbg.Verbose(0, "gdcmElValSet::SetElValueByName",
108                             "multipe entries for this key (FIXME) !");
109                 return 0;
110         }
111         NameHt.find(TagName)->second->SetValue(content);
112         NameHt.find(TagName)->second->SetLength(strlen(content.c_str()));        
113         return(1);              
114 }
115
116
117 int gdcmElValSet::SetElValueLengthByNumber(guint32 l,
118                                            guint32 group, guint32 element) {
119         TagKey key = gdcmDictEntry::TranslateToKey(group, element);
120         if ( ! tagHt.count(key))
121                 return 0;
122         if (tagHt.count(key) > 1) {
123                 dbg.Verbose(0, "gdcmElValSet::SetElValueLengthByNumber",
124                             "multiple entries for this key (FIXME) !");
125                 return (0); 
126         }                                      
127    // FIXME JPR: comments in English please !
128         // m à j LgrElem 
129         tagHt[key]->SetLength(l);        
130         return(1);              
131 }
132
133
134 int gdcmElValSet::SetElValueLengthByName(guint32 l, string TagName) {
135         if ( ! NameHt.count(TagName))
136                 return 0;
137         if (NameHt.count(TagName) > 1) {
138                 dbg.Verbose(0, "gdcmElValSet::SetElValueByName",
139                             "multipe entries for this key (FIXME) !");
140                 return 0;
141         }
142         NameHt.find(TagName)->second->SetLength(l);      
143         return(1);              
144 }
145
146
147 int gdcmElValSet::Write(FILE * _fp) {
148
149 // ATTENTION : fonction non terminée (commitée a titre de precaution)
150
151         guint16 gr, el;
152         guint32 lgr;
153         const char * val;
154         string vr;
155         guint32 val_uint32;
156         gint32  val_int32;
157         guint16 val_uint16;
158         gint16  val_int16;
159         
160         vector<string> tokens;
161         
162         void *ptr;
163         char str_lgrCalcGroupe[10];
164         
165         string implicitVRTransfertSyntax = "1.2.840.10008.1.2";
166         
167         // Utilisées pour le calcul Group Length
168         int deja = 0;
169         guint32 lgrCalcGroupe=0;
170         gdcmElValue *elem, *elemZ, *elemZPrec;
171         guint16 grCourant = 0;
172         
173         // Question :
174         // Comment pourrait-on tester si on est TrueDicom ou non ,
175         // (FileType est un champ de gdcmHeader ...)
176         //
177
178         // On parcourt la table pour recalculer la longueur des 'elements 0x0000'
179         // au cas ou un tag ai été ajouté par rapport à ce qui a été lu
180         // dans l'image native
181         //
182         // cf : code IdDcmWriteFile dans libido/src/dcmwrite.c
183                 
184         if (0)  // Risque de pb dans le calcul des lgr de chaque groupe. On le saute pour le moment!
185         
186         for (TagElValueHT::iterator tag = tagHt.begin();
187                   tag != tagHt.end();
188                   ++tag){
189
190                 elem = tag->second;
191                 printf("gr %04x el %04x lgr %d\n",elem->GetGroup(), elem->GetElement(), elem->GetLength());
192         
193                 if ( (elem->GetGroup() != grCourant) &&   
194                          (elem->GetGroup() != 0xfffe)   ) {     // On arrive sur un nv Groupe
195                          
196                 printf("Nouv Groupegr %04x el %04x \n",elem->GetGroup(), elem->GetElement());
197
198                         elemZ = elem; 
199                          
200                         if(elemZ->GetElement() != 0x0000) {     // pas d'element 'Lgr groupe'
201                                 // On crée
202                                 gdcmDictEntry * tagZ = new gdcmDictEntry(grCourant, 0x0000, "UL");
203                                 elemZ = new gdcmElValue(tagZ); // on le cree
204                                 elemZ->SetLength(4);
205                                 Add(elemZ);                                      // On l'accroche à sa place    
206                         }       
207                         
208                         if (deja) {
209                                 //sprintf(str_lgrCalcGroupe,"%d",lgrCalcGroupe);
210                                 elemZPrec->SetValue(str_lgrCalcGroupe);
211                                 lgrCalcGroupe = 0;
212                         }
213                         deja = 1;
214                         
215                         lgrCalcGroupe =  12; //2 + 2 + 4 + 4; // Gr + Num + Lgr + LgrGroupe
216                         printf ("lgrCalcGroupe %d\n",lgrCalcGroupe);
217                         
218                         elemZPrec = elemZ;
219                         grCourant = elem->GetGroup();
220                                                         
221                 } else {                // On n'EST PAS sur un nv Groupe
222                 
223                         printf ("lgrCalcGroupe avant : %d LgrElem %d\n",lgrCalcGroupe,elem->GetLength());
224
225                         lgrCalcGroupe += 2 + 2 + 4 + elem->GetLength();  // Gr + Num + Lgr + LgrElem 
226                         
227                         printf ("lgrCalcGroupe apres %d\n",lgrCalcGroupe);
228                 }               
229         }
230         
231         // Si on fait de l'implicit VR little Endian 
232         // (pour moins se fairche sur processeur INTEL)
233         // penser a forcer le TRANSFERT SYNTAX UID
234                                 
235         SetElValueByNumber(implicitVRTransfertSyntax, 0x0002, 0x0010);  
236         SetElValueLengthByNumber(18, 0x0002, 0x0010);  // Le 0 de fin de chaine doit etre stocké, dans ce cas   
237                 
238         // restent à tester les echecs en écriture (apres chaque fwrite)
239         
240         for (TagElValueHT::iterator tag2 = tagHt.begin();
241                   tag2 != tagHt.end();
242                   ++tag2){
243                 
244                 gr =  tag2->second->GetGroup();
245                 el =  tag2->second->GetElement();
246                 lgr = tag2->second->GetLength();
247                 val = tag2->second->GetValue().c_str();
248                 vr =  tag2->second->GetVR();
249                         
250                 fwrite ( &gr,(size_t)2 ,(size_t)1 ,_fp);        //group
251                 fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp);        //element
252                 
253                 //fwrite ( vr,(size_t)2 ,(size_t)1 ,_fp);       //VR
254                 
255                 // si on n'est pas en IMPLICIT VR voir pb (lgr  + VR)
256                 
257                 fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp);               //lgr
258                 
259                 tokens.erase(tokens.begin(),tokens.end());
260                 Tokenize (tag2->second->GetValue(), tokens, "\\");
261                 
262                 //printf ("%04x %04x [%s] : [%s]\n",gr, el, vr.c_str(), val);
263                 //if (tokens.size() > 1) { printf ("size : %d\n",tokens.size());}
264                 
265                 
266                 if (vr == "US" || vr == "SS") {
267                         /*
268                         val_int16 = atoi(val);
269                         ptr = &val_int16;
270                         fwrite ( ptr,(size_t)2 ,(size_t)1 ,_fp);        
271                         continue;
272                         */
273                         
274                         for (unsigned int i=0; i<tokens.size();i++) {
275                                 val_uint16 = atoi(tokens[i].c_str());           
276                                 ptr = &val_uint16;
277                                 fwrite ( ptr,(size_t)2 ,(size_t)1 ,_fp);
278                         }
279                         continue;
280                         
281                 }
282                 if (vr == "UL" || vr == "SL") {
283                         /*
284                         val_int32 = atoi(val);
285                         ptr = &val_int32;
286                         fwrite ( ptr,(size_t)4 ,(size_t)1 ,_fp);        
287                         continue;
288                         */
289                         
290                         
291                         for (unsigned int i=0; i<tokens.size();i++) {
292                                 val_uint32 = atoi(tokens[i].c_str());           
293                                 ptr = &val_uint32;
294                                 fwrite ( ptr,(size_t)4 ,(size_t)1 ,_fp);
295                         }
296                         continue;                               
297                         
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
311
312 int gdcmElValSet::WriteAcr(FILE * _fp) {
313
314
315 // ATTENTION : fonction non terminée (commitée a titre de precaution)
316 // ATTENTION : fusioner le code avec celui de lValSet::Write
317
318
319         guint16 gr, el;
320         guint32 lgr;
321         const char * val;
322         string vr;
323         guint32 val_uint32;
324         gint32  val_int32;
325         guint16 val_uint16;
326         gint16  val_int16;
327         
328         vector<string> tokens;
329         
330         void *ptr;
331         char str_lgrCalcGroupe[10];
332         
333         //string implicitVRTransfertSyntax = "1.2.840.10008.1.2"; // supprime par rapport à Write
334         
335         // Utilisées pour le calcul Group Length
336         int deja = 0;
337         guint32 lgrCalcGroupe=0;
338         gdcmElValue *elem, *elemZ, *elemZPrec;
339         guint16 grCourant = 0;
340         
341         // Question :
342         // Comment pourrait-on tester si on est TrueDicom ou non ,
343         // (FileType est un champ de gdcmHeader ...)
344         //
345
346         // On parcourt la table pour recalculer la longueur des 'elements 0x0000'
347         // au cas ou un tag ai été ajouté par rapport à ce qui a été lu
348         // dans l'image native
349         //
350         // cf : code IdDcmWriteFile dans libido/src/dcmwrite.c
351                 
352         if (1)  // Risque de pb dans le calcul des lgr de chaque groupe. On le saute pour le moment!
353         
354         for (TagElValueHT::iterator tag = tagHt.begin();
355                   tag != tagHt.end();
356                   ++tag){
357
358                 elem = tag->second;
359                 //printf("gr %04x el %04x lgr %d\n",elem->GetGroup(), elem->GetElement(), elem->GetLength());
360         
361                 if ( (elem->GetGroup() != grCourant) &&   
362                          (elem->GetGroup() != 0xfffe)   ) {     // On arrive sur un nv Groupe
363                          
364                 //printf("Nouv Groupegr %04x el %04x \n",elem->GetGroup(), elem->GetElement());
365
366                         elemZ = elem; 
367                          
368                         if(elemZ->GetElement() != 0x0000) {     // pas d'element 'Lgr groupe'
369                                 // On crée
370                                 gdcmDictEntry * tagZ = new gdcmDictEntry(grCourant, 0x0000, "UL");
371                                 elemZ = new gdcmElValue(tagZ); // on le cree
372                                 elemZ->SetLength(4);
373                                 Add(elemZ);                                      // On l'accroche à sa place    
374                         }       
375                         
376                         if (deja) {
377                                 //sprintf(str_lgrCalcGroupe,"%d",lgrCalcGroupe);
378                                 elemZPrec->SetValue(str_lgrCalcGroupe);
379                                 lgrCalcGroupe = 0;
380                         }
381                         deja = 1;
382                         
383                         lgrCalcGroupe =  12; //2 + 2 + 4 + 4; // Gr + Num + Lgr + LgrGroupe
384                         //printf ("lgrCalcGroupe %d\n",lgrCalcGroupe);
385                         
386                         elemZPrec = elemZ;
387                         grCourant = elem->GetGroup();
388                                                         
389                 } else {                // On n'EST PAS sur un nv Groupe
390                 
391                         //printf ("lgrCalcGroupe avant : %d LgrElem %d\n",lgrCalcGroupe,elem->GetLength());
392
393                         lgrCalcGroupe += 2 + 2 + 4 + elem->GetLength();  // Gr + Num + Lgr + LgrElem 
394                         
395                         //printf ("lgrCalcGroupe apres %d\n",lgrCalcGroupe);
396                 }               
397         }
398         
399         // Si on fait de l'implicit VR little Endian 
400         // (pour moins se fairche sur processeur INTEL)
401         // penser a forcer le TRANSFERT SYNTAX UID
402         
403         // supprime par rapport à Write         
404         //SetElValueByNumber(implicitVRTransfertSyntax, 0x0002, 0x0010);        
405         //SetElValueLengthByNumber(18, 0x0002, 0x0010);  // Le 0 de fin de chaine doit etre stocké, dans ce cas 
406                 
407         // restent à tester les echecs en écriture (apres chaque fwrite)
408         
409         for (TagElValueHT::iterator tag2 = tagHt.begin();
410                   tag2 != tagHt.end();
411                   ++tag2){
412
413                 gr =  tag2->second->GetGroup();
414                                                 // saut des groupes speciaux DICOM V3
415                 if (gr < 0x0008) continue;      // ajouté par rapport à Write
416                                                 // saut des groupes impairs
417                 if (gr %2)       continue;      // ajouté par rapport à Write
418                 
419                 el =  tag2->second->GetElement();
420                 lgr = tag2->second->GetLength();
421                 val = tag2->second->GetValue().c_str();
422                 vr =  tag2->second->GetVR();
423                         
424                 fwrite ( &gr,(size_t)2 ,(size_t)1 ,_fp);        //group
425                 fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp);        //element
426                                 
427                 // si on n'est pas en IMPLICIT VR voir pb (lgr  + VR)
428                 
429                 fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp);               //lgr
430                 
431                 tokens.erase(tokens.begin(),tokens.end());
432                 Tokenize (tag2->second->GetValue(), tokens, "\\");
433                 
434                 if (vr == "US" || vr == "SS") {
435
436                         for (unsigned int i=0; i<tokens.size();i++) {
437                                 val_uint16 = atoi(tokens[i].c_str());           
438                                 ptr = &val_uint16;
439                                 fwrite ( ptr,(size_t)2 ,(size_t)1 ,_fp);
440                         }
441                         continue;
442                         
443                 }
444                 if (vr == "UL" || vr == "SL") {
445                         for (unsigned int i=0; i<tokens.size();i++) {
446                                 val_uint32 = atoi(tokens[i].c_str());           
447                                 ptr = &val_uint32;
448                                 fwrite ( ptr,(size_t)4 ,(size_t)1 ,_fp);
449                         }
450                         continue;                               
451                         
452                 }       
453                 
454                 // Les pixels ne sont pas chargés dans l'element !
455                 if ((gr == 0x7fe0) && (el == 0x0010) ) break;
456
457                 fwrite ( val,(size_t)lgr ,(size_t)1 ,_fp); //valeur Elem
458         }
459                 
460         return(1);
461 }