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