From: jpr Date: Mon, 7 Jun 2004 14:41:35 +0000 (+0000) Subject: Last commit before the final(?) one, for the new version. X-Git-Tag: Version0.5.bp~152 X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=commitdiff_plain;h=98b5c3d02083ad65fce19ff79007fcc3f370e7c5;p=gdcm.git Last commit before the final(?) one, for the new version. Please keep on wainting. --- diff --git a/src/gdcmBinEntry.cxx b/src/gdcmBinEntry.cxx index 8478f586..63260fd4 100644 --- a/src/gdcmBinEntry.cxx +++ b/src/gdcmBinEntry.cxx @@ -31,7 +31,7 @@ gdcmBinEntry::~gdcmBinEntry(){ void gdcmBinEntry::Print(std::ostream &os = std::cout) { PrintCommonPart(os); - std::cout << "gdcmBinEntry : Print, et alors ?" < #include "gdcmDictEntry.h" +//#include "gdcmValEntry.h" class gdcmHeader; //----------------------------------------------------------------------------- @@ -18,15 +19,7 @@ class gdcmHeader; class GDCM_EXPORT gdcmDocEntry { public: gdcmDocEntry(gdcmDictEntry*); - - /// \brief Returns the 'Value' (e.g. "Dupond Marcel") converted into a - /// 'string', if it's stored as an integer in the Dicom Header of the - /// current Dicom Header Entry - /// TODO virtual? - //inline std::string GetValue(void) { return value; }; - // Pour continuer a compiler :-( - inline std::string GetValue(void) { return "value"; }; - + /// Returns the Dicom Group number of the current Dicom Header Entry inline guint16 GetGroup(void) { return entry->GetGroup(); }; @@ -124,7 +117,12 @@ public: bool isItemDelimitor(); bool isSequenceDelimitor(); - + + inline int GetDepthLevel(void) + {return(SQDepthLevel);} + void SetDepthLevel(int depth) + {SQDepthLevel = depth;} + private: // FIXME: In fact we should be more specific and use : // friend gdcmDocEntry * gdcmHeader::ReadNextElement(void); diff --git a/src/gdcmDocEntrySet.cxx b/src/gdcmDocEntrySet.cxx index 8f54c1bf..9b7286f0 100644 --- a/src/gdcmDocEntrySet.cxx +++ b/src/gdcmDocEntrySet.cxx @@ -18,7 +18,8 @@ * \ingroup gdcmDocEntrySet * \brief Constructor from a given gdcmDocEntrySet */ -gdcmDocEntrySet::gdcmDocEntrySet() { +gdcmDocEntrySet::gdcmDocEntrySet(int depthLevel) { + SQDepthLevel = depthLevel + 1; } /** * \brief Canonical destructor. diff --git a/src/gdcmDocEntrySet.h b/src/gdcmDocEntrySet.h index b2132bfe..94566ad2 100644 --- a/src/gdcmDocEntrySet.h +++ b/src/gdcmDocEntrySet.h @@ -13,13 +13,18 @@ class GDCM_EXPORT gdcmDocEntrySet public: - gdcmDocEntrySet(void); + gdcmDocEntrySet(int depth = 0); ~gdcmDocEntrySet(void); 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 - + + inline int GetDepthLevel(void) + {return(SQDepthLevel);} + void SetDepthLevel(int depth) + {SQDepthLevel = depth;} + protected: void gdcmDocEntrySet::FindDocEntryLength (gdcmDocEntry *Entry); @@ -28,10 +33,10 @@ protected: virtual gdcmDocEntry *NewDocEntryByNumber(guint16 group, guint16 element)=0; // pure virtual - virtual gdcmDocEntry *NewDocEntryByName (std::string Name)=0; // pure virtual - + virtual gdcmDocEntry *NewDocEntryByName (std::string Name)=0;// pure virtual - + int SQDepthLevel; + private: }; diff --git a/src/gdcmDocument.cxx b/src/gdcmDocument.cxx index 67a114e2..d5852766 100644 --- a/src/gdcmDocument.cxx +++ b/src/gdcmDocument.cxx @@ -26,11 +26,9 @@ #define UI1_2_840_10008_1_2_1 "1.2.840.10008.1.2.1" #define UI1_2_840_10008_1_2_2 "1.2.840.10008.1.2.2" #define UI1_2_840_10008_1_2_1_99 "1.2.840.10008.1.2.1.99" +#define UI1_1_2_840_10008_1_2_5 "1.2.840.10008.1.2.5" -typedef struct { - guint32 totalSQlength; - guint32 alreadyParsedlength; -} pileElem; +#define str2num(str, typeNum) *((typeNum *)(str)) //----------------------------------------------------------------------------- // Refer to gdcmDocument::CheckSwap() @@ -61,7 +59,8 @@ const unsigned int gdcmDocument::MAX_SIZE_PRINT_ELEMENT_VALUE = 64; gdcmDocument::gdcmDocument(const char *inFilename, bool exception_on_error, bool enable_sequences, - bool ignore_shadow) { + bool ignore_shadow) + : gdcmElementSet(-1) { enableSequences=enable_sequences; ignoreShadow =ignore_shadow; @@ -84,12 +83,10 @@ gdcmDocument::gdcmDocument(const char *inFilename, long beg = ftell(fp); lgt -= beg; - //std::cout << "beg, lgt : " << beg << " " << lgt << std::endl; - + SQDepthLevel=0; + long l=ParseDES( this, beg, lgt, false); // le Load sera fait a la volee - CloseFile(); - - /* TO DO : uncomment when everything else is OK + CloseFile(); // -------------------------------------------------------------- // Special Patch to allow gdcm to read ACR-LibIDO formated images @@ -103,15 +100,13 @@ gdcmDocument::gdcmDocument(const char *inFilename, RecCode == "CANRME_AILIBOD1_1." ) // for brain-damaged softwares // with "little-endian strings" { - filetype = ACR_LIBIDO; + filetype = gdcmACR_LIBIDO; std::string rows = GetEntryByNumber(0x0028, 0x0010); std::string columns = GetEntryByNumber(0x0028, 0x0011); SetEntryByNumber(columns, 0x0028, 0x0010); SetEntryByNumber(rows , 0x0028, 0x0011); } // ----------------- End of Special Patch ---------------- - */ - printLevel = 1; // 'Medium' print level by default } @@ -120,8 +115,9 @@ gdcmDocument::gdcmDocument(const char *inFilename, * \brief constructor * @param exception_on_error */ -gdcmDocument::gdcmDocument(bool exception_on_error) { - (void)exception_on_error; +gdcmDocument::gdcmDocument(bool exception_on_error) + :gdcmElementSet(-1) { + (void)exception_on_error; enableSequences=0; SetMaxSizeLoadEntry(MAX_SIZE_LOAD_ELEMENT_VALUE); @@ -203,9 +199,11 @@ bool gdcmDocument::SetShaDict(DictKey dictName){ */ bool gdcmDocument::IsReadable(void) { if(filetype==gdcmUnknown) { + std::cout << "wrong filetype" <GetValue(); + std::string Transfer = ((gdcmValEntry *)Element)->GetValue(); if ( Transfer == UI1_2_840_10008_1_2 ) return true; return false; @@ -240,7 +238,7 @@ bool gdcmDocument::IsExplicitVRLittleEndianTransferSyntax(void) { return false; LoadDocEntrySafe(Element); - std::string Transfer = Element->GetValue(); + std::string Transfer = ((gdcmValEntry *)Element)->GetValue(); if ( Transfer == UI1_2_840_10008_1_2_1 ) return true; return false; @@ -257,7 +255,7 @@ bool gdcmDocument::IsDeflatedExplicitVRLittleEndianTransferSyntax(void) { return false; LoadDocEntrySafe(Element); - std::string Transfer = Element->GetValue(); + std::string Transfer = ((gdcmValEntry *)Element)->GetValue(); if ( Transfer == UI1_2_840_10008_1_2_1_99 ) return true; return false; @@ -274,7 +272,7 @@ bool gdcmDocument::IsExplicitVRBigEndianTransferSyntax(void) { return false; LoadDocEntrySafe(Element); - std::string Transfer = Element->GetValue(); + std::string Transfer = ((gdcmValEntry *)Element)->GetValue(); if ( Transfer == UI1_2_840_10008_1_2_2 ) //1.2.2 ??? A verifier ! return true; return false; @@ -354,7 +352,7 @@ bool gdcmDocument::Write(FILE *fp, FileType type) { /// ============== /// The stuff will have to be rewritten using the SeQuence based /// tree-like stucture instead of the chained list . -/// (so we shall remove the GroupHT from the gdcmDocument) +/// (so we shall remove the Group*HT from the gdcmDocument) /// To be checked /// ============= @@ -508,7 +506,7 @@ std::string gdcmDocument::GetEntryVRByName(std::string tagName) { return GDCM_UNFOUND; gdcmDocEntry* elem = GetDocEntryByNumber(dictEntry->GetGroup(), - dictEntry->GetElement()); + dictEntry->GetElement()); return elem->GetVR(); } @@ -526,7 +524,7 @@ std::string gdcmDocument::GetEntryByNumber(guint16 group, guint16 element){ TagKey key = gdcmDictEntry::TranslateToKey(group, element); if ( ! tagHT.count(key)) return GDCM_UNFOUND; - return tagHT.find(key)->second->GetValue(); + return ((gdcmValEntry *)tagHT.find(key)->second)->GetValue(); } /** @@ -602,18 +600,8 @@ bool gdcmDocument::SetEntryByNumber(std::string content, } gdcmDocEntry * a; - IterHT p; - TagDocEntryHT::iterator p2; - // DO NOT remove the following lines : they explain the stuff - //p= tagHT.equal_range(key); // get a pair of iterators first-last synonym - //p2=p.first; // iterator on the first synonym - //a=p2->second; // H Table target column (2-nd col) - - // or, easier : - - // Oops ! this was for multimap, right ? - a = ((tagHT.equal_range(key)).first)->second; - + a = tagHT[key]; + ((gdcmValEntry*)a)->SetValue(content); std::string vr = a->GetVR(); @@ -749,7 +737,9 @@ bool gdcmDocument::SetEntryVoidAreaByNumber(void * area, void gdcmDocument::UpdateShaEntries(void) { gdcmDictEntry *entry; std::string vr; - + + // TODO : if still any use (?) explore recursively the whole structure +/* for(ListTag::iterator it=listEntries.begin(); it!=listEntries.end(); ++it) @@ -769,15 +759,13 @@ void gdcmDocument::UpdateShaEntries(void) { else vr=(*it)->GetVR(); - //(*it)->SetValue(GetDocEntryUnvalue(*it)); - // to go on compiling + (*it)->SetValue(GetDocEntryUnvalue(*it)); // to go on compiling if(entry){ // Set the new entry and the new value (*it)->SetDictEntry(entry); CheckDocEntryVR(*it,vr); - //(*it)->SetValue(GetDocEntryValue(*it)); - // to go on compiling + (*it)->SetValue(GetDocEntryValue(*it)); // to go on compiling } else @@ -786,6 +774,7 @@ void gdcmDocument::UpdateShaEntries(void) { (*it)->SetDictEntry(NewVirtualDictEntry((*it)->GetGroup(),(*it)->GetElement(),vr)); } } +*/ } /** @@ -821,18 +810,6 @@ gdcmDocEntry* gdcmDocument::GetDocEntryByNumber(guint16 group, guint16 element) return tagHT.find(key)->second; } -/** - * \brief retrieves the Dicom Elements (all of them) using (group, element) - * @param group Group number of the searched Dicom Element. - * @param element Element number of the searched Dicom Element. - * @return a range (i.e.pair<,>) containing all elements whose key is group|element) - */ - -IterHT gdcmDocument::GetDocEntrySameNumber(guint16 group, guint16 element){ - TagKey key = gdcmDictEntry::TranslateToKey(group, element); - return (tagHT.equal_range(key)); -} - /** * \brief Loads the element while preserving the current * underlying file position indicator as opposed to @@ -846,116 +823,6 @@ void gdcmDocument::LoadDocEntrySafe(gdcmDocEntry * entry) { fseek(fp, PositionOnEntry, SEEK_SET); } -/** - * \brief Re-computes the length of a ACR-NEMA/Dicom group from a DcmHeader - * \warning : to be re-written using the chained list instead of the H table. - * \warning : DO NOT use (doesn't work any longer because of the multimap) - * \todo : to be re-written using the chained list instead of the H table - * @param SkipSequence TRUE if we don't want to write Sequences (ACR-NEMA Files) - * @param type Type of the File (ExplicitVR,ImplicitVR, ACR, ...) - */ - - /* Probabely useless, now ! - -void gdcmDocument::UpdateGroupLength(bool SkipSequence, FileType type) { - guint16 gr, el; - std::string vr; - - gdcmDocEntry *elem; - char trash[10]; - std::string str_trash; - - GroupKey key; - GroupHT groupHt; // to hold the length of each group - TagKey tk; - // remember : - // typedef std::map GroupHT; - - gdcmDocEntry *elemZ; - - // for each Tag in the DCM Header - - for (TagDocEntryHT::iterator tag2 = tagHT.begin(); - tag2 != tagHT.end(); - ++tag2) - { - elem = tag2->second; - gr = elem->GetGroup(); - el = elem->GetElement(); - vr = elem->GetVR(); - - sprintf(trash, "%04x", gr); - key = trash; // generate 'group tag' - - // if the caller decided not to take SEQUENCEs into account - // e.g : he wants to write an ACR-NEMA File - - if (SkipSequence && vr == "SQ") - continue; - - // Still unsolved problem : - // we cannot find the 'Sequence Delimitation Item' - // since it's at the end of the Hash Table - // (fffe,e0dd) - - // there is SEQUENCE in ACR-NEMA - // WARNING : - // --> la descente a l'interieur' des SQ - // devrait etre faite avec une liste chainee, pas avec une HTable... - - if ( groupHt.count(key) == 0) // we just read the first elem of a given group - { - if (el == 0x0000) // the first elem is 0x0000 - { - groupHt[key] = 0; // initialize group length - } - else - { - groupHt[key] = 2 + 2 + 4 + elem->GetLength(); // non 0x0000 first group elem - } - } - else // any elem but the first - { - if (type == ExplicitVR) - { - if ( (vr == "OB") || (vr == "OW") || (vr == "SQ") ) - { - groupHt[key] += 4; // explicit VR AND OB, OW, SQ : 4 more bytes - } - } - groupHt[key] += 2 + 2 + 4 + elem->GetLength(); - } - } - - unsigned short int gr_bid; - - for (GroupHT::iterator g = groupHt.begin(); // for each group we found - g != groupHt.end(); - ++g) - { - // FIXME: g++ -Wall -Wstrict-prototypes reports on following line: - // warning: unsigned int format, different type arg - sscanf(g->first.c_str(),"%x",&gr_bid); //FIXME - tk = g->first + "|0000"; // generate the element full tag - - if ( tagHT.count(tk) == 0) // if element 0x0000 not found - { - gdcmDictEntry * tagZ = new gdcmDictEntry(gr_bid, 0x0000, "UL"); - elemZ = new gdcmDocEntry(tagZ); - elemZ->SetLength(4); - AddEntry(elemZ); // create it - } - else - { - elemZ=GetDocEntryByNumber(gr_bid, 0x0000); - } - sprintf(trash ,"%d",g->second); - str_trash=trash; - //elemZ->SetValue(str_trash); // to go on compiling - } -} - -*/ /** * \brief Writes in a file (according to the requested format) @@ -1044,8 +911,7 @@ void gdcmDocument::WriteEntryValue(gdcmDocEntry *tag, FILE *_fp,FileType type) return; void *voidArea; - // voidArea = tag->GetVoidArea(); - // to go on compiling + // voidArea = tag->GetVoidArea(); // to go on compiling if (voidArea != NULL) { // there is a 'non string' LUT, overlay, etc fwrite ( voidArea,(size_t)lgr ,(size_t)1 ,_fp); // Elem value @@ -1059,7 +925,7 @@ void gdcmDocument::WriteEntryValue(gdcmDocEntry *tag, FILE *_fp,FileType type) // 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 (tag->GetValue(), tokens, "\\"); + Tokenize (((gdcmValEntry *)tag)->GetValue(), tokens, "\\"); for (unsigned int i=0; i tokens; tokens.erase(tokens.begin(),tokens.end()); // clean any previous value - Tokenize (tag->GetValue(), tokens, "\\"); + Tokenize (((gdcmValEntry *)tag)->GetValue(), tokens, "\\"); for (unsigned int i=0; iGetValue().c_str(), (size_t)lgr ,(size_t)1, _fp); // Elem value + fwrite (((gdcmValEntry *)tag)->GetValue().c_str(), (size_t)lgr ,(size_t)1, _fp); // Elem value } /** @@ -1106,8 +972,7 @@ bool gdcmDocument::WriteEntry(gdcmDocEntry *tag, FILE *_fp,FileType type) // bytes. When this is not the case, pad with an additional byte: if(length%2==1) { -// tag->SetValue(tag->GetValue()+"\0"); -// to go on compiling +// tag->SetValue(tag->GetValue()+"\0"); // to go on compiling tag->SetLength(tag->GetReadLength()+1); } @@ -1132,64 +997,34 @@ bool gdcmDocument::WriteEntry(gdcmDocEntry *tag, FILE *_fp,FileType type) */ bool gdcmDocument::WriteEntries(FILE *_fp,FileType type) -{ +{ + +// FIXME : explore recursively the whole structure... + /// \todo (?) check write failures (after *each* fwrite) - for (ListTag::iterator tag2=listEntries.begin(); - tag2 != listEntries.end(); - ++tag2) + for (TagDocEntryHT::iterator tag2=tagHT.begin(); + tag2 != tagHT.end(); + ++tag2) { if ( type == gdcmACR ){ - if ((*tag2)->GetGroup() < 0x0008) + if ((*tag2).second->GetGroup() < 0x0008) // Ignore pure DICOM V3 groups continue; - if ((*tag2)->GetElement() %2) + if ((*tag2).second->GetElement() %2) // Ignore the "shadow" groups continue; - if ((*tag2)->GetVR() == "SQ" ) // ignore Sequences + if ((*tag2).second->GetVR() == "SQ" ) // ignore Sequences continue; - if ((*tag2)->GetSQDepthLevel() != 0) // Not only ignore the SQ element + if ((*tag2).second->GetSQDepthLevel() != 0) // Not only ignore the SQ element continue; } - if (! WriteEntry(*tag2,_fp,type) ) + if (! WriteEntry((*tag2).second,_fp,type) ) return false; } return true; } -/** - * \brief writes on disc according to the requested format - * (ACR-NEMA, ExplicitVR, ImplicitVR) the image, - * using only the last synonym of each mutimap H Table post. - * \warning Uses the H Table, instead of the Chained List - * in order to be compliant with the old way to proceed - * (added elements taken in to account) - * Only THERALYS, during a transitory phase is supposed - * to use this method !!! - * \warning DON'T try, right now, to write a DICOM image - * from an ACR Header (meta elements will be missing!) - * \sa WriteEntries - * @param _fp already open file pointer - * @param type type of the File to be written - * (ACR-NEMA, ExplicitVR, ImplicitVR) - */ -void gdcmDocument::WriteEntriesDeprecated(FILE *_fp,FileType type) { - - // restent a tester les echecs en ecriture (apres chaque fwrite) - - for (TagDocEntryHT::iterator tag2=tagHT.begin(); - tag2 != tagHT.end(); - ++tag2){ - 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 - if ((*tag2->second).GetSQDepthLevel() != 0) continue; // Not only ignore the SQ element - } - if ( ! WriteEntry(tag2->second,_fp,type)) - break; - } -} /** * \brief Swaps back the bytes of 4-byte long integer accordingly to @@ -1250,8 +1085,6 @@ guint16 gdcmDocument::UnswapShort(guint16 a) { //----------------------------------------------------------------------------- // Private - - /** * \brief Parses a DocEntrySet (Zero-level DocEntries or SQ Item DocEntries) * @return false if file is not ACR-NEMA / PAPYRUS / DICOM @@ -1265,27 +1098,17 @@ long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool gdcmSeqEntry *sq; string vr; long l; - cout << hex << "offset " << offset - << " l_max "<< l_max - << " ftell a l'entree " << ftell(fp) - << endl; + int depth; + + depth = set->GetDepthLevel(); while (true) { + + if ( !delim_mode && ftell(fp)-offset >= l_max) { + break; + } NewDocEntry = ReadNextDocEntry( ); if (!NewDocEntry) break; - - std::cout << hex - << " gr " - << NewDocEntry->GetGroup() - << " el " - << NewDocEntry->GetElement() - << " vr " - << NewDocEntry->GetVR() - << " lgt " - << NewDocEntry->GetReadLength() - << " off " - << NewDocEntry->GetOffset() - << std::endl; vr = NewDocEntry->GetVR(); if (vr!="SQ") { @@ -1293,24 +1116,20 @@ long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool 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 == "SH" || vr == "ST" || vr == "DS" || vr == "SL" || vr == "SS" || vr == "UL" || vr == "US" ) { // --- ValEntry vl= new gdcmValEntry(NewDocEntry->GetDictEntry()); - vl->Copy(NewDocEntry); - set->AddEntry(vl); + vl->Copy(NewDocEntry); + vl->SetDepthLevel(depth), + set->AddEntry(vl); LoadDocEntry(vl); - std::cout << "value [" << vl->GetValue() << "]" << std::endl; if (/*!delim_mode && */vl->isItemDelimitor()) break; - cout << hex - << " l_max = "<< l_max - << " offset = " << offset - << " ftell(fp) = " << ftell(fp) - << endl; - if ( !delim_mode && ftell(fp)-offset >= l_max) - break; + if ( !delim_mode && ftell(fp)-offset >= l_max) { + break; + } } else { // BinEntry // Hope the following VR *do* correspond to a BinEntry @@ -1325,44 +1144,47 @@ long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool bn = new gdcmBinEntry(NewDocEntry->GetDictEntry()); bn->Copy(NewDocEntry); + set->AddEntry(bn); LoadDocEntry(bn); - std::cout << "value [" << "Bin Entry, in voidArea" << "]" << std::endl; } - - SkipToNextDocEntry(NewDocEntry); // to be sure we are at the beginning - l = NewDocEntry->GetFullLength(); - + if (NewDocEntry->GetGroup() == 0x7fe0 && + NewDocEntry->GetElement() == 0x0010 ) { + if (NewDocEntry->GetLength()==0xffffffff) + // Broke US.3405.1.dcm + + Parse7FE0(); // to skip the pixels + // (multipart JPEG/RLE are trouble makers) + } else { + SkipToNextDocEntry(NewDocEntry); // to be sure we are at the beginning + l = NewDocEntry->GetFullLength(); + } } else { // VR = "SQ" - - 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()); + + l=NewDocEntry->GetReadLength(); + if (l != 0) // don't mess the delim_mode for zero-length sequence + if (l == 0xffffffff) + delim_mode = true; + else + delim_mode = false; + // no other way to create it ... + sq = new gdcmSeqEntry(NewDocEntry->GetDictEntry(),set->GetDepthLevel()); sq->Copy(NewDocEntry); sq->SetDelimitorMode(delim_mode); + sq->SetDepthLevel(depth); - if (l != 0) { // Don't try to parse zero-length sequences - long lgt = ParseSQ((gdcmDocEntrySet *)sq, - //NewDocEntry->GetOffset(), - offset, // marche pour DICOMDIR, plante sur 3...dcm + if (l != 0) { // Don't try to parse zero-length sequences + + long lgt = ParseSQ( sq, + NewDocEntry->GetOffset(), l, delim_mode); - } + } // FIXME : on en fait quoi, de lgt ? set->AddEntry(sq); - cout << " l_max = " << l_max - << " offset = " << offset - << "ftell(fp) = " << ftell(fp) - << endl; - if ( !delim_mode && ftell(fp)-offset >= l_max) + if ( !delim_mode && ftell(fp)-offset >= l_max) { break; + } } } - cout << endl; delete NewDocEntry; return l; // ?? } @@ -1371,125 +1193,47 @@ long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool * \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) { - - cout << "=================== gdcmDocument::ParseSQ on entre ds une Sequence" - << hex - << " offset " << offset - << " l_max " << l_max - << " delim_mode " << delim_mode - <GetDepthLevel(); while (true) { - std::cout << " ===== gdcmDocument::ParseSQ on itere " - << "sur les SQ Items : num " - << SQItemNumber << std::endl; - NewDocEntry = ReadNextDocEntry(); -cout << "=============================== isSequenceDelimitor " - << NewDocEntry->isSequenceDelimitor() - << endl; + NewDocEntry = ReadNextDocEntry(); if(delim_mode) { if (NewDocEntry->isSequenceDelimitor()) { - cout << " SequenceDelimitationItem found" << endl; - // add the Sequence Delimitor // TODO : find the trick to put it proprerly ! - // ((gdcmSeqEntry *)set)->SetSequenceDelimitationItem(NewDocEntry); + //add the Sequence Delimitor // TODO : find the trick to put it properly ! + set->SetSequenceDelimitationItem(NewDocEntry); break; } } if (!delim_mode && (ftell(fp)-offset) >= l_max) { - cout << hex - << " offset " << offset - << " l_max " << l_max - << " ftell " << ftell(fp) - << endl; - cout << "depasse ou atteint : on sort " << endl; break; - } - itemSQ = new gdcmSQItem(); + } + itemSQ = new gdcmSQItem(set->GetDepthLevel()); itemSQ->AddEntry(NewDocEntry); // no value, no voidArea. Think of it while printing ! l= NewDocEntry->GetReadLength(); - cout << "NewDocEntry->GetReadLength() " << l << endl; + if (l ==0xffffffff) dlm_mod = true; else dlm_mod=false; -cout << "================================ appel ParseDES :dlm_mod = " << dlm_mod <GetOffset(), l, dlm_mod); - ((gdcmSeqEntry *)set)->AddEntry(itemSQ); -cout << "================================ sortie ParseDES " << endl; - SQItemNumber ++; + + set->AddEntry(itemSQ); + SQItemNumber ++; // a voir + if (!delim_mode && (ftell(fp)-offset) >= l_max) { + break; + } } - //Update(lgth); lgth = ftell(fp) - offset; - cout << "=============== lgr Sequence :" << lgth <GetGroup()%2) == 0) { - AddEntry(newDocEntry); - } - } - rewind(fp); - // Be carefull : merging this two loops may cause troubles ... - for (ListTag::iterator i = GetListEntry().begin(); - i != GetListEntry().end(); - ++i) - { - LoadDocEntry(*i); - } - rewind(fp); - - // Load 'non string' values - - - // -------------------------------------------------------------- - // Special Patch to allow gdcm to read ACR-LibIDO formated images - // - // if recognition code tells us we deal with a LibIDO image - // we switch lineNumber and columnNumber - // - std::string RecCode; - RecCode = GetEntryByNumber(0x0008, 0x0010); // recognition code - if (RecCode == "ACRNEMA_LIBIDO_1.1" || - RecCode == "CANRME_AILIBOD1_1." ) // for brain-damaged softwares - // with "little-endian strings" - { - filetype = ACR_LIBIDO; - std::string rows = GetEntryByNumber(0x0028, 0x0010); - std::string columns = GetEntryByNumber(0x0028, 0x0011); - SetEntryByNumber(columns, 0x0028, 0x0010); - SetEntryByNumber(rows , 0x0028, 0x0011); - } - // ----------------- End of Special Patch ---------------- - return true; -} -======================================================================= */ - - /** * \brief Loads the element content if its length doesn't exceed * the value specified with gdcmDocument::SetMaxSizeLoadEntry() @@ -1526,11 +1270,10 @@ void gdcmDocument::LoadDocEntry(gdcmDocEntry *Entry) { // the element content and it's length. if (length > MaxSizeLoadEntry) { std::ostringstream s; - s << "gdcm::NotLoaded."; - s << " Address:" << (long)Entry->GetOffset(); - s << " Length:" << Entry->GetLength(); - s << " x(" << std::hex << Entry->GetLength() << ")"; ((gdcmValEntry *)Entry)->SetValue(s.str()); + // to be sure we are at the end of the value ... + fseek(fp,(long)Entry->GetOffset()+(long)Entry->GetLength(),SEEK_SET); + return; } @@ -1825,7 +1568,7 @@ std::string gdcmDocument::GetDocEntryValue(gdcmDocEntry *Entry) { if ( (IsDocEntryAnInteger(Entry)) && (Entry->IsImplicitVR()) ) { - std::string val=Entry->GetValue(); + std::string val=((gdcmValEntry *)Entry)->GetValue(); std::string vr=Entry->GetVR(); guint32 length = Entry->GetLength(); std::ostringstream s; @@ -1880,7 +1623,7 @@ std::string gdcmDocument::GetDocEntryValue(gdcmDocEntry *Entry) return(s.str()); } - return(Entry->GetValue()); + return(((gdcmValEntry *)Entry)->GetValue()); } /** @@ -1904,7 +1647,7 @@ std::string gdcmDocument::GetDocEntryUnvalue(gdcmDocEntry *Entry) guint16 NewInt16; tokens.erase(tokens.begin(),tokens.end()); // clean any previous value - Tokenize (Entry->GetValue(), tokens, "\\"); + Tokenize (((gdcmValEntry *)Entry)->GetValue(), tokens, "\\"); for (unsigned int i=0; iGetValue(), tokens, "\\"); + Tokenize (((gdcmValEntry *)Entry)->GetValue(), tokens, "\\"); for (unsigned int i=0; iGetValue()); + return(((gdcmValEntry *)Entry)->GetValue()); } /** @@ -2647,5 +2390,212 @@ gdcmDictEntry *gdcmDocument::GetDictEntryByNumber(guint16 group,guint16 element) } +/** + * \ingroup gdcmDocument + * \brief Parse pixel data from disk for multi-fragment Jpeg/Rle files + * \ No other way so 'skip' the Data + * + */ +void gdcmDocument::Parse7FE0 (void) { + + gdcmDocEntry* Element = GetDocEntryByNumber(0x0002, 0x0010); + if ( !Element ) + return; + + std::string Transfer = ((gdcmValEntry *)Element)->GetValue(); + if (Transfer == UI1_2_840_10008_1_2 ) + return; + if ( Transfer == UI1_2_840_10008_1_2_1 ) + return; + if ( Transfer == UI1_2_840_10008_1_2_2 ) //1.2.2 ??? A verifier ! + return; + if ( Transfer == UI1_2_840_10008_1_2_1_99 ) + return; + + int nb; + std::string str_nb=GetEntryByNumber(0x0028,0x0100); + if (str_nb == GDCM_UNFOUND ) { + nb = 16; + } else { + nb = atoi(str_nb.c_str() ); + if (nb == 12) nb =16; + } + + guint16 ItemTagGr,ItemTagEl; + int ln; + long ftellRes; + + // -------------------- for Parsing : Position on begining of Jpeg/RLE Pixels + + if ( Transfer != UI1_1_2_840_10008_1_2_5 ) { // !RLELossLessTransferSyntax + // JPEG Image + ftellRes=ftell(fp); + fread(&ItemTagGr,2,1,fp); //Reading (fffe):Basic Offset Table Item Tag Gr + fread(&ItemTagEl,2,1,fp); //Reading (e000):Basic Offset Table Item Tag El + if(GetSwapCode()) { + ItemTagGr=SwapShort(ItemTagGr); + ItemTagEl=SwapShort(ItemTagEl); + } + printf ("at %x : ItemTag (should be fffe,e000): %04x,%04x\n", + (unsigned)ftellRes,ItemTagGr,ItemTagEl ); + ftellRes=ftell(fp); + fread(&ln,4,1,fp); + if(GetSwapCode()) + ln=SwapLong(ln); // Basic Offset Table Item Length + printf("at %x : Basic Offset Table Item Length (\?\?) %d x(%08x)\n", + (unsigned)ftellRes,ln,ln); + if (ln != 0) { + // What is it used for ?? + char * BasicOffsetTableItemValue= new char[ln+1]; + fread(BasicOffsetTableItemValue,ln,1,fp); + guint32 a; + for (int i=0;i1) { // skipping (not reading) RLE Segments + for(unsigned int k=1; k<=nbRleSegments-1; k++) { + RleSegmentLength[k]= RleSegmentOffsetTable[k+1] + - RleSegmentOffsetTable[k]; + ftellRes=ftell(fp); + printf (" Segment %d : Length = %d x(%x) Start at %x\n", + k,(unsigned)RleSegmentLength[k],(unsigned)RleSegmentLength[k], (unsigned)ftellRes); + fseek(fp,RleSegmentLength[k],SEEK_CUR); + } + } + RleSegmentLength[nbRleSegments]= fragmentLength + - RleSegmentOffsetTable[nbRleSegments]; + ftellRes=ftell(fp); + printf (" Segment %d : Length = %d x(%x) Start at %x\n", + nbRleSegments,(unsigned)RleSegmentLength[nbRleSegments], + (unsigned)RleSegmentLength[nbRleSegments],(unsigned)ftellRes); + + fseek(fp,RleSegmentLength[nbRleSegments],SEEK_CUR); + + // ------------------ end of scanning fragment pixels + + ftellRes=ftell(fp); + fread(&ItemTagGr,2,1,fp); // Reading (fffe) : Item Tag Gr + fread(&ItemTagEl,2,1,fp); // Reading (e000) : Item Tag El + if(GetSwapCode()) { + ItemTagGr=SwapShort(ItemTagGr); + ItemTagEl=SwapShort(ItemTagEl); + } + printf ("at %x : ItemTag (should be fffe,e000 or e0dd): %04x,%04x\n", + (unsigned)ftellRes,ItemTagGr,ItemTagEl ); + } + } + return; +} + + //----------------------------------------------------------------------------- diff --git a/src/gdcmDocument.h b/src/gdcmDocument.h index a8f7cb19..bebde32a 100644 --- a/src/gdcmDocument.h +++ b/src/gdcmDocument.h @@ -10,6 +10,8 @@ #include "gdcmException.h" #include "gdcmDictSet.h" #include "gdcmDocEntry.h" +//#include "gdcmSeqEntry.h" +class gdcmSeqEntry; #include "gdcmDocEntrySet.h" #include "gdcmElementSet.h" @@ -17,20 +19,12 @@ #include - //----------------------------------------------------------------------------- typedef std::string VRKey; typedef std::string VRAtr; typedef std::map VRHT; // Value Representation Hash Table typedef std::map TagDocEntryHT; -typedef std::pair PairHT; -typedef std::pair IterHT; -/// for linking together the Elements -typedef std::list ListTag; - -typedef std::string GroupKey; -typedef std::map GroupHT; //----------------------------------------------------------------------------- /** @@ -59,9 +53,7 @@ private: /// \brief Size threshold above which an element value will NOT be *printed* /// in order no to polute the screen output. By default, this upper bound /// is fixed to 64 bytes. - guint32 MaxSizePrintEntry; - - + guint32 MaxSizePrintEntry; protected: /// Refering underlying filename. @@ -92,12 +84,6 @@ protected: /// \ref gdcmDocument::SetMaxSizePrintEntry() static const unsigned int MAX_SIZE_PRINT_ELEMENT_VALUE; - /// Hash Table (multimap), to provide fast access - TagDocEntryHT tagHT; - - /// Chained list, to keep the 'spacial' ordering - ListTag listEntries; - /// Will be set 1 if user asks to 'go inside' the 'sequences' (VR = "SQ") int enableSequences; @@ -146,7 +132,6 @@ public: 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); - void WriteEntriesDeprecated(FILE *_fp,FileType type); // JPR gdcmDocEntry * ReplaceOrCreateByNumber(std::string Value, guint16 Group, guint16 Elem); @@ -171,6 +156,8 @@ protected: bool enable_sequences = false, bool ignore_shadow = false); virtual ~gdcmDocument(void); + + void gdcmDocument::Parse7FE0 (void); // Entry int CheckIfEntryExistByNumber(guint16 Group, guint16 Elem ); // int ! virtual std::string GetEntryByName (std::string tagName); @@ -194,8 +181,6 @@ protected: // Header entry gdcmDocEntry *GetDocEntryByNumber (guint16 group, guint16 element); gdcmDocEntry *GetDocEntryByName (std::string Name); - IterHT GetDocEntrySameNumber(guint16 group, guint16 element); -// IterHT GetDocEntrySameName (std::string Name); void LoadDocEntrySafe(gdcmDocEntry *); @@ -213,8 +198,8 @@ private: // What about exception_on_error ? long ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool delim_mode); - long ParseSQ(gdcmDocEntrySet *set, long offset, long l_max, bool delim_mode); - + // long ParseSQ(gdcmDocEntrySet *set, long offset, long l_max, bool delim_mode); + long ParseSQ(gdcmSeqEntry *seq, long offset, long l_max, bool delim_mode); void LoadDocEntry (gdcmDocEntry *); void FindDocEntryLength(gdcmDocEntry *); @@ -281,7 +266,7 @@ public: inline TagDocEntryHT &GetEntry(void) { return tagHT; }; /// Accessor to \ref gdcmDocument::listEntries - inline ListTag &GetListEntry(void) { return listEntries; }; + //inline ListTag &GetListEntry(void) { return listEntries; }; /// 'Swap code' accessor (see \ref sw ) inline int GetSwapCode(void) { return sw; } diff --git a/src/gdcmElementSet.cxx b/src/gdcmElementSet.cxx index 8dbeb6d3..d357da30 100644 --- a/src/gdcmElementSet.cxx +++ b/src/gdcmElementSet.cxx @@ -10,10 +10,8 @@ * \ingroup gdcmElementSet * \brief Constructor from a given gdcmElementSet */ -gdcmElementSet::gdcmElementSet() { - //TagDocEntryHT tagHT est un champ de gdcmElementSet. - // inutile de faire new ? - +gdcmElementSet::gdcmElementSet(int depthLevel) + : gdcmDocEntrySet(depthLevel) { } /** @@ -57,13 +55,15 @@ void gdcmElementSet::Print(std::ostream & os) { //----------------------------------------------------------------------------- // Protected +//----------------------------------------------------------------------------- + //----------------------------------------------------------------------------- // Private /** * \brief add a new Dicom Element pointer to the H Table - * @param newDocEntry entry to add + * @param NewEntry entry to add */ bool gdcmElementSet::AddEntry( gdcmDocEntry *NewEntry) { TagKey key; diff --git a/src/gdcmElementSet.h b/src/gdcmElementSet.h index cca67455..258e58dd 100644 --- a/src/gdcmElementSet.h +++ b/src/gdcmElementSet.h @@ -16,7 +16,7 @@ typedef std::map TagDocEntryHT; class GDCM_EXPORT gdcmElementSet : public gdcmDocEntrySet { public: - gdcmElementSet(void); + gdcmElementSet(int); ~gdcmElementSet(void); virtual bool AddEntry(gdcmDocEntry *Entry); // add to the H Table @@ -24,12 +24,12 @@ public: protected: -private: - // Variables /// Hash Table (map), to provide fast access - TagDocEntryHT tagHT; + TagDocEntryHT tagHT; + +private: }; diff --git a/src/gdcmSQItem.cxx b/src/gdcmSQItem.cxx index 79debf62..ce080c60 100644 --- a/src/gdcmSQItem.cxx +++ b/src/gdcmSQItem.cxx @@ -4,6 +4,7 @@ #include "gdcmSQItem.h" #include "gdcmGlobal.h" #include "gdcmUtil.h" +#include "gdcmValEntry.h" //----------------------------------------------------------------------------- @@ -12,8 +13,9 @@ * \ingroup gdcmSQItem * \brief Constructor from a given gdcmSQItem */ -gdcmSQItem::gdcmSQItem( ) - : gdcmDocEntrySet() { +gdcmSQItem::gdcmSQItem(int depthLevel ) + : gdcmDocEntrySet(depthLevel) { + SQDepthLevel = depthLevel +1; } /** @@ -38,7 +40,11 @@ gdcmSQItem::~gdcmSQItem() */ void gdcmSQItem::Print(std::ostream & os) { std::ostringstream s; - s << " | " ; + + if (SQDepthLevel>0) { + for (int i=0;iGetGroup() - << " " - << entry->GetElement() - << " lgt " - << entry->GetReadLength() - << std::endl; - docEntries.push_back(entry); //TODO : check if it worked return true; } - + + +/** + * \brief Sets Entry (Dicom Element) value of an element, + * specified by it's tag (Group, Number) + * and the length, too ... inside a SQ Item + * If the Element is not found, it's just created ! + * \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. + * @return true if element was found or created successfully + */ + bool gdcmSQItem::SetEntryByNumber(std::string val,guint16 group, + guint16 element) { + + for(ListDocEntry::iterator i=docEntries.begin();i!=docEntries.end();++i) { + if ( (*i)->GetGroup() == 0xfffe && (*i)->GetElement() == 0xe000 ) + continue; + if ( group < (*i)->GetGroup() || + (group == (*i)->GetGroup() && element < (*i)->GetElement()) ){ + // instead of ReplaceOrCreateByNumber + // that is a method of gdcmDocument :-( + gdcmDocEntry *Entry; + TagKey key = gdcmDictEntry::TranslateToKey(group, element); + if ( ! ptagHT->count(key)) { + // we assume a Public Dictionnary *is* loaded + gdcmDict *PubDict = gdcmGlobal::GetDicts()->GetDefaultPubDict(); + // if the invoked (group,elem) doesn't exist inside the Dictionary + // we create a VirtualDictEntry + gdcmDictEntry *DictEntry = PubDict->GetDictEntryByNumber(group, element); + if (DictEntry == NULL) { + DictEntry=gdcmGlobal::GetDicts()->NewVirtualDictEntry(group,element,"UN","??","??"); + } + // we assume the constructor didn't fail + Entry = new gdcmDocEntry(DictEntry); + /// \todo + /// ---- + /// better we don't assume too much ! + /// gdcmSQItem is now used to describe any DICOMDIR related object + /// + } else { + Entry = ptagHT->find(key)->second; + } + ((gdcmValEntry*)Entry)->SetValue(val); + Entry->SetLength(val.length()); + docEntries.insert(i,Entry); + return true; + } + if (group == (*i)->GetGroup() && element == (*i)->GetElement() ) { + ((gdcmValEntry*)(*i))->SetValue(val); + (*i)->SetLength(val.length()); + return true; + } + } +} //----------------------------------------------------------------------------- // Protected @@ -77,13 +131,73 @@ bool gdcmSQItem::AddEntry(gdcmDocEntry *entry) { gdcmDocEntry *gdcmSQItem::NewDocEntryByNumber(guint16 group, guint16 element) { // TODO - gdcmDocEntry *a; + 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) { + for(ListDocEntry::iterator i=docEntries.begin();i!=docEntries.end();++i) { + if ( (*i)->GetGroup()==group && (*i)->GetElement()==element) + return (*i); + } + return NULL; +} + +/* + * \ingroup gdcmSQItem + * \brief Get the value of a Dicom Element inside a SQ Item Entry, by number + * @return + */ + +std::string gdcmSQItem::GetEntryByNumber(guint16 group, guint16 element) { + for(ListDocEntry::iterator i=docEntries.begin();i!=docEntries.end();++i) { + if ( (*i)->GetGroup()==group && (*i)->GetElement()==element) { + return ((gdcmValEntry *)(*i))->GetValue(); + } + } + return GDCM_UNFOUND; +} + +/** + * \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 d5bd12c6..fa5f2559 100644 --- a/src/gdcmSQItem.h +++ b/src/gdcmSQItem.h @@ -7,14 +7,14 @@ #include "gdcmDocEntry.h" #include "gdcmDocEntrySet.h" - +#include "gdcmDocument.h" //----------------------------------------------------------------------------- typedef std::list ListDocEntry; //----------------------------------------------------------------------------- class GDCM_EXPORT gdcmSQItem : public gdcmDocEntrySet { public: - gdcmSQItem(void); + gdcmSQItem(int); ~gdcmSQItem(void); virtual void Print(std::ostream &os = std::cout); @@ -28,23 +28,42 @@ public: {docEntries.push_back(e);}; virtual bool AddEntry(gdcmDocEntry *Entry); // add to the List - + + gdcmDocEntry *GetDocEntryByNumber(guint16 group, + guint16 element); + gdcmDocEntry *GetDocEntryByName (std::string Name); + + bool SetEntryByNumber(std::string val,guint16 group, + guint16 element); + + std::string GetEntryByNumber(guint16 group, guint16 element); + std::string GetEntryByName(TagName name); + protected: -private: - // DocEntry related utilities virtual gdcmDocEntry *NewDocEntryByNumber(guint16 group, - guint16 element); - virtual gdcmDocEntry *NewDocEntryByName (std::string Name); + guint16 element); // TODO + virtual gdcmDocEntry *NewDocEntryByName (std::string Name); //TODO // Variables /// \brief chained list of (Elementary) Doc Entries ListDocEntry docEntries; + /// \brief SQ Item ordinal number int SQItemNumber; + +/** +* \brief pointer to the HTable of the gdcmDocument, +* (because we don't know it within any gdcmObject nor any gdcmSQItem) +*/ + TagDocEntryHT *ptagHT; + +private: + + }; diff --git a/src/gdcmSeqEntry.cxx b/src/gdcmSeqEntry.cxx index 0955a1b4..70e96f2b 100644 --- a/src/gdcmSeqEntry.cxx +++ b/src/gdcmSeqEntry.cxx @@ -15,11 +15,12 @@ * \ingroup gdcmSeqEntry * \brief Constructor from a given gdcmSeqEntry */ -gdcmSeqEntry::gdcmSeqEntry(gdcmDictEntry* e) +gdcmSeqEntry::gdcmSeqEntry(gdcmDictEntry* e, int depth) : gdcmDocEntry(e) { delimitor_mode = false; - seq_term = NULL; + seq_term = NULL; + SQDepthLevel = depth; // +1; // ?? } /** @@ -43,7 +44,7 @@ gdcmSeqEntry::~gdcmSeqEntry() { */ void gdcmSeqEntry::Print(std::ostream &os){ - std::ostringstream s; + std::ostringstream s,s2; string vr; unsigned short int g, e; long lgth; @@ -51,69 +52,30 @@ void gdcmSeqEntry::Print(std::ostream &os){ char greltag[10]; //group element tag char st[20]; - + // First, Print the Dicom Element itself. SetPrintLevel(2); -// PrintCommonPart(os); // FIXME : why doesn't it work ? - - // First, Print the Dicom Element itself. - g = GetGroup(); - e = GetElement(); - o = GetOffset(); - vr = GetVR(); - sprintf(greltag,"%04x|%04x ",g,e); - s << greltag ; - if (GetPrintLevel()>=2) { - s << "lg : "; - lgth = GetReadLength(); // ReadLength, as opposed to UsableLength - if (lgth == 0xffffffff) { - sprintf(st,"x(ffff)"); // I said : "x(ffff)" ! - s.setf(std::ios::left); - s << std::setw(10-strlen(st)) << " "; - s << st << " "; - s.setf(std::ios::left); - s << std::setw(8) << "-1"; - } else { - sprintf(st,"x(%x)",lgth); - s.setf(std::ios::left); - s << std::setw(10-strlen(st)) << " "; - s << st << " "; - s.setf(std::ios::left); - s << std::setw(8) << lgth; - } - s << " Off.: "; - sprintf(st,"x(%x)",o); - s << std::setw(10-strlen(st)) << " "; - s << st << " "; - s << std::setw(8) << o; - } - - s << "[" << vr << "] "; - if (GetPrintLevel()>=1) { - s.setf(std::ios::left); - s << std::setw(66-GetName().length()) << " "; - } - - s << "[" << GetName()<< "]"; - + PrintCommonPart(os); s << std::endl; - os << s.str(); - + 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); + (*cc)->Print(os); } // at end, print the sequence terminator item, if any - /* - if (delimitor_mode) { // TODO : find the trick to print it properly - s << " | " ; - os << s.str(); - if (seq_term = NULL) - seq_term->Print(os); - } - */ + + if (delimitor_mode) { + s2 << " | " ; + os << s2.str(); + if (seq_term != NULL) { + seq_term->Print(os); + } + else + std::cout << " -------------- should have a sequence terminator item" + << std::endl; + } } //----------------------------------------------------------------------------- @@ -123,6 +85,11 @@ void gdcmSeqEntry::Print(std::ostream &os){ void gdcmSeqEntry::AddEntry(gdcmSQItem *sqItem) { items.push_back(sqItem); } + + +void gdcmSeqEntry::SetDepthLevel(int depth) { + SQDepthLevel = depth; +} //----------------------------------------------------------------------------- // Protected @@ -131,6 +98,7 @@ void gdcmSeqEntry::AddEntry(gdcmSQItem *sqItem) { // Private // end-user intended : the guy *wants* to create his own SeQuence ?!? + gdcmDocEntry *gdcmSeqEntry::NewDocEntryByNumber(guint16 group, guint16 element) { // TODO @@ -141,6 +109,13 @@ gdcmDocEntry *gdcmSeqEntry::NewDocEntryByNumber(guint16 group, gdcmDocEntry *gdcmSeqEntry::NewDocEntryByName (std::string Name) { // TODO : gdcmDocEntry *a; - return a; + return a; +} + +gdcmDocEntry *gdcmSeqEntry::GetDocEntryByNumber(guint16 group, + guint16 element) { +// TODO + gdcmDocEntry *a; + return a; } //----------------------------------------------------------------------------- diff --git a/src/gdcmSeqEntry.h b/src/gdcmSeqEntry.h index 6456a572..9b9e6076 100644 --- a/src/gdcmSeqEntry.h +++ b/src/gdcmSeqEntry.h @@ -15,7 +15,7 @@ typedef std::list ListSQItem; class GDCM_EXPORT gdcmSeqEntry : public gdcmDocEntry { public: - gdcmSeqEntry(gdcmDictEntry* e); + gdcmSeqEntry(gdcmDictEntry* e, int depth); ~gdcmSeqEntry(void); virtual void Print(std::ostream &os = std::cout); @@ -39,7 +39,10 @@ public: gdcmDocEntry *NewDocEntryByNumber(guint16 group, guint16 element); gdcmDocEntry *NewDocEntryByName (std::string Name); - + gdcmDocEntry *GetDocEntryByNumber(guint16 group, guint16 element); + + void SetDepthLevel(int depth); + protected: private: @@ -55,6 +58,8 @@ private: /// \brief sequence terminator item gdcmDocEntry *seq_term; + //int SQDepthLevel; + }; diff --git a/src/gdcmValEntry.h b/src/gdcmValEntry.h index 1c87450b..6721b8d8 100644 --- a/src/gdcmValEntry.h +++ b/src/gdcmValEntry.h @@ -7,12 +7,12 @@ #include #include "gdcmDocEntry.h" + //----------------------------------------------------------------------------- /** - * \ingroup gdcmBinEntry + * \ingroup gdcmValEntry * \brief The dicom header of a Dicom file contains a set of such entries * (when successfuly parsed against a given Dicom dictionary) - * This one contains a 'non string' value */ class GDCM_EXPORT gdcmValEntry : public gdcmDocEntry { @@ -22,11 +22,11 @@ public: ~gdcmValEntry(void); /// \brief Returns the 'Value' (e.g. "Dupond Marcel") converted into a - /// 'string', if it's stored as an integer in the Dicom Header of the - /// current Dicom Header Entry + /// 'string', if it's stored as an integer in the header of the + /// current Dicom Document Entry inline std::string GetValue(void) { return value; }; - /// Sets the value (string) of the current Dicom Header Entry + /// Sets the value (string) of the current Dicom Document Entry inline void SetValue(std::string val) { value = val; }; virtual void Print(std::ostream &os = std::cout); @@ -39,13 +39,10 @@ private: // Variables - /// \brief Header Entry value, stored as a std::string (VR will be used, + /// \brief Document Entry value, stored as a std::string (VR will be used, /// later, to decode) std::string value; - - - };