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