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