4 #include "gdcmElValSet.h"
8 static void Tokenize (const string& str, vector<string>& tokens, const string& delimiters = " ");
11 TagElValueHT & ElValSet::GetTagHt(void) {
15 void ElValSet::Add(ElValue * newElValue) {
16 tagHt [newElValue->GetKey()] = newElValue;
17 NameHt[newElValue->GetName()] = newElValue;
20 void ElValSet::Print(ostream & os) {
21 for (TagElValueHT::iterator tag = tagHt.begin();
24 os << tag->first << ": ";
25 os << "[" << tag->second->GetValue() << "]";
26 os << "[" << tag->second->GetName() << "]";
27 os << "[" << tag->second->GetVR() << "]" << endl;
31 void ElValSet::PrintByName(ostream & os) {
32 for (TagElValueNameHT::iterator tag = NameHt.begin();
35 os << tag->first << ": ";
36 os << "[" << tag->second->GetValue() << "]";
37 os << "[" << tag->second->GetKey() << "]";
38 os << "[" << tag->second->GetVR() << "]" << endl;
42 ElValue* ElValSet::GetElementByNumber(guint32 group, guint32 element) {
43 TagKey key = gdcmDictEntry::TranslateToKey(group, element);
44 if ( ! tagHt.count(key))
46 if (tagHt.count(key) > 1)
47 dbg.Verbose(0, "ElValSet::GetElementByNumber",
48 "multiple entries for this key (FIXME) !");
49 return tagHt.find(key)->second;
52 ElValue* ElValSet::GetElementByName(string TagName) {
53 if ( ! NameHt.count(TagName))
55 if (NameHt.count(TagName) > 1)
56 dbg.Verbose(0, "ElValSet::GetElement",
57 "multipe entries for this key (FIXME) !");
58 return NameHt.find(TagName)->second;
61 string ElValSet::GetElValueByNumber(guint32 group, guint32 element) {
62 TagKey key = gdcmDictEntry::TranslateToKey(group, element);
63 if ( ! tagHt.count(key))
64 return "gdcm::Unfound";
65 if (tagHt.count(key) > 1)
66 dbg.Verbose(0, "ElValSet::GetElValueByNumber",
67 "multiple entries for this key (FIXME) !");
68 return tagHt.find(key)->second->GetValue();
71 string ElValSet::GetElValueByName(string TagName) {
72 if ( ! NameHt.count(TagName))
73 return "gdcm::Unfound";
74 if (NameHt.count(TagName) > 1)
75 dbg.Verbose(0, "ElValSet::GetElValue",
76 "multipe entries for this key (FIXME) !");
77 return NameHt.find(TagName)->second->GetValue();
80 int ElValSet::SetElValueByNumber(string content, guint32 group, guint32 element) {
81 TagKey key = gdcmDictEntry::TranslateToKey(group, element);
82 if ( ! tagHt.count(key))
84 if (tagHt.count(key) > 1) {
85 dbg.Verbose(0, "ElValSet::SetElValueByNumber",
86 "multiple entries for this key (FIXME) !");
89 tagHt[key]->SetValue(content);
91 // Question : m à j LgrElem ?
92 tagHt[key]->SetLength(strlen(content.c_str()));
94 // FIXME should we really update the element length ?
95 tagHt[key]->SetLength(content.length());
100 int ElValSet::SetElValueByName(string content, string TagName) {
101 if ( ! NameHt.count(TagName))
103 if (NameHt.count(TagName) > 1) {
104 dbg.Verbose(0, "ElValSet::SetElValueByName",
105 "multipe entries for this key (FIXME) !");
108 NameHt.find(TagName)->second->SetValue(content);
109 NameHt.find(TagName)->second->SetLength(strlen(content.c_str()));
114 int ElValSet::SetElValueLengthByNumber(guint32 l, guint32 group, guint32 element) {
115 TagKey key = gdcmDictEntry::TranslateToKey(group, element);
116 if ( ! tagHt.count(key))
118 if (tagHt.count(key) > 1) {
119 dbg.Verbose(0, "ElValSet::SetElValueLengthByNumber",
120 "multiple entries for this key (FIXME) !");
124 tagHt[key]->SetLength(l);
129 int ElValSet::SetElValueLengthByName(guint32 l, string TagName) {
130 if ( ! NameHt.count(TagName))
132 if (NameHt.count(TagName) > 1) {
133 dbg.Verbose(0, "ElValSet::SetElValueByName",
134 "multipe entries for this key (FIXME) !");
137 NameHt.find(TagName)->second->SetLength(l);
142 int ElValSet::Write(FILE * _fp) {
144 // ATTENTION : fonction non terminée (commitée a titre de precaution)
155 vector<string> tokens;
158 char str_lgrCalcGroupe[10];
160 string implicitVRTransfertSyntax = "1.2.840.10008.1.2";
162 // Utilisées pour le calcul Group Length
164 guint32 lgrCalcGroupe=0;
165 ElValue *elem, *elemZ, *elemZPrec;
166 guint16 grCourant = 0;
169 // Comment pourrait-on tester si on est TrueDicom ou non ,
170 // (FileType est un champ de gdcmHeader ...)
173 // On parcourt la table pour recalculer la longueur des 'elements 0x0000'
174 // au cas ou un tag ai été ajouté par rapport à ce qui a été lu
175 // dans l'image native
177 // cf : code IdDcmWriteFile dans libido/src/dcmwrite.c
179 if (0) // Risque de pb dans le calcul des lgr de chaque groupe. On le saute pour le moment!
181 for (TagElValueHT::iterator tag = tagHt.begin();
186 printf("gr %04x el %04x lgr %d\n",elem->GetGroup(), elem->GetElement(), elem->GetLength());
188 if ( (elem->GetGroup() != grCourant) &&
189 (elem->GetGroup() != 0xfffe) ) { // On arrive sur un nv Groupe
191 printf("Nouv Groupegr %04x el %04x \n",elem->GetGroup(), elem->GetElement());
195 if(elemZ->GetElement() != 0x0000) { // pas d'element 'Lgr groupe'
197 gdcmDictEntry * tagZ = new gdcmDictEntry(grCourant, 0x0000, "UL");
198 elemZ = new ElValue(tagZ); // on le cree
200 Add(elemZ); // On l'accroche à sa place
204 //sprintf(str_lgrCalcGroupe,"%d",lgrCalcGroupe);
205 elemZPrec->SetValue(str_lgrCalcGroupe);
210 lgrCalcGroupe = 12; //2 + 2 + 4 + 4; // Gr + Num + Lgr + LgrGroupe
211 printf ("lgrCalcGroupe %d\n",lgrCalcGroupe);
214 grCourant = elem->GetGroup();
216 } else { // On n'EST PAS sur un nv Groupe
218 printf ("lgrCalcGroupe avant : %d LgrElem %d\n",lgrCalcGroupe,elem->GetLength());
220 lgrCalcGroupe += 2 + 2 + 4 + elem->GetLength(); // Gr + Num + Lgr + LgrElem
222 printf ("lgrCalcGroupe apres %d\n",lgrCalcGroupe);
226 // Si on fait de l'implicit VR little Endian
227 // (pour moins se fairche sur processeur INTEL)
228 // penser a forcer le TRANSFERT SYNTAX UID
230 SetElValueByNumber(implicitVRTransfertSyntax, 0x0002, 0x0010);
231 SetElValueLengthByNumber(18, 0x0002, 0x0010); // Le 0 de fin de chaine doit etre stocké, dans ce cas
233 // restent à tester les echecs en écriture (apres chaque fwrite)
235 for (TagElValueHT::iterator tag2 = tagHt.begin();
239 gr = tag2->second->GetGroup();
240 el = tag2->second->GetElement();
241 lgr = tag2->second->GetLength();
242 val = tag2->second->GetValue().c_str();
243 vr = tag2->second->GetVR();
245 fwrite ( &gr,(size_t)2 ,(size_t)1 ,_fp); //group
246 fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp); //element
248 //fwrite ( vr,(size_t)2 ,(size_t)1 ,_fp); //VR
250 // si on n'est pas en IMPLICIT VR voir pb (lgr + VR)
252 fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp); //lgr
254 tokens.erase(tokens.begin(),tokens.end());
255 Tokenize (tag2->second->GetValue(), tokens, "\\");
257 //printf ("%04x %04x [%s] : [%s]\n",gr, el, vr.c_str(), val);
258 //if (tokens.size() > 1) { printf ("size : %d\n",tokens.size());}
261 if (vr == "US" || vr == "SS") {
263 val_int16 = atoi(val);
265 fwrite ( ptr,(size_t)2 ,(size_t)1 ,_fp);
269 for (unsigned int i=0; i<tokens.size();i++) {
270 val_uint16 = atoi(tokens[i].c_str());
272 fwrite ( ptr,(size_t)2 ,(size_t)1 ,_fp);
277 if (vr == "UL" || vr == "SL") {
279 val_int32 = atoi(val);
281 fwrite ( ptr,(size_t)4 ,(size_t)1 ,_fp);
286 for (unsigned int i=0; i<tokens.size();i++) {
287 val_uint32 = atoi(tokens[i].c_str());
289 fwrite ( ptr,(size_t)4 ,(size_t)1 ,_fp);
295 // Les pixels ne sont pas chargés dans l'element !
296 if ((gr == 0x7fe0) && (el == 0x0010) ) break;
298 fwrite ( val,(size_t)lgr ,(size_t)1 ,_fp); //valeur Elem
307 int ElValSet::WriteAcr(FILE * _fp) {
310 // ATTENTION : fonction non terminée (commitée a titre de precaution)
311 // ATTENTION : fusioner le code avec celui de lValSet::Write
323 vector<string> tokens;
326 char str_lgrCalcGroupe[10];
328 //string implicitVRTransfertSyntax = "1.2.840.10008.1.2"; // supprime par rapport à Write
330 // Utilisées pour le calcul Group Length
332 guint32 lgrCalcGroupe=0;
333 ElValue *elem, *elemZ, *elemZPrec;
334 guint16 grCourant = 0;
337 // Comment pourrait-on tester si on est TrueDicom ou non ,
338 // (FileType est un champ de gdcmHeader ...)
341 // On parcourt la table pour recalculer la longueur des 'elements 0x0000'
342 // au cas ou un tag ai été ajouté par rapport à ce qui a été lu
343 // dans l'image native
345 // cf : code IdDcmWriteFile dans libido/src/dcmwrite.c
347 if (1) // Risque de pb dans le calcul des lgr de chaque groupe. On le saute pour le moment!
349 for (TagElValueHT::iterator tag = tagHt.begin();
354 //printf("gr %04x el %04x lgr %d\n",elem->GetGroup(), elem->GetElement(), elem->GetLength());
356 if ( (elem->GetGroup() != grCourant) &&
357 (elem->GetGroup() != 0xfffe) ) { // On arrive sur un nv Groupe
359 //printf("Nouv Groupegr %04x el %04x \n",elem->GetGroup(), elem->GetElement());
363 if(elemZ->GetElement() != 0x0000) { // pas d'element 'Lgr groupe'
365 gdcmDictEntry * tagZ = new gdcmDictEntry(grCourant, 0x0000, "UL");
366 elemZ = new ElValue(tagZ); // on le cree
368 Add(elemZ); // On l'accroche à sa place
372 //sprintf(str_lgrCalcGroupe,"%d",lgrCalcGroupe);
373 elemZPrec->SetValue(str_lgrCalcGroupe);
378 lgrCalcGroupe = 12; //2 + 2 + 4 + 4; // Gr + Num + Lgr + LgrGroupe
379 //printf ("lgrCalcGroupe %d\n",lgrCalcGroupe);
382 grCourant = elem->GetGroup();
384 } else { // On n'EST PAS sur un nv Groupe
386 //printf ("lgrCalcGroupe avant : %d LgrElem %d\n",lgrCalcGroupe,elem->GetLength());
388 lgrCalcGroupe += 2 + 2 + 4 + elem->GetLength(); // Gr + Num + Lgr + LgrElem
390 //printf ("lgrCalcGroupe apres %d\n",lgrCalcGroupe);
394 // Si on fait de l'implicit VR little Endian
395 // (pour moins se fairche sur processeur INTEL)
396 // penser a forcer le TRANSFERT SYNTAX UID
398 // supprime par rapport à Write
399 //SetElValueByNumber(implicitVRTransfertSyntax, 0x0002, 0x0010);
400 //SetElValueLengthByNumber(18, 0x0002, 0x0010); // Le 0 de fin de chaine doit etre stocké, dans ce cas
402 // restent à tester les echecs en écriture (apres chaque fwrite)
404 for (TagElValueHT::iterator tag2 = tagHt.begin();
408 gr = tag2->second->GetGroup();
409 // saut des groupes speciaux DICOM V3
410 if (gr < 0x0008) continue; // ajouté par rapport à Write
411 // saut des groupes impairs
412 if (gr %2) continue; // ajouté par rapport à Write
414 el = tag2->second->GetElement();
415 lgr = tag2->second->GetLength();
416 val = tag2->second->GetValue().c_str();
417 vr = tag2->second->GetVR();
419 fwrite ( &gr,(size_t)2 ,(size_t)1 ,_fp); //group
420 fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp); //element
422 // si on n'est pas en IMPLICIT VR voir pb (lgr + VR)
424 fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp); //lgr
426 tokens.erase(tokens.begin(),tokens.end());
427 Tokenize (tag2->second->GetValue(), tokens, "\\");
429 if (vr == "US" || vr == "SS") {
431 for (unsigned int i=0; i<tokens.size();i++) {
432 val_uint16 = atoi(tokens[i].c_str());
434 fwrite ( ptr,(size_t)2 ,(size_t)1 ,_fp);
439 if (vr == "UL" || vr == "SL") {
440 for (unsigned int i=0; i<tokens.size();i++) {
441 val_uint32 = atoi(tokens[i].c_str());
443 fwrite ( ptr,(size_t)4 ,(size_t)1 ,_fp);
449 // Les pixels ne sont pas chargés dans l'element !
450 if ((gr == 0x7fe0) && (el == 0x0010) ) break;
452 fwrite ( val,(size_t)lgr ,(size_t)1 ,_fp); //valeur Elem
461 // mettre ça dans une bibliothèque d'utilitaires ?
464 static void Tokenize (const string& str, vector<string>& tokens, const string& delimiters = " ") {
465 string::size_type lastPos = str.find_first_not_of(delimiters,0);
466 string::size_type pos = str.find_first_of(delimiters,lastPos);
467 while (string::npos != pos || string::npos != lastPos) {
468 tokens.push_back(str.substr(lastPos, pos - lastPos));
469 lastPos = str.find_first_not_of(delimiters, pos);
470 pos = str.find_first_of(delimiters, lastPos);