From e8be02129ece7a8c7dd90307a8c83e1ef5d157b6 Mon Sep 17 00:00:00 2001 From: frog Date: Tue, 22 Oct 2002 14:10:49 +0000 Subject: [PATCH] * src/gdcmHeader.cxx : - RecupLgr renamed to FindLength and cut off with new IsAnInteger method. - SetLgrElem renamed to SetLength - GetLgrElem renamed to GetLength - ~gdcmHeader() made virtual to pesky warning messages at compile. * src/gdcmElValSet.cxx fixed both GetElValue methods * Dicts/dicomV3.dic falacious entry [7fe0 0010 OT PXL Pixel Data] due to IdoDude was cleaned out. --- Frog --- ChangeLog | 11 ++++ Dicts/dicomV3.dic | 1 - src/gdcmDict.cxx | 1 - src/gdcmElValSet.cxx | 43 +++++++++++-- src/gdcmHeader.cxx | 143 ++++++++++++++++++++++++++----------------- src/gdcmlib.h | 21 ++++--- 6 files changed, 148 insertions(+), 72 deletions(-) diff --git a/ChangeLog b/ChangeLog index d5fbb52c..12603787 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2002-10-22 Eric Boix + * src/gdcmHeader.cxx : + - RecupLgr renamed to FindLength and cut off with new IsAnInteger + method. + - SetLgrElem renamed to SetLength + - GetLgrElem renamed to GetLength + - ~gdcmHeader() made virtual to pesky warning messages at compile. + * src/gdcmElValSet.cxx fixed both GetElValue methods + * Dicts/dicomV3.dic falacious entry [7fe0 0010 OT PXL Pixel Data] + due to IdoDude was cleaned out. + 2002-10-21 Eric Boix * src/gdcmHeader.cxx RecupLgr split in FindVR and RecupLgr. FindVR concentrates on finding the value representation (when it exists). diff --git a/Dicts/dicomV3.dic b/Dicts/dicomV3.dic index e6c4cf58..a83f4ab5 100644 --- a/Dicts/dicomV3.dic +++ b/Dicts/dicomV3.dic @@ -1385,6 +1385,5 @@ 6000 3000 OW OLY Data 6000 4000 LO OLY Comments (RET) 7fe0 0000 UL PXL Group Length -7fe0 0010 OT PXL Pixel Data fffe e000 UL XX item ffff ffff UKN UKN Unknown Code diff --git a/src/gdcmDict.cxx b/src/gdcmDict.cxx index f21e37a1..8b42624d 100644 --- a/src/gdcmDict.cxx +++ b/src/gdcmDict.cxx @@ -9,7 +9,6 @@ gdcmDict::gdcmDict(char * FileName) { guint16 group, element; // CLEANME : use defines for all those constants char buff[1024]; - char trash[10]; TagKey key, vr, fourth, name; while (!from.eof()) { from >> hex >> group >> element; diff --git a/src/gdcmElValSet.cxx b/src/gdcmElValSet.cxx index 57512516..9101d26f 100644 --- a/src/gdcmElValSet.cxx +++ b/src/gdcmElValSet.cxx @@ -1,16 +1,49 @@ #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(); +} + diff --git a/src/gdcmHeader.cxx b/src/gdcmHeader.cxx index 95541120..dc6bbf41 100644 --- a/src/gdcmHeader.cxx +++ b/src/gdcmHeader.cxx @@ -289,7 +289,7 @@ void gdcmHeader::FindVR( ElValue *pleCourant) { 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; @@ -307,7 +307,7 @@ void gdcmHeader::RecupLgr( ElValue *pleCourant) { 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); @@ -319,17 +319,17 @@ void gdcmHeader::RecupLgr( ElValue *pleCourant) { } } } 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); } /** @@ -386,8 +386,8 @@ short int gdcmHeader::SwapShort(short int a) { */ ElValue * gdcmHeader::ReadNextElement(void) { - unsigned short g; - unsigned short n; + guint16 g; + guint16 n; guint32 l; size_t lgrLue; ElValue * nouvDcmElem; @@ -431,19 +431,18 @@ ElValue * gdcmHeader::ReadNextElement(void) { 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' @@ -462,41 +461,58 @@ ElValue * gdcmHeader::ReadNextElement(void) { // 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; } /** @@ -505,12 +521,6 @@ ElValue * gdcmHeader::ReadNextElement(void) { * (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), @@ -527,6 +537,20 @@ void gdcmHeader::SetAsidePixelData(ElValue* elem) { // * 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 <GetGroup(); @@ -542,7 +566,7 @@ void gdcmHeader::SetAsidePixelData(ElValue* elem) { 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); @@ -586,7 +610,12 @@ gdcmDictEntry * gdcmHeader::IsInDicts(guint32 group, guint32 element) { 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); } /** @@ -599,16 +628,16 @@ string gdcmHeader::GetPubElValByNumber(unsigned short, unsigned short) { 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) { diff --git a/src/gdcmlib.h b/src/gdcmlib.h index bdf786f6..7c16dba9 100644 --- a/src/gdcmlib.h +++ b/src/gdcmlib.h @@ -134,11 +134,11 @@ public: 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(); }; @@ -147,14 +147,18 @@ public: }; typedef map TagElValueHT; +typedef map 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 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 @@ -202,7 +206,7 @@ private: void Initialise(void); void CheckSwap(void); - void RecupLgr(ElValue *); + void FindLength(ElValue *); void FindVR(ElValue *); guint32 SwapLong(guint32); short int SwapShort(short int); @@ -225,9 +229,10 @@ protected: ///// 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 @@ -247,7 +252,7 @@ public: // 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 : -- 2.48.1