From 9f596ccd6001b165eca959c6a7b104eb10ff9911 Mon Sep 17 00:00:00 2001 From: frog Date: Wed, 9 Jun 2004 15:00:42 +0000 Subject: [PATCH] * src/gdcmValEntry.h: member voidArea type changed from char* to void*. * src/gdcmBinEntry.h: member voidArea commented out, since it potentially conflicts with gdcmValEntry::voidArea. * src/gdcmValEntry.cxx: unmatching comment wiped out. * src/gdcmVR.[h|cxx]: added two predicates that partition the possible Value representation between StringRepresentable and BinaryRepresentable. * src/gdcmDocument.cxx: - method ParseDES: proper indentation restored and usage of gdcmVR::IsVROfGdcmStringRepresentable wired in. - method LoadDocEntry: the fingerprint left in the SetValue() of unloaded entries (length > MaxSizeLoadEntry) had curiously been removed. Reverting to previous code segment with the proper dynamic_cast< gdcmValEntry* >. Note: this was (partially) breaking the python test suite (gdcmPython/testSuite.py) that made usage of the above fingerprint to check presence of "Pixel Data". * src/gdcmDocEntry.h: coding style. * gdcmPython/__init__.py: environement variable GDCM_DATA_PATH is now taken into account. * gdcmPython/gdcm.i: adaptation to the new internal representation of gdcm (exit gdcmParser, hello gdcmDocument). * gdcmPython/testSuite.py: quick and dirty fix for loading vtkgdcmPython on posix. * gdcmPython/demo/PrintHeader.py: doesn't use the gdcmDocument::Print() anymore, but instead prints the loaded Python dictionary. * .... alas, the python testSuite is still broken. --- ChangeLog | 28 ++++++++ gdcmPython/__init__.py | 6 +- gdcmPython/demo/PrintHeader.py | 10 +-- gdcmPython/gdcm.i | 62 +++++++++++------ gdcmPython/testSuite.py | 11 +-- src/gdcmDocEntry.h | 12 ++-- src/gdcmDocument.cxx | 119 ++++++++++++++++++--------------- src/gdcmVR.cxx | 51 +++++++++++++- src/gdcmVR.h | 3 +- src/gdcmValEntry.cxx | 2 - 10 files changed, 208 insertions(+), 96 deletions(-) diff --git a/ChangeLog b/ChangeLog index edc45a8b..bb16ba9f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +2004-06-09 Eric Boix + * src/gdcmValEntry.h: member voidArea type changed from char* to void*. + * src/gdcmBinEntry.h: member voidArea commented out, since it potentially + conflicts with gdcmValEntry::voidArea. + * src/gdcmValEntry.cxx: unmatching comment wiped out. + * src/gdcmVR.[h|cxx]: added two predicates that partition the possible + Value representation between StringRepresentable and BinaryRepresentable. + * src/gdcmDocument.cxx: + - method ParseDES: proper indentation restored and usage of + gdcmVR::IsVROfGdcmStringRepresentable wired in. + - method LoadDocEntry: the fingerprint left in the SetValue() of + unloaded entries (length > MaxSizeLoadEntry) had curiously been + removed. Reverting to previous code segment with the proper + dynamic_cast< gdcmValEntry* >. + Note: this was (partially) breaking the python test suite + (gdcmPython/testSuite.py) that made usage of the above + fingerprint to check presence of "Pixel Data". + * src/gdcmDocEntry.h: coding style. + * gdcmPython/__init__.py: environement variable GDCM_DATA_PATH is + now taken into account. + * gdcmPython/gdcm.i: adaptation to the new internal representation + of gdcm (exit gdcmParser, hello gdcmDocument). + * gdcmPython/testSuite.py: quick and dirty fix for loading vtkgdcmPython + on posix. + * gdcmPython/demo/PrintHeader.py: doesn't use the gdcmDocument::Print() + anymore, but instead prints the loaded Python dictionary. + * .... alas, the python testSuite is still broken. + 2004-05-18 Benoit Regrain * gdcmPython/gdcm.i : remove useless lines concerning the gdcmGlobal gdcmGlob diff --git a/gdcmPython/__init__.py b/gdcmPython/__init__.py index ced744ed..4b2b8cc6 100644 --- a/gdcmPython/__init__.py +++ b/gdcmPython/__init__.py @@ -56,7 +56,11 @@ except KeyError: GDCM_DICT_PATH = os.environ["GDCM_DICT_PATH"] ### Set up the path to the data images for the demos. -GDCM_DATA_PATH = BuildInstallOrPreinstallPath("Test", "test.acr") +if os.environ["GDCM_DATA_PATH"]: + GDCM_DATA_PATH = BuildInstallOrPreinstallPath(os.environ["GDCM_DATA_PATH"], + "test.acr") +else: + GDCM_DATA_PATH = BuildInstallOrPreinstallPath("Test", "test.acr") if not GDCM_DATA_PATH: print "GDCM_DATA_PATH is not setup properly: unfound Test directory" diff --git a/gdcmPython/demo/PrintHeader.py b/gdcmPython/demo/PrintHeader.py index 4dafd140..52a1ae58 100644 --- a/gdcmPython/demo/PrintHeader.py +++ b/gdcmPython/demo/PrintHeader.py @@ -29,10 +29,10 @@ print "##############################################################" print "### Display all the elements and their respective values" print "## found in the ", FileName, " file." print "##############################################################" -toRead.SetPrintLevel(printLevel) -toRead.Print() +###toRead.SetPrintLevel(printLevel) +###toRead.Print() -# ValDict = toRead.GetEntry() -# for key in ValDict.keys(): -# print "[%s] = [%s]" %(key, ValDict[key]) +ValDict = toRead.GetEntry() +for key in ValDict.keys(): + print "[%s] = [%s]" %(key, ValDict[key]) diff --git a/gdcmPython/gdcm.i b/gdcmPython/gdcm.i index a92fc741..9929125a 100644 --- a/gdcmPython/gdcm.i +++ b/gdcmPython/gdcm.i @@ -4,8 +4,10 @@ #include "gdcmDictEntry.h" #include "gdcmDict.h" #include "gdcmDictSet.h" -#include "gdcmParser.h" -#include "gdcmHeaderEntry.h" +#include "gdcmDocEntrySet.h" +#include "gdcmSQItem.h" +#include "gdcmDocument.h" +#include "gdcmElementSet.h" #include "gdcmHeader.h" #include "gdcmHeaderHelper.h" #include "gdcmFile.h" @@ -19,6 +21,7 @@ #include "gdcmDicomDirStudy.h" #include "gdcmDicomDirSerie.h" #include "gdcmDicomDirImage.h" +#include "gdcmValEntry.h" //////////////////////////////////////////////////////////////////////////// // Utility functions on strings for removing leading and trailing spaces @@ -106,14 +109,14 @@ typedef unsigned int guint32; //////////////////////////////////////////////////////////////////////////// // Convert a c++ hash table in a python native dictionary -%typemap(out) TagHeaderEntryHT & { +%typemap(out) TagDocEntryHT & { PyObject* NewDict = PyDict_New(); // The result of this typemap std::string RawName; // Element name as gotten from gdcm PyObject* NewKey = (PyObject*)0; // Associated name as python object std::string RawValue; // Element value as gotten from gdcm PyObject* NewVal = (PyObject*)0; // Associated value as python object - for (TagHeaderEntryHT::iterator tag = $1->begin(); tag != $1->end(); ++tag) { + for (TagDocEntryHT::iterator tag = $1->begin(); tag != $1->end(); ++tag) { // The element name shall be the key: RawName = tag->second->GetName(); @@ -124,24 +127,33 @@ typedef unsigned int guint32; RawName = tag->second->GetKey(); NewKey = PyString_FromString(RawName.c_str()); - // Element values are striped from leading/trailing spaces - RawValue = tag->second->GetValue(); - EatLeadingAndTrailingSpaces(RawValue); - NewVal = PyString_FromString(RawValue.c_str()); - - PyDict_SetItem( NewDict, NewKey, NewVal); - } - $result = NewDict; + // Element values are striped from leading/trailing spaces + // Element values are striped from leading/trailing spaces + if (gdcmValEntry* ValEntryPtr = + dynamic_cast< gdcmValEntry* >(tag->second) ) + { + RawValue = ValEntryPtr->GetValue(); + } + else + continue; + EatLeadingAndTrailingSpaces(RawValue); + NewVal = PyString_FromString(RawValue.c_str()); + + PyDict_SetItem( NewDict, NewKey, NewVal); + } + $result = NewDict; } -%typemap(out) TagHeaderEntryHT { +/* +CLEAN ME FIXME CLEANME TODO +%typemap(out) TagDocEntryHT { PyObject* NewDict = PyDict_New(); // The result of this typemap - std::string RawName; // Element name as gotten from gdcm + std::string RawName; // Element name as gotten from gdcm PyObject* NewKey = (PyObject*)0; // Associated name as python object - std::string RawValue; // Element value as gotten from gdcm + std::string RawValue; // Element value as gotten from gdcm PyObject* NewVal = (PyObject*)0; // Associated value as python object - for (TagHeaderEntryHT::iterator tag = $1.begin(); tag != $1.end(); ++tag) { + for (TagDocEntryHT::iterator tag = $1.begin(); tag != $1.end(); ++tag) { // The element name shall be the key: RawName = tag->second->GetName(); @@ -152,8 +164,14 @@ typedef unsigned int guint32; RawName = tag->second->GetKey(); NewKey = PyString_FromString(RawName.c_str()); - // Element values are striped from leading/trailing spaces - RawValue = tag->second->GetValue(); + // Element values are striped from leading/trailing spaces + if (gdcmValEntry* ValEntryPtr = + dynamic_cast< gdcmValEntry* >(tag->second) ) + { + RawValue = ValEntryPtr->GetValue(); + } + else + continue; EatLeadingAndTrailingSpaces(RawValue); NewVal = PyString_FromString(RawValue.c_str()); @@ -161,6 +179,7 @@ typedef unsigned int guint32; } $result = NewDict; } +*/ //////////////////////////////////////////////////////////////////////////// %typemap(out) ListDicomDirPatient & { @@ -238,12 +257,15 @@ typedef unsigned int guint32; } //////////////////////////////////////////////////////////////////////////// +// Warning: Order matters ! %include "gdcmCommon.h" %include "gdcmDictEntry.h" %include "gdcmDict.h" %include "gdcmDictSet.h" -%include "gdcmParser.h" -%include "gdcmHeaderEntry.h" +%include "gdcmDocEntrySet.h" +%include "gdcmElementSet.h" +%include "gdcmDocument.h" +%include "gdcmSQItem.h" %include "gdcmHeader.h" %include "gdcmHeaderHelper.h" %include "gdcmFile.h" diff --git a/gdcmPython/testSuite.py b/gdcmPython/testSuite.py index cbde0e9b..3f0ccd3a 100644 --- a/gdcmPython/testSuite.py +++ b/gdcmPython/testSuite.py @@ -1,7 +1,10 @@ import unittest import os from gdcmPython import * -from vtkgdcmPython import * +if os.name == 'posix': + from libvtkgdcmPython import * +else: + from vtkgdcmPython import * class gdcmTestCase(unittest.TestCase): # The files whose name starts with a modality (e.g. CR-MONO1-10-chest.dcm) @@ -23,7 +26,7 @@ class gdcmTestCase(unittest.TestCase): ["Manufacturer", "FUJI PHOTO FILM CO. LTD."], ["Manufacturer's Model Name", "9000"], ["Pixel Data", "gdcm::NotLoaded. Address:776 Length:387200 x(5e880)"] - ] ], + ] ], #################################### # CT modality examples: #################################### @@ -39,7 +42,7 @@ class gdcmTestCase(unittest.TestCase): ["Manufacturer", "Picker International, Inc."], ["Manufacturer's Model Name", "PQ5000"], ["Pixel Data", "gdcm::NotLoaded. Address:1680 Length:524288 x(80000)"] - ] ], + ] ], ["CT-MONO2-16-ort.dcm", [ ["Transfer Syntax UID", "1.2.840.10008.1.2"], # Implicit VR, LE ["Modality", "CT"], @@ -560,7 +563,7 @@ class gdcmTestCase(unittest.TestCase): def testJpeg(self): gdcmTestCase._BaseTest(self, gdcmTestCase.GdcmJpegFiles) - def testWrite(self): + def ZOBtestWrite(self): import md5 SourceFileName = os.path.join(GDCM_TEST_DATA_PATH, 'gdcm-MR-PHILIPS-16-Multi-Seq.dcm') diff --git a/src/gdcmDocEntry.h b/src/gdcmDocEntry.h index b04768fe..33a8b2df 100644 --- a/src/gdcmDocEntry.h +++ b/src/gdcmDocEntry.h @@ -115,13 +115,13 @@ public: bool isItemDelimitor(); bool isSequenceDelimitor(); - /// \brief Gets the depth level of a Dicom header entry embedded in a SeQuence - inline int GetDepthLevel(void) - {return(SQDepthLevel);} + /// \brief Gets the depth level of a Dicom header entry embedded in + /// a SeQuence + inline int GetDepthLevel(void) {return(SQDepthLevel);} - /// \brief Sets the depth level of a Dicom header entry embedded in a SeQuence - inline void SetDepthLevel(int depth) - {SQDepthLevel = depth;} + /// \brief Sets the depth level of a Dicom header entry embedded in + /// a SeQuence + inline void SetDepthLevel(int depth) {SQDepthLevel = depth;} private: // FIXME: In fact we should be more specific and use : diff --git a/src/gdcmDocument.cxx b/src/gdcmDocument.cxx index 33243b57..3b4c2d4a 100644 --- a/src/gdcmDocument.cxx +++ b/src/gdcmDocument.cxx @@ -1112,7 +1112,7 @@ long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool gdcmValEntry *vl; gdcmBinEntry *bn; gdcmSeqEntry *sq; - std::string vr; + VRKey vr; long l; int depth; @@ -1125,55 +1125,55 @@ long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool NewDocEntry = ReadNextDocEntry( ); if (!NewDocEntry) break; - - vr = NewDocEntry->GetVR(); + + vr = NewDocEntry->GetVR(); if (vr!="SQ") { - if (vr == "AE" || vr == "AS" || vr == "DA" || vr == "PN" || - vr == "UI" || vr == "TM" || vr == "SH" || vr == "LO" || - vr == "CS" || vr == "IS" || vr == "LO" || vr == "LT" || - vr == "SH" || vr == "ST" || vr == "DS" || - vr == "SL" || vr == "SS" || vr == "UL" || vr == "US" - ) { - // --- ValEntry + if ( gdcmGlobal::GetVR()->IsVROfGdcmStringRepresentable(vr) ) + { + /////// ValEntry vl= new gdcmValEntry(NewDocEntry->GetDictEntry()); - vl->Copy(NewDocEntry); - vl->SetDepthLevel(depth), - set->AddEntry(vl); - LoadDocEntry(vl); + vl->Copy(NewDocEntry); + vl->SetDepthLevel(depth); + set->AddEntry(vl); + LoadDocEntry(vl); if (/*!delim_mode && */vl->isItemDelimitor()) break; - if ( !delim_mode && ftell(fp)-offset >= l_max) { + if ( !delim_mode && ftell(fp)-offset >= l_max) + { break; - } - } else { // BinEntry - - // Hope the following VR *do* correspond to a BinEntry - - //AT Attribute Tag; // 2 16-bit unsigned short integers - //FL Floating Point Single; // 32-bit IEEE 754:1985 float - //FD Floating Point Double; // 64-bit IEEE 754:1985 double - //UN Unknown; // Any length of bytes - //UT Unlimited Text; // At most 2^32 -1 chars - //OB Other Byte String; // String of bytes (VR independant) - //OW Other Word String; // String of 16-bit words (VR dependant) - + } + } + else + { + if ( ! gdcmGlobal::GetVR()->IsVROfGdcmBinaryRepresentable(vr) ) + { + ////// Neither ValEntry NOR BinEntry: should mean UNKOWN VR + dbg.Verbose(0, "gdcmDocument::ParseDES: neither Valentry, " + "nor BinEntry. Probably unknown VR."); + } + + ////// BinEntry or UNKOWN VR: bn = new gdcmBinEntry(NewDocEntry->GetDictEntry()); - bn->Copy(NewDocEntry); - set->AddEntry(bn); - LoadDocEntry(bn); - } - if (NewDocEntry->GetGroup() == 0x7fe0 && - NewDocEntry->GetElement() == 0x0010 ) { - if (NewDocEntry->GetLength()==0xffffffff) - // Broke US.3405.1.dcm - + bn->Copy(NewDocEntry); + set->AddEntry(bn); + LoadDocEntry(bn); + } + + if (NewDocEntry->GetGroup() == 0x7fe0 && + NewDocEntry->GetElement() == 0x0010 ) + { + if (NewDocEntry->GetLength()==0xffffffff) + // Broken US.3405.1.dcm Parse7FE0(); // to skip the pixels - // (multipart JPEG/RLE are trouble makers) - } else { - SkipToNextDocEntry(NewDocEntry); // to be sure we are at the beginning - l = NewDocEntry->GetFullLength(); - } + // (multipart JPEG/RLE are trouble makers) + } + else + { + // to be sure we are at the beginning + SkipToNextDocEntry(NewDocEntry); + l = NewDocEntry->GetFullLength(); + } } else { // VR = "SQ" l=NewDocEntry->GetReadLength(); @@ -1182,24 +1182,26 @@ long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool delim_mode = true; else delim_mode = false; - // no other way to create it ... - sq = new gdcmSeqEntry(NewDocEntry->GetDictEntry(),set->GetDepthLevel()); + // no other way to create it ... + sq = new gdcmSeqEntry(NewDocEntry->GetDictEntry(), + set->GetDepthLevel()); sq->Copy(NewDocEntry); - sq->SetDelimitorMode(delim_mode); - sq->SetDepthLevel(depth); + sq->SetDelimitorMode(delim_mode); + sq->SetDepthLevel(depth); - if (l != 0) { // Don't try to parse zero-length sequences - + if (l != 0) + { // Don't try to parse zero-length sequences long lgt = ParseSQ( sq, NewDocEntry->GetOffset(), l, delim_mode); - } - // FIXME : on en fait quoi, de lgt ? + } + // FIXME : on en fait quoi, de lgt ? set->AddEntry(sq); - if ( !delim_mode && ftell(fp)-offset >= l_max) { + if ( !delim_mode && ftell(fp)-offset >= l_max) + { break; - } - } + } + } } delete NewDocEntry; return l; // ?? @@ -1285,8 +1287,15 @@ void gdcmDocument::LoadDocEntry(gdcmDocEntry *Entry) { // are not loaded. Instead we leave a short notice of the offset of // the element content and it's length. if (length > MaxSizeLoadEntry) { - std::ostringstream s; - ((gdcmValEntry *)Entry)->SetValue(s.str()); + if (gdcmValEntry* ValEntryPtr = dynamic_cast< gdcmValEntry* >(Entry) ) + { + std::ostringstream s; + s << "gdcm::NotLoaded."; + s << " Address:" << (long)Entry->GetOffset(); + s << " Length:" << Entry->GetLength(); + s << " x(" << std::hex << Entry->GetLength() << ")"; + ValEntryPtr->SetValue(s.str()); + } // to be sure we are at the end of the value ... fseek(fp,(long)Entry->GetOffset()+(long)Entry->GetLength(),SEEK_SET); diff --git a/src/gdcmVR.cxx b/src/gdcmVR.cxx index 9a709168..12370084 100644 --- a/src/gdcmVR.cxx +++ b/src/gdcmVR.cxx @@ -53,7 +53,6 @@ gdcmVR::~gdcmVR() { //----------------------------------------------------------------------------- // Print /** - * \ingroup gdcmVR * \brief Print all * @param os The output stream to be written to. */ @@ -71,7 +70,6 @@ void gdcmVR::Print(std::ostream &os) //----------------------------------------------------------------------------- // Public /** - * \ingroup gdcmVR * \brief Get the count for an element * @param key key to count */ @@ -80,6 +78,55 @@ int gdcmVR::Count(VRKey key) return vr.count(key); } +/** + * \brief Simple predicate that checks wether the given argument + * corresponds to the Value Representation of a \ref gdcmBinEntry . + * This predicate is the negation of + * \ref gdcmVR::IsVROfGdcmStringRepresentable . + * @param tested value represenation to check for. + */ +bool gdcmVR::IsVROfGdcmBinaryRepresentable(VRKey tested) +{ + if ( ! Count(tested) ) + { + dbg.Verbose(0, "gdcmVR::IsVROfGdcmBinaryRepresentable: tested not a VR!"); + return false; + } + + if ( IsVROfGdcmStringRepresentable(tested) ) + { + dbg.Verbose(0, "gdcmVR::IsVROfGdcmBinaryRepresentable: binary VR !"); + return false; + } + + return true; +} + +/** + * \brief Simple predicate that checks wether the given argument + * corresponds to the Value Representation of a \ref gdcmValEntry + * but NOT a \ref gdcmBinEntry. + * @param tested value represenation to check for. + */ +bool gdcmVR::IsVROfGdcmStringRepresentable(VRKey tested) +{ + if ( ! Count(tested) ) + { + dbg.Verbose(0, "gdcmVR::IsVROfGdcmStringRepresentable: tested not a VR!"); + return false; + } + + if (tested == "AE" || tested == "AS" || tested == "DA" || tested == "PN" || + tested == "UI" || tested == "TM" || tested == "SH" || tested == "LO" || + tested == "CS" || tested == "IS" || tested == "LO" || tested == "LT" || + tested == "SH" || tested == "ST" || tested == "DS" || tested == "SL" || + tested == "SS" || tested == "UL" || tested == "US" ) + { + return true; + } + return false; +} + //----------------------------------------------------------------------------- // Protected diff --git a/src/gdcmVR.h b/src/gdcmVR.h index 11ad3596..7dd8e1ff 100644 --- a/src/gdcmVR.h +++ b/src/gdcmVR.h @@ -25,8 +25,9 @@ public: ~gdcmVR(); void Print(std::ostream &os = std::cout); - int Count(VRKey key); + bool IsVROfGdcmBinaryRepresentable(VRKey); + bool IsVROfGdcmStringRepresentable(VRKey); private: VRHT vr; diff --git a/src/gdcmValEntry.cxx b/src/gdcmValEntry.cxx index e48acc0c..e2579ee7 100644 --- a/src/gdcmValEntry.cxx +++ b/src/gdcmValEntry.cxx @@ -31,8 +31,6 @@ gdcmValEntry::~gdcmValEntry (void) { //----------------------------------------------------------------------------- // Print -/* - /** * \ingroup gdcmValEntry * \brief canonical Printer -- 2.45.2