]> Creatis software - gdcm.git/blob - src/gdcmElValSet.cxx
9b001c5d5563532e406415ada44597dfe2944c26
[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         // restent à tester les echecs en écriture (apres chaque fwrite)
220    for (TagElValueHT::iterator tag2 = tagHt.begin();
221         tag2 != tagHt.end();
222         ++tag2){
223
224       gr =  tag2->second->GetGroup();
225       el =  tag2->second->GetElement();
226       lgr = tag2->second->GetLength();
227       val = tag2->second->GetValue().c_str();
228       vr =  tag2->second->GetVR();
229       if(DEBUG)printf ("%04x %04x [%s] : [%s]\n",gr, el, vr.c_str(), val);
230
231       if ( type == ACR ) { 
232          if (gr < 0x0008) continue;
233          if (gr %2)   continue;
234          if (vr == "SQ" ) continue;
235       } 
236
237
238       fwrite ( &gr,(size_t)2 ,(size_t)1 ,_fp);  //group
239       fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp);  //element
240
241       if ( (type == ExplicitVR) && (gr <= 0x0002) ) {
242          // On est en EXPLICIT VR
243          guint16 z=0, shortLgr;
244          fwrite (vr.c_str(),(size_t)2 ,(size_t)1 ,_fp);
245
246          if ( (vr == "OB") || (vr == "OW") || (vr == "SQ") ) {
247             fwrite ( &z,  (size_t)2 ,(size_t)1 ,_fp);
248             fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp);
249
250          } else {
251             shortLgr=lgr;
252             fwrite ( &shortLgr,(size_t)2 ,(size_t)1 ,_fp);
253          }
254       } else {
255          fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp);
256       }
257
258       tokens.erase(tokens.begin(),tokens.end());
259       Tokenize (tag2->second->GetValue(), tokens, "\\");
260
261       if (vr == "US" || vr == "SS") {
262          for (unsigned int i=0; i<tokens.size();i++) {
263             val_uint16 = atoi(tokens[i].c_str());
264             ptr = &val_uint16;
265             fwrite ( ptr,(size_t)2 ,(size_t)1 ,_fp);
266          }
267          continue;
268       }
269       if (vr == "UL" || vr == "SL") {
270          for (unsigned int i=0; i<tokens.size();i++) {
271             val_uint32 = atoi(tokens[i].c_str());
272             ptr = &val_uint32;
273             fwrite ( ptr,(size_t)4 ,(size_t)1 ,_fp);
274          }
275          continue;
276       }
277
278       // Les pixels ne sont pas chargés dans l'element !
279       if ((gr == 0x7fe0) && (el == 0x0010) ) break;
280
281       fwrite ( val,(size_t)lgr ,(size_t)1 ,_fp); //valeur Elem
282    }
283 }
284
285 int gdcmElValSet::Write(FILE * _fp, FileType type) {
286
287    if (type == ImplicitVR) {
288       string implicitVRTransfertSyntax = "1.2.840.10008.1.2";
289       SetElValueByNumber(implicitVRTransfertSyntax, 0x0002, 0x0010);
290       //FIXME Refer to standards on page 21, chapter 6.2 "Value representation":
291       //      values with a VR of UI shall be padded with a single trailing null
292       //      Dans le cas suivant on doit pader manuellement avec un 0.
293       SetElValueLengthByNumber(18, 0x0002, 0x0010);
294    }
295    if (type == ExplicitVR) {
296       string explicitVRTransfertSyntax = "1.2.840.10008.1.2.1";
297       SetElValueByNumber(explicitVRTransfertSyntax, 0x0002, 0x0010);
298       // See above comment 
299       SetElValueLengthByNumber(20, 0x0002, 0x0010);
300    }
301
302    if ( (type == ImplicitVR) || (type == ExplicitVR) )
303       UpdateGroupLength();
304    if ( type == ACR)
305       UpdateGroupLength(true);
306
307    WriteElements(type, _fp);
308
309    return(1);
310 }