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