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