]> Creatis software - gdcm.git/blob - src/gdcmElValSet.cxx
UpdateGroupLength re-written using H-Table
[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
122
123 void gdcmElValSet::UpdateGroupLength(bool SkipSequence, FileType type) {
124    guint16 gr, el;
125    string vr;
126    
127    gdcmElValue *elem;
128    char trash[10];
129    string str_trash;
130    GroupKey key;
131    GroupHT groupHt;
132    TagKey tk;
133    gdcmElValue *elemZ;
134    
135    for (TagElValueHT::iterator tag2 = tagHt.begin();
136         tag2 != tagHt.end();
137         ++tag2){
138
139       elem  = tag2->second;
140       gr = elem->GetGroup();
141       el = elem->GetElement();
142       vr = elem->GetVR(); 
143                  
144       sprintf(trash, "%04x", gr);
145       key = trash;
146             
147       if (SkipSequence && vr == "SQ") continue;
148          // pas SEQUENCE en ACR-NEMA
149          // WARNING : pb CERTAIN
150          //           si on est descendu 'a l'interieur' des SQ 
151          //
152          // --> la descente a l'interieur' des SQ 
153          // devra etre faite avec une liste chainee, pas avec une HTable...
154              
155       if ( groupHt.count(key) == 0) { 
156          if (el ==0x0000) {
157             groupHt[key] = 0;
158          } else {
159             groupHt[key] =2 + 2 + 4 + elem->GetLength();
160          } 
161       } else {       
162          if (type = ExplicitVR) {
163             if ( (vr == "OB") || (vr == "OW") || (vr == "SQ") ) {
164                groupHt[key] +=  4;
165             }
166          }
167          groupHt[key] += 2 + 2 + 4 + elem->GetLength(); 
168       } 
169    }
170   
171    unsigned short int gr_bid;
172   
173    for (GroupHT::iterator g = groupHt.begin();
174         g != groupHt.end();
175         ++g){ 
176   
177       tk = g->first + "|0000";
178       sscanf(g->first.c_str(),"%x",&gr_bid);
179                
180       if ( tagHt.count(tk) == 0) { 
181          gdcmDictEntry * tagZ = new gdcmDictEntry(gr_bid, 0x0000, "UL");       
182          elemZ = new gdcmElValue(tagZ);
183          elemZ->SetLength(4);
184          Add(elemZ);
185       } else {
186          elemZ=GetElementByNumber(gr_bid, 0x0000);
187       }
188       str_trash=trash;
189       elemZ->SetValue(str_trash);
190    }   
191    
192    // Liberer groupHt !
193    
194 }
195
196 void gdcmElValSet::WriteElements(FileType type, FILE * _fp) {
197    guint16 gr, el;
198    guint32 lgr;
199    const char * val;
200    string vr;
201    guint32 val_uint32;
202    guint16 val_uint16;
203    
204    vector<string> tokens;
205
206    void *ptr;
207
208    // Tout ceci ne marche QUE parce qu'on est sur un proc Little Endian 
209    // restent à tester les echecs en écriture (apres chaque fwrite)
210
211    for (TagElValueHT::iterator tag2=tagHt.begin();
212         tag2 != tagHt.end();
213         ++tag2){
214
215       gr =  tag2->second->GetGroup();
216       el =  tag2->second->GetElement();
217       lgr = tag2->second->GetLength();
218       val = tag2->second->GetValue().c_str();
219       vr =  tag2->second->GetVR();
220       if(DEBUG)printf ("%04x %04x [%s] : [%s]\n",gr, el, vr.c_str(), val);
221
222       if ( type == ACR ) { 
223          if (gr < 0x0008) continue;
224          if (gr %2)   continue;
225          if (vr == "SQ" ) continue;
226       } 
227
228       fwrite ( &gr,(size_t)2 ,(size_t)1 ,_fp);  //group
229       fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp);  //element
230
231       if ( (type == ExplicitVR) && (gr <= 0x0002) ) {
232          // On est en EXPLICIT VR
233          guint16 z=0, shortLgr;
234          fwrite (vr.c_str(),(size_t)2 ,(size_t)1 ,_fp);
235
236          if ( (vr == "OB") || (vr == "OW") || (vr == "SQ") ) {
237             fwrite ( &z,  (size_t)2 ,(size_t)1 ,_fp);
238             fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp);
239
240          } else {
241             shortLgr=lgr;
242             fwrite ( &shortLgr,(size_t)2 ,(size_t)1 ,_fp);
243          }
244       } else {
245          fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp);
246       }
247
248       tokens.erase(tokens.begin(),tokens.end());
249       Tokenize (tag2->second->GetValue(), tokens, "\\");
250
251       if (vr == "US" || vr == "SS") {
252          for (unsigned int i=0; i<tokens.size();i++) {
253             val_uint16 = atoi(tokens[i].c_str());
254             ptr = &val_uint16;
255             fwrite ( ptr,(size_t)2 ,(size_t)1 ,_fp);
256          }
257          continue;
258       }
259       if (vr == "UL" || vr == "SL") {
260          for (unsigned int i=0; i<tokens.size();i++) {
261             val_uint32 = atoi(tokens[i].c_str());
262             ptr = &val_uint32;
263             fwrite ( ptr,(size_t)4 ,(size_t)1 ,_fp);
264          }
265          continue;
266       }
267
268       // Les pixels ne sont pas chargés dans l'element !
269       if ((gr == 0x7fe0) && (el == 0x0010) ) break;
270
271       fwrite ( val,(size_t)lgr ,(size_t)1 ,_fp); //valeur Elem
272    }
273 }
274
275 int gdcmElValSet::Write(FILE * _fp, FileType type) {
276
277    if (type == ImplicitVR) {
278       string implicitVRTransfertSyntax = "1.2.840.10008.1.2";
279       SetElValueByNumber(implicitVRTransfertSyntax, 0x0002, 0x0010);
280       
281       //FIXME Refer to standards on page 21, chapter 6.2 "Value representation":
282       //      values with a VR of UI shall be padded with a single trailing null
283       //      Dans le cas suivant on doit pader manuellement avec un 0.
284       SetElValueLengthByNumber(18, 0x0002, 0x0010);
285    }
286    
287         // Question :
288         // Comment pourrait-on si le DcmHeader vient d'un fichoer DicomV3 ou non ,
289         // (FileType est un champ de gdcmHeader ...)
290         // WARNING : Si on veut ecrire du DICOM V3 a partir d'un DcmHeader ACR-NEMA
291         // no way
292         
293         
294    if (type == ExplicitVR) {
295       string explicitVRTransfertSyntax = "1.2.840.10008.1.2.1";
296       SetElValueByNumber(explicitVRTransfertSyntax, 0x0002, 0x0010);
297       // See above comment 
298       SetElValueLengthByNumber(20, 0x0002, 0x0010);
299    }
300
301    if ( (type == ImplicitVR) || (type == ExplicitVR) )
302       UpdateGroupLength(false,type);
303    if ( type == ACR)
304       UpdateGroupLength(true,ACR);
305
306    WriteElements(type, _fp);
307
308    return(1);
309 }