From 0d33ba5ffb1c6beac21f33bd3e3aad67b7608c9d Mon Sep 17 00:00:00 2001 From: jpr Date: Tue, 18 May 2004 17:55:48 +0000 Subject: [PATCH] PLEASE : keep on waiting for the final version ! --- src/gdcmBinEntry.cxx | 5 +- src/gdcmBinEntry.h | 3 +- src/gdcmDocEntry.cxx | 74 ++------ src/gdcmDocEntry.h | 6 +- src/gdcmDocEntrySet.cxx | 3 +- src/gdcmDocEntrySet.h | 20 +-- src/gdcmDocument.cxx | 362 ++++++++++++++++++++++++---------------- src/gdcmDocument.h | 32 ++-- src/gdcmElementSet.cxx | 48 +++--- src/gdcmElementSet.h | 9 +- src/gdcmSQItem.cxx | 6 +- src/gdcmSeqEntry.cxx | 27 ++- src/gdcmSeqEntry.h | 16 +- src/gdcmValEntry.cxx | 84 +++++++++- src/gdcmValEntry.h | 9 +- 15 files changed, 437 insertions(+), 267 deletions(-) diff --git a/src/gdcmBinEntry.cxx b/src/gdcmBinEntry.cxx index 15110221..8478f586 100644 --- a/src/gdcmBinEntry.cxx +++ b/src/gdcmBinEntry.cxx @@ -29,7 +29,10 @@ gdcmBinEntry::~gdcmBinEntry(){ * \brief canonical Printer */ - +void gdcmBinEntry::Print(std::ostream &os = std::cout) { + PrintCommonPart(os); + std::cout << "gdcmBinEntry : Print, et alors ?" < // for std::ios::left, ... - +// CLEAN ME #define MAX_SIZE_PRINT_ELEMENT_VALUE 64 //----------------------------------------------------------------------------- @@ -24,36 +24,39 @@ gdcmDocEntry::gdcmDocEntry(gdcmDictEntry* in) { entry = in; } +void gdcmDocEntry::Print(std::ostream & os) { + std::ostringstream s; + s << std::endl; + PrintCommonPart(os); + os << s.str(); +} + //----------------------------------------------------------------------------- // Print /** * \ingroup gdcmDocEntry - * \brief canonical Printer + * \brief Prints the common part of gdcmValEntry, gdcmBinEntry, gdcmSeqEntry */ -void gdcmDocEntry::Print(std::ostream & os) { - -// TODO : (no more chained list ...) +void gdcmDocEntry::PrintCommonPart(std::ostream & os) { -/* + printLevel=2; // FIXME + size_t o; unsigned short int g, e; char st[20]; TSKey v; std::string d2, vr; - gdcmTS * ts = gdcmGlobal::GetTS(); std::ostringstream s; guint32 lgth; char greltag[10]; //group element tag g = GetGroup(); e = GetElement(); - v = GetValue(); o = GetOffset(); vr = GetVR(); sprintf(greltag,"%04x|%04x ",g,e); s << greltag ; - d2 = CreateCleanString(v); // replace non printable characters by '.' if (printLevel>=2) { s << "lg : "; lgth = GetReadLength(); // ReadLength, as opposed to UsableLength @@ -87,52 +90,7 @@ void gdcmDocEntry::Print(std::ostream & os) { } s << "[" << GetName()<< "]"; - - if (voidArea != NULL) { - s << " [gdcm::Non String Data Loaded in Unsecure Area (" - << GetLength() << ") ]"; - } - - else { - if( (GetLength()=3) || - (d2.find("gdcm::NotLoaded.") < d2.length()) ) - s << " [" << d2 << "]"; - else - s << " [gdcm::too long for print (" << GetLength() << ") ]"; - } - - // Display the UID value (instead of displaying only the rough code) - if (g == 0x0002) { // Any more to be displayed ? - if ( (e == 0x0010) || (e == 0x0002) ) - s << " ==>\t[" << ts->GetValue(v) << "]"; - } else { - if (g == 0x0008) { - if ( (e == 0x0016) || (e == 0x1150) ) - s << " ==>\t[" << ts->GetValue(v) << "]"; - } else { - if (g == 0x0004) { - if ( (e == 0x1510) || (e == 0x1512) ) - s << " ==>\t[" << ts->GetValue(v) << "]"; - } - } - } - //if (e == 0x0000) { // elem 0x0000 --> group length - if ( (vr == "UL") || (vr == "US") || (vr == "SL") || (vr == "SS") ) { - if (v == "4294967295") // to avoid troubles in convertion - sprintf (st," x(ffffffff)"); - else { - if ( GetLength() !=0 ) - sprintf(st," x(%x)", atoi(v.c_str()));//FIXME - else - sprintf(st," "); - } - s << st; - } - s << std::endl; - os << s.str(); - - */ + os << s.str(); } //----------------------------------------------------------------------------- @@ -140,11 +98,11 @@ void gdcmDocEntry::Print(std::ostream & os) { /** * \ingroup gdcmDocEntry - * \brief Gets the full length of the DocEntry (not only value length) + * \brief Gets the full length of the elementary DocEntry (not only value length) */ guint32 gdcmDocEntry::GetFullLength(void) { guint32 l; - l = GetLength(); + l = GetReadLength(); if ( IsImplicitVR() ) l = l + 8; // 2 (gr) + 2 (el) + 4 (lgth) else @@ -167,7 +125,7 @@ void gdcmDocEntry::Copy (gdcmDocEntry* e) { this->ImplicitVR = e->ImplicitVR; this->Offset = e->Offset; this->printLevel = e->printLevel; - this->SQDepthLevel = e->SQDepthLevel; + // TODO : remove gdcmDocEntry SQDepth } bool gdcmDocEntry::isItemDelimitor() { diff --git a/src/gdcmDocEntry.h b/src/gdcmDocEntry.h index 37b9aa39..b48e3cb0 100644 --- a/src/gdcmDocEntry.h +++ b/src/gdcmDocEntry.h @@ -111,7 +111,9 @@ public: /// \brief Gets the print level for the Dicom Header Elements int GetPrintLevel(void) { return(printLevel); }; - void Print (std::ostream & os = std::cout); + virtual void Print (std::ostream & os = std::cout); + + void gdcmDocEntry::PrintCommonPart(std::ostream & os); /// Gets the depth level of a Dicom Header Entry embedded in a SeQuence inline int GetSQDepthLevel(void) { return (SQDepthLevel); }; @@ -131,6 +133,8 @@ private: /// Sets the depth level of a Dicom Header Entry embedded in a SeQuence inline void SetSQDepthLevel(int depthLevel) { SQDepthLevel = depthLevel; }; + +protected: // Variables gdcmDictEntry *entry; diff --git a/src/gdcmDocEntrySet.cxx b/src/gdcmDocEntrySet.cxx index 32301489..00f790da 100644 --- a/src/gdcmDocEntrySet.cxx +++ b/src/gdcmDocEntrySet.cxx @@ -41,7 +41,6 @@ gdcmDocEntrySet::~gdcmDocEntrySet(){ // Protected - //----------------------------------------------------------------------------- // Private @@ -108,7 +107,7 @@ bool gdcmDocEntrySet::LoadDocEntrySet(bool exception_on_error) // Maybe the following VR do correspond to a BinEntry - //AT Attribute Tag; // OK // 2 16-bit unsigned short integers + //AT Attribute Tag; // 2 16-bit unsigned short integers //FL Floating Point Single; // 32-bit IEEE 754:1985 float //FD Floating Point Double; // 64-bit IEEE 754:1985 double //UN Unknown; // Any length of bytes diff --git a/src/gdcmDocEntrySet.h b/src/gdcmDocEntrySet.h index ff309a33..b2132bfe 100644 --- a/src/gdcmDocEntrySet.h +++ b/src/gdcmDocEntrySet.h @@ -16,20 +16,13 @@ public: gdcmDocEntrySet(void); ~gdcmDocEntrySet(void); - void FindDocEntryLength (gdcmDocEntry *Entry, FileType filetype, FILE* fp); - virtual bool AddEntry(gdcmDocEntry *Entry) =0; // pure virtual - bool CheckEntryVR(gdcmDocEntry *Entry, std::string vr); - gdcmDictEntry *NewVirtualDictEntry(guint16 group, - guint16 element, - std::string vr = "unkn", - std::string fourth = "unkn", - std::string name = "unkn"); - + virtual bool AddEntry(gdcmDocEntry *Entry) = 0; // pure virtual + bool CheckEntryVR(gdcmDocEntry *Entry, std::string vr); + virtual void Print (std::ostream & os = std::cout) = 0;// pure virtual + protected: void gdcmDocEntrySet::FindDocEntryLength (gdcmDocEntry *Entry); - -private: // DocEntry related utilities @@ -37,7 +30,10 @@ private: guint16 element)=0; // pure virtual virtual gdcmDocEntry *NewDocEntryByName (std::string Name)=0; // pure virtual - + + +private: + }; diff --git a/src/gdcmDocument.cxx b/src/gdcmDocument.cxx index db729329..6ac00db8 100644 --- a/src/gdcmDocument.cxx +++ b/src/gdcmDocument.cxx @@ -71,10 +71,22 @@ gdcmDocument::gdcmDocument(const char *inFilename, if ( !OpenFile(exception_on_error)) return; + + rewind(fp); + //if (!CheckSwap()) + // return false; // to go on compiling + + fseek(fp,0L,SEEK_END); + long lgt = ftell(fp); + + rewind(fp); + CheckSwap(); + long beg = ftell(fp); + lgt -= beg; + + //std::cout << "beg, lgt : " << beg << " " << lgt << std::endl; - //LoadHeaderEntries(); - long l=ParseES( (gdcmDocEntrySet *)this, 120L, 0x7fffffff, false); - // TODO : find the right values + long l=ParseDES( this, beg, lgt, false); // le Load sera fait a la volee CloseFile(); printLevel = 1; // 'Medium' print level by default @@ -105,21 +117,7 @@ gdcmDocument::~gdcmDocument (void) { //----------------------------------------------------------------------------- // Print /** - * \brief Prints the Header Entries (Dicom Elements) - * from the chained list - * @return - */ -void gdcmDocument::PrintEntry(std::ostream & os) { - - for (ListTag::iterator i = listEntries.begin(); - i != listEntries.end(); - ++i) - { - (*i)->SetPrintLevel(printLevel); - (*i)->Print(os); - } -} - + /** * \brief Prints The Dict Entries of THE public Dicom Dictionary @@ -180,7 +178,7 @@ bool gdcmDocument::SetShaDict(DictKey dictName){ * false otherwise. */ bool gdcmDocument::IsReadable(void) { - if(filetype==Unknown) { + if(filetype==gdcmUnknown) { return(false); } if(listEntries.size()<=0) { @@ -348,7 +346,7 @@ bool gdcmDocument::Write(FILE *fp, FileType type) { /// a moins de se livrer a un tres complique ajout des champs manquants. /// faire un CheckAndCorrectHeader (?) - if (type == ImplicitVR) + if (type == gdcmImplicitVR) { std::string implicitVRTransfertSyntax = UI1_2_840_10008_1_2; ReplaceOrCreateByNumber(implicitVRTransfertSyntax,0x0002, 0x0010); @@ -361,7 +359,7 @@ bool gdcmDocument::Write(FILE *fp, FileType type) { SetEntryLengthByNumber(18, 0x0002, 0x0010); } - if (type == ExplicitVR) + if (type == gdcmExplicitVR) { std::string explicitVRTransfertSyntax = UI1_2_840_10008_1_2_1; ReplaceOrCreateByNumber(explicitVRTransfertSyntax,0x0002, 0x0010); @@ -413,7 +411,7 @@ gdcmDocEntry * gdcmDocument::ReplaceOrCreateByNumber( a =NewDocEntryByNumber(Group, Elem); if (a == NULL) return NULL; - AddDocEntry(a); + AddEntry(a); } SetEntryByNumber(Value, Group, Elem); //a->SetValue(Value); @@ -921,7 +919,7 @@ void gdcmDocument::UpdateGroupLength(bool SkipSequence, FileType type) { gdcmDictEntry * tagZ = new gdcmDictEntry(gr_bid, 0x0000, "UL"); elemZ = new gdcmDocEntry(tagZ); elemZ->SetLength(4); - AddDocEntry(elemZ); // create it + AddEntry(elemZ); // create it } else { @@ -961,7 +959,7 @@ void gdcmDocument::WriteEntryTagVRLength(gdcmDocEntry *tag, fwrite ( &group,(size_t)2 ,(size_t)1 ,_fp); //group fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp); //element - if ( type == ExplicitVR ) { + if ( type == gdcmExplicitVR ) { // Special case of delimiters: if (group == 0xfffe) { @@ -1117,7 +1115,7 @@ bool gdcmDocument::WriteEntries(FILE *_fp,FileType type) tag2 != listEntries.end(); ++tag2) { - if ( type == ACR ){ + if ( type == gdcmACR ){ if ((*tag2)->GetGroup() < 0x0008) // Ignore pure DICOM V3 groups continue; @@ -1158,7 +1156,7 @@ void gdcmDocument::WriteEntriesDeprecated(FILE *_fp,FileType type) { for (TagDocEntryHT::iterator tag2=tagHT.begin(); tag2 != tagHT.end(); ++tag2){ - if ( type == ACR ){ + if ( type == gdcmACR ){ if ((*tag2->second).GetGroup() < 0x0008) continue; // ignore pure DICOM V3 groups if ((*tag2->second).GetElement() %2) continue; // ignore shadow groups if ((*tag2->second).GetVR() == "SQ" ) continue; // ignore Sequences @@ -1191,6 +1189,7 @@ guint32 gdcmDocument::SwapLong(guint32 a) { a=( ((a<<8) & 0xff00ff00) | ((a>>8) & 0x00ff00ff) ); break; default : + std::cout << "swapCode= " << sw << std::endl; dbg.Error(" gdcmDocument::SwapLong : unset swap code"); a=0; } @@ -1234,75 +1233,139 @@ guint16 gdcmDocument::UnswapShort(guint16 a) { * @return false if file is not ACR-NEMA / PAPYRUS / DICOM */ -long gdcmDocument::ParseES(gdcmDocEntrySet *set, long offset, long l_max, bool delim_mode) { +long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool delim_mode) { gdcmDocEntry *NewDocEntry = (gdcmDocEntry *)0; gdcmValEntry *vl; + gdcmBinEntry *bn; gdcmSeqEntry *sq; + string vr; long l; while (true) { NewDocEntry = ReadNextDocEntry( ); if (!NewDocEntry) break; - if (NewDocEntry->GetVR() !="SQ") { - vl= new gdcmValEntry(NewDocEntry->GetDictEntry()); - vl->Copy(NewDocEntry); - delete NewDocEntry; - set->AddEntry(vl); - if (!delim_mode && vl->isItemDelimitor()) - break; + + std::cout << hex << NewDocEntry->GetGroup() + << " " + << NewDocEntry->GetElement() + << " " + << NewDocEntry->GetVR() + << " " + << NewDocEntry->GetReadLength() + << " " + << NewDocEntry->GetOffset() + << std::endl; + + vr = NewDocEntry->GetVR(); + if (vr!="SQ") { + + if (vr == "AE" || vr == "AS" || vr == "DA" || vr == "PN" || + vr == "UI" || vr == "TM" || vr == "SH" || vr == "LO" || + vr == "CS" || vr == "IS" || vr == "LO" || vr == "LT" || + vr == "SH" || vr == "ST" || + vr == "SL" || vr == "SS" || vr == "UL" || vr == "US" + ) { + // --- ValEntry + vl= new gdcmValEntry(NewDocEntry->GetDictEntry()); + vl->Copy(NewDocEntry); + set->AddEntry(vl); + LoadDocEntry(vl); + std::cout << "value [" << vl->GetValue() << "]" << std::endl; + if (!delim_mode && vl->isItemDelimitor()) + break; + } else { // BinEntry + + // Hope the following VR *do* correspond to a BinEntry + + //AT Attribute Tag; // 2 16-bit unsigned short integers + //FL Floating Point Single; // 32-bit IEEE 754:1985 float + //FD Floating Point Double; // 64-bit IEEE 754:1985 double + //UN Unknown; // Any length of bytes + //UT Unlimited Text; // At most 2^32 -1 chars + //OB Other Byte String; // String of bytes (VR independant) + //OW Other Word String; // String of 16-bit words (VR dependant) + + bn = new gdcmBinEntry(NewDocEntry->GetDictEntry()); + bn->Copy(NewDocEntry); + LoadDocEntry(bn); + std::cout << "value [" << "Bin Entry, in voidArea" << "]" << std::endl; + } + + SkipToNextDocEntry(NewDocEntry); // to be sure to be at the beginning + l = NewDocEntry->GetFullLength(); + + } else { // VR = "SQ" - } else { // VR = "SQ" - l=NewDocEntry->GetReadLength(); - if (l == 0xffffffff) - delim_mode = true; - else - delim_mode = false; - sq = new gdcmSeqEntry(NewDocEntry->GetDictEntry()); - sq->Copy(NewDocEntry); - long lgt = ParseSQ((gdcmDocEntrySet *)sq, offset, l, delim_mode); - set->AddEntry(sq); - if ( !delim_mode && ftell(fp)-offset >= l_max) - break; + //SkipDocEntry(NewDocEntry); + + std::cout << "gdcmDocument::ParseDES : SQ found " << std::endl; + l=NewDocEntry->GetReadLength(); + if (l == 0xffffffff) + delim_mode = true; + else + delim_mode = false; + sq = new gdcmSeqEntry(NewDocEntry->GetDictEntry()); + sq->Copy(NewDocEntry); + sq->SetDelimitorMode(delim_mode); + long lgt = ParseSQ((gdcmDocEntrySet *)sq, offset, l, delim_mode); + // FIXME : on en fait quoi, de lgt ? + set->AddEntry(sq); + if ( !delim_mode && ftell(fp)-offset >= l_max) + break; } - } + } + cout << endl; + delete NewDocEntry; return l; // ?? } +/** + * \brief Parses a Sequence ( SeqEntry after SeqEntry) + * @return parsed length for this level + */ + long gdcmDocument::ParseSQ(gdcmDocEntrySet *set, long offset, long l_max, bool delim_mode) { + std::cout << "Entree ds gdcmDocument::ParseSQ" << std::endl; + gdcmDocEntry *NewDocEntry = (gdcmDocEntry *)0; gdcmSQItem *itemSQ; bool dlm_mod; int lgr, l, lgth; + cout << "=============== on entre ds une Sequence" <isSequenceDelimitor()) - // =====> ATTENTION : il faudra tout de meme ajouter - // le Sequence Delimiter ?!? - //set.Add(???); + if (NewDocEntry->isSequenceDelimitor()) { + // add the Sequence Delimitor // TODO : find the trick to put it proprerly ! + // ((gdcmSeqEntry *)set)->SetSequenceDelimitationItem(NewDocEntry); break; + } } if (!delim_mode && (ftell(fp)-offset) >= l_max){ break; } itemSQ = new gdcmSQItem(); - + itemSQ->AddEntry(NewDocEntry); // no value, no voidArea. Think of it while printing ! l= NewDocEntry->GetLength(); if (l ==0xffffffff) dlm_mod = true; else dlm_mod=false; - lgr=ParseES(itemSQ, offset, l, dlm_mod); + lgr=ParseDES(itemSQ, offset, l, dlm_mod); ((gdcmSeqEntry *)set)->AddEntry(itemSQ); } - //Update(lgth); // TODO // to go on compiling + //Update(lgth); + lgth = ftell(fp) - offset; + cout << "=============== lgr Sequence :" << lgth <GetGroup()%2) == 0) { - AddDocEntry(newDocEntry); + AddEntry(newDocEntry); } } rewind(fp); @@ -1469,19 +1532,6 @@ void gdcmDocument::LoadDocEntry(gdcmDocEntry *Entry) { ((gdcmValEntry *)Entry)->SetValue(NewValue); } -/** - * \brief add a new Dicom Element pointer to - * the H Table and at the end of the chained List - * \warning push_bash in listEntries ONLY during ParseHeader - * \todo something to allow further Elements addition, - * (at their right place in the chained list) - * when position to be taken care of - * @param newDocEntry - */ -void gdcmDocument::AddDocEntry(gdcmDocEntry *newDocEntry) { - tagHT.insert( PairHT( newDocEntry->GetKey(),newDocEntry) ); - listEntries.push_back(newDocEntry); -} /** * \brief Find the value Length of the passed Header Entry @@ -1494,7 +1544,7 @@ void gdcmDocument::AddDocEntry(gdcmDocEntry *newDocEntry) { guint16 length16; - if ( (filetype == ExplicitVR) && (! Entry->IsImplicitVR()) ) + if ( (filetype == gdcmExplicitVR) && (! Entry->IsImplicitVR()) ) { if ( (vr=="OB") || (vr=="OW") || (vr=="SQ") || (vr=="UN") ) { @@ -1601,7 +1651,7 @@ void gdcmDocument::AddDocEntry(gdcmDocEntry *newDocEntry) { */ void gdcmDocument::FindDocEntryVR( gdcmDocEntry *Entry) { - if (filetype != ExplicitVR) + if (filetype != gdcmExplicitVR) return; char VR[3]; @@ -1831,9 +1881,30 @@ std::string gdcmDocument::GetDocEntryUnvalue(gdcmDocEntry *Entry) */ void gdcmDocument::SkipDocEntry(gdcmDocEntry *entry) { - SkipBytes(entry->GetLength()); + SkipBytes(entry->GetLength()); } +/** + * \brief Skips to the begining of the next Header Entry + * \warning NOT end user intended method ! + * @param entry + */ +void gdcmDocument::SkipToNextDocEntry(gdcmDocEntry *entry) +{ + (void)fseek(fp, (long)(entry->GetOffset()), SEEK_SET); + (void)fseek(fp, (long)(entry->GetReadLength()), SEEK_CUR); +} + +/** + * \brief Loads the value for a a given VLEntry + * \warning NOT end user intended method ! + * @param entry + */ +void gdcmDocument::LoadVLEntry(gdcmDocEntry *entry) +{ + //SkipBytes(entry->GetLength()); + LoadDocEntry(entry); +} /** * \brief When the length of an element value is obviously wrong (because * the parser went Jabberwocky) one can hope improving things by @@ -2122,13 +2193,13 @@ bool gdcmDocument::CheckSwap() { // Use gdcmDocument::dicom_vr to test all the possibilities // instead of just checking for UL, OB and UI !? group 0000 { - filetype = ExplicitVR; + filetype = gdcmExplicitVR; dbg.Verbose(1, "gdcmDocument::CheckSwap:", "explicit Value Representation"); } else { - filetype = ImplicitVR; + filetype = gdcmImplicitVR; dbg.Verbose(1, "gdcmDocument::CheckSwap:", "not an explicit Value Representation"); } @@ -2173,19 +2244,19 @@ bool gdcmDocument::CheckSwap() { switch (s32) { case 0x00040000 : sw = 3412; - filetype = ACR; + filetype = gdcmACR; return true; case 0x04000000 : sw = 4321; - filetype = ACR; + filetype = gdcmACR; return true; case 0x00000400 : sw = 2143; - filetype = ACR; + filetype = gdcmACR; return true; case 0x00000004 : sw = 0; - filetype = ACR; + filetype = gdcmACR; return true; default : @@ -2211,18 +2282,18 @@ bool gdcmDocument::CheckSwap() { case 0x0004 : case 0x0008 : sw = 0; - filetype = ACR; + filetype = gdcmACR; return true; case 0x0200 : case 0x0400 : case 0x0800 : sw = 4321; - filetype = ACR; + filetype = gdcmACR; return true; default : dbg.Verbose(0, "gdcmDocument::CheckSwap:", "ACR/NEMA unfound swap info (Really hopeless !)"); - filetype = Unknown; + filetype = gdcmUnknown; return false; } @@ -2296,70 +2367,13 @@ void gdcmDocument::SetMaxSizePrintEntry(long NewSize) MaxSizePrintEntry = NewSize; } -/** - * \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 of the searched DictEntry - * @param element element 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 Read the next tag but WITHOUT loading it's value + * (read the 'Group Number', the 'Element Number', + * gets the Dict Entry + * gets the VR, gets the length, gets the offset value) * @return On succes the newly created DocEntry, NULL on failure. */ gdcmDocEntry *gdcmDocument::ReadNextDocEntry(void) { @@ -2388,6 +2402,7 @@ gdcmDocEntry *gdcmDocument::ReadNextDocEntry(void) { if (errno == 1) { // Call it quits + delete NewEntry; return NULL; } NewEntry->SetOffset(ftell(fp)); @@ -2485,7 +2500,7 @@ gdcmDocEntry *gdcmDocument::NewDocEntryByNumber(guint16 Group, guint16 Elem) // DictEntry = NewVirtualDictEntry(StuffGroup, FreeElem, // VR, "GDCM", NewTagName); // NewEntry = new gdcmDocEntry(DictEntry); -// AddDocEntry(NewEntry); +// AddEntry(NewEntry); // return NewEntry; //} @@ -2506,4 +2521,69 @@ guint32 gdcmDocument::GenerateFreeTagKeyInGroup(guint16 group) return UINT32_MAX; } + +/** + * \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 of the searched DictEntry + * @param element element 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; +} + + + //----------------------------------------------------------------------------- diff --git a/src/gdcmDocument.h b/src/gdcmDocument.h index 88abb074..a8f7cb19 100644 --- a/src/gdcmDocument.h +++ b/src/gdcmDocument.h @@ -11,6 +11,7 @@ #include "gdcmDictSet.h" #include "gdcmDocEntry.h" #include "gdcmDocEntrySet.h" +#include "gdcmElementSet.h" #include #include @@ -35,7 +36,7 @@ typedef std::map GroupHT; /** * \brief used by both gdcmHeader and gdcmDicomDir */ -class GDCM_EXPORT gdcmDocument +class GDCM_EXPORT gdcmDocument : public gdcmElementSet { private: /// Public dictionary used to parse this header @@ -59,6 +60,8 @@ private: /// in order no to polute the screen output. By default, this upper bound /// is fixed to 64 bytes. guint32 MaxSizePrintEntry; + + protected: /// Refering underlying filename. @@ -106,10 +109,13 @@ public: // Print - /// Canonical Printing method (see also gdcmDocument::SetPrintLevel) - virtual void Print (std::ostream &os = std::cout) - {PrintEntry(os);}; - virtual void PrintEntry (std::ostream &os = std::cout); + // Canonical Printing method (see also gdcmDocument::SetPrintLevel) + // virtual void Print (std::ostream &os = std::cout); + // {PrintEntry(os);}; + + // no more Print method for gdcmDocument (inherits from gdcmElementSet + // virtual void PrintEntry (std::ostream &os = std::cout) + // { return Print(os);}; // the 2 following will be merged virtual void PrintPubDict (std::ostream &os = std::cout); @@ -147,7 +153,8 @@ public: bool ReplaceIfExistByNumber (char *Value, guint16 Group, guint16 Elem); virtual void *LoadEntryVoidArea (guint16 Group, guint16 Element); - + void LoadVLEntry (gdcmDocEntry *entry); + // System access guint16 SwapShort(guint16); // needed by gdcmFile guint32 SwapLong(guint32); // needed by gdcmFile @@ -196,16 +203,16 @@ protected: //void UpdateGroupLength(bool SkipSequence = false, // FileType type = ImplicitVR); - void AddDocEntry (gdcmDocEntry *); + //void AddDocEntry (gdcmDocEntry *); private: // Read //bool LoadHeaderEntries(bool exception_on_error = false) throw(gdcmFormatError); - // remplacé par ParseES. + // remplacé par ParseDES. // What about exception_on_error ? - long ParseES(gdcmDocEntrySet *set, long offset, long l_max, bool delim_mode); + long ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool delim_mode); long ParseSQ(gdcmDocEntrySet *set, long offset, long l_max, bool delim_mode); @@ -218,6 +225,8 @@ private: std::string GetDocEntryUnvalue(gdcmDocEntry *); void SkipDocEntry (gdcmDocEntry *); + void SkipToNextDocEntry (gdcmDocEntry *); + void FixDocEntryFoundLength(gdcmDocEntry *, guint32); bool IsDocEntryAnInteger (gdcmDocEntry *); @@ -233,7 +242,8 @@ private: void SetMaxSizeLoadEntry(long); void SetMaxSizePrintEntry(long); - // DictEntry related utilities + // DictEntry related utilities + gdcmDictEntry *GetDictEntryByName (std::string Name); gdcmDictEntry *GetDictEntryByNumber(guint16, guint16); gdcmDictEntry *NewVirtualDictEntry(guint16 group, @@ -241,7 +251,7 @@ private: std::string vr = "unkn", std::string fourth = "unkn", std::string name = "unkn"); - //gdcmDictEntry *NewVirtualDictEntry(gdcmDocEntry *); // never defined + //gdcmDictEntry *NewVirtualDictEntry(gdcmDocEntry *); // never defined // DocEntry related utilities diff --git a/src/gdcmElementSet.cxx b/src/gdcmElementSet.cxx index 067896c8..8dbeb6d3 100644 --- a/src/gdcmElementSet.cxx +++ b/src/gdcmElementSet.cxx @@ -36,6 +36,35 @@ gdcmElementSet::~gdcmElementSet() //----------------------------------------------------------------------------- // Public + +//----------------------------------------------------------------------------- +// Print +/** + * \brief Prints the Header Entries (Dicom Elements) + * from the H Table + * @return + */ +void gdcmElementSet::Print(std::ostream & os) { + cout << "entree ds gdcmElementSet::Print" << endl; + for (TagDocEntryHT::iterator i = tagHT.begin(); i != tagHT.end(); ++i) + { + //(*i)->second->SetPrintLevel(printLevel); + (i->second)->Print(os); + } +} + + +//----------------------------------------------------------------------------- +// Protected + +//----------------------------------------------------------------------------- +// Private + + +/** + * \brief add a new Dicom Element pointer to the H Table + * @param newDocEntry entry to add + */ bool gdcmElementSet::AddEntry( gdcmDocEntry *NewEntry) { TagKey key; key = NewEntry->GetKey(); @@ -52,22 +81,3 @@ bool gdcmElementSet::AddEntry( gdcmDocEntry *NewEntry) { } } -// end-user intended : the guy *wants* to create his own SeQuence ?!? -gdcmDocEntry *gdcmElementSet::NewDocEntryByNumber(guint16 group, - guint16 element) { -// TODO - gdcmDocEntry *a; - return a; -} - -gdcmDocEntry *gdcmElementSet::NewDocEntryByName (std::string Name) { -// TODO : - gdcmDocEntry *a; - return a; -} - -//----------------------------------------------------------------------------- -// Protected - -//----------------------------------------------------------------------------- -// Private diff --git a/src/gdcmElementSet.h b/src/gdcmElementSet.h index f4003e57..cca67455 100644 --- a/src/gdcmElementSet.h +++ b/src/gdcmElementSet.h @@ -20,17 +20,12 @@ public: ~gdcmElementSet(void); virtual bool AddEntry(gdcmDocEntry *Entry); // add to the H Table - + virtual void Print (std::ostream &os = std::cout); + protected: private: - // DocEntry related utilities - virtual gdcmDocEntry *NewDocEntryByNumber(guint16 group, - guint16 element); - virtual gdcmDocEntry *NewDocEntryByName (std::string Name); - - // Variables /// Hash Table (map), to provide fast access diff --git a/src/gdcmSQItem.cxx b/src/gdcmSQItem.cxx index f0ed2598..d8d9153a 100644 --- a/src/gdcmSQItem.cxx +++ b/src/gdcmSQItem.cxx @@ -37,12 +37,15 @@ gdcmSQItem::~gdcmSQItem() * \brief canonical Printer */ void gdcmSQItem::Print(std::ostream & os) { - + std::ostringstream s; + s << " | " ; for (ListDocEntry::iterator i = docEntries.begin(); i != docEntries.end(); ++i) { + os << s.str(); //(*i)->SetPrintLevel(printLevel); //self->GetPrintLevel() ? + (*i)->SetPrintLevel(2); (*i)->Print(os); } } @@ -51,6 +54,7 @@ gdcmSQItem::~gdcmSQItem() // Public bool gdcmSQItem::AddEntry(gdcmDocEntry *entry) { + std::cout << " entree ds gdcmSQItem::AddEntry" << std::endl; docEntries.push_back(entry); //TODO : check if it worked return true; diff --git a/src/gdcmSeqEntry.cxx b/src/gdcmSeqEntry.cxx index c2864f04..20c2e51a 100644 --- a/src/gdcmSeqEntry.cxx +++ b/src/gdcmSeqEntry.cxx @@ -19,8 +19,9 @@ gdcmSeqEntry::gdcmSeqEntry(gdcmDictEntry* e) : gdcmDocEntry(e) { //ListSQItem items est un *champ* de gdcmSeqEntry. - // inutile de faire new ? - + + delimitor_mode = false; + seq_term = NULL; } /** @@ -48,8 +49,12 @@ void gdcmSeqEntry::Print(std::ostream &os){ long lgth; size_t o; char greltag[10]; //group element tag - char st[20]; - + char st[20]; + + + SetPrintLevel(2); +// PrintCommonPart(os); // FIXME : why doesn't it work ? + // First, Print the Dicom Element itself. g = GetGroup(); e = GetElement(); @@ -89,16 +94,26 @@ void gdcmSeqEntry::Print(std::ostream &os){ } s << "[" << GetName()<< "]"; + s << std::endl; os << s.str(); + // Then, Print each SQ Item for(ListSQItem::iterator cc = items.begin();cc != items.end();++cc) { //(*cc)->SetPrintLevel(GetPrintLevel()); aurait-ce un sens ? (*cc)->Print(os); - } - + } + // at end, print the sequence terminator item, if any + /* + if (delimitor_mode) { + s << " | " ; + os << s.str(); + if (seq_term = NULL) + seq_term->Print(os); + } + */ } //----------------------------------------------------------------------------- diff --git a/src/gdcmSeqEntry.h b/src/gdcmSeqEntry.h index 1d52a936..6456a572 100644 --- a/src/gdcmSeqEntry.h +++ b/src/gdcmSeqEntry.h @@ -23,7 +23,15 @@ public: /// \brief returns the SQITEM chained List for this SeQuence. inline ListSQItem &GetSQItems() {return items;}; - + + /// \brief Sets the delimitor mode + inline void SetDelimitorMode(bool dm) + { delimitor_mode = dm;} + + /// \brief Sets the Sequence Delimitation Item + inline void SetSequenceDelimitationItem(gdcmDocEntry * e) + { seq_term = e;} + void AddEntry(gdcmSQItem *it); /// \brief creates a new SQITEM for this SeQuence. @@ -38,8 +46,14 @@ private: // Variables +/// \brief If this Sequence is in delimitor mode (length =0xffffffff) or not + bool delimitor_mode; + /// \brief chained list of SQ Items ListSQItem items; + +/// \brief sequence terminator item + gdcmDocEntry *seq_term; }; diff --git a/src/gdcmValEntry.cxx b/src/gdcmValEntry.cxx index f568133f..e48acc0c 100644 --- a/src/gdcmValEntry.cxx +++ b/src/gdcmValEntry.cxx @@ -6,33 +6,107 @@ #include "gdcmGlobal.h" #include "gdcmUtil.h" +// CLEAN ME +#define MAX_SIZE_PRINT_ELEMENT_VALUE 128 //----------------------------------------------------------------------------- // Constructor / Destructor /** * \ingroup gdcmValEntry * \brief Constructor from a given gdcmDictEntry - * @param in Pointer to existing dictionary entry + * @param e Pointer to existing dictionary entry */ gdcmValEntry::gdcmValEntry(gdcmDictEntry* e) : gdcmDocEntry(e) { - - + voidArea = NULL; } /** * \brief Canonical destructor. */ gdcmValEntry::~gdcmValEntry (void) { - + if (!voidArea) // will be in BinEntry + free(voidArea); } //----------------------------------------------------------------------------- // Print /* - * \ingroup gdcmDocEntry + +/** + * \ingroup gdcmValEntry * \brief canonical Printer */ +void gdcmValEntry::Print(std::ostream & os) { + + std::ostringstream s; + size_t o; + unsigned short int g, e; + char st[20]; + TSKey v; + std::string d2, vr; + + PrintCommonPart(os); + + g = GetGroup(); + + if (g == 0xfffe) { + s << std::endl; + os << s.str(); + return; // just to avoid identing all the remaining code + } + + e = GetElement(); + vr = GetVR(); + gdcmTS * ts = gdcmGlobal::GetTS(); + + if (voidArea != NULL) { // should be moved in gdcmBinEntry Printer (when any) + s << " [gdcm::Non String Data Loaded in Unsecure Area (" + << GetLength() << ") ]"; + } + + else { + v = GetValue(); // not applicable for SQ ... + d2 = CreateCleanString(v); // replace non printable characters by '.' + if( (GetLength()<=MAX_SIZE_PRINT_ELEMENT_VALUE) || + (printLevel>=3) || + (d2.find("gdcm::NotLoaded.") < d2.length()) ) + s << " [" << d2 << "]"; + else + s << " [gdcm::too long for print (" << GetLength() << ") ]"; + } + + // Display the UID value (instead of displaying only the rough code) + if (g == 0x0002) { // Any more to be displayed ? + if ( (e == 0x0010) || (e == 0x0002) ) + s << " ==>\t[" << ts->GetValue(v) << "]"; + } else { + if (g == 0x0008) { + if ( (e == 0x0016) || (e == 0x1150) ) + s << " ==>\t[" << ts->GetValue(v) << "]"; + } else { + if (g == 0x0004) { + if ( (e == 0x1510) || (e == 0x1512) ) + s << " ==>\t[" << ts->GetValue(v) << "]"; + } + } + } + //if (e == 0x0000) { // elem 0x0000 --> group length + if ( (vr == "UL") || (vr == "US") || (vr == "SL") || (vr == "SS") ) { + if (v == "4294967295") // to avoid troubles in convertion + sprintf (st," x(ffffffff)"); + else { + if ( GetLength() !=0 ) + sprintf(st," x(%x)", atoi(v.c_str()));//FIXME + else + sprintf(st," "); + } + s << st; + } + + s << std::endl; + os << s.str(); +} //----------------------------------------------------------------------------- diff --git a/src/gdcmValEntry.h b/src/gdcmValEntry.h index 1ff269f4..1c87450b 100644 --- a/src/gdcmValEntry.h +++ b/src/gdcmValEntry.h @@ -28,16 +28,23 @@ public: /// Sets the value (string) of the current Dicom Header Entry inline void SetValue(std::string val) { value = val; }; - + + virtual void Print(std::ostream &os = std::cout); + protected: + char* voidArea; // clean it out later + private: // Variables /// \brief Header Entry value, stored as a std::string (VR will be used, /// later, to decode) + std::string value; + + }; -- 2.48.1