From c11dce1faf0053eb984aed57f01e6b7d29cbd1ab Mon Sep 17 00:00:00 2001 From: jpr Date: Mon, 19 Apr 2004 14:48:53 +0000 Subject: [PATCH] 2004-19-02 Jean-Pierre Roux * ADD gdcmData/Wrist.pap (PAPYRUS 3.0 -single frame-) for checking purpose * ENH add parameters : bool exception_on_error = false, bool enable_sequences = false, bool ignore_shadow = false to the gdcmFile constructors to be full gdcmParser compliant * FIX vtk/vtkGdcmReader.cxx now uses enable_sequences = true in gdcmFile to allow reading of PAPYRUS 3.0 files --- ChangeLog | 12 ++++++- Dicts/DicomDir.dic | 31 +++++++++-------- Dicts/dicomV3.dic | 1 + Doc/DoxyfileDeveloppers | 35 ------------------- gdcmVersion.py | 2 +- src/gdcmFile.cxx | 20 ++++++++--- src/gdcmFile.h | 12 +++++-- src/gdcmHeaderEntry.cxx | 17 +++++++++ src/gdcmHeaderEntry.h | 4 ++- src/gdcmParser.cxx | 77 +++++++++++++++++++++++++++++++++++++---- src/gdcmParser.h | 5 ++- vtk/vtkGdcmReader.cxx | 11 +++--- vtk/vtkgdcmViewer.cxx | 2 +- 13 files changed, 157 insertions(+), 72 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8138e2bc..71db94f7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,14 @@ -2004-04-02 Jean-Pierre Roux +2004-19-02 Jean-Pierre Roux + * ADD gdcmData/Wrist.pap (PAPYRUS 3.0 -single frame-) for checking purpose + * ENH add parameters : + bool exception_on_error = false, + bool enable_sequences = false, + bool ignore_shadow = false + to the gdcmFile constructors to be full gdcmParser compliant + * FIX vtk/vtkGdcmReader.cxx now uses enable_sequences = true in gdcmFile + to allow reading of PAPYRUS 3.0 files + +2004-06-02 Jean-Pierre Roux * ADD gdcmData/E00001S03I0015.dcm for SQ checking purpose 2004-04-02 Jean-Pierre Roux diff --git a/Dicts/DicomDir.dic b/Dicts/DicomDir.dic index 5e6b5aaa..99b82899 100644 --- a/Dicts/DicomDir.dic +++ b/Dicts/DicomDir.dic @@ -5,6 +5,7 @@ metaElem 0002 0003 "" // Media Stored SOP Instance UID : metaElem 0002 0010 "1.2.840.10008.1.2.1" // Transfer Syntax UID i.e. : Explicit VR - Little Endian metaElem 0002 0012 "" // Implementation Class UID : may be forged later metaElem 0002 0013 "gdcmLib " // Implementation Version Name don't remove trailing space ! +metaElem 0002 0016 " " // Source Application Entity Title (our ?) metaElem 0004 1130 "" // File-set ID metaElem 0004 1200 "0" // Offset of the first dir of root dir entity : to be computed later metaElem 0004 1202 "0" // Offset of the last dir of root dir entity : to be computed later @@ -12,8 +13,8 @@ metaElem 0004 1212 "0" // File-set consistency flag metaElem 0004 1220 "123456879" // Directory record sequence : *length* to be set later patientElem fffe e000 "0" -patientElem 0004 1400 "0" // Offset of next directory record : to be computed later -patientElem 0004 1410 "65535" // Record in use flag : 65535 ? +patientElem 0004 1400 "0" // Offset of next directory record : = 0x0 : fffe e00d at end ! +patientElem 0004 1410 "65535" // Record in use flag : 65535 = 0xFFFF (see 03_10PU.PDF p 31) patientElem 0004 1420 "0" // Offset of referenced lower-level dir entity : to be computed later patientElem 0004 1430 "PATIENT " // Directory Record Type don't remove trailing space ! patientElem 0008 0005 "ISO_IR 100" // Specific Character Set @@ -24,8 +25,8 @@ patientElem 0010 0040 "" // Patient's Sex patientElem fffe e00d "0" studyElem fffe e000 "0" -studyElem 0004 1400 "0" // Offset of next directory record : to be computed later -studyElem 0004 1410 "65535" // Record in use flag : 65535 ? +studyElem 0004 1400 "0" // Offset of next directory record : = 0x0 : fffe e00d at end ! +studyElem 0004 1410 "65535" // Record in use flag : 65535 = 0xFFFF (see 03_10PU.PDF p 31) studyElem 0004 1420 "0" // Offset of referenced lower-level dir entity : to be computed later studyElem 0004 1430 "STUDY " // Directory Record Type don't remove trailing space ! studyElem 0008 0005 "ISO_IR 100" // Specific Character Set @@ -34,42 +35,42 @@ studyElem 0008 0030 "" // Study Time studyElem 0008 0050 "" // Accession Number studyElem 0008 1030 "" // Study Description studyElem 0020 000d "" // Study Instance UID : may be forged later -studyElem 0020 0010 "" // Study ID : may be forged later +studyElem 0020 0010 "" // Study ID : may be forged later studyElem fffe e00d "0" serieElem fffe e000 "0" -serieElem 0004 1400 "0" // Offset of next directory record : to be computed later -serieElem 0004 1410 "65535" // Record in use flag : 65535 ? +serieElem 0004 1400 "0" // Offset of next directory record : = 0x0 : fffe e00d at end ! +serieElem 0004 1410 "65535" // Record in use flag : 65535 = 0xFFFF (see 03_10PU.PDF p 31) serieElem 0004 1420 "0" // Offset of referenced lower-level dir entity : to be computed later serieElem 0004 1430 "SERIES" // Directory Record Type don't add trailing space ! serieElem 0008 0005 "ISO_IR 100" // Specific Character Set serieElem 0008 0021 "" // Series Date serieElem 0008 0031 "" // Series Time serieElem 0008 0060 "" // Modality -serieElem 0008 0080 "" // Institution Name : may be forged later +serieElem 0008 0080 "" // Institution Name : may be forged later serieElem 0008 0081 "" // Institution Address : may be forged later serieElem 0008 103e "" // Series Description : may be forged later serieElem 0020 000e "" // Series Instance UID : may be forged later -serieElem 0020 0011 "0" // Series Number : may be forged later +serieElem 0020 0011 "0" // Series Number : may be forged later serieElem fffe e00d "0" imageElem fffe e000 "0" -imageElem 0004 1400 "0" // Offset of next directory record : to be computed later -imageElem 0004 1410 "65535" // Record in use flag : 65535 ? +imageElem 0004 1400 "0" // Offset of next directory record : = 0x0 : fffe e00d at end ! +imageElem 0004 1410 "65535" // Record in use flag : 65535 = 0xFFFF (see 03_10PU.PDF p 31) imageElem 0004 1420 "0" // Offset of referenced lower-level dir entity : to be computed later imageElem 0004 1430 "IMAGE " // Directory Record Type don't remove trailing space ! -imageElem 0004 1500 "" // Referenced File ID : to be set later = relative File Name +imageElem 0004 1500 "" // Referenced File ID : will be set later = relative File Name imageElem 0004 1510 "" // Referenced SOP Class UID in File : may be forged later imageElem 0004 1511 "" // Referenced SOP Instance UID in File : may be forged later imageElem 0004 1512 "" // Referenced Transfer Syntax in File imageElem 0008 0005 "ISO_IR 100" // Specific Character Set imageElem 0008 0008 "" // Image Type -imageElem 0008 0016 "" // SOP Class UID : to be set/forged later +imageElem 0008 0016 "" // SOP Class UID : to be set/forged later imageElem 0008 0018 "" // SOP Instance UID : to be set/forged later imageElem 0008 0023 "" // Content Date imageElem 0008 0033 "" // Content Time -imageElem 0008 1040 "" // Referenced Image Sequence : to be set/forged later -imageElem 0008 1150 "" // Referenced SOP Class UID : to be set/forged later +imageElem 0008 1040 "" // Referenced Image Sequence : to be set/forged later +imageElem 0008 1150 "" // Referenced SOP Class UID : to be set/forged later imageElem 0008 1155 "" // Referenced SOP Instance UID : to be set/forged later imageElem 0020 0013 "0" // Image Number imageElem 0020 0032 "1.0\1.0\1.0 " // Image Position Patient diff --git a/Dicts/dicomV3.dic b/Dicts/dicomV3.dic index e70cf25e..be2e1a7d 100644 --- a/Dicts/dicomV3.dic +++ b/Dicts/dicomV3.dic @@ -1153,6 +1153,7 @@ 0040 db0c UI PRC Template Extension Organization UID (RET) 0040 db0d UI PRC Template Extension Creator UID (RET) 0040 db73 UL PRC Referenced Content Item Identifier +0041 1050 SQ ??? Special PAPYRUS 3.0 (?) 0050 0000 UL DEV Group Length 0050 0004 CS DEV Calibration Image 0050 0010 SQ DEV Device Sequence diff --git a/Doc/DoxyfileDeveloppers b/Doc/DoxyfileDeveloppers index 330ae543..b43ef43e 100644 --- a/Doc/DoxyfileDeveloppers +++ b/Doc/DoxyfileDeveloppers @@ -1065,38 +1065,3 @@ DOT_CLEANUP = YES # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO - -# The CGI_NAME tag should be the name of the CGI script that -# starts the search engine (doxysearch) with the correct parameters. -# A script with this name will be generated by doxygen. - -CGI_NAME = search.cgi - -# The CGI_URL tag should be the absolute URL to the directory where the -# cgi binaries are located. See the documentation of your http daemon for -# details. - -CGI_URL = - -# The DOC_URL tag should be the absolute URL to the directory where the -# documentation is located. If left blank the absolute path to the -# documentation, with file:// prepended to it, will be used. - -DOC_URL = - -# The DOC_ABSPATH tag should be the absolute path to the directory where the -# documentation is located. If left blank the directory on the local machine -# will be used. - -DOC_ABSPATH = - -# The BIN_ABSPATH tag must point to the directory where the doxysearch binary -# is installed. - -BIN_ABSPATH = /usr/local/bin/ - -# The EXT_DOC_PATHS tag can be used to specify one or more paths to -# documentation generated for other projects. This allows doxysearch to search -# the documentation for these projects as well. - -EXT_DOC_PATHS = diff --git a/gdcmVersion.py b/gdcmVersion.py index e58269d5..c99e46de 100644 --- a/gdcmVersion.py +++ b/gdcmVersion.py @@ -1,2 +1,2 @@ -gdcmVERSION="0.4" +gdcmVERSION="0.4.1" diff --git a/src/gdcmFile.cxx b/src/gdcmFile.cxx index 4477a95d..7b46a51a 100644 --- a/src/gdcmFile.cxx +++ b/src/gdcmFile.cxx @@ -44,8 +44,14 @@ gdcmFile::gdcmFile(gdcmHeader *header) { * seen as a side effect). * @param filename file to be opened for parsing */ -gdcmFile::gdcmFile(std::string & filename) { - Header=new gdcmHeader(filename.c_str()); +gdcmFile::gdcmFile(std::string & filename, + bool exception_on_error, + bool enable_sequences, + bool ignore_shadow) { + Header=new gdcmHeader(filename.c_str(), + exception_on_error, + enable_sequences, + ignore_shadow); SelfHeader=true; PixelRead=-1; // no ImageData read yet. @@ -66,8 +72,14 @@ gdcmFile::gdcmFile(std::string & filename) { * seen as a side effect). * @param filename file to be opened for parsing */ - gdcmFile::gdcmFile(const char * filename) { - Header=new gdcmHeader(filename); + gdcmFile::gdcmFile(const char * filename, + bool exception_on_error, + bool enable_sequences, + bool ignore_shadow) { + Header=new gdcmHeader(filename, + exception_on_error, + enable_sequences, + ignore_shadow); SelfHeader=true; PixelRead=-1; // no ImageData read yet. diff --git a/src/gdcmFile.h b/src/gdcmFile.h index d5c602c8..da6ce949 100644 --- a/src/gdcmFile.h +++ b/src/gdcmFile.h @@ -16,8 +16,16 @@ class GDCM_EXPORT gdcmFile { public: gdcmFile(gdcmHeader *header); - gdcmFile(std::string & filename); - gdcmFile(const char * filename); + gdcmFile(std::string & filename, + bool exception_on_error = false, + bool enable_sequences = false, + bool skip_shadow = false); + + gdcmFile(const char * filename, + bool exception_on_error = false, + bool enable_sequences = false, + bool skip_shadow = false); + virtual ~gdcmFile(void); gdcmHeader *GetHeader(void); diff --git a/src/gdcmHeaderEntry.cxx b/src/gdcmHeaderEntry.cxx index 4ed41724..1b433881 100644 --- a/src/gdcmHeaderEntry.cxx +++ b/src/gdcmHeaderEntry.cxx @@ -134,6 +134,23 @@ void gdcmHeaderEntry::Print(std::ostream & os) { //----------------------------------------------------------------------------- // Public +/** + * \ingroup gdcmHeaderEntry + * \brief Gets the full length of the HeaderEntry (not only value length) + */ +guint32 gdcmHeaderEntry::GetFullLength(void) { + guint32 l; + l = GetLength(); + if ( IsImplicitVR() ) + l = l + 8; // 2 (gr) + 2 (el) + 4 (lgth) + else + if ( GetVR()=="OB" || GetVR()=="OW" || GetVR()=="SQ" ) + l = l + 12; // 2 (gr) + 2 (el) + 2 (vr) + 2 (unused) + 4 (lgth) + else + l = l + 8; // 2 (gr) + 2 (el) + 2 (vr) + 2 (lgth) + return(l); +} + //----------------------------------------------------------------------------- // Protected diff --git a/src/gdcmHeaderEntry.h b/src/gdcmHeaderEntry.h index 1dbc5cd2..3d86e54c 100644 --- a/src/gdcmHeaderEntry.h +++ b/src/gdcmHeaderEntry.h @@ -192,7 +192,9 @@ public: */ void SetPrintLevel(int level) { printLevel = level; }; void Print (std::ostream & os = std::cout); - + + guint32 GetFullLength(void); + private: // FIXME: In fact we should be more specific and use : // friend gdcmHeaderEntry * gdcmHeader::ReadNextElement(void); diff --git a/src/gdcmParser.cxx b/src/gdcmParser.cxx index 8a7a84f1..056fb8e4 100644 --- a/src/gdcmParser.cxx +++ b/src/gdcmParser.cxx @@ -70,7 +70,7 @@ gdcmParser::gdcmParser(const char *inFilename, return; if (ParseHeader()) { LoadHeaderEntries(); - } + } CloseFile(); wasUpdated = 0; // will be set to 1 if user adds an entry @@ -106,11 +106,10 @@ gdcmParser::~gdcmParser (void) { /** * \ingroup gdcmParser * \brief Prints the Header Entries (Dicom Elements) - * both from the H Table and the chained list + * from the chained list * @return */ void gdcmParser::PrintEntry(std::ostream & os) { - std::ostringstream s; for (ListTag::iterator i = listEntries.begin(); i != listEntries.end(); @@ -119,11 +118,75 @@ void gdcmParser::PrintEntry(std::ostream & os) { (*i)->SetPrintLevel(printLevel); (*i)->Print(os); } - os<GetVR() == "SQ"){ + countSQ ++; + } + + if ( (*i)->GetGroup() == 0xfffe && (*i)->GetElement() == 0xe0dd){ + countSQ --; + continue; + } + + if (countSQ == 0) { + (*i)->SetPrintLevel(printLevel); + (*i)->Print(os); + } + } +} + +/** + * \ingroup gdcmParser + * \brief Prints the Header Entries (Dicom Elements) + * from the chained list + * and indents the elements belonging to a SeQuence + * @return + */ +void gdcmParser::PrintEntryNiceSQ(std::ostream & os) { + int countSQ = 0; + std::ostringstream tab; + tab << " "; + for (ListTag::iterator i = listEntries.begin(); + i != listEntries.end(); + ++i) + { + // we ignore '0 length' SeQuences + if ( (*i)->GetVR() == "SQ" && (*i)->GetReadLength()!=0){ + countSQ ++; + } + // a SeQuence is over when a Sequence Delimiter Item is found + // pb : 'actual length' Sequence have NO Sequence Delimiter + // --> They 'never' finish : check the global length ! + if ( (*i)->GetGroup() == 0xfffe && (*i)->GetElement() == 0xe0dd){ + countSQ --; + continue; + } + + + if (countSQ != 0) { + for (int i=0;iSetPrintLevel(printLevel); + (*i)->Print(os); + } +} +/** + * \brief Prints The Dict Entries of THE public Dicom Dictionary * @return */ void gdcmParser::PrintPubDict(std::ostream & os) { @@ -131,7 +194,7 @@ void gdcmParser::PrintPubDict(std::ostream & os) { } /** - * \brief Prints The Dict Entries of THE shadow Dicom Dictionnary + * \brief Prints The Dict Entries of THE shadow Dicom Dictionary * @return */ void gdcmParser::PrintShaDict(std::ostream & os) { @@ -878,7 +941,7 @@ void gdcmParser::UpdateGroupLength(bool SkipSequence, FileType type) { // since it's at the end of the Hash Table // (fffe,e0dd) - // pas SEQUENCE en ACR-NEMA + // there is SEQUENCE in ACR-NEMA // WARNING : // --> la descente a l'interieur' des SQ // devrait etre faite avec une liste chainee, pas avec une HTable... diff --git a/src/gdcmParser.h b/src/gdcmParser.h index c9306c39..4cd3311e 100644 --- a/src/gdcmParser.h +++ b/src/gdcmParser.h @@ -105,7 +105,10 @@ public: /// Canonical Printing method (see also gdcmParser::SetPrintLevel) virtual void Print (std::ostream &os = std::cout) {PrintEntry(os);}; - virtual void PrintEntry (std::ostream &os = std::cout); + virtual void PrintEntry (std::ostream &os = std::cout); + virtual void PrintEntryNoSQ (std::ostream &os = std::cout); + virtual void PrintEntryNiceSQ(std::ostream &os = std::cout); + virtual void PrintPubDict (std::ostream &os = std::cout); virtual void PrintShaDict (std::ostream &os = std::cout); diff --git a/vtk/vtkGdcmReader.cxx b/vtk/vtkGdcmReader.cxx index 1e3f9a21..0b240f61 100644 --- a/vtk/vtkGdcmReader.cxx +++ b/vtk/vtkGdcmReader.cxx @@ -421,9 +421,11 @@ int vtkGdcmReader::CheckFileCoherence() continue; } fclose(fp); - + + cout << " Try to gdcmHeader ... " << endl; // Stage 1.2: check for Gdcm parsability - gdcmHeaderHelper GdcmHeader(FileName->c_str()); + gdcmHeaderHelper GdcmHeader(FileName->c_str(), false, true); + // true : for enableSequences if (!GdcmHeader.IsReadable()) { vtkErrorMacro("Gdcm cannot parse file " << FileName->c_str()); @@ -587,8 +589,9 @@ size_t vtkGdcmReader::LoadImageInMemory( const unsigned long UpdateProgressTarget, unsigned long & UpdateProgressCount) { - vtkDebugMacro("Copying to memory image" << FileName.c_str()); - gdcmFile GdcmFile(FileName.c_str()); + vtkDebugMacro("Copying to memory image [" << FileName.c_str() << "]"); + gdcmFile GdcmFile(FileName.c_str(),false,true); + // true : to enable SeQuences size_t size; // If the data structure of vtk for image/volume representation diff --git a/vtk/vtkgdcmViewer.cxx b/vtk/vtkgdcmViewer.cxx index 816192e7..e0a17943 100644 --- a/vtk/vtkgdcmViewer.cxx +++ b/vtk/vtkgdcmViewer.cxx @@ -58,7 +58,7 @@ int main(int argc, char *argv[]) for(int i=1; i< argc; i++) reader->AddFileName( argv[i] ); - //reader->DebugOn(); + reader->DebugOn(); reader->Update(); //print debug info: -- 2.45.2