From cb5e6c7cb10e5a644ebb8deb9bb4d35c89f6e736 Mon Sep 17 00:00:00 2001 From: frog Date: Wed, 11 Dec 2002 17:56:00 +0000 Subject: [PATCH] * src/gdcm.h, gdcmHeader.cxx: - historic references to glib's g_malloc and g_free (#defined) were definitively removed. - gdcm.h: cosmetic changes (part of comments moved to Doc/requirements) * src/gdcmElValSet.cxx: - GetElement(guint32, guint32) renamed to GetElementByNumber. - GetElValue(guint32, guint32) renamed to GetElValueByNumber. - GetElValue(string) renamed to GetElValueByName. - Added GetElementByName(string). * src/gdcmHeader.cxx: added - GetPubElValRepByNumber(guint16, guint16) - GetPubElValRepByName(string) - GetShaElValRepByNumber(guint16, guint16) - GetShaElValRepByName(string) - GetShaElValByNumber(guint16, guint16) - GetShaElValRepByName(string) - GetElValRepByNumber(guint16, guint16) - GetElValRepByName(string) - GetElValByNumber(guint16, guint16) - GetElValRepByName(string) * Doc/requirements.txt added. --- Frog --- ChangeLog | 23 ++++++ Doc/requirement.txt | 31 ++++++++ src/gdcm.h | 173 ++++++++++++++++++------------------------- src/gdcmElValSet.cxx | 23 ++++-- src/gdcmHeader.cxx | 131 +++++++++++++++++++------------- 5 files changed, 222 insertions(+), 159 deletions(-) create mode 100644 Doc/requirement.txt diff --git a/ChangeLog b/ChangeLog index b5a0c1f6..c81c2ee0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2002-12-11 Eric Boix + * src/gdcm.h, gdcmHeader.cxx: + - historic references to glib's g_malloc and g_free (#defined) + were definitively removed. + - gdcm.h: cosmetic changes (part of comments moved to Doc/requirements) + * src/gdcmElValSet.cxx: + - GetElement(guint32, guint32) renamed to GetElementByNumber. + - GetElValue(guint32, guint32) renamed to GetElValueByNumber. + - GetElValue(string) renamed to GetElValueByName. + - Added GetElementByName(string). + * src/gdcmHeader.cxx: added + - GetPubElValRepByNumber(guint16, guint16) + - GetPubElValRepByName(string) + - GetShaElValRepByNumber(guint16, guint16) + - GetShaElValRepByName(string) + - GetShaElValByNumber(guint16, guint16) + - GetShaElValRepByName(string) + - GetElValRepByNumber(guint16, guint16) + - GetElValRepByName(string) + - GetElValByNumber(guint16, guint16) + - GetElValRepByName(string) + * Doc/requirements.txt added. + 2002-12-9 Eric Boix * Test/Makefile building now depends on the one of libgdcm.so * src/gdcmHeader.cxx and gdcm.h are now OB (undefined length encoded diff --git a/Doc/requirement.txt b/Doc/requirement.txt new file mode 100644 index 00000000..dd4999ae --- /dev/null +++ b/Doc/requirement.txt @@ -0,0 +1,31 @@ +Design notes: + * STL hash table ("#include ") requirements: + 1/ iterator: first(), ++, (i.e. iterate or next). + 2/ should be sortable (i.e. sorted by TagKey). This condition shall be + droped since the Win32/VC++6.0 implementation doesn't look like + providing this facility. + 3/ has a setup some default size value (in number of items), which should + be around 4500 entries which appears to be the average dictionary size + (said JPR). + + +Examples: + * gdcmFile WriteDicom; + WriteDicom.SetFileName("MyDicomFile.dcm"); + string * AllTags = gdcmHeader.GetDcmTagNames(); + WriteDicom.SetDcmTag(AllTags[5], "253"); + WriteDicom.SetDcmTag("Patient Name", "bozo"); + WriteDicom.SetDcmTag("Patient Name", "bozo"); + WriteDicom.SetImageData(Image); + WriteDicom.Write(); + + + Anonymize(ostream& output) { + a = gdcmFile("toto1"); + a.SetPubValueByName("Patient Name", ""); + a.SetPubValueByName("Date", ""); + a.SetPubValueByName("Study Date", ""); + a.write(output); + } + + diff --git a/src/gdcm.h b/src/gdcm.h index f0b4b91a..2d81ecf6 100644 --- a/src/gdcm.h +++ b/src/gdcm.h @@ -16,42 +16,33 @@ // the declaration once you provided the definition of the method... #include +#ifdef _MSC_VER +using namespace std; // string type lives in the std namespace on VC++ +#endif + #include #include // For size_t #include // FIXME For FILE on GCC only -#include // The requirement for the hash table (or map) that - // we shall use: - // 1/ First, next, last (iterators) - // 2/ should be sortable (i.e. sorted by TagKey). This - // condition shall be droped since the Win32/VC++ - // implementation doesn't look a sorted one. Pffff.... - // 3/ Make sure we can setup some default size value, - // which should be around 4500 entries which is the - // average dictionary size (said JPR) - -#define g_malloc malloc -#define g_free free +#include #ifdef __GNUC__ #include #define guint16 uint16_t #define guint32 uint32_t #endif + #ifdef _MSC_VER typedef unsigned short guint16; typedef unsigned int guint32; - #endif -#ifdef _MSC_VER - using namespace std; // string type lives in the std namespace on VC++ -#endif #ifdef _MSC_VER #define GDCM_EXPORT __declspec( dllexport ) #else #define GDCM_EXPORT #endif +//////////////////////////////////////////////////////////////////////////// // Tag based hash tables. // We shall use as keys the strings (as the C++ type) obtained by // concatenating the group value and the element value (both of type @@ -69,16 +60,14 @@ private: string vr; // Value Representation i.e. some clue about the nature // of the data represented e.g. "FD" short for // "Floating Point Double" - // CLEAN ME: find the official dicom name for this field ! + // CLEANME: find the official dicom name for this field ! string fourth; // Fourth field containing some semantics. string name; // e.g. "Patient_Name" - TagKey key; // This is redundant zith (group, element) but we add + TagKey key; // Redundant with (group, element) but we add it // on efficiency purposes. // DCMTK has many fields for handling a DictEntry (see below). What are the // relevant ones for gdcmlib ? // struct DBI_SimpleEntry { - // Uint16 group; - // Uint16 element; // Uint16 upperGroup; // Uint16 upperElement; // DcmEVR evr; @@ -90,11 +79,10 @@ private: // DcmDictRangeRestriction elementRestriction; // }; public: - //CLEANME gdcmDictEntry(); gdcmDictEntry(guint16 group, guint16 element, string vr = "Unknown", - string fourth = "Unknown", - string name = "Unknown"); + string fourth = "Unknown", + string name = "Unknown"); static TagKey TranslateToKey(guint16 group, guint16 element); guint16 GetGroup(void) { return group;}; guint16 GetElement(void){return element;}; @@ -106,12 +94,13 @@ public: string GetKey(void) {return key;}; }; -typedef map TagHT; - +//////////////////////////////////////////////////////////////////////////// // A single DICOM dictionary i.e. a container for a collection of dictionary // entries. There should be a single public dictionary (THE dictionary of // the actual DICOM v3) but as many shadow dictionaries as imagers // combined with all software versions... +typedef map TagHT; + class GDCM_EXPORT gdcmDict { string name; string filename; @@ -123,12 +112,14 @@ public: void Print(ostream&); }; +//////////////////////////////////////////////////////////////////////////// // Container for managing a set of loaded dictionaries. Sharing dictionaries // should avoid : -// * reloading an allready loaded dictionary. +// * reloading an allready loaded dictionary, // * having many in memory representations of the same dictionary. typedef string DictKey; typedef map DictSetHT; + class GDCM_EXPORT gdcmDictSet { private: string DictPath; // Directory path to dictionaries @@ -139,9 +130,9 @@ private: public: gdcmDictSet(void); // loads THE DICOM v3 dictionary // TODO Swig int LoadDictFromFile(string filename); -///// QUESTION: the following function might not be thread safe !? Maybe -///// we need some mutex here, to avoid concurent creation of -///// the same dictionary !?!?! + // QUESTION: the following function might not be thread safe !? Maybe + // we need some mutex here, to avoid concurent creation of + // the same dictionary !?!?! // TODO Swig int LoadDictFromName(string filename); // TODO Swig int LoadAllDictFromDirectory(string DirectoryName); // TODO Swig string* GetAllDictNames(); @@ -151,6 +142,7 @@ public: gdcmDict* GetDefaultPublicDict(void); }; +//////////////////////////////////////////////////////////////////////////// // The dicom header of a Dicom file contains a set of such ELement VALUES // (when successfuly parsed against a given Dicom dictionary) class GDCM_EXPORT ElValue { @@ -186,66 +178,68 @@ public: string GetName(void) { return entry->GetName();}; }; -typedef map TagElValueHT; -typedef map TagElValueNameHT; +//////////////////////////////////////////////////////////////////////////// // Container for a set of succefully parsed ElValues. +typedef map TagElValueHT; + typedef map TagElValueNameHT; + class GDCM_EXPORT ElValSet { - // We need both accesses with a TagKey and the Dictentry.Name + // We need both accesses with a TagKey and the Dictentry.Name TagElValueHT tagHt; TagElValueNameHT NameHt; public: void Add(ElValue*); void Print(ostream &); void PrintByName(ostream &); - ElValue* GetElement(guint32 group, guint32 element); - string GetElValue(guint32 group, guint32 element); - string GetElValue(string); + ElValue* GetElementByNumber(guint32 group, guint32 element); + ElValue* GetElementByName(string); + string GetElValueByNumber(guint32 group, guint32 element); + string GetElValueByName(string); TagElValueHT & GetTagHt(void); }; -// The various entries of the explicit value representation (VR) shall -// be managed within a dictionary. -typedef string VRKey; -typedef string VRAtr; -typedef map VRHT; // Value Representation Hash Table - -// The typical usage of objects of this class is to classify a set of +//////////////////////////////////////////////////////////////////////////// +// The typical usage of instances of class gdcmHeader is to classify a set of // dicom files according to header information e.g. to create a file hierachy // reflecting the Patient/Study/Serie informations, or extracting a given // SerieId. Accesing the content (image[s] or volume[s]) is beyond the -// functionality of this class (see dmcFile below). +// functionality of this class and belong to gdmcFile (see below). // Notes: +// * the various entries of the explicit value representation (VR) shall +// be managed within a dictionary which is shared by all gdcmHeader instances // * the gdcmHeader::Set*Tag* family members cannot be defined as protected // (Swig limitations for as Has_a dependency between gdcmFile and gdcmHeader) + +typedef string VRKey; +typedef string VRAtr; +typedef map VRHT; // Value Representation Hash Table + class GDCM_EXPORT gdcmHeader { -//FIXME sw should be qn EndianType !!! - //enum EndianType { - //LittleEndian, - //BadLittleEndian, - //BigEndian, - //BadBigEndian}; void SkipBytes(guint32); private: - // All instances share the same Value Representation dictionary static VRHT *dicom_vr; // Dictionaries of data elements: - static gdcmDictSet* Dicts; // Global dictionary container - gdcmDict* RefPubDict; // Public Dictionary - gdcmDict* RefShaDict; // Shadow Dictionary (optional) + static gdcmDictSet* Dicts; // global dictionary container + gdcmDict* RefPubDict; // public dictionary + gdcmDict* RefShaDict; // shadow dictionary (optional) // Parsed element values: ElValSet PubElVals; // parsed with Public Dictionary ElValSet ShaElVals; // parsed with Shadow Dictionary - // In order to inspect/navigate through the file - string filename; + string filename; // refering underlying file FILE * fp; - // The tag Image Location ((0028,0200) containing the adress of + // The tag Image Location ((0028,0200) containing the address of // the pixels) is not allways present. When we store this information // FIXME // outside of the elements: guint16 grPixel; guint16 numPixel; // Swap code (little, big, big-bad endian): this code is not fixed - // during parsing. + // during parsing.FIXME sw should be an enum e.g. + //enum EndianType { + //LittleEndian, + //BadLittleEndian, + //BigEndian, + //BadBigEndian}; int sw; // Only the elements whose size are below this bound shall be loaded. // By default, this upper bound is limited to 1024 (which looks reasonable @@ -280,13 +274,10 @@ protected: ExplicitVR, ImplicitVR, ACR, - ACR_LIBIDO}; + ACR_LIBIDO}; // CLEANME FileType filetype; -///// QUESTION: Maybe Print is a better name than write !? int write(ostream&); -///// QUESTION: Maybe anonymize should be a friend function !?!? -///// See below for an example of how anonymize might be implemented. - int anonymize(ostream&); + int anonymize(ostream&); // FIXME : anonymize should be a friend ? public: void LoadElements(void); virtual void ParseHeader(void); @@ -299,35 +290,36 @@ public: // TODO Swig int SetShaDict(string filename); // Retrieve all potentially available tag [tag = (group, element)] names - // from the standard (or public) dictionary (hence static). Typical usage: - // enable the user of a GUI based interface to select his favorite fields - // for sorting or selection. + // from the standard (or public) dictionary. Typical usage: enable the + // user of a GUI based interface to select his favorite fields for sorting + // or selection. // TODO Swig string* GetPubTagNames(); // Get the element values themselves: string GetPubElValByName(string TagName); string GetPubElValByNumber(guint16 group, guint16 element); - // Get the element value representation: (VR) might be needed by caller + // Getting the element value representation (VR) might be needed by caller // to convert the string typed content to caller's native type (think // of C/C++ vs Python). - // TODO Swig string GetPubElValRepByName(string TagName); - // TODO Swig string GetPubElValRepByNumber(guint16 group, guint16 element); + string GetPubElValRepByName(string TagName); + string GetPubElValRepByNumber(guint16 group, guint16 element); TagElValueHT & GetPubElVal(void) { return PubElVals.GetTagHt(); }; void PrintPubElVal(ostream & os = cout); void PrintPubDict(ostream &); // Same thing with the shadow : // TODO Swig string* GetShaTagNames(); - // TODO Swig string GetShaElValByName(string TagName); - // TODO Swig string GetShaElValByNumber(guint16 group, guint16 element); - // TODO Swig string GetShaElValRepByName(string TagName); - // TODO Swig string GetShaElValRepByNumber(guint16 group, guint16 element); + string GetShaElValByName(string TagName); + string GetShaElValByNumber(guint16 group, guint16 element); + string GetShaElValRepByName(string TagName); + string GetShaElValRepByNumber(guint16 group, guint16 element); - // Wrappers of the above (both public and shadow) to avoid bugging the - // caller with knowing if ElVal is from the public or shadow dictionary. - // TODO Swig string GetElValByName(string TagName); - // TODO Swig string GetElValByNumber(guint16 group, guint16 element); - // TODO Swig string GetElValRepByName(string TagName); - // TODO Swig string GetElValRepByNumber(guint16 group, guint16 element); + // Wrappers of the above (public is privileged over shadow) to avoid + // bugging the caller with knowing if ElVal is from the public or shadow + // dictionary. + string GetElValByName(string TagName); + string GetElValByNumber(guint16 group, guint16 element); + string GetElValRepByName(string TagName); + string GetElValRepByNumber(guint16 group, guint16 element); // TODO Swig int SetPubElValByName(string content, string TagName); // TODO Swig int SetPubElValByNumber(string content, guint16 group, guint16 element); @@ -337,6 +329,7 @@ public: // TODO Swig int GetSwapCode(); }; +//////////////////////////////////////////////////////////////////////////// // In addition to Dicom header exploration, this class is designed // for accessing the image/volume content. One can also use it to // write Dicom files. @@ -347,8 +340,8 @@ class GDCM_EXPORT gdcmFile: gdcmHeader { private: void* Data; - int Parsed; // weather allready parsed - string OrigFileName; // To avoid file overwrite + int Parsed; // weather allready parsed + string OrigFileName; // To avoid file overwrite public: // Constructor dedicated to writing a new DICOMV3 part10 compliant // file (see SetFileName, SetDcmTag and Write) @@ -388,23 +381,3 @@ public: //class gdcmSerie : gdcmFile; //class gdcmMultiFrame : gdcmFile; - -// -//Examples: -// * gdcmFile WriteDicom; -// WriteDicom.SetFileName("MyDicomFile.dcm"); -// string * AllTags = gdcmHeader.GetDcmTagNames(); -// WriteDicom.SetDcmTag(AllTags[5], "253"); -// WriteDicom.SetDcmTag("Patient Name", "bozo"); -// WriteDicom.SetDcmTag("Patient Name", "bozo"); -// WriteDicom.SetImageData(Image); -// WriteDicom.Write(); -// -// -// Anonymize(ostream& output) { -// a = gdcmFile("toto1"); -// a.SetPubValueByName("Patient Name", ""); -// a.SetPubValueByName("Date", ""); -// a.SetPubValueByName("Study Date", ""); -// a.write(output); -// } diff --git a/src/gdcmElValSet.cxx b/src/gdcmElValSet.cxx index 2b5656fe..b74b475e 100644 --- a/src/gdcmElValSet.cxx +++ b/src/gdcmElValSet.cxx @@ -32,29 +32,38 @@ void ElValSet::PrintByName(ostream & os) { } } -ElValue* ElValSet::GetElement(guint32 group, guint32 element) { +ElValue* ElValSet::GetElementByNumber(guint32 group, guint32 element) { TagKey key = gdcmDictEntry::TranslateToKey(group, element); if ( ! tagHt.count(key)) return (ElValue*)0; if (tagHt.count(key) > 1) - dbg.Verbose(0, "ElValSet::GetElValue", + dbg.Verbose(0, "ElValSet::GetElementByNumber", "multiple entries for this key (FIXME) !"); return tagHt.find(key)->second; } -string ElValSet::GetElValue(guint32 group, guint32 element) { +ElValue* ElValSet::GetElementByName(string TagName) { + if ( ! NameHt.count(TagName)) + return (ElValue*)0; + if (NameHt.count(TagName) > 1) + dbg.Verbose(0, "ElValSet::GetElement", + "multipe entries for this key (FIXME) !"); + return NameHt.find(TagName)->second; +} + +string ElValSet::GetElValueByNumber(guint32 group, guint32 element) { TagKey key = gdcmDictEntry::TranslateToKey(group, element); if ( ! tagHt.count(key)) - return "UNFOUND"; + return "gdcm::Unfound"; if (tagHt.count(key) > 1) - dbg.Verbose(0, "ElValSet::GetElValue", + dbg.Verbose(0, "ElValSet::GetElValueByNumber", "multiple entries for this key (FIXME) !"); return tagHt.find(key)->second->GetValue(); } -string ElValSet::GetElValue(string TagName) { +string ElValSet::GetElValueByName(string TagName) { if ( ! NameHt.count(TagName)) - return "UNFOUND"; + return "gdcm::Unfound"; if (NameHt.count(TagName) > 1) dbg.Verbose(0, "ElValSet::GetElValue", "multipe entries for this key (FIXME) !"); diff --git a/src/gdcmHeader.cxx b/src/gdcmHeader.cxx index d3e99c20..4d08f021 100644 --- a/src/gdcmHeader.cxx +++ b/src/gdcmHeader.cxx @@ -88,24 +88,15 @@ void gdcmHeader::InitVRDict (void) { /** * \ingroup gdcmHeader - * \brief La seule maniere sure que l'on aie pour determiner - * si on est en LITTLE_ENDIAN, BIG-ENDIAN, - * BAD-LITTLE-ENDIAN, BAD-BIG-ENDIAN - * est de trouver l'element qui donne la longueur d'un 'GROUP' - * (on sait que la longueur de cet element vaut 0x00000004) - * et de regarder comment cette longueur est codee en memoire - * - * Le probleme vient de ce que parfois, il n'y en a pas ... - * - * On fait alors le pari qu'on a a faire a du LITTLE_ENDIAN propre. - * (Ce qui est la norme -pas respectee- depuis ACR-NEMA) - * Si ce n'est pas le cas, on ne peut rien faire. - * - * (il faudrait avoir des fonctions auxquelles - * on passe le code Swap en parametre, pour faire des essais 'manuels') + * \brief Discover what the swap code is (among little endian, big endian, + * bad little endian, bad big endian). */ void gdcmHeader::CheckSwap() { + // The only guaranted way of finding the swap code is to find a + // group tag since we know it's length has to be of four bytes i.e. + // 0x00000004. Finding the swap code in then straigthforward. Trouble + // occurs when we can't find such group... guint32 s; guint32 x=4; // x : pour ntohs bool net2host; // true when HostByteOrder is the same as NetworkByteOrder @@ -216,8 +207,6 @@ void gdcmHeader::CheckSwap() // It is time for despaired wild guesses. So, let's assume this file // happens to be 'dirty' ACR/NEMA, i.e. the length of the group is // not present. Then the only info we have is the net2host one. - //FIXME Si c'est du RAW, ca degagera + tard - if (! net2host ) sw = 0; else @@ -246,34 +235,7 @@ void gdcmHeader::SwitchSwapToBigEndian(void) { /** * \ingroup gdcmHeader - * \brief recupere la longueur d'un champ DICOM. - * Preconditions: - * 1/ le fichier doit deja avoir ete ouvert, - * 2/ CheckSwap() doit avoir ete appele - * 3/ la partie 'group' ainsi que la partie 'elem' - * de l'acr_element doivent avoir ete lues. - * - * ACR-NEMA : we allways get - * GroupNumber (2 Octets) - * ElementNumber (2 Octets) - * ElementSize (4 Octets) - * DICOM en implicit Value Representation : - * GroupNumber (2 Octets) - * ElementNumber (2 Octets) - * ElementSize (4 Octets) - * - * DICOM en explicit Value Representation : - * GroupNumber (2 Octets) - * ElementNumber (2 Octets) - * ValueRepresentation (2 Octets) - * ElementSize (2 Octets) - * - * ATTENTION : dans le cas ou ValueRepresentation = OB, OW, SQ, UN - * GroupNumber (2 Octets) - * ElementNumber (2 Octets) - * ValueRepresentation (2 Octets) - * zone reservee (2 Octets) - * ElementSize (4 Octets) + * \brief Find the value representation of the current tag. * * @param sw code swap * @param skippedLength pointeur sur nombre d'octets que l'on a saute qd @@ -367,7 +329,7 @@ void gdcmHeader::FindVR( ElValue *ElVal) { * @return True when big endian found. False in all other cases. */ bool gdcmHeader::IsBigEndianTransferSyntax(void) { - ElValue* Element = PubElVals.GetElement(0x0002, 0x0010); + ElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010); if ( !Element ) return false; LoadElementValueSafe(Element); @@ -646,7 +608,7 @@ void gdcmHeader::LoadElementValue(ElValue * ElVal) { } // FIXME The exact size should be length if we move to strings or whatever - char* NewValue = (char*)g_malloc(length+1); + char* NewValue = (char*)malloc(length+1); if( !NewValue) { dbg.Verbose(1, "LoadElementValue: Failed to allocate NewValue"); return; @@ -655,7 +617,7 @@ void gdcmHeader::LoadElementValue(ElValue * ElVal) { item_read = fread(NewValue, (size_t)length, (size_t)1, fp); if ( item_read != 1 ) { - g_free(NewValue); + free(NewValue); Error::FileReadError(fp, "gdcmHeader::LoadElementValue"); ElVal->SetValue("gdcm::UnRead"); return; @@ -796,7 +758,7 @@ size_t gdcmHeader::GetPixelOffset(void) { guint16 numPixel; string ImageLocation = GetPubElValByName("Image Location"); if ( ImageLocation == "UNFOUND" ) { - grPixel = 0x7FE0; + grPixel = 0x7fe0; } else { grPixel = (guint16) atoi( ImageLocation.c_str() ); } @@ -806,7 +768,7 @@ size_t gdcmHeader::GetPixelOffset(void) { numPixel = 0x1010; else numPixel = 0x0010; - ElValue* PixelElement = PubElVals.GetElement(grPixel, numPixel); + ElValue* PixelElement = PubElVals.GetElementByNumber(grPixel, numPixel); if (PixelElement) return PixelElement->GetOffset(); else @@ -833,11 +795,76 @@ gdcmDictEntry * gdcmHeader::IsInDicts(guint32 group, guint32 element) { } string gdcmHeader::GetPubElValByNumber(guint16 group, guint16 element) { - return PubElVals.GetElValue(group, element); + return PubElVals.GetElValueByNumber(group, element); +} + +string gdcmHeader::GetPubElValRepByNumber(guint16 group, guint16 element) { + ElValue* elem = PubElVals.GetElementByNumber(group, element); + if ( !elem ) + return "gdcm::Unfound"; + return elem->GetVR(); } string gdcmHeader::GetPubElValByName(string TagName) { - return PubElVals.GetElValue(TagName); + return PubElVals.GetElValueByName(TagName); +} + +string gdcmHeader::GetPubElValRepByName(string TagName) { + ElValue* elem = PubElVals.GetElementByName(TagName); + if ( !elem ) + return "gdcm::Unfound"; + return elem->GetVR(); +} + +string gdcmHeader::GetShaElValByNumber(guint16 group, guint16 element) { + return ShaElVals.GetElValueByNumber(group, element); +} + +string gdcmHeader::GetShaElValRepByNumber(guint16 group, guint16 element) { + ElValue* elem = ShaElVals.GetElementByNumber(group, element); + if ( !elem ) + return "gdcm::Unfound"; + return elem->GetVR(); +} + +string gdcmHeader::GetShaElValByName(string TagName) { + return ShaElVals.GetElValueByName(TagName); +} + +string gdcmHeader::GetShaElValRepByName(string TagName) { + ElValue* elem = ShaElVals.GetElementByName(TagName); + if ( !elem ) + return "gdcm::Unfound"; + return elem->GetVR(); +} + + +string gdcmHeader::GetElValByNumber(guint16 group, guint16 element) { + string pub = GetPubElValByNumber(group, element); + if (pub.length()) + return pub; + return GetShaElValByNumber(group, element); +} + +string gdcmHeader::GetElValRepByNumber(guint16 group, guint16 element) { + string pub = GetPubElValRepByNumber(group, element); + if (pub.length()) + return pub; + return GetShaElValRepByNumber(group, element); +} + +string gdcmHeader::GetElValByName(string TagName) { + string pub = GetPubElValByName(TagName); + if (pub.length()) + return pub; + return GetShaElValByName(TagName); +} + +string gdcmHeader::GetElValRepByName(string TagName) { + string pub = GetPubElValRepByName(TagName); + if (pub.length()) + return pub; + return GetShaElValRepByName(TagName); } /** -- 2.48.1