From b1520ca5b7b3665aa40c14b63169bfab92eece55 Mon Sep 17 00:00:00 2001 From: jpr Date: Tue, 22 Jun 2004 13:47:33 +0000 Subject: [PATCH] 2004-06-22 Jean-Pierre Roux In order : to write Sequences, whatever their imbrication level, : to allow user to create his own Sequences a lot of modif where necessary (adding, moving, or virtualising methods) WARNING : save your own sources *before* cvs up ! - gdcmBinEntry ADD virtual void Write(FILE *fp, FileType filetype); - gdcmDocEntry ADD virtual void Write(FILE *fp, FileType filetype); ADD void gdcmDocEntry::WriteCommonPart(FILE *fp, FileType filetype); - gdcmDocEntrySet ADD virtual void Write (FILE *fp, FileType filetype)=0; ADD virtual gdcmDocEntry *GetDocEntryByNumber(guint16 group,guint16 element) = 0; ADD gdcmDocEntry *GetDocEntryByName(std::string name); ADD virtual std::string GetEntryByNumber(guint16 group,guint16 element) = 0; ADD std::string GetEntryByName(TagName name); ADD gdcmDictEntry *NewVirtualDictEntry(guint16 group, guint16 element, std::string vr = "unkn", std::string fourth = "unkn", std::string name = "unkn"); ADD gdcmValEntry *NewValEntryByNumber(guint16 group, guint16 element); ADD gdcmBinEntry *NewBinEntryByNumber(guint16 group, guint16 element); ADD gdcmDocEntry *NewDocEntryByNumber(guint16 group, guint16 element); ADD gdcmDocEntry *NewDocEntryByName (std::string Name); ADD gdcmDictEntry *GetDictEntryByName (std::string Name); ADD gdcmDictEntry *GetDictEntryByNumber(guint16, guint16); REM virtual gdcmDocEntry *NewDocEntryByNumber(guint16 group, guint16 element)=0; REM virtual gdcmDocEntry *NewDocEntryByName (std::string Name)=0; - gdcmDocument ADD virtual bool WriteF(FileType type); // New stuff, with recursive exploration ADD virtual std::string GetEntryByName (TagName tagName); ADD virtual std::string GetEntryVRByName (TagName tagName); REM virtual bool Write(FILE *, FileType); REM virtual void WriteEntryTagVRLength(gdcmDocEntry *tag, FILE *_fp, FileType type); REM virtual void WriteEntryValue(gdcmDocEntry *tag,FILE *_fp,FileType type); REM virtual bool WriteEntry(gdcmDocEntry *tag,FILE *_fp,FileType type); REM virtual bool WriteEntries(FILE *_fp,FileType type); REM virtual std::string GetEntryByName (std::string tagName); REM virtual std::string GetEntryVRByName (std::string tagName); REM gdcmDictEntry *GetDictEntryByName (std::string Name); REM gdcmDictEntry *GetDictEntryByNumber(guint16, guint16); REM gdcmDictEntry *NewVirtualDictEntry(guint16 group, guint16 element, std::string vr = "unkn", std::string fourth = "unkn", std::string name = "unkn"); REM gdcmDocEntry *NewDocEntryByNumber(guint16 group, guint16 element); REM gdcmDocEntry *NewDocEntryByName (std::string Name); REM gdcmValEntry *NewValEntryByNumber(guint16 group, guint16 element); REM gdcmBinEntry *NewBinEntryByNumber(guint16 group, guint16 element); - gdcmElementSet ADD virtual void Write(FILE *fp, FileType filetype); - gdcmSeqEntry ADD virtual void Write(FILE *fp,FileType filetype); - gdcmSQItem ADD virtual void Write(FILE *fp, FileType filetype); ADD virtual std::string GetEntryByNumber(guint16 group, guint16 element); REM std::string GetEntryByNumber(guint16 group, guint16 element); REM std::string GetEntryByName(TagName name); - gdcmValEntry ADD virtual void gdcmValEntry::Write(FILE *fp, FileType filetype); --- src/CMakeLists.txt | 20 +- src/gdcmBinEntry.cxx | 23 +- src/gdcmBinEntry.h | 8 +- src/gdcmDicomDir.cxx | 45 ++-- src/gdcmDict.cxx | 6 +- src/gdcmDocEntry.cxx | 81 ++++++- src/gdcmDocEntry.h | 15 +- src/gdcmDocEntrySet.cxx | 186 +++++++++++++++- src/gdcmDocEntrySet.h | 45 ++-- src/gdcmDocument.cxx | 463 +++------------------------------------- src/gdcmDocument.h | 44 ++-- src/gdcmElementSet.cxx | 46 +++- src/gdcmElementSet.h | 11 +- src/gdcmFile.cxx | 12 +- src/gdcmFile.h | 35 ++- src/gdcmJpeg.cxx | 50 ++--- src/gdcmJpeg12.cxx | 49 ++--- src/gdcmParsePixels.cxx | 6 +- src/gdcmSQItem.cxx | 103 ++++----- src/gdcmSQItem.h | 23 +- src/gdcmSeqEntry.cxx | 50 +++-- src/gdcmSeqEntry.h | 7 +- src/gdcmTS.cxx | 5 +- src/gdcmValEntry.cxx | 57 ++++- src/gdcmValEntry.h | 7 +- 25 files changed, 679 insertions(+), 718 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 09a360ea..40a85f93 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,15 +11,7 @@ INCLUDE_DIRECTORIES( ) SET(libgdcm_la_SOURCES - gdcmDicomDirElement.cxx - gdcmDicomDir.cxx - gdcmDicomDirMeta.cxx - gdcmDicomDirPatient.cxx - gdcmDicomDirStudy.cxx - gdcmDicomDirSerie.cxx - gdcmDicomDirImage.cxx gdcmDirList.cxx - gdcmObject.cxx gdcmDebug.cxx gdcmDict.cxx gdcmDictEntry.cxx @@ -40,12 +32,20 @@ SET(libgdcm_la_SOURCES gdcmDocEntry.cxx gdcmDocEntrySet.cxx gdcmBinEntry.cxx - gdcmDocument.cxx gdcmSeqEntry.cxx gdcmSQItem.cxx gdcmElementSet.cxx gdcmValEntry.cxx -) + gdcmDicomDirElement.cxx + gdcmDocument.cxx + gdcmDicomDir.cxx + gdcmDicomDirMeta.cxx + gdcmDicomDirPatient.cxx + gdcmDicomDirStudy.cxx + gdcmDicomDirSerie.cxx + gdcmDicomDirImage.cxx + gdcmObject.cxx + ) ADD_LIBRARY(gdcm ${libgdcm_la_SOURCES} ) IF(UNIX) diff --git a/src/gdcmBinEntry.cxx b/src/gdcmBinEntry.cxx index aca20db6..f5dddb09 100644 --- a/src/gdcmBinEntry.cxx +++ b/src/gdcmBinEntry.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmBinEntry.cxx,v $ Language: C++ - Date: $Date: 2004/06/21 12:38:28 $ - Version: $Revision: 1.12 $ + Date: $Date: 2004/06/22 13:47:33 $ + Version: $Revision: 1.13 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -64,11 +64,13 @@ gdcmBinEntry::~gdcmBinEntry(){ void gdcmBinEntry::Print(std::ostream &os) { - gdcmValEntry::Print(os); + //gdcmValEntry::Print(os); // replaced by PrintCommonPart + // to avoid bugging the display + PrintCommonPart(os); std::ostringstream s; if (voidArea != NULL) { - s << " [gdcm::Binary data loaded with lenght is " + s << " [gdcm::Binary data loaded with length is " << GetLength() << "]" << std::endl; } @@ -79,6 +81,19 @@ void gdcmBinEntry::Print(std::ostream &os) } os << s.str(); } + +/* + * \brief canonical Writer + */ +void gdcmBinEntry::Write(FILE *fp, FileType filetype) { + void *voidArea = GetVoidArea(); + int lgr=GetLength(); + if (voidArea != NULL) + { // there is a 'non string' LUT, overlay, etc + fwrite ( voidArea,(size_t)lgr ,(size_t)1 ,fp); // Elem value + return; + } +} //----------------------------------------------------------------------------- // Public diff --git a/src/gdcmBinEntry.h b/src/gdcmBinEntry.h index 3865bcd2..946b8a32 100644 --- a/src/gdcmBinEntry.h +++ b/src/gdcmBinEntry.h @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmBinEntry.h,v $ Language: C++ - Date: $Date: 2004/06/20 18:08:47 $ - Version: $Revision: 1.8 $ + Date: $Date: 2004/06/22 13:47:33 $ + Version: $Revision: 1.9 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -36,10 +36,12 @@ class GDCM_EXPORT gdcmBinEntry : public gdcmValEntry { public: gdcmBinEntry(gdcmDictEntry* e); - gdcmBinEntry(gdcmDocEntry* d); + gdcmBinEntry(gdcmDocEntry* d); + ~gdcmBinEntry(void); void Print(std::ostream &os = std::cout); + virtual void Write(FILE *fp, FileType filetype); /// \brief Returns the area value of the current Dicom Header Entry /// when it's not string-translatable (e.g : a LUT table) diff --git a/src/gdcmDicomDir.cxx b/src/gdcmDicomDir.cxx index a542b0b4..eaa705e4 100644 --- a/src/gdcmDicomDir.cxx +++ b/src/gdcmDicomDir.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmDicomDir.cxx,v $ Language: C++ - Date: $Date: 2004/06/19 23:51:03 $ - Version: $Revision: 1.48 $ + Date: $Date: 2004/06/22 13:47:33 $ + Version: $Revision: 1.49 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -133,7 +133,9 @@ gdcmDicomDir::gdcmDicomDir(const char *FileName, bool parseDir, gdcmDicomDir::gdcmDicomDir(bool exception_on_error): gdcmDocument(exception_on_error) { + Initialize(); + std::string pathBidon = "Bidon"; // Sorry, NULL not allowed ... SetElement(pathBidon, GDCM_DICOMDIR_META, NULL); // Set the META elements AddDicomDirMeta(); @@ -366,8 +368,8 @@ void gdcmDicomDir::WriteEntries(FILE *_fp) for(i=(*itPatient)->debut();i!=(*itPatient)->fin();++i) { WriteEntry(*i,_fp, gdcmExplicitVR); } - itStudy = ((*itPatient)->GetDicomDirStudies()).begin(); - while (itStudy != (*itPatient)->GetDicomDirStudies().end() ) { + itStudy = ((*itPatient)->GetDicomDirStudies()).begin(); + while (itStudy != (*itPatient)->GetDicomDirStudies().end() ) { for(i=(*itStudy)->debut();i!=(*itStudy)->fin();++i) { WriteEntry(*i,_fp, gdcmExplicitVR); } @@ -381,11 +383,11 @@ void gdcmDicomDir::WriteEntries(FILE *_fp) for(i=(*itImage)->debut();i!=(*itImage)->fin();++i) { WriteEntry(*i,_fp, gdcmExplicitVR); } - ++itImage; - } - ++itSerie; + ++itImage; + } + ++itSerie; } - ++itStudy; + ++itStudy; } ++itPatient; } @@ -533,8 +535,7 @@ void gdcmDicomDir::SetElement(std::string &path,gdcmDicomDirType type, gdcmValEntry *entry; std::string val; - switch(type) - { + switch(type){ case GDCM_DICOMDIR_PATIENT: elemList=gdcmGlobal::GetDicomDirElements()->GetDicomDirPatientElements(); break; @@ -554,12 +555,13 @@ void gdcmDicomDir::SetElement(std::string &path,gdcmDicomDirType type, return; } - for(it=elemList.begin();it!=elemList.end();++it) - { + for(it=elemList.begin();it!=elemList.end();++it) { + cout << "it " << endl; tmpGr=it->group; tmpEl=it->elem; dictEntry=GetPubDict()->GetDictEntryByNumber(tmpGr,tmpEl); - entry=new gdcmValEntry(dictEntry); + entry=new gdcmValEntry(dictEntry); // Be sure it's never a BinEntry ! + entry->SetOffset(0); // just to avoid further missprinting if(header) @@ -602,23 +604,22 @@ void gdcmDicomDir::SetElement(std::string &path,gdcmDicomDirType type, if(dictEntry) { - if(dictEntry->GetGroup()==0xfffe) - { + if(dictEntry->GetGroup()==0xfffe) { entry->SetLength(entry->GetValue().length()); - } - else if( (dictEntry->GetVR()=="UL") || (dictEntry->GetVR()=="SL") ) + } + else if( (dictEntry->GetVR()=="UL") || (dictEntry->GetVR()=="SL") ) { entry->SetLength(4); } - else if( (dictEntry->GetVR()=="US") || (dictEntry->GetVR()=="SS") ) + else if( (dictEntry->GetVR()=="US") || (dictEntry->GetVR()=="SS") ) { entry->SetLength(2); } - else if(dictEntry->GetVR()=="SQ") + else if(dictEntry->GetVR()=="SQ") { entry->SetLength(0xffffffff); } - else + else { entry->SetLength(entry->GetValue().length()); } @@ -778,7 +779,7 @@ void gdcmDicomDir::CreateDicomDir() AddDicomDirImageToEnd(s); break; case gdcmDicomDir::GDCM_DICOMDIR_NONE: - AddDicomDirImageToEnd(s); //FIXME + AddDicomDirImageToEnd(s); //FIXME break; } } @@ -957,7 +958,7 @@ void gdcmDicomDir::UpdateDirectoryRecordSequenceLength() { } } //bool res=SetEntryLengthByNumber(offset, 0x0004, 0x1220); // Hope there is no dupps. - SetEntryLengthByNumber(offset, 0x0004, 0x1220); // Hope there is no dupps. + SetEntryLengthByNumber(offset, 0x0004, 0x1220); // Hope there is no dupps. return; */ } diff --git a/src/gdcmDict.cxx b/src/gdcmDict.cxx index d9b9bb69..b8ed20ab 100644 --- a/src/gdcmDict.cxx +++ b/src/gdcmDict.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmDict.cxx,v $ Language: C++ - Date: $Date: 2004/06/21 04:43:02 $ - Version: $Revision: 1.36 $ + Date: $Date: 2004/06/22 13:47:33 $ + Version: $Revision: 1.37 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -47,7 +47,7 @@ gdcmDict::gdcmDict(std::string & FileName) { from >> element; from >> vr; from >> fourth; - eatwhite(from); + eatwhite(from); getline(from, name); /// MEMORY LEAK in std::getline<> gdcmDictEntry * newEntry = new gdcmDictEntry(group, element, diff --git a/src/gdcmDocEntry.cxx b/src/gdcmDocEntry.cxx index 0afb302f..6dff08d1 100644 --- a/src/gdcmDocEntry.cxx +++ b/src/gdcmDocEntry.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmDocEntry.cxx,v $ Language: C++ - Date: $Date: 2004/06/20 18:08:47 $ - Version: $Revision: 1.7 $ + Date: $Date: 2004/06/22 13:47:33 $ + Version: $Revision: 1.8 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -112,6 +112,83 @@ void gdcmDocEntry::PrintCommonPart(std::ostream & os) { os << s.str(); } +/** + * \ingroup gdcmDocEntry + * \brief Writes the common part of any gdcmValEntry, gdcmBinEntry, gdcmSeqEntry + */ +void gdcmDocEntry::Write(FILE *fp, FileType filetype) { + std::cout << "gdcmDocEntry::Write : Is that what you wanted to do ? " << std::endl; + WriteCommonPart(fp, filetype); +} + +/** + * \ingroup gdcmDocEntry + * \brief Writes the common part of any gdcmValEntry, gdcmBinEntry, gdcmSeqEntry + */ +void gdcmDocEntry::WriteCommonPart(FILE *fp, FileType filetype) { + + guint16 group = GetGroup(); + VRKey vr = GetVR(); + guint16 el = GetElement(); + guint32 lgr = GetReadLength(); + + if ( (group == 0xfffe) && (el == 0x0000) ) + // Fix in order to make some MR PHILIPS images e-film readable + // see gdcmData/gdcm-MR-PHILIPS-16-Multi-Seq.dcm: + // we just *always* ignore spurious fffe|0000 tag ! + return; + +// +// ----------- Writes the common part +// + fwrite ( &group,(size_t)2 ,(size_t)1 ,fp); //group + fwrite ( &el, (size_t)2 ,(size_t)1 ,fp); //element + + if ( filetype == gdcmExplicitVR ) { + + // Special case of delimiters: + if (group == 0xfffe) { + // Delimiters have NO Value Representation + // Hence we skip writing the VR. + // In order to avoid further troubles, we choose to write them + // as 'no-length' Item Delimitors (we pad by writing 0xffffffff) + // The end of a given Item will be found when : + // - a new Item Delimitor Item is encountered (the Seq goes on) + // - a Sequence Delimitor Item is encountered (the Seq just ended) + + // TODO : verify if the Sequence Delimitor Item was forced during Parsing + + int ff=0xffffffff; + fwrite (&ff,(size_t)4 ,(size_t)1 ,fp); + return; + } + + guint16 z=0; + guint16 shortLgr = lgr; + if (vr == "unkn") { // Unknown was 'written' + // deal with Little Endian + fwrite ( &shortLgr,(size_t)2 ,(size_t)1 ,fp); + fwrite ( &z, (size_t)2 ,(size_t)1 ,fp); + } else { + fwrite (vr.c_str(),(size_t)2 ,(size_t)1 ,fp); + +// TODO : better we set SQ length to ffffffff +// and write a Sequence Delimitor Item at the end of the Sequence! + if ( (vr == "OB") || (vr == "OW") || (vr == "SQ") ) + { + fwrite ( &z, (size_t)2 ,(size_t)1 ,fp); + fwrite ( &lgr,(size_t)4 ,(size_t)1 ,fp); + } else { + fwrite ( &shortLgr,(size_t)2 ,(size_t)1 ,fp); + } + } + } + else // IMPLICIT VR + { + fwrite ( &lgr,(size_t)4 ,(size_t)1 ,fp); + } +} + //----------------------------------------------------------------------------- // Public diff --git a/src/gdcmDocEntry.h b/src/gdcmDocEntry.h index 2f7dc1d4..11d2b0bf 100644 --- a/src/gdcmDocEntry.h +++ b/src/gdcmDocEntry.h @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmDocEntry.h,v $ Language: C++ - Date: $Date: 2004/06/20 18:08:47 $ - Version: $Revision: 1.9 $ + Date: $Date: 2004/06/22 13:47:33 $ + Version: $Revision: 1.10 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -23,8 +23,11 @@ #include #include "gdcmDictEntry.h" -//#include "gdcmValEntry.h" + class gdcmHeader; +class gdcmValEntry; +class gdcmBinEntry; +class gdcmSeqEntry; //----------------------------------------------------------------------------- /** @@ -41,7 +44,7 @@ public: /// Returns the Dicom Element number of the current Dicom Header Entry inline guint16 GetElement(void) { return entry->GetElement();}; - + /// Returns the 'key' of the current Dicom Header Entry inline std::string GetKey(void) { return entry->GetKey(); }; @@ -60,7 +63,7 @@ public: inline size_t GetOffset(void) { return Offset; }; /// \brief Returns the actual value length of the current Dicom Header Entry - /// \warning this value is not *allways* the one stored in the Dicom Header + /// \warning this value is not *always* the one stored in the Dicom Header /// in case of well knowned bugs inline guint32 GetLength(void) { return UsableLength; }; @@ -121,8 +124,10 @@ public: int GetPrintLevel(void) { return(printLevel); }; virtual void Print (std::ostream & os = std::cout); + virtual void Write(FILE *fp, FileType filetype); void gdcmDocEntry::PrintCommonPart(std::ostream & os); + void gdcmDocEntry::WriteCommonPart(FILE *fp, FileType filetype); guint32 GetFullLength(void); diff --git a/src/gdcmDocEntrySet.cxx b/src/gdcmDocEntrySet.cxx index c888737b..8ed29fb1 100644 --- a/src/gdcmDocEntrySet.cxx +++ b/src/gdcmDocEntrySet.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmDocEntrySet.cxx,v $ Language: C++ - Date: $Date: 2004/06/20 18:08:47 $ - Version: $Revision: 1.9 $ + Date: $Date: 2004/06/22 13:47:33 $ + Version: $Revision: 1.10 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -52,9 +52,191 @@ gdcmDocEntrySet::~gdcmDocEntrySet(){ //----------------------------------------------------------------------------- // Public + + +/** + * \brief Build a new Element Value from all the low level arguments. + * Check for existence of dictionary entry, and build + * a default one when absent. + * @param Group group number of the underlying DictEntry + * @param Elem element number of the underlying DictEntry + */ +gdcmValEntry *gdcmDocEntrySet::NewValEntryByNumber(guint16 Group, guint16 Elem) +{ + // Find out if the tag we encountered is in the dictionaries: + gdcmDictEntry *DictEntry = GetDictEntryByNumber(Group, Elem); + if (!DictEntry) + DictEntry = NewVirtualDictEntry(Group, Elem); + + gdcmValEntry *NewEntry = new gdcmValEntry(DictEntry); + if (!NewEntry) + { + dbg.Verbose(1, "gdcmDocument::NewValEntryByNumber", + "failed to allocate gdcmValEntry"); + return NULL; + } + return NewEntry; +} + + +/** + * \brief Build a new Element Value from all the low level arguments. + * Check for existence of dictionary entry, and build + * a default one when absent. + * @param Group group number of the underlying DictEntry + * @param Elem element number of the underlying DictEntry + */ +gdcmBinEntry *gdcmDocEntrySet::NewBinEntryByNumber(guint16 Group, guint16 Elem) +{ + // Find out if the tag we encountered is in the dictionaries: + gdcmDictEntry *DictEntry = GetDictEntryByNumber(Group, Elem); + if (!DictEntry) + DictEntry = NewVirtualDictEntry(Group, Elem); + + gdcmBinEntry *NewEntry = new gdcmBinEntry(DictEntry); + if (!NewEntry) + { + dbg.Verbose(1, "gdcmDocument::NewBinEntryByNumber", + "failed to allocate gdcmBinEntry"); + return NULL; + } + return NewEntry; +} //----------------------------------------------------------------------------- // Protected +/** + * \brief Gets a Dicom Element inside a SQ Item Entry, by name + * @return + */ + gdcmDocEntry *gdcmDocEntrySet::GetDocEntryByName(std::string name) { + gdcmDict *PubDict=gdcmGlobal::GetDicts()->GetDefaultPubDict(); + gdcmDictEntry *dictEntry = (*PubDict).GetDictEntryByName(name); + if( dictEntry == NULL) + return NULL; + return GetDocEntryByNumber(dictEntry->GetGroup(),dictEntry->GetElement()); +} + + +/** + * \brief Get the value of a Dicom Element inside a SQ Item Entry, by name + * @param name : name of the searched element. + * @return + */ + +std::string gdcmDocEntrySet::GetEntryByName(TagName name) { + gdcmDict *PubDict=gdcmGlobal::GetDicts()->GetDefaultPubDict(); + gdcmDictEntry *dictEntry = (*PubDict).GetDictEntryByName(name); + + if( dictEntry == NULL) + return GDCM_UNFOUND; + return GetEntryByNumber(dictEntry->GetGroup(),dictEntry->GetElement()); +} + + +/** + * \brief Request a new virtual dict entry to the dict set + * @param group group number of the underlying DictEntry + * @param element element number of the underlying DictEntry + * @param vr VR of the underlying DictEntry + * @param fourth owner group + * @param name english name + */ +gdcmDictEntry *gdcmDocEntrySet::NewVirtualDictEntry(guint16 group, guint16 element, + std::string vr, + std::string fourth, + std::string name) +{ + return gdcmGlobal::GetDicts()->NewVirtualDictEntry(group,element,vr,fourth,name); +} + +/// \brief + +// +// Probabely move, as is, to gdcmDocEntrySet, as a non virtual method +// an remove gdcmDocument::NewDocEntryByNumber +gdcmDocEntry *gdcmDocEntrySet::NewDocEntryByNumber(guint16 group, + guint16 elem) { + + // Find out if the tag we encountered is in the dictionaries: + gdcmDict *PubDict=gdcmGlobal::GetDicts()->GetDefaultPubDict(); + gdcmDictEntry *DictEntry = (*PubDict).GetDictEntryByNumber(group, elem); + if (!DictEntry) + DictEntry = NewVirtualDictEntry(group, elem); + + gdcmDocEntry *NewEntry = new gdcmDocEntry(DictEntry); + if (!NewEntry) + { + dbg.Verbose(1, "gdcmSQItem::NewDocEntryByNumber", + "failed to allocate gdcmDocEntry"); + return (gdcmDocEntry*)0; + } + return NewEntry; +} + +/// \brief +gdcmDocEntry *gdcmDocEntrySet::NewDocEntryByName (std::string Name) { + + gdcmDict *PubDict=gdcmGlobal::GetDicts()->GetDefaultPubDict(); + gdcmDictEntry *NewTag = (*PubDict).GetDictEntryByName(Name); + if (!NewTag) + NewTag = NewVirtualDictEntry(0xffff, 0xffff, "LO", "unkn", Name); + + gdcmDocEntry* NewEntry = new gdcmDocEntry(NewTag); + if (!NewEntry) + { + dbg.Verbose(1, "gdcmSQItem::ObtainDocEntryByName", + "failed to allocate gdcmDocEntry"); + return (gdcmDocEntry *)0; + } + return NewEntry; +} + + +/** + * \brief Searches both the public and the shadow dictionary (when they + * exist) for the presence of the DictEntry with given name. + * The public dictionary has precedence on the shadow one. + * @param Name name of the searched DictEntry + * @return Corresponding DictEntry when it exists, NULL otherwise. + */ +gdcmDictEntry *gdcmDocEntrySet::GetDictEntryByName(std::string Name) +{ + gdcmDictEntry *found = (gdcmDictEntry *)0; + gdcmDict *PubDict=gdcmGlobal::GetDicts()->GetDefaultPubDict(); + if (!PubDict) + { + dbg.Verbose(0, "gdcmDocument::GetDictEntry", + "we SHOULD have a default dictionary"); + } + else + found = PubDict->GetDictEntryByName(Name); + return found; +} + +/** + * \brief Searches both the public and the shadow dictionary (when they + * exist) for the presence of the DictEntry with given + * group and element. The public dictionary has precedence on the + * shadow one. + * @param group group number of the searched DictEntry + * @param element element number of the searched DictEntry + * @return Corresponding DictEntry when it exists, NULL otherwise. + */ +gdcmDictEntry *gdcmDocEntrySet::GetDictEntryByNumber(guint16 group,guint16 element) +{ + gdcmDictEntry *found = (gdcmDictEntry *)0; + gdcmDict *PubDict=gdcmGlobal::GetDicts()->GetDefaultPubDict(); + if (!PubDict) + { + dbg.Verbose(0, "gdcmDocument::GetDictEntry", + "we SHOULD have a default dictionary"); + } + else + found = PubDict->GetDictEntryByNumber(group, element); + return found; +} + //----------------------------------------------------------------------------- // Private diff --git a/src/gdcmDocEntrySet.h b/src/gdcmDocEntrySet.h index ac827fe9..695eb39e 100644 --- a/src/gdcmDocEntrySet.h +++ b/src/gdcmDocEntrySet.h @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmDocEntrySet.h,v $ Language: C++ - Date: $Date: 2004/06/21 04:43:02 $ - Version: $Revision: 1.11 $ + Date: $Date: 2004/06/22 13:47:33 $ + Version: $Revision: 1.12 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -38,6 +38,9 @@ public: /// \brief prints any type of entry to the entry set (pure vitual) virtual void Print (std::ostream & os = std::cout) = 0;// pure virtual + /// \brief write any type of entry to the entry set + virtual void Write (FILE *fp, FileType filetype)=0;// pure virtual + /// \brief Gets the depth level of a Dicom Header Entry embedded in a /// SeQuence inline int GetDepthLevel(void) { return SQDepthLevel; } @@ -45,18 +48,34 @@ public: /// \brief Sets the depth level of a Dicom Header Entry embedded in a /// SeQuence inline void SetDepthLevel(int depth) { SQDepthLevel = depth; } - -protected: - /// \brief Build a new Element Value from all the low level arguments. - /// Check for existence of dictionary entry, and build - /// a default one when absent (pure virtual) - virtual gdcmDocEntry *NewDocEntryByNumber(guint16 group, - guint16 element)=0; // pure virtual - /// \brief Build a new Element Value from all the low level arguments. - /// Check for existence of dictionary entry, and build - /// a default one when absent (pure virtual) - virtual gdcmDocEntry *NewDocEntryByName (std::string Name)=0;// pure virtual + virtual gdcmDocEntry *GetDocEntryByNumber(guint16 group,guint16 element) = 0; + gdcmDocEntry *GetDocEntryByName(std::string name); + virtual std::string GetEntryByNumber(guint16 group,guint16 element) = 0; + std::string GetEntryByName(TagName name); + gdcmDictEntry *NewVirtualDictEntry(guint16 group, + guint16 element, + std::string vr = "unkn", + std::string fourth = "unkn", + std::string name = "unkn"); + + protected: + + // DocEntry related utilities + + gdcmValEntry *NewValEntryByNumber(guint16 group, + guint16 element); + gdcmBinEntry *NewBinEntryByNumber(guint16 group, + guint16 element); + gdcmDocEntry *NewDocEntryByNumber(guint16 group, + guint16 element); + gdcmDocEntry *NewDocEntryByName (std::string Name); + + // DictEntry related utilities + + gdcmDictEntry *GetDictEntryByName (std::string Name); + gdcmDictEntry *GetDictEntryByNumber(guint16, guint16); + /// Gives the depth level of the element set inside SeQuences int SQDepthLevel; diff --git a/src/gdcmDocument.cxx b/src/gdcmDocument.cxx index fa1d4a7d..b246b791 100644 --- a/src/gdcmDocument.cxx +++ b/src/gdcmDocument.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmDocument.cxx,v $ Language: C++ - Date: $Date: 2004/06/21 12:38:29 $ - Version: $Revision: 1.21 $ + Date: $Date: 2004/06/22 13:47:33 $ + Version: $Revision: 1.22 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -66,7 +66,7 @@ #define UI1_2_840_10008_1_2_4_91 "1.2.840.10008.1.2.4.91" // RLE Lossless #define UI1_2_840_10008_1_2_5 "1.2.840.10008.1.2.5" - +// UI1_1_2_840_10008_1_2_5 #define str2num(str, typeNum) *((typeNum *)(str)) //----------------------------------------------------------------------------- @@ -175,8 +175,8 @@ gdcmDocument::~gdcmDocument (void) { // Recursive clean up of sequences for (TagDocEntryHT::iterator it = tagHT.begin(); it != tagHT.end(); ++it ) - { - delete (it->second); + { + delete it->second; } tagHT.clear(); } @@ -256,6 +256,7 @@ bool gdcmDocument::IsReadable(void) { return(true); } + /** * \brief Internal function that checks whether the Transfer Syntax given * as argument is the one present in the current document. @@ -490,34 +491,28 @@ bool gdcmDocument::CloseFile(void) { /** * \brief Writes in a file all the Header Entries (Dicom Elements) - * of the Chained List * @param fp file pointer on an already open file - * @param type Type of the File to be written + * @param filetype Type of the File to be written * (ACR-NEMA, ExplicitVR, ImplicitVR) * \return Always true. */ -bool gdcmDocument::Write(FILE *fp, FileType type) { +bool gdcmDocument::WriteF(FileType filetype) { /// \todo -/// ============== -/// The stuff will have to be rewritten using the SeQuence based -/// tree-like stucture instead of the chained list . -/// (so we shall remove the Group*HT from the gdcmDocument) +/// ============== +/// The stuff is rewritten using the SeQuence based +/// tree-like stucture (cf : Print ) /// To be checked /// ============= /// \todo move the following lines (and a lot of others, to be written) /// to a future function CheckAndCorrectHeader - /// \todo - /// Question : - /// Comment pourrait-on savoir si le DcmHeader vient d'un fichier - /// DicomV3 ou non (FileType est un champ de gdcmDocument ...) /// WARNING : Si on veut ecrire du DICOM V3 a partir d'un DcmHeader ACR-NEMA - /// no way + /// no way (check : FileType est un champ de gdcmDocument ...) /// a moins de se livrer a un tres complique ajout des champs manquants. /// faire un CheckAndCorrectHeader (?) - if (type == gdcmImplicitVR) + if (filetype == gdcmImplicitVR) { std::string implicitVRTransfertSyntax = UI1_2_840_10008_1_2; ReplaceOrCreateByNumber(implicitVRTransfertSyntax,0x0002, 0x0010); @@ -530,7 +525,7 @@ bool gdcmDocument::Write(FILE *fp, FileType type) { SetEntryLengthByNumber(18, 0x0002, 0x0010); } - if (type == gdcmExplicitVR) + if (filetype == gdcmExplicitVR) { std::string explicitVRTransfertSyntax = UI1_2_840_10008_1_2_1; ReplaceOrCreateByNumber(explicitVRTransfertSyntax,0x0002, 0x0010); @@ -545,18 +540,21 @@ bool gdcmDocument::Write(FILE *fp, FileType type) { /** * \todo rewrite later, if really usefull + * ('Group Length' element is optional in DICOM) * - * --> Warning : un-updated odd groups lengths can causes pb + * --> Warning : un-updated odd groups lengthes can causes pb * --> (xmedcon breaks) * --> to be re- written with future org. * - * if ( (type == ImplicitVR) || (type == ExplicitVR) ) - * UpdateGroupLength(false,type); - * if ( type == ACR) + * if ( (filetype == ImplicitVR) || (filetype == ExplicitVR) ) + * UpdateGroupLength(false,filetype); + * if ( filetype == ACR) * UpdateGroupLength(true,ACR); */ + + Write(fp,filetype); // the gdcmElementSet one ! - WriteEntries(fp,type); + /// WriteEntries(fp,type); // old stuff return true; } @@ -716,7 +714,7 @@ std::string gdcmDocument::GetEntryByName(std::string tagName) { * @return Corresponding element value representation when it exists, * and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise. */ -std::string gdcmDocument::GetEntryVRByName(std::string tagName) { +std::string gdcmDocument::GetEntryVRByName(TagName tagName) { gdcmDictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName); if( dictEntry == NULL) return GDCM_UNFOUND; @@ -956,7 +954,7 @@ void *gdcmDocument::LoadEntryVoidArea(guint16 Group, guint16 Elem) /** * \brief Sets a 'non string' value to a given Dicom Element - * @param area + * @param area area containing the 'non string' value * @param group Group number of the searched Dicom Element * @param element Element number of the searched Dicom Element * @return @@ -1086,233 +1084,6 @@ void gdcmDocument::LoadDocEntrySafe(gdcmDocEntry * entry) { fseek(fp, PositionOnEntry, SEEK_SET); } - -/** - * \brief Writes in a file (according to the requested format) - * the group, the element, the value representation and the length - * of a single gdcmDocEntry passed as argument. - * @param tag pointer on the gdcmDocEntry to be written - * @param _fp already open file pointer - * @param type type of the File to be written - */ -void gdcmDocument::WriteEntryTagVRLength(gdcmDocEntry *tag, - FILE *_fp, - FileType type) -{ - guint16 group = tag->GetGroup(); - VRKey vr = tag->GetVR(); - guint16 el = tag->GetElement(); - guint32 lgr = tag->GetReadLength(); - - if ( (group == 0xfffe) && (el == 0x0000) ) - // Fix in order to make some MR PHILIPS images e-film readable - // see gdcmData/gdcm-MR-PHILIPS-16-Multi-Seq.dcm: - // we just *always* ignore spurious fffe|0000 tag ! - return; - - fwrite ( &group,(size_t)2 ,(size_t)1 ,_fp); //group - fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp); //element - - if ( type == gdcmExplicitVR ) { - - // Special case of delimiters: - if (group == 0xfffe) { - // Delimiters have NO Value Representation and have NO length. - // Hence we skip writing the VR and length and we pad by writing - // 0xffffffff - - int ff=0xffffffff; - fwrite (&ff,(size_t)4 ,(size_t)1 ,_fp); - return; - } - - guint16 z=0; - guint16 shortLgr = lgr; - if (vr == "unkn") { // Unknown was 'written' - // deal with Little Endian - fwrite ( &shortLgr,(size_t)2 ,(size_t)1 ,_fp); - fwrite ( &z, (size_t)2 ,(size_t)1 ,_fp); - } else { - fwrite (vr.c_str(),(size_t)2 ,(size_t)1 ,_fp); - if ( (vr == "OB") || (vr == "OW") || (vr == "SQ") ) - { - fwrite ( &z, (size_t)2 ,(size_t)1 ,_fp); - fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp); - } else { - fwrite ( &shortLgr,(size_t)2 ,(size_t)1 ,_fp); - } - } - } - else // IMPLICIT VR - { - fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp); - } -} - -/** - * \brief Writes in a file (according to the requested format) - * the value of a single gdcmDocEntry passed as argument. - * @param tag Pointer on the gdcmDocEntry to be written - * @param _fp Already open file pointer - * @param type type of the File to be written - */ - -// \todo TODO : to be re -written recursively ! -void gdcmDocument::WriteEntryValue(gdcmDocEntry *Entry, FILE *_fp,FileType type) -{ - (void)type; - guint16 group = Entry->GetGroup(); - VRKey vr = Entry->GetVR(); - guint32 lgr = Entry->GetReadLength(); - - if (vr == "SQ") - // SeQuences have no value: - return; - if (group == 0xfffe) - // Delimiters have no associated value: - return; - -// if (gdcmBinEntry* BinEntry = dynamic_cast< gdcmBinEntry* >(Entry) ) { - void *voidArea; - gdcmBinEntry *BinEntry= (gdcmBinEntry *)Entry;; - voidArea = BinEntry->GetVoidArea(); - if (voidArea != NULL) - { // there is a 'non string' LUT, overlay, etc - fwrite ( voidArea,(size_t)lgr ,(size_t)1 ,_fp); // Elem value - return; - } -// } - - if (vr == "US" || vr == "SS") - { - // some 'Short integer' fields may be mulivaluated - // each single value is separated from the next one by '\' - // we split the string and write each value as a short int - std::vector tokens; - tokens.erase(tokens.begin(),tokens.end()); // clean any previous value - Tokenize (((gdcmValEntry *)Entry)->GetValue(), tokens, "\\"); - for (unsigned int i=0; i tokens; - tokens.erase(tokens.begin(),tokens.end()); // clean any previous value - Tokenize (((gdcmValEntry *)Entry)->GetValue(), tokens, "\\"); - for (unsigned int i=0; iGetValue().c_str(), - (size_t)lgr ,(size_t)1, _fp); // Elem value -} - -/** - * \brief Writes in a file (according to the requested format) - * a single gdcmDocEntry passed as argument. - * \sa WriteEntryValue, WriteEntryTagVRLength. - * @param tag Pointer on the gdcmDocEntry to be written - * @param _fp Already open file pointer - * @param type type of the File to be written - */ - -bool gdcmDocument::WriteEntry(gdcmDocEntry *tag, FILE *_fp,FileType type) -{ - guint32 length = tag->GetLength(); - - if (gdcmValEntry* ValEntry = dynamic_cast< gdcmValEntry* >(tag) ) - { - // The value of a tag MUST (see the DICOM norm) be an odd number of - // bytes. When this is not the case, pad with an additional byte: - if(length%2==1) { - ValEntry->SetValue(ValEntry->GetValue()+"\0"); - ValEntry->SetLength(ValEntry->GetReadLength()+1); - } - WriteEntryTagVRLength(ValEntry, _fp, type); - WriteEntryValue(ValEntry, _fp, type); - return true; - } - - if (gdcmBinEntry* BinEntry = dynamic_cast< gdcmBinEntry* >(tag) ) - { - (void)BinEntry; //not used - /// \todo FIXME : when voidArea belong to gdcmBinEntry only, fix - /// voidArea length - // - // The value of a tag MUST (see the DICOM norm) be an odd number of - // bytes. When this is not the case, pad with an additional byte: -/* - if(length%2==1) { - tag->SetValue(tag->GetValue()+"\0"); - tag->SetLength(tag->GetReadLength()+1); - } -*/ - WriteEntryTagVRLength(tag, _fp, type); - WriteEntryValue(tag, _fp, type); - return true; - } - - return false; //default behavior ? -} - -/** - * \brief writes on disc according to the requested format - * (ACR-NEMA, ExplicitVR, ImplicitVR) the image - * using the Chained List - * \warning does NOT add the missing elements in the header : - * it's up to the user doing it ! - * (function CheckHeaderCoherence to be written) - * \warning DON'T try, right now, to write a DICOM image - * from an ACR Header (meta elements will be missing!) - * @param type type of the File to be written - * (ACR-NEMA, ExplicitVR, ImplicitVR) - * @param _fp already open file pointer - */ - -bool gdcmDocument::WriteEntries(FILE *_fp,FileType type) -{ - /// \todo FIXME : explore recursively the whole structure... - /// \todo (?) check write failures (after *each* fwrite) - - dbg.Verbose(0, "gdcmDocument::WriteEntries: entering."); - for (TagDocEntryHT::iterator it = tagHT.begin(); it != tagHT.end(); ++it ) - { - gdcmDocEntry * entry = it->second; - - if ( type == gdcmACR ){ - if (entry->GetGroup() < 0x0008) - // Ignore pure DICOM V3 groups - continue; - if (entry->GetGroup() %2) - // Ignore the "shadow" groups - continue; - if (entry->GetVR() == "SQ" ) // ignore Sequences - continue; - } - if (! WriteEntry(entry, _fp, type) ) { - dbg.Verbose(0, "gdcmDocument::WriteEntries: write failure."); - return false; - } - } - return true; -} - - /** * \brief Swaps back the bytes of 4-byte long integer accordingly to * processor order. @@ -1340,7 +1111,7 @@ guint32 gdcmDocument::SwapLong(guint32 a) { a=0; } return(a); -} +} /** * \brief Unswaps back the bytes of 4-byte long integer accordingly to @@ -1374,7 +1145,7 @@ guint16 gdcmDocument::UnswapShort(guint16 a) { /** * \brief Parses a DocEntrySet (Zero-level DocEntries or SQ Item DocEntries) - * @return false if file is not ACR-NEMA / PAPYRUS / DICOM + * @return length of the parsed set. */ long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool delim_mode) { @@ -1503,8 +1274,6 @@ long gdcmDocument::ParseSQ(gdcmSeqEntry *set, NewDocEntry = ReadNextDocEntry(); if(delim_mode) { if (NewDocEntry->isSequenceDelimitor()) { - /// \todo add the Sequence Delimitor - /// \todo find the trick to put it properly ! set->SetSequenceDelimitationItem(NewDocEntry); break; } @@ -1515,7 +1284,6 @@ long gdcmDocument::ParseSQ(gdcmSeqEntry *set, itemSQ = new gdcmSQItem(set->GetDepthLevel()); itemSQ->AddEntry(NewDocEntry); - /// \todo no value, no voidArea. Think of it while printing ! l= NewDocEntry->GetReadLength(); if (l == 0xffffffff) @@ -2529,117 +2297,6 @@ gdcmDocEntry *gdcmDocument::ReadNextDocEntry(void) { return NewEntry; } -/** - * \brief Build a new Element Value from all the low level arguments. - * Check for existence of dictionary entry, and build - * a default one when absent. - * @param Name Name of the underlying DictEntry - */ -gdcmDocEntry *gdcmDocument::NewDocEntryByName(std::string Name) -{ - gdcmDictEntry *NewTag = GetDictEntryByName(Name); - if (!NewTag) - NewTag = NewVirtualDictEntry(0xffff, 0xffff, "LO", "unkn", Name); - - gdcmDocEntry* NewEntry = new gdcmDocEntry(NewTag); - if (!NewEntry) - { - dbg.Verbose(1, "gdcmDocument::ObtainDocEntryByName", - "failed to allocate gdcmDocEntry"); - return (gdcmDocEntry *)0; - } - return NewEntry; -} - -/** - * \brief Request a new virtual dict entry to the dict set - * @param group group number of the underlying DictEntry - * @param element element number of the underlying DictEntry - * @param vr VR of the underlying DictEntry - * @param fourth owner group - * @param name english name - */ -gdcmDictEntry *gdcmDocument::NewVirtualDictEntry(guint16 group, guint16 element, - std::string vr, - std::string fourth, - std::string name) -{ - return gdcmGlobal::GetDicts()->NewVirtualDictEntry(group,element,vr,fourth,name); -} - -/** - * \brief Build a new Element Value from all the low level arguments. - * Check for existence of dictionary entry, and build - * a default one when absent. - * @param Group group number of the underlying DictEntry - * @param Elem element number of the underlying DictEntry - */ -gdcmDocEntry* gdcmDocument::NewDocEntryByNumber(guint16 Group, guint16 Elem) -{ - // Find out if the tag we encountered is in the dictionaries: - gdcmDictEntry *DictEntry = GetDictEntryByNumber(Group, Elem); - if (!DictEntry) - DictEntry = NewVirtualDictEntry(Group, Elem); - - gdcmDocEntry *NewEntry = new gdcmDocEntry(DictEntry); - if (!NewEntry) - { - dbg.Verbose(1, "gdcmDocument::NewDocEntryByNumber", - "failed to allocate gdcmDocEntry"); - return (gdcmDocEntry*)0; - } - return NewEntry; -} - - -/** - * \brief Build a new Element Value from all the low level arguments. - * Check for existence of dictionary entry, and build - * a default one when absent. - * @param Group group number of the underlying DictEntry - * @param Elem element number of the underlying DictEntry - */ -gdcmValEntry *gdcmDocument::NewValEntryByNumber(guint16 Group, guint16 Elem) -{ - // Find out if the tag we encountered is in the dictionaries: - gdcmDictEntry *DictEntry = GetDictEntryByNumber(Group, Elem); - if (!DictEntry) - DictEntry = NewVirtualDictEntry(Group, Elem); - - gdcmValEntry *NewEntry = new gdcmValEntry(DictEntry); - if (!NewEntry) - { - dbg.Verbose(1, "gdcmDocument::NewValEntryByNumber", - "failed to allocate gdcmValEntry"); - return NULL; - } - return NewEntry; -} - - -/** - * \brief Build a new Element Value from all the low level arguments. - * Check for existence of dictionary entry, and build - * a default one when absent. - * @param Group group number of the underlying DictEntry - * @param Elem element number of the underlying DictEntry - */ -gdcmBinEntry *gdcmDocument::NewBinEntryByNumber(guint16 Group, guint16 Elem) -{ - // Find out if the tag we encountered is in the dictionaries: - gdcmDictEntry *DictEntry = GetDictEntryByNumber(Group, Elem); - if (!DictEntry) - DictEntry = NewVirtualDictEntry(Group, Elem); - - gdcmBinEntry *NewEntry = new gdcmBinEntry(DictEntry); - if (!NewEntry) - { - dbg.Verbose(1, "gdcmDocument::NewBinEntryByNumber", - "failed to allocate gdcmBinEntry"); - return NULL; - } - return NewEntry; -} /** * \brief Generate a free TagKey i.e. a TagKey that is not present @@ -2659,68 +2316,6 @@ guint32 gdcmDocument::GenerateFreeTagKeyInGroup(guint16 group) } -/** - * \brief Searches both the public and the shadow dictionary (when they - * exist) for the presence of the DictEntry with given name. - * The public dictionary has precedence on the shadow one. - * @param Name name of the searched DictEntry - * @return Corresponding DictEntry when it exists, NULL otherwise. - */ -gdcmDictEntry *gdcmDocument::GetDictEntryByName(std::string Name) -{ - gdcmDictEntry *found = (gdcmDictEntry *)0; - if (!RefPubDict && !RefShaDict) - { - dbg.Verbose(0, "gdcmDocument::GetDictEntry", - "we SHOULD have a default dictionary"); - } - if (RefPubDict) - { - found = RefPubDict->GetDictEntryByName(Name); - if (found) - return found; - } - if (RefShaDict) - { - found = RefShaDict->GetDictEntryByName(Name); - if (found) - return found; - } - return found; -} - -/** - * \brief Searches both the public and the shadow dictionary (when they - * exist) for the presence of the DictEntry with given - * group and element. The public dictionary has precedence on the - * shadow one. - * @param group group number of the searched DictEntry - * @param element element number of the searched DictEntry - * @return Corresponding DictEntry when it exists, NULL otherwise. - */ -gdcmDictEntry *gdcmDocument::GetDictEntryByNumber(guint16 group,guint16 element) -{ - gdcmDictEntry *found = (gdcmDictEntry *)0; - if (!RefPubDict && !RefShaDict) - { - dbg.Verbose(0, "gdcmDocument::GetDictEntry", - "we SHOULD have a default dictionary"); - } - if (RefPubDict) - { - found = RefPubDict->GetDictEntryByNumber(group, element); - if (found) - return found; - } - if (RefShaDict) - { - found = RefShaDict->GetDictEntryByNumber(group, element); - if (found) - return found; - } - return found; -} - /** * \brief Assuming the internal file pointer \ref gdcmDocument::fp * is placed at the beginning of a tag (TestGroup, TestElement), @@ -2788,7 +2383,7 @@ guint32 gdcmDocument::ReadItemTagLength(void) } /** - * \brief Read the length of an exptected Sequence Delimiter tag i.e. + * \brief Read the length of an expected Sequence Delimiter tag i.e. * (0xfffe, 0xe0dd). * \sa \ref gdcmDocument::ReadTagLength * \warning See warning of \ref gdcmDocument::ReadTagLength @@ -2806,6 +2401,7 @@ guint32 gdcmDocument::ReadSequenceDelimiterTagLength(void) * No other way so 'skip' the Data * */ + void gdcmDocument::Parse7FE0 (void) { gdcmDocEntry* Element = GetDocEntryByNumber(0x0002, 0x0010); @@ -2898,6 +2494,8 @@ void gdcmDocument::Parse7FE0 (void) } } + + /** * \brief Compares two documents, according to \ref gdcmDicomDir rules * \warning Does NOT work with ACR-NEMA files @@ -2946,7 +2544,6 @@ bool gdcmDocument::operator<(gdcmDocument &document) } } } - return false; } diff --git a/src/gdcmDocument.h b/src/gdcmDocument.h index 95f7e610..3cf32f68 100644 --- a/src/gdcmDocument.h +++ b/src/gdcmDocument.h @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmDocument.h,v $ Language: C++ - Date: $Date: 2004/06/21 04:18:25 $ - Version: $Revision: 1.12 $ + Date: $Date: 2004/06/22 13:47:33 $ + Version: $Revision: 1.13 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -141,18 +141,14 @@ public: bool CloseFile(void); // Write (used in gdcmFile, gdcmDicomDir) - virtual bool Write(FILE *, FileType); - virtual void WriteEntryTagVRLength(gdcmDocEntry *tag, - FILE *_fp, FileType type); - virtual void WriteEntryValue(gdcmDocEntry *tag,FILE *_fp,FileType type); - virtual bool WriteEntry(gdcmDocEntry *tag,FILE *_fp,FileType type); - virtual bool WriteEntries(FILE *_fp,FileType type); + + virtual bool WriteF(FileType type); // New stuff, with recursive exploration gdcmValEntry * ReplaceOrCreateByNumber(std::string Value, guint16 Group, guint16 Elem); - + gdcmBinEntry * ReplaceOrCreateByNumber(void *voidArea, int lgth, - guint16 Group, guint16 Elem); + guint16 Group, guint16 Elem); bool ReplaceIfExistByNumber (char *Value, guint16 Group, guint16 Elem); virtual void *LoadEntryVoidArea (guint16 Group, guint16 Element); @@ -179,8 +175,8 @@ protected: // Entry int CheckIfEntryExistByNumber(guint16 Group, guint16 Elem ); // int ! public: - virtual std::string GetEntryByName (std::string tagName); - virtual std::string GetEntryVRByName (std::string tagName); + virtual std::string GetEntryByName (TagName tagName); + virtual std::string GetEntryVRByName (TagName tagName); virtual std::string GetEntryByNumber (guint16 group, guint16 element); virtual std::string GetEntryVRByNumber(guint16 group, guint16 element); virtual int GetEntryLengthByNumber(guint16 group, guint16 element); @@ -189,7 +185,7 @@ protected: virtual bool SetEntryByNumber(std::string content, guint16 group, guint16 element); virtual bool SetEntryByNumber(void *content, int lgth, - guint16 group, guint16 element); + guint16 group, guint16 element); virtual bool SetEntryLengthByNumber(guint32 length, guint16 group, guint16 element); @@ -202,7 +198,7 @@ protected: // Header entry gdcmDocEntry *GetDocEntryByNumber (guint16 group, guint16 element); gdcmDocEntry *GetDocEntryByName (std::string Name); - + gdcmValEntry *GetValEntryByNumber (guint16 group, guint16 element); gdcmBinEntry *GetBinEntryByNumber (guint16 group, guint16 element); @@ -242,25 +238,11 @@ private: void SetMaxSizeLoadEntry(long); void SetMaxSizePrintEntry(long); - // DictEntry related utilities - - gdcmDictEntry *GetDictEntryByName (std::string Name); - gdcmDictEntry *GetDictEntryByNumber(guint16, guint16); - gdcmDictEntry *NewVirtualDictEntry(guint16 group, - guint16 element, - std::string vr = "unkn", - std::string fourth = "unkn", - std::string name = "unkn"); + // DocEntry related utilities gdcmDocEntry *ReadNextDocEntry (); - gdcmDocEntry *NewDocEntryByNumber(guint16 group, - guint16 element); - gdcmDocEntry *NewDocEntryByName (std::string Name); - - gdcmValEntry *NewValEntryByNumber(guint16 group, - guint16 element); - gdcmBinEntry *NewBinEntryByNumber(guint16 group, - guint16 element); + + guint32 GenerateFreeTagKeyInGroup(guint16 group); public: diff --git a/src/gdcmElementSet.cxx b/src/gdcmElementSet.cxx index 8c10b275..fbf2d31d 100644 --- a/src/gdcmElementSet.cxx +++ b/src/gdcmElementSet.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmElementSet.cxx,v $ Language: C++ - Date: $Date: 2004/06/20 18:08:47 $ - Version: $Revision: 1.8 $ + Date: $Date: 2004/06/22 13:47:33 $ + Version: $Revision: 1.9 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -18,6 +18,9 @@ #include "gdcmElementSet.h" #include "gdcmDebug.h" +#include "gdcmValEntry.h" +#include "gdcmBinEntry.h" +#include "gdcmSeqEntry.h" //----------------------------------------------------------------------------- // Constructor / Destructor @@ -40,7 +43,7 @@ gdcmElementSet::~gdcmElementSet() { EntryToDelete = cc->second; if ( EntryToDelete ) - delete EntryToDelete; // TODO : a verifier + delete EntryToDelete; } tagHT.clear(); } @@ -60,12 +63,47 @@ gdcmElementSet::~gdcmElementSet() void gdcmElementSet::Print(std::ostream & os) { for (TagDocEntryHT::iterator i = tagHT.begin(); i != tagHT.end(); ++i) { - //(*i)->second->SetPrintLevel(printLevel); + //(i)->second->SetPrintLevel(printLevel); (i->second)->Print(os); } } +/** + * \brief Writes the Header Entries (Dicom Elements) + * from the H Table + * @return + */ +void gdcmElementSet::Write(FILE *fp, FileType filetype) { + +// Troubles expected : BinEntries ARE ValEntries :-( +// BinEntry is checked first, then ValEntry; + gdcmDocEntry *e; + for (TagDocEntryHT::iterator i = tagHT.begin(); i != tagHT.end(); ++i) + { + e=i->second; + e->WriteCommonPart(fp, filetype); + std::cout<GetKey() << " " << hex << e->GetVR() << " " + << e->GetName() + << std::endl; + +// e->Write(fp,filetype); // This will be the right way to proceed ! + + if (gdcmBinEntry* BinEntry = dynamic_cast< gdcmBinEntry* >(e) ) { + BinEntry->Write(fp,filetype); + continue; + } + if (gdcmValEntry* ValEntry = dynamic_cast< gdcmValEntry* >(e) ) { + ValEntry->Write(fp,filetype); + continue; + } + + if (gdcmSeqEntry* SeqEntry = dynamic_cast< gdcmSeqEntry* >(e) ) { + SeqEntry->Write(fp,filetype); + continue; + } + } +} //----------------------------------------------------------------------------- // Protected diff --git a/src/gdcmElementSet.h b/src/gdcmElementSet.h index 56486efe..a7b8b672 100644 --- a/src/gdcmElementSet.h +++ b/src/gdcmElementSet.h @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmElementSet.h,v $ Language: C++ - Date: $Date: 2004/06/20 18:08:47 $ - Version: $Revision: 1.8 $ + Date: $Date: 2004/06/22 13:47:33 $ + Version: $Revision: 1.9 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -24,6 +24,11 @@ #include "gdcmCommon.h" #include "gdcmDocEntrySet.h" +class gdcmValEntry; +class gdcmBinEntry; +class gdcmSeqEntry; + + typedef std::map TagDocEntryHT; //----------------------------------------------------------------------------- @@ -37,6 +42,8 @@ public: virtual bool RemoveEntry(gdcmDocEntry *EntryToRemove); virtual void Print(std::ostream &os = std::cout); + virtual void Write(FILE *fp, FileType filetype); + protected: // Variables diff --git a/src/gdcmFile.cxx b/src/gdcmFile.cxx index e13944b2..1e816219 100644 --- a/src/gdcmFile.cxx +++ b/src/gdcmFile.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmFile.cxx,v $ Language: C++ - Date: $Date: 2004/06/21 04:52:08 $ - Version: $Revision: 1.104 $ + Date: $Date: 2004/06/22 13:47:33 $ + Version: $Revision: 1.105 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -102,14 +102,6 @@ gdcmFile::~gdcmFile(void) { //----------------------------------------------------------------------------- // Public -/** - * \ingroup gdcmFile - * \brief returns the gdcmHeader *Header - * @return - */ -gdcmHeader *gdcmFile::GetHeader(void) { - return(Header); -} /** * \ingroup gdcmFile diff --git a/src/gdcmFile.h b/src/gdcmFile.h index 3538a865..9fc38498 100644 --- a/src/gdcmFile.h +++ b/src/gdcmFile.h @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmFile.h,v $ Language: C++ - Date: $Date: 2004/06/21 04:52:08 $ - Version: $Revision: 1.31 $ + Date: $Date: 2004/06/22 13:47:33 $ + Version: $Revision: 1.32 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -39,16 +39,17 @@ public: virtual ~gdcmFile(void); - gdcmHeader *GetHeader(void); + /// \brief returns the gdcmHeader *Header + inline gdcmHeader *GetHeader(void) {return(Header);}; - // For promotion (performs a deepcopy of pointed header object) - // TODO Swig gdcmFile(gdcmHeader* header); - // TODO Swig ~gdcmFile(); + // For promotion (performs a deepcopy of pointed header object) + // TODO Swig gdcmFile(gdcmHeader* header); + // TODO Swig ~gdcmFile(); - // On writing purposes. When instance was created through - // gdcmFile(std::string filename) then the filename argument MUST be + // On writing purposes. When instance was created through + // gdcmFile(std::string filename) then the filename argument MUST be // different from the constructor's one (no overwriting allowed). - // TODO Swig int SetFileName(std::string filename); + // TODO Swig int SetFileName(std::string filename); void SetPixelDataSizeFromHeader(void); size_t GetImageDataSize(); @@ -58,7 +59,7 @@ public: size_t GetImageDataIntoVector(void* destination, size_t MaxSize); void * GetImageDataRaw(); size_t GetImageDataIntoVectorRaw(void* destination, size_t MaxSize); - + // Allocates ExpectedSize bytes of memory at this->Data and copies the // pointed data to it. Copying the image might look useless but // the caller might destroy it's image (without knowing it: think @@ -69,12 +70,10 @@ public: bool SetImageData (void * Data, size_t ExpectedSize); // When the caller is aware we simply point to the data: // TODO int SetImageDataNoCopy (void * Data, size_t ExpectedSize); - - // Push to disk. - // A NE PAS OUBLIER : que fait-on en cas de Transfert Syntax (dans l'entete) - // incohérente avec l'ordre des octets en mémoire ? - // TODO Swig int Write(); - + + // Push to disk. + // TODO Swig int Write(); + // Write pixels of ONE image on hard drive // No test is made on processor "endianity" // The user must call his reader correctly @@ -116,8 +115,8 @@ private: /// \brief Header to use to load the file gdcmHeader *Header; - - /// \brief Whether the underlying \ref gdcmHeader was loaded by + + /// \brief Whether the underlying \ref gdcmHeader was loaded by /// the constructor or passed to the constructor. When false /// the destructor is in charge of deletion. bool SelfHeader; diff --git a/src/gdcmJpeg.cxx b/src/gdcmJpeg.cxx index e4b548c7..123f68e1 100644 --- a/src/gdcmJpeg.cxx +++ b/src/gdcmJpeg.cxx @@ -5,6 +5,8 @@ #define BITS_IN_JSAMPLE 8 +#define GDCM_jpr_DEBUG 0 + /* DICOM provides a mechanism for supporting the use of JPEG Image Compression through the Encapsulated Format (see PS 3.3 of the DICOM Standard). @@ -189,9 +191,9 @@ bool gdcmFile::gdcm_read_JPEG_file (FILE *fp,void * image_buffer) { int row_stride; /* physical row width in output buffer */ -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf("entree dans gdcmFile::gdcm_read_JPEG_file12, depuis gdcmJpeg\n"); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG /* In this example we want to open the input file before doing anything else, * so that the setjmp() error recovery below can assume the file is open. @@ -200,9 +202,9 @@ bool gdcmFile::gdcm_read_JPEG_file (FILE *fp,void * image_buffer) { */ /* Step 1: allocate and initialize JPEG decompression object */ -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf("Entree Step 1\n"); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG /* We set up the normal JPEG error routines, then override error_exit. */ @@ -221,16 +223,16 @@ bool gdcmFile::gdcm_read_JPEG_file (FILE *fp,void * image_buffer) { jpeg_create_decompress(&cinfo); /* Step 2: specify data source (eg, a file) */ -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf("Entree Step 2\n"); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG jpeg_stdio_src(&cinfo, fp); /* Step 3: read file parameters with jpeg_read_header() */ -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf("Entree Step 3\n"); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG (void) jpeg_read_header(&cinfo, TRUE); @@ -240,7 +242,7 @@ bool gdcmFile::gdcm_read_JPEG_file (FILE *fp,void * image_buffer) { * See libjpeg.doc for more info. */ -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf("--------------Header contents :----------------\n"); printf("image_width %d image_height %d\n", cinfo.image_width , cinfo.image_height); @@ -248,7 +250,7 @@ bool gdcmFile::gdcm_read_JPEG_file (FILE *fp,void * image_buffer) { cinfo.output_components); printf("nb of color components returned %d \n", cinfo.data_precision); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG /* @@ -261,17 +263,17 @@ bool gdcmFile::gdcm_read_JPEG_file (FILE *fp,void * image_buffer) { */ /* Step 4: set parameters for decompression */ -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf("Entree Step 4\n"); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG /* In this example, we don't need to change any of the defaults set by * jpeg_read_header(), so we do nothing here. */ /* Step 5: Start decompressor */ -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf("Entree Step 5\n"); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG (void) jpeg_start_decompress(&cinfo); /* We can ignore the return value since suspension is not possible @@ -288,28 +290,28 @@ bool gdcmFile::gdcm_read_JPEG_file (FILE *fp,void * image_buffer) { /* JSAMPLEs per row in output buffer */ row_stride = cinfo.output_width * cinfo.output_components; -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf ("cinfo.output_width %d cinfo.output_components %d row_stride %d\n", cinfo.output_width, cinfo.output_components,row_stride); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG /* Make a one-row-high sample array that will go away when done with image */ buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); /* Step 6: while (scan lines remain to be read) */ -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf("Entree Step 6\n"); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG /* jpeg_read_scanlines(...); */ /* Here we use the library's state variable cinfo.output_scanline as the * loop counter, so that we don't have to keep track ourselves. */ -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf ("cinfo.output_height %d cinfo.output_width %d\n", cinfo.output_height,cinfo.output_width); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG pimage=(char *)image_buffer; while (cinfo.output_scanline < cinfo.output_height) { @@ -336,9 +338,9 @@ bool gdcmFile::gdcm_read_JPEG_file (FILE *fp,void * image_buffer) { } /* Step 7: Finish decompression */ -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf("Entree Step 7\n"); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG (void) jpeg_finish_decompress(&cinfo); @@ -348,9 +350,9 @@ bool gdcmFile::gdcm_read_JPEG_file (FILE *fp,void * image_buffer) { /* Step 8: Release JPEG decompression object */ -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf("Entree Step 8\n"); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG /* This is an important step since it will release a good deal of memory. */ diff --git a/src/gdcmJpeg12.cxx b/src/gdcmJpeg12.cxx index 6b84a957..294ab89d 100644 --- a/src/gdcmJpeg12.cxx +++ b/src/gdcmJpeg12.cxx @@ -5,6 +5,7 @@ #define BITS_IN_JSAMPLE 12 +#define GDCM_jpr_DEBUG 0 // BITS_IN_JSAMPLE is a compile time defined options. // We need both 8 an 12; // To avoid renaming *all* the Jpeg functions, @@ -201,9 +202,9 @@ bool gdcmFile::gdcm_read_JPEG_file12 (FILE *fp,void * image_buffer) { // typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ int row_stride; /* physical row width in output buffer */ -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf("entree dans gdcmFile::gdcm_read_JPEG_file12, depuis gdcmJpeg\n"); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG /* In this example we want to open the input file before doing anything else, * so that the setjmp() error recovery below can assume the file is open. @@ -212,9 +213,9 @@ bool gdcmFile::gdcm_read_JPEG_file12 (FILE *fp,void * image_buffer) { */ /* Step 1: allocate and initialize JPEG decompression object */ -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf("Entree Step 1\n"); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG /* We set up the normal JPEG error routines, then override error_exit. */ @@ -234,15 +235,15 @@ bool gdcmFile::gdcm_read_JPEG_file12 (FILE *fp,void * image_buffer) { jpeg_create_decompress(&cinfo); /* Step 2: specify data source (eg, a file) */ -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf("Entree Step 2\n"); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG jpeg_stdio_src(&cinfo, fp); /* Step 3: read file parameters with jpeg_read_header() */ -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf("Entree Step 3\n"); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG (void) jpeg_read_header(&cinfo, TRUE); /* We can ignore the return value from jpeg_read_header since @@ -251,7 +252,7 @@ bool gdcmFile::gdcm_read_JPEG_file12 (FILE *fp,void * image_buffer) { * See libjpeg.doc for more info. */ -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf("--------------Header contents :----------------\n"); printf("image_width %d image_height %d\n", cinfo.image_width , cinfo.image_height); @@ -259,7 +260,7 @@ bool gdcmFile::gdcm_read_JPEG_file12 (FILE *fp,void * image_buffer) { cinfo.output_components); printf("nb of color components returned %d \n", cinfo.data_precision); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG /* @@ -272,18 +273,18 @@ bool gdcmFile::gdcm_read_JPEG_file12 (FILE *fp,void * image_buffer) { */ /* Step 4: set parameters for decompression */ -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf("Entree Step 4\n"); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG /* In this example, we don't need to change any of the defaults set by * jpeg_read_header(), so we do nothing here. */ /* Step 5: Start decompressor */ -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf("Entree Step 5\n"); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG (void) jpeg_start_decompress(&cinfo); /* We can ignore the return value since suspension is not possible @@ -300,19 +301,19 @@ bool gdcmFile::gdcm_read_JPEG_file12 (FILE *fp,void * image_buffer) { /* JSAMPLEs per row in output buffer */ row_stride = cinfo.output_width * cinfo.output_components; -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf ("cinfo.output_width %d cinfo.output_components %d row_stride %d\n", cinfo.output_width, cinfo.output_components,row_stride); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG /* Make a one-row-high sample array that will go away when done with image */ buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); /* Step 6: while (scan lines remain to be read) */ -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf("Entree Step 6\n"); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG /* jpeg_read_scanlines(...); */ @@ -320,10 +321,10 @@ bool gdcmFile::gdcm_read_JPEG_file12 (FILE *fp,void * image_buffer) { * loop counter, so that we don't have to keep track ourselves. */ -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf ("cinfo.output_height %d cinfo.output_width %d\n", cinfo.output_height,cinfo.output_width); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG pimage=(char *)image_buffer; @@ -345,18 +346,18 @@ bool gdcmFile::gdcm_read_JPEG_file12 (FILE *fp,void * image_buffer) { } /* Step 7: Finish decompression */ -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf("Entree Step 7\n"); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG (void) jpeg_finish_decompress(&cinfo); /* We can ignore the return value since suspension is not possible * with the stdio data source. */ /* Step 8: Release JPEG decompression object */ -#ifdef GDCM_DEBUG +#ifdef GDCM_jpr_DEBUG printf("Entree Step 8\n"); -#endif //GDCM_DEBUG +#endif //GDCM_jpr_DEBUG /* This is an important step since it will release a good deal of memory. */ jpeg_destroy_decompress(&cinfo); diff --git a/src/gdcmParsePixels.cxx b/src/gdcmParsePixels.cxx index 268492e7..8918bd92 100644 --- a/src/gdcmParsePixels.cxx +++ b/src/gdcmParsePixels.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmParsePixels.cxx,v $ Language: C++ - Date: $Date: 2004/06/20 18:08:48 $ - Version: $Revision: 1.6 $ + Date: $Date: 2004/06/22 13:47:33 $ + Version: $Revision: 1.7 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -62,7 +62,7 @@ bool gdcmFile::ParsePixelData(void) { nb = atoi(str_nb.c_str() ); if (nb == 12) nb =16; } - //int nBytes= nb/8; //FIXME + //int nBytes= nb/8; //FIXME //int taille = Header->GetXSize() * Header->GetYSize() * Header->GetSamplesPerPixel(); diff --git a/src/gdcmSQItem.cxx b/src/gdcmSQItem.cxx index 02ac489c..709456b3 100644 --- a/src/gdcmSQItem.cxx +++ b/src/gdcmSQItem.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmSQItem.cxx,v $ Language: C++ - Date: $Date: 2004/06/19 23:51:04 $ - Version: $Revision: 1.10 $ + Date: $Date: 2004/06/22 13:47:33 $ + Version: $Revision: 1.11 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -22,8 +22,10 @@ #include "gdcmBinEntry.h" #include "gdcmGlobal.h" #include "gdcmUtil.h" + #include "gdcmDebug.h" + //----------------------------------------------------------------------------- // Constructor / Destructor /** @@ -61,7 +63,7 @@ gdcmSQItem::~gdcmSQItem() for (int i=0;iWriteCommonPart(fp, filetype); + + if (gdcmBinEntry* BinEntry = dynamic_cast< gdcmBinEntry* >(Entry) ) { + BinEntry->Write(fp,filetype); + return; + } + if (gdcmValEntry* ValEntry = dynamic_cast< gdcmValEntry* >(Entry) ) { + ValEntry->Write(fp,filetype); + return; + } + if (gdcmSeqEntry* SeqEntry = dynamic_cast< gdcmSeqEntry* >(Entry) ) { + SeqEntry->Write(fp,filetype); + return; + } + } +} + + //----------------------------------------------------------------------------- // Public /** @@ -93,10 +125,11 @@ bool gdcmSQItem::AddEntry(gdcmDocEntry *entry) * \warning we suppose, right now, the element belongs to a Public Group * (NOT a shadow one) * @param val string value to set - * @param group Group of the searched tag. - * @param element Element of the searched tag. + * @param group Group number of the searched tag. + * @param element Element number of the searched tag. * @return true if element was found or created successfully */ + bool gdcmSQItem::SetEntryByNumber(std::string val,guint16 group, guint16 element) { @@ -104,6 +137,7 @@ bool gdcmSQItem::SetEntryByNumber(std::string val,guint16 group, { if ( (*i)->GetGroup() == 0xfffe && (*i)->GetElement() == 0xe000 ) continue; + if ( ( group < (*i)->GetGroup() ) ||( group == (*i)->GetGroup() && element < (*i)->GetElement()) ) { @@ -111,6 +145,7 @@ bool gdcmSQItem::SetEntryByNumber(std::string val,guint16 group, // that is a method of gdcmDocument :-( gdcmValEntry* Entry = (gdcmValEntry*)0; TagKey key = gdcmDictEntry::TranslateToKey(group, element); + if ( ! ptagHT->count(key)) { // we assume a Public Dictionnary *is* loaded @@ -144,7 +179,7 @@ bool gdcmSQItem::SetEntryByNumber(std::string val,guint16 group, Entry->SetLength(val.length()); docEntries.insert(i,Entry); return true; - } + } if (group == (*i)->GetGroup() && element == (*i)->GetElement() ) { if ( gdcmValEntry* Entry = dynamic_cast(*i) ) @@ -157,55 +192,20 @@ bool gdcmSQItem::SetEntryByNumber(std::string val,guint16 group, //----------------------------------------------------------------------------- // Protected -//----------------------------------------------------------------------------- -// Private - -// end-user intended : the guy *wants* to create his own SeQuence ?!? - -/// \brief to be written if really usefull -gdcmDocEntry *gdcmSQItem::NewDocEntryByNumber(guint16 group, - guint16 element) { -/// \todo TODO - gdcmDocEntry *a; - std::cout << " gdcmSQItem::NewDocEntryByNumber : TODO" <GetDefaultPubDict(); - gdcmDictEntry *dictEntry = (*PubDict).GetDictEntryByName(name); - if( dictEntry == NULL) - return NULL; - return GetDocEntryByNumber(dictEntry->GetGroup(),dictEntry->GetElement()); -} /** - * \ingroup gdcmSQItem * \brief Gets a Dicom Element inside a SQ Item Entry, by number * @return */ -gdcmDocEntry *gdcmSQItem::GetDocEntryByNumber(guint16 group, guint16 element) { +gdcmDocEntry *gdcmSQItem::GetDocEntryByNumber(guint16 group, guint16 element) { for(ListDocEntry::iterator i=docEntries.begin();i!=docEntries.end();++i) { if ( (*i)->GetGroup()==group && (*i)->GetElement()==element) return (*i); } - return NULL; + return NULL; } /** - * \ingroup gdcmSQItem * \brief Get the value of a Dicom Element inside a SQ Item Entry, by number * @return */ @@ -218,21 +218,8 @@ std::string gdcmSQItem::GetEntryByNumber(guint16 group, guint16 element) { } return GDCM_UNFOUND; } +//----------------------------------------------------------------------------- +// Private -/** - * \ingroup gdcmSQItem - * \brief Get the value of a Dicom Element inside a SQ Item Entry, by name - * @param name : name of the searched element. - * @return - */ - -std::string gdcmSQItem::GetEntryByName(TagName name) { - gdcmDict *PubDict=gdcmGlobal::GetDicts()->GetDefaultPubDict(); - gdcmDictEntry *dictEntry = (*PubDict).GetDictEntryByName(name); - - if( dictEntry == NULL) - return GDCM_UNFOUND; - return GetEntryByNumber(dictEntry->GetGroup(),dictEntry->GetElement()); -} //----------------------------------------------------------------------------- diff --git a/src/gdcmSQItem.h b/src/gdcmSQItem.h index e08ae79c..1cfae31f 100644 --- a/src/gdcmSQItem.h +++ b/src/gdcmSQItem.h @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmSQItem.h,v $ Language: C++ - Date: $Date: 2004/06/20 18:08:48 $ - Version: $Revision: 1.9 $ + Date: $Date: 2004/06/22 13:47:33 $ + Version: $Revision: 1.10 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -23,6 +23,9 @@ #include "gdcmDocEntrySet.h" #include "gdcmDocument.h" + +class gdcmBinEntry; + //----------------------------------------------------------------------------- typedef std::list ListDocEntry; //----------------------------------------------------------------------------- @@ -33,6 +36,7 @@ public: ~gdcmSQItem(void); virtual void Print(std::ostream &os = std::cout); + virtual void Write(FILE *fp, FileType filetype); /// \brief returns the DocEntry chained List for this SQ Item. inline ListDocEntry &GetDocEntries() {return docEntries;}; @@ -48,20 +52,19 @@ public: bool SetEntryByNumber(std::string val,guint16 group, guint16 element); - std::string GetEntryByNumber(guint16 group, guint16 element); - std::string GetEntryByName(TagName name); + virtual std::string GetEntryByNumber(guint16 group, guint16 element); + + inline int GetSQItemNumber() + {return SQItemNumber;}; - inline int GetSQItemNumber() { return SQItemNumber;}; + inline void SetSQItemNumber(int itemNumber) + {SQItemNumber=itemNumber;}; - inline void SetSQItemNumber(int itemNumber) { SQItemNumber=itemNumber;}; protected: // DocEntry related utilities - - virtual gdcmDocEntry *NewDocEntryByNumber(guint16 group, - guint16 element); // TODO - virtual gdcmDocEntry *NewDocEntryByName (std::string Name); //TODO + // Variables /// \brief chained list of (Elementary) Doc Entries diff --git a/src/gdcmSeqEntry.cxx b/src/gdcmSeqEntry.cxx index abc8b9cf..c589f78c 100644 --- a/src/gdcmSeqEntry.cxx +++ b/src/gdcmSeqEntry.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmSeqEntry.cxx,v $ Language: C++ - Date: $Date: 2004/06/21 04:43:02 $ - Version: $Revision: 1.13 $ + Date: $Date: 2004/06/22 13:47:33 $ + Version: $Revision: 1.14 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -46,6 +46,7 @@ gdcmSeqEntry::~gdcmSeqEntry() { for(ListSQItem::iterator cc = items.begin();cc != items.end();++cc) { delete *cc; + cout << "delete SQItem" << endl; } if (!seq_term) delete seq_term; @@ -61,30 +62,25 @@ void gdcmSeqEntry::Print(std::ostream &os){ std::ostringstream s,s2; std::string vr; - //unsigned short int g, e; //not used - //long lgth; //not used - //size_t o; //not used - //char greltag[10]; //group element tag //not used - //char st[20]; //not used - // First, Print the Dicom Element itself. SetPrintLevel(2); PrintCommonPart(os); s << std::endl; os << s.str(); - + + if (GetReadLength() == 0) + return; + // Then, Print each SQ Item for(ListSQItem::iterator cc = items.begin();cc != items.end();++cc) - { + { (*cc)->Print(os); } - // at end, print the sequence terminator item, if any + // at end, print the sequence terminator item, if any if (delimitor_mode) { - if (SQDepthLevel>0) { - for (int i=0;iPrint(os); @@ -96,6 +92,18 @@ void gdcmSeqEntry::Print(std::ostream &os){ } } + +/* + * \brief canonical Writer + */ +void gdcmSeqEntry::Write(FILE *fp, FileType filetype) { + for(ListSQItem::iterator cc = GetSQItems().begin(); + cc != GetSQItems().end(); + ++cc) { + std::cout << "Et un SQItem !" << std::endl; + (*cc)->Write(fp, filetype); + } +} //----------------------------------------------------------------------------- // Public @@ -116,15 +124,15 @@ void gdcmSeqEntry::SetDepthLevel(int depth) { gdcmSQItem *gdcmSeqEntry::GetSQItemByOrdinalNumber(int nb) { if (nb<0) - return (*(items.begin())); - int count = 0 ; + return (*(items.begin())); + int count = 0 ; for(ListSQItem::iterator cc = items.begin(); - cc != items.end(); - count ++, ++cc){ + cc != items.end(); + count ++, ++cc){ if (count==nb) - return (*cc); + return (*cc); } - return (*(items.end())); + return (*(items.end())); } //----------------------------------------------------------------------------- // Protected diff --git a/src/gdcmSeqEntry.h b/src/gdcmSeqEntry.h index 325aff66..764ab321 100644 --- a/src/gdcmSeqEntry.h +++ b/src/gdcmSeqEntry.h @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmSeqEntry.h,v $ Language: C++ - Date: $Date: 2004/06/21 04:43:02 $ - Version: $Revision: 1.11 $ + Date: $Date: 2004/06/22 13:47:33 $ + Version: $Revision: 1.12 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -35,6 +35,7 @@ public: virtual ~gdcmSeqEntry(); virtual void Print(std::ostream &os = std::cout); + virtual void Write(FILE *fp,FileType filetype); /// \brief returns the SQITEM chained List for this SeQuence. inline ListSQItem &GetSQItems() { return items; } @@ -44,7 +45,7 @@ public: /// \brief Sets the Sequence Delimitation Item inline void SetSequenceDelimitationItem(gdcmDocEntry * e) { seq_term = e;} - + void AddEntry(gdcmSQItem *it, int itemNumber); gdcmSQItem *GetSQItemByOrdinalNumber(int itemNumber); diff --git a/src/gdcmTS.cxx b/src/gdcmTS.cxx index 864367c0..4a8fffbd 100644 --- a/src/gdcmTS.cxx +++ b/src/gdcmTS.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmTS.cxx,v $ Language: C++ - Date: $Date: 2004/06/21 04:43:02 $ - Version: $Revision: 1.19 $ + Date: $Date: 2004/06/22 13:47:33 $ + Version: $Revision: 1.20 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -41,6 +41,7 @@ gdcmTS::gdcmTS(void) while (!from.eof()) { from >> key; + eatwhite(from); getline(from, name); /// MEMORY LEAK diff --git a/src/gdcmValEntry.cxx b/src/gdcmValEntry.cxx index 194bd88d..8f543f34 100644 --- a/src/gdcmValEntry.cxx +++ b/src/gdcmValEntry.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmValEntry.cxx,v $ Language: C++ - Date: $Date: 2004/06/21 12:38:29 $ - Version: $Revision: 1.9 $ + Date: $Date: 2004/06/22 13:47:33 $ + Version: $Revision: 1.10 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -111,9 +111,9 @@ void gdcmValEntry::Print(std::ostream & os) s << " ==>\t[" << ts->GetValue(v) << "]"; } else { if (g == 0x0004) { - if ( (e == 0x1510) || (e == 0x1512) ) - s << " ==>\t[" << ts->GetValue(v) << "]"; - } + if ( (e == 0x1510) || (e == 0x1512) ) + s << " ==>\t[" << ts->GetValue(v) << "]"; + } } } //if (e == 0x0000) { // elem 0x0000 --> group length @@ -123,8 +123,8 @@ void gdcmValEntry::Print(std::ostream & os) else { if ( GetLength() !=0 ) sprintf(st," x(%x)", atoi(v.c_str()));//FIXME - else - sprintf(st," "); + else + sprintf(st," "); } s << st; } @@ -132,7 +132,48 @@ void gdcmValEntry::Print(std::ostream & os) s << std::endl; os << s.str(); } - + + +/* + * \brief canonical Writer + */ +void gdcmValEntry::Write(FILE *fp, FileType filetype) { + string vr=GetVR(); + int lgr=GetLength(); + if (vr == "US" || vr == "SS") { + // some 'Short integer' fields may be mulivaluated + // each single value is separated from the next one by '\' + // we split the string and write each value as a short int + std::vector tokens; + tokens.erase(tokens.begin(),tokens.end()); // clean any previous value + Tokenize (GetValue(), tokens, "\\"); + for (unsigned int i=0; i tokens; + tokens.erase(tokens.begin(),tokens.end()); // clean any previous value + Tokenize (GetValue(), tokens, "\\"); + for (unsigned int i=0; i