#include "gdcmlib.h"
+#include "gdcmUtil.h"
-int ElValSet::Add(ElValue * newElValue) {
+void ElValSet::Add(ElValue * newElValue) {
tagHt[newElValue->GetKey()] = newElValue;
NameHt[newElValue->GetName()] = newElValue;
}
-int ElValSet::Print(ostream & os) {
+void ElValSet::Print(ostream & os) {
for (TagElValueHT::iterator tag = tagHt.begin();
tag != tagHt.end();
++tag){
- os << tag->first << ": [";
- os << tag->second->GetValue() << "] [";
- os << tag->second->GetName() << "]" << endl;
+ os << tag->first << ": ";
+ os << "[" << tag->second->GetValue() << "]";
+ os << "[" << tag->second->GetName() << "]";
+ os << "[" << tag->second->GetVR() << "]" << endl;
}
}
+
+void ElValSet::PrintByName(ostream & os) {
+ for (TagElValueNameHT::iterator tag = NameHt.begin();
+ tag != NameHt.end();
+ ++tag){
+ os << tag->first << ": ";
+ os << "[" << tag->second->GetValue() << "]";
+ os << "[" << tag->second->GetKey() << "]";
+ os << "[" << tag->second->GetVR() << "]" << endl;
+ }
+}
+
+string ElValSet::GetElValue(guint32 group, guint32 element) {
+ TagKey key = gdcmDictEntry::TranslateToKey(group, element);
+ if ( ! tagHt.count(key))
+ return "UNFOUND";
+ if (tagHt.count(key) > 1)
+ dbg.Verbose(0, "ElValSet::GetElValue",
+ "multiple entries for this key (FIXME) !");
+ return tagHt.find(key)->second->GetValue();
+}
+
+string ElValSet::GetElValue(string TagName) {
+ if ( ! NameHt.count(TagName))
+ return "UNFOUND";
+ if (NameHt.count(TagName) > 1)
+ dbg.Verbose(0, "ElValSet::GetElValue",
+ "multipe entries for this key (FIXME) !");
+ return NameHt.find(TagName)->second->GetValue();
+}
+
fseek(fp, PositionOnEntry, SEEK_SET);
}
-void gdcmHeader::RecupLgr( ElValue *pleCourant) {
+void gdcmHeader::FindLength( ElValue *pleCourant) {
int lgrLue;
guint32 l_gr;
unsigned short int l_gr_2;
l_gr = SwapLong((guint32)l_gr);
} else {
- //on lit la lgr sur DEUX octets
+ // Length is encoded on 2 bytes.
lgrLue=fread (&l_gr_2, (size_t)2,(size_t)1, fp);
l_gr_2 = SwapShort((unsigned short)l_gr_2);
}
}
} else {
- // Explicit VR = 0
- //on lit la lgr sur QUATRE octets
+ // Either implicit VR or an explicit VR that (at least for this
+ // element) lied a little bit. Length is on 4 bytes.
lgrLue=fread (&l_gr, (size_t)4,(size_t)1, fp);
l_gr= SwapLong((long)l_gr);
}
// Traitement des curiosites sur la longueur
- if ( (int)l_gr == 0xffffffff)
+ if ( l_gr == 0xffffffff)
l_gr=0;
- pleCourant->SetLgrElem(l_gr);
+ pleCourant->SetLength(l_gr);
}
/**
*/
ElValue * gdcmHeader::ReadNextElement(void) {
- unsigned short g;
- unsigned short n;
+ guint16 g;
+ guint16 n;
guint32 l;
size_t lgrLue;
ElValue * nouvDcmElem;
return(NULL);
}
- // ------------------------- Lecture longueur element : l
-
FindVR(nouvDcmElem);
- RecupLgr(nouvDcmElem);
+ FindLength(nouvDcmElem);
nouvDcmElem->SetOffset(ftell(fp));
- l = nouvDcmElem->GetLgrElem();
+ l = nouvDcmElem->GetLength();
//FIXMEif(!memcmp( VR,"SQ",(size_t)2 )) { // ca annonce une SEQUENCE d'items ?!
//FIXME l_gr=0; // on lira donc les items de la sequence
//FIXME}
//FIXMEreturn(l_gr);
-
+ // Une sequence contient un ensemble de group element repetes n fois
+ // et g=fffe indique la fin (contient une longueur bidon).
if(g==0xfffe) l=0; // pour sauter les indicateurs de 'SQ'
// pas etre charge's !!!! Voir TODO.
lgrLue=fread (NewValue, (size_t)l,(size_t)1, fp);
+ if ( IsAnInteger(g, n, NewTag->GetVR(), l) ) {
+ // CLEANME THe following is really UGLY !
+ if( l == 4 ) {
+ *(guint32 *) NewValue = SwapLong ((*(guint32 *) NewValue));
+ } else {
+ if( l == 2 )
+ *(guint16 *) NewValue = SwapShort ((*(guint16 *)NewValue));
+ }
+ //FIXME: don't we have to distinguish guin16 and guint32
+ //FIXME: make the following an util fonction
+ ostringstream s;
+ s << *(guint32 *) NewValue;
+ nouvDcmElem->value = s.str();
+ g_free(NewValue);
+ } else
+ nouvDcmElem->value = NewValue;
+ return nouvDcmElem;
+}
- // ------------------------- Doit-on le Swapper ?
-
- if ((n==0) && sw) { // n=0 : lgr du groupe : guint32
- *(guint32 *) NewValue = SwapLong ((*(guint32 *) NewValue));
- } else {
- if(sw) {
- if ( (g/2)*2-g==0) { /* on ne teste pas les groupes impairs */
-
- if ((l==4)||(l==2)) { // pour eviter de swapper les chaines
- // de lgr 2 ou 4
-
- // FIXME make reference to nouvDcmElem->GetTag
- string VR = NewTag->GetVR();
- if ( (VR == "UL") || (VR == "US")
- || (VR == "SL") || (VR == "SS")
- || (g == 0x0028 && ( n == 0x0005 || n == 0x0200) )) {
- // seuls (28,5) de vr RET et (28,200) sont des entiers
- // ... jusqu'a preuve du contraire
-
- if(l==4) {
- *(guint32 *) NewValue =
- SwapLong ((*(guint32 *) NewValue));
- } else {
- if(l==2)
- *(unsigned short *) NewValue =
- SwapShort ((*(unsigned short *)NewValue));
- }
- }
- } /* fin if l==2 ==4 */
- } /* fin if g pair */
- } /* fin sw */
+bool gdcmHeader::IsAnInteger(guint16 group, guint16 element,
+ string vr, guint32 length ) {
+ // When we have some semantics on the element we just read, and we
+ // a priori now we are dealing with an integer, then we can swap it's
+ // element value properly.
+ if ( element == 0 ) { // This is the group length of the group
+ if (length != 4)
+ dbg.Error("gdcmHeader::ShouldBeSwaped", "should be four");
+ return true;
}
- nouvDcmElem->value = NewValue;
- return nouvDcmElem;
+
+ if ( group % 2 != 0 )
+ // We only have some semantics on documented elements, which are
+ // the even ones.
+ return false;
+
+ if ( (length != 4) && ( length != 2) )
+ // Swapping only make sense on integers which are 2 or 4 bytes long.
+ return false;
+
+ if ( (vr == "UL") || (vr == "US") || (vr == "SL") || (vr == "SS") )
+ return true;
+
+ if ( (group == 0x0028) && (element == 0x0005) )
+ // This tag is retained from ACR/NEMA
+ // CHECKME Why should "Image Dimensions" be a single integer ?
+ return true;
+
+ if ( (group == 0x0028) && (element == 0x0200) )
+ // This tag is retained from ACR/NEMA
+ return true;
+
+ return false;
}
/**
* (Pixel Data) then keep the info aside.
*/
void gdcmHeader::SetAsidePixelData(ElValue* elem) {
- /// FIXME this wall process is bizarre:
- // on peut pas lire pixel data et pixel location puis
- // a la fin de la lecture aller interpreter ce qui existe ?
- // penser a nettoyer les variables globales associes genre
- // PixelsTrouve ou grPixelTrouve...
- //
// They are two cases :
// * the pixel data (i.e. the image or the volume) is pointed by it's
// default official tag (0x7fe0,0x0010),
// * if it does not exist, look for the "Pixel Location" tag.
// 2/ look at the proper tag ("Pixel Data" or "Pixel Location" when
// it exists) what the offset is.
+ cout << "aaaaaaaaaaaaaaaaaaaaa";
+ // PubElVals.PrintByName(cout);
+ ostringstream val;
+ val << hex << GetPubElValByName("Image Location");
+ cout << GetPubElValByName("Image Location") << endl;
+ cout <<hex << GetPubElValByName("Image Location") << dec << endl;
+ cout << "aaaa" << hex << val << dec << endl;
+ if (val)
+ //grPixel = val.hex().str();
+ grPixel = 0;
+ else
+ grPixel = 0x7FE0;
+ return;
+
guint16 g;
guint16 n;
g = elem->GetGroup();
if (g == 0x0028) {
if (n == 0x0200) {
grPixelTrouve = 1;
- char* NewValue = (char*)g_malloc(elem->GetLgrElem()+1);
+ char* NewValue = (char*)g_malloc(elem->GetLength()+1);
// FIXME: not very elegant conversion
for(int i=0;i<4;i++)
*((char*)(&grPixel)+i) = *(NewValue+i);
return found;
}
-string gdcmHeader::GetPubElValByNumber(unsigned short, unsigned short) {
+string gdcmHeader::GetPubElValByNumber(guint16 group, guint16 element) {
+ return PubElVals.GetElValue(group, element);
+}
+
+string gdcmHeader::GetPubElValByName(string TagName) {
+ return PubElVals.GetElValue(TagName);
}
/**
void gdcmHeader::BuildHeader(void) {
ElValue * newElValue = (ElValue *)0;
- rewind(fp);
rewind(fp);
CheckSwap();
while ( (newElValue = ReadNextElement()) ) {
PubElVals.Add(newElValue);
}
+ SetAsidePixelData((ElValue*)0);
}
-int gdcmHeader::PrintPubElVal(ostream & os) {
- return PubElVals.Print(os);
+void gdcmHeader::PrintPubElVal(ostream & os) {
+ PubElVals.Print(os);
}
void gdcmHeader::PrintPubDict(ostream & os) {
ElValue(gdcmDictEntry*);
void SetVR(string);
string GetVR(void);
- void SetLgrElem(guint32 l) {LgrElem = l; };
+ void SetLength(guint32 l){LgrElem = l; };
void SetValue(string val){ value = val; };
void SetOffset(size_t of){ Offset = of; };
string GetValue(void) { return value; };
- guint32 GetLgrElem(void) { return LgrElem; };
+ guint32 GetLength(void) { return LgrElem; };
size_t GetOffset(void) { return Offset; };
guint16 GetGroup(void) { return entry->GetGroup(); };
guint16 GetElement(void) { return entry->GetElement(); };
};
typedef map<TagKey, ElValue*> TagElValueHT;
+typedef map<string, ElValue*> TagElValueNameHT;
// Container for a set of succefully parsed ElValues.
class ElValSet {
// We need both accesses with a TagKey and the Dicentry.Name
TagElValueHT tagHt;
- map<string, ElValue*> NameHt;
+ TagElValueNameHT NameHt;
public:
- int Add(ElValue*);
- int Print(ostream &);
+ void Add(ElValue*);
+ void Print(ostream &);
+ void PrintByName(ostream &);
+ string GetElValue(guint32 group, guint32 element);
+ string GetElValue(string);
};
// The various entries of the explicit value representation (VR) shall
void Initialise(void);
void CheckSwap(void);
- void RecupLgr(ElValue *);
+ void FindLength(ElValue *);
void FindVR(ElValue *);
guint32 SwapLong(guint32);
short int SwapShort(short int);
///// See below for an example of how anonymize might be implemented.
int anonymize(ostream&);
public:
+ bool IsAnInteger(guint16, guint16, string, guint32);
virtual void BuildHeader(void);
gdcmHeader(char* filename);
- ~gdcmHeader();
+ virtual ~gdcmHeader();
int SetPubDict(string filename);
// When some proprietary shadow groups are disclosed, whe can set
// of C/C++ vs Python).
string GetPubElValRepByName(string TagName);
string GetPubElValRepByNumber(guint16 group, guint16 element);
- int PrintPubElVal(ostream &);
+ void PrintPubElVal(ostream &);
void PrintPubDict(ostream &);
// Same thing with the shadow :