X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmParser.cxx;h=384aa6e045beb73fd36eafe99c6ad616f2a64896;hb=41cc62fb86c116bd195581980c27480c213c958b;hp=dead892a71c58282fb6357a89fa9a80c90fd6d94;hpb=74ca8b85ac694824c885c36b5ed199f69de406d2;p=gdcm.git diff --git a/src/gdcmParser.cxx b/src/gdcmParser.cxx index dead892a..384aa6e0 100644 --- a/src/gdcmParser.cxx +++ b/src/gdcmParser.cxx @@ -17,6 +17,12 @@ # else # include #endif +# include + +#define UI1_2_840_10008_1_2 "1.2.840.10008.1.2" +#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" //----------------------------------------------------------------------------- // Refer to gdcmParser::CheckSwap() @@ -93,7 +99,7 @@ gdcmParser::~gdcmParser (void) * both from the H Table and the chained list * @return */ -void gdcmParser::PrintPubEntry(std::ostream & os) +void gdcmParser::PrintEntry(std::ostream & os) { std::ostringstream s; @@ -183,9 +189,7 @@ bool gdcmParser::IsReadable(void) { std::string res = GetEntryByNumber(0x0028, 0x0005); if ( res != GDCM_UNFOUND && atoi(res.c_str()) > 4 ) - { return false; // Image Dimensions - } if ( !GetHeaderEntryByNumber(0x0028, 0x0100) ) return false; // "Bits Allocated" @@ -213,7 +217,7 @@ bool gdcmParser::IsImplicitVRLittleEndianTransferSyntax(void) LoadHeaderEntrySafe(Element); std::string Transfer = Element->GetValue(); - if ( Transfer == "1.2.840.10008.1.2" ) + if ( Transfer == UI1_2_840_10008_1_2 ) return true; return false; } @@ -233,7 +237,7 @@ bool gdcmParser::IsExplicitVRLittleEndianTransferSyntax(void) LoadHeaderEntrySafe(Element); std::string Transfer = Element->GetValue(); - if ( Transfer == "1.2.840.10008.1.2.1" ) + if ( Transfer == UI1_2_840_10008_1_2_1 ) return true; return false; } @@ -253,7 +257,7 @@ bool gdcmParser::IsDeflatedExplicitVRLittleEndianTransferSyntax(void) LoadHeaderEntrySafe(Element); std::string Transfer = Element->GetValue(); - if ( Transfer == "1.2.840.10008.1.2.1.99" ) + if ( Transfer == UI1_2_840_10008_1_2_1_99 ) return true; return false; } @@ -273,7 +277,7 @@ bool gdcmParser::IsExplicitVRBigEndianTransferSyntax(void) LoadHeaderEntrySafe(Element); std::string Transfer = Element->GetValue(); - if ( Transfer == "1.2.840.10008.1.2.2" ) //1.2.2 ??? A verifier ! + if ( Transfer == UI1_2_840_10008_1_2_2 ) //1.2.2 ??? A verifier ! return true; return false; } @@ -324,7 +328,6 @@ FILE *gdcmParser::OpenFile(bool exception_on_error) dbg.Verbose(0, "gdcmParser::gdcmParser not DICOM/ACR", filename.c_str()); } else { - std::cerr<GetTagByName(tagName); + gdcmDictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName); if( dictEntry == NULL) return GDCM_UNFOUND; @@ -537,7 +523,7 @@ std::string gdcmParser::GetEntryByName(std::string tagName) */ std::string gdcmParser::GetEntryVRByName(std::string tagName) { - gdcmDictEntry *dictEntry = RefPubDict->GetTagByName(tagName); + gdcmDictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName); if( dictEntry == NULL) return GDCM_UNFOUND; @@ -596,7 +582,7 @@ std::string gdcmParser::GetEntryVRByNumber(guint16 group, guint16 element) */ bool gdcmParser::SetEntryByName(std::string content,std::string tagName) { - gdcmDictEntry *dictEntry = RefPubDict->GetTagByName(tagName); + gdcmDictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName); if( dictEntry == NULL) return false; @@ -666,13 +652,13 @@ bool gdcmParser::SetEntryByNumber(std::string content, * the given value. * \warning Use with extreme caution. * @param length new length to substitute with - * @param group group of the ElVal to modify - * @param element element of the ElVal to modify + * @param group group of the entry to modify + * @param element element of the Entry to modify * @return 1 on success, 0 otherwise. */ bool gdcmParser::SetEntryLengthByNumber(guint32 length, - guint16 group, guint16 element) + guint16 group, guint16 element) { TagKey key = gdcmDictEntry::TranslateToKey(group, element); if ( ! tagHT.count(key)) @@ -770,6 +756,52 @@ bool gdcmParser::SetEntryVoidAreaByNumber(void * area,guint16 group, guint16 ele return true; } +/** + * \ingroup gdcmParser + * \brief Update the entries with the shadow dictionary. Only odd entries are + * analized + */ +void gdcmParser::UpdateShaEntries(void) +{ + gdcmDictEntry *entry; + std::string vr; + + for(ListTag::iterator it=listEntries.begin(); + it!=listEntries.end(); + ++it) + { + // Odd group => from public dictionary + if((*it)->GetGroup()%2==0) + continue; + + // Peer group => search the corresponding dict entry + if(RefShaDict) + entry=RefShaDict->GetDictEntryByNumber((*it)->GetGroup(),(*it)->GetElement()); + else + entry=NULL; + + if((*it)->IsImplicitVR()) + vr="Implicit"; + else + vr=(*it)->GetVR(); + + (*it)->SetValue(GetHeaderEntryUnvalue(*it)); + if(entry) + { + // Set the new entry and the new value + (*it)->SetDictEntry(entry); + CheckHeaderEntryVR(*it,vr); + + (*it)->SetValue(GetHeaderEntryValue(*it)); + } + else + { + // Remove precedent value transformation + (*it)->SetDictEntry(NewVirtualDictEntry((*it)->GetGroup(),(*it)->GetElement(),vr)); + } + } +} + /** * \ingroup gdcmParser * \brief Searches within the Header Entries for a Dicom Element of @@ -780,7 +812,7 @@ bool gdcmParser::SetEntryVoidAreaByNumber(void * area,guint16 group, guint16 ele */ gdcmHeaderEntry *gdcmParser::GetHeaderEntryByName(std::string tagName) { - gdcmDictEntry *dictEntry = RefPubDict->GetTagByName(tagName); + gdcmDictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName); if( dictEntry == NULL) return NULL; @@ -1071,6 +1103,17 @@ guint32 gdcmParser::SwapLong(guint32 a) return(a); } +/** + * \ingroup gdcmParser + * \brief Unswaps back the bytes of 4-byte long integer accordingly to + * processor order. + * @return The properly unswaped 32 bits integer. + */ +guint32 gdcmParser::UnswapLong(guint32 a) +{ + return (SwapLong(a)); +} + /** * \ingroup gdcmParser * \brief Swaps the bytes so they agree with the processor order @@ -1083,8 +1126,35 @@ guint16 gdcmParser::SwapShort(guint16 a) return (a); } +/** + * \ingroup gdcmParser + * \brief Unswaps the bytes so they agree with the processor order + * @return The properly unswaped 16 bits integer. + */ +guint16 gdcmParser::UnswapShort(guint16 a) +{ + return (SwapShort(a)); +} + //----------------------------------------------------------------------------- // Private +/** + * \ingroup gdcmParser + * \brief Parses the header of the file but WITHOUT loading element values. + */ +void gdcmParser::Parse(bool exception_on_error) throw(gdcmFormatError) +{ + gdcmHeaderEntry *newHeaderEntry = (gdcmHeaderEntry *)0; + + rewind(fp); + CheckSwap(); + while ( (newHeaderEntry = ReadNextHeaderEntry()) ) + { + SkipHeaderEntry(newHeaderEntry); + AddHeaderEntry(newHeaderEntry); + } +} + /** * \ingroup gdcmParser * \brief Loads the element values of all the Header Entries pointed in the @@ -1093,12 +1163,12 @@ guint16 gdcmParser::SwapShort(guint16 a) void gdcmParser::LoadHeaderEntries(void) { rewind(fp); - for (ListTag::iterator i = GetPubListEntry().begin(); - i != GetPubListEntry().end(); + for (ListTag::iterator i = GetListEntry().begin(); + i != GetListEntry().end(); ++i) { - LoadHeaderEntry(*i); - } + LoadHeaderEntry(*i); + } rewind(fp); @@ -1141,17 +1211,17 @@ void gdcmParser::LoadHeaderEntries(void) * \brief Loads the element content if it's length is not bigger * than the value specified with * gdcmParser::SetMaxSizeLoadEntry() - * @param ElVal Header Entry (Dicom Element) to be dealt with + * @param Entry Header Entry (Dicom Element) to be dealt with */ -void gdcmParser::LoadHeaderEntry(gdcmHeaderEntry * ElVal) +void gdcmParser::LoadHeaderEntry(gdcmHeaderEntry *Entry) { size_t item_read; - guint16 group = ElVal->GetGroup(); - std::string vr= ElVal->GetVR(); - guint32 length = ElVal->GetLength(); + guint16 group = Entry->GetGroup(); + std::string vr= Entry->GetVR(); + guint32 length = Entry->GetLength(); bool SkipLoad = false; - fseek(fp, (long)ElVal->GetOffset(), SEEK_SET); + fseek(fp, (long)Entry->GetOffset(), SEEK_SET); // the test was commented out to 'go inside' the SeQuences // we don't any longer skip them ! @@ -1168,15 +1238,15 @@ void gdcmParser::LoadHeaderEntry(gdcmHeaderEntry * ElVal) if ( SkipLoad ) { - ElVal->SetLength(0); - ElVal->SetValue("gdcm::Skipped"); + Entry->SetLength(0); + Entry->SetValue("gdcm::Skipped"); return; } // When the length is zero things are easy: if ( length == 0 ) { - ElVal->SetValue(""); + Entry->SetValue(""); return; } @@ -1187,10 +1257,10 @@ void gdcmParser::LoadHeaderEntry(gdcmHeaderEntry * ElVal) { std::ostringstream s; s << "gdcm::NotLoaded."; - s << " Address:" << (long)ElVal->GetOffset(); - s << " Length:" << ElVal->GetLength(); - s << " x(" << std::hex << ElVal->GetLength() << ")"; - ElVal->SetValue(s.str()); + s << " Address:" << (long)Entry->GetOffset(); + s << " Length:" << Entry->GetLength(); + s << " x(" << std::hex << Entry->GetLength() << ")"; + Entry->SetValue(s.str()); return; } @@ -1201,12 +1271,12 @@ void gdcmParser::LoadHeaderEntry(gdcmHeaderEntry * ElVal) // contain a set of integers (not a single one) // Any compacter code suggested (?) - if ( IsHeaderEntryAnInteger(ElVal) ) + if ( IsHeaderEntryAnInteger(Entry) ) { guint32 NewInt; std::ostringstream s; int nbInt; - if (vr == "US" || vr == "SS") + if (vr == "US" || vr == "SS") { nbInt = length / 2; NewInt = ReadInt16(); @@ -1221,7 +1291,7 @@ void gdcmParser::LoadHeaderEntry(gdcmHeaderEntry * ElVal) } } - } + } else if (vr == "UL" || vr == "SL") { nbInt = length / 4; @@ -1236,33 +1306,28 @@ void gdcmParser::LoadHeaderEntry(gdcmHeaderEntry * ElVal) s << NewInt; } } - } + } #ifdef GDCM_NO_ANSI_STRING_STREAM s << std::ends; // to avoid oddities on Solaris #endif //GDCM_NO_ANSI_STRING_STREAM - ElVal->SetValue(s.str()); + Entry->SetValue(s.str()); return; } // We need an additional byte for storing \0 that is not on disk - char* NewValue = (char*)malloc(length+1); - if( !NewValue) - { - dbg.Verbose(1, "LoadElementValue: Failed to allocate NewValue"); - return; - } - NewValue[length]= 0; - - item_read = fread(NewValue, (size_t)length, (size_t)1, fp); + std::string NewValue(length,0); + item_read = fread(&(NewValue[0]), (size_t)length, (size_t)1, fp); if ( item_read != 1 ) { - free(NewValue); dbg.Verbose(1, "gdcmParser::LoadElementValue","unread element value"); - ElVal->SetValue("gdcm::UnRead"); + Entry->SetValue("gdcm::UnRead"); return; } - ElVal->SetValue(NewValue); - free(NewValue); + + if( (vr == "UI") ) // Because of correspondance with the VR dic + Entry->SetValue(NewValue.c_str()); + else + Entry->SetValue(NewValue); } /** @@ -1274,7 +1339,7 @@ void gdcmParser::LoadHeaderEntry(gdcmHeaderEntry * ElVal) * \ when position to be taken care of * @param newHeaderEntry */ -void gdcmParser::AddHeaderEntry(gdcmHeaderEntry * newHeaderEntry) +void gdcmParser::AddHeaderEntry(gdcmHeaderEntry *newHeaderEntry) { tagHT.insert( PairHT( newHeaderEntry->GetKey(),newHeaderEntry) ); listEntries.push_back(newHeaderEntry); @@ -1284,15 +1349,15 @@ void gdcmParser::AddHeaderEntry(gdcmHeaderEntry * newHeaderEntry) /** * \ingroup gdcmParser * \brief - * @param ElVal : Header Entry whose length of the value shall be loaded. + * @param Entry Header Entry whose length of the value shall be loaded. * @return */ - void gdcmParser::FindHeaderEntryLength (gdcmHeaderEntry * ElVal) + void gdcmParser::FindHeaderEntryLength (gdcmHeaderEntry *Entry) { - guint16 element = ElVal->GetElement(); - guint16 group = ElVal->GetGroup(); - std::string vr = ElVal->GetVR(); + guint16 element = Entry->GetElement(); + guint16 group = Entry->GetGroup(); + std::string vr = Entry->GetVR(); guint16 length16; if( (element == 0x0010) && (group == 0x7fe0) ) { @@ -1301,7 +1366,7 @@ void gdcmParser::AddHeaderEntry(gdcmHeaderEntry * newHeaderEntry) "we reached 7fe0 0010"); } - if ( (filetype == ExplicitVR) && ! ElVal->IsImplicitVr() ) + if ( (filetype == ExplicitVR) && (! Entry->IsImplicitVR()) ) { if ( (vr=="OB") || (vr=="OW") || (vr=="SQ") || (vr=="UN") ) { @@ -1313,10 +1378,10 @@ void gdcmParser::AddHeaderEntry(gdcmHeaderEntry * newHeaderEntry) if ( (vr == "OB") && (length32 == 0xffffffff) ) { - ElVal->SetLength(FindHeaderEntryLengthOB()); + Entry->SetLength(FindHeaderEntryLengthOB()); return; } - FixHeaderEntryFoundLength(ElVal, length32); + FixHeaderEntryFoundLength(Entry, length32); return; } @@ -1362,8 +1427,8 @@ void gdcmParser::AddHeaderEntry(gdcmHeaderEntry * newHeaderEntry) SwitchSwapToBigEndian(); // Restore the unproperly loaded values i.e. the group, the element // and the dictionary entry depending on them. - guint16 CorrectGroup = SwapShort(ElVal->GetGroup()); - guint16 CorrectElem = SwapShort(ElVal->GetElement()); + guint16 CorrectGroup = SwapShort(Entry->GetGroup()); + guint16 CorrectElem = SwapShort(Entry->GetElement()); gdcmDictEntry * NewTag = GetDictEntryByNumber(CorrectGroup, CorrectElem); if (!NewTag) @@ -1373,7 +1438,7 @@ void gdcmParser::AddHeaderEntry(gdcmHeaderEntry * newHeaderEntry) } // FIXME this can create a memory leaks on the old entry that be // left unreferenced. - ElVal->SetDictEntry(NewTag); + Entry->SetDictEntry(NewTag); } // Heuristic: well some files are really ill-formed. @@ -1386,34 +1451,34 @@ void gdcmParser::AddHeaderEntry(gdcmHeaderEntry * newHeaderEntry) // Unknown Sequence Length } - FixHeaderEntryFoundLength(ElVal, (guint32)length16); + FixHeaderEntryFoundLength(Entry, (guint32)length16); + return; + } + else + { + // Either implicit VR or a non DICOM conformal (see not below) explicit + // VR that ommited the VR of (at least) this element. Farts happen. + // [Note: according to the part 5, PS 3.5-2001, section 7.1 p25 + // on Data elements "Implicit and Explicit VR Data Elements shall + // not coexist in a Data Set and Data Sets nested within it".] + // Length is on 4 bytes. + FixHeaderEntryFoundLength(Entry, ReadInt32()); return; } - - // Either implicit VR or a non DICOM conformal (see not below) explicit - // VR that ommited the VR of (at least) this element. Farts happen. - // [Note: according to the part 5, PS 3.5-2001, section 7.1 p25 - // on Data elements "Implicit and Explicit VR Data Elements shall - // not coexist in a Data Set and Data Sets nested within it".] - // Length is on 4 bytes. - FixHeaderEntryFoundLength(ElVal, ReadInt32()); - return; } /** * \ingroup gdcmParser * \brief Find the Value Representation of the current Dicom Element. - * @param ElVal + * @param Entry */ -void gdcmParser::FindHeaderEntryVR( gdcmHeaderEntry *ElVal) +void gdcmParser::FindHeaderEntryVR( gdcmHeaderEntry *Entry) { if (filetype != ExplicitVR) return; char VR[3]; - std::string vr; int lgrLue; - char msg[100]; // for sprintf. Sorry long PositionOnEntry = ftell(fp); // Warning: we believe this is explicit VR (Value Representation) because @@ -1423,12 +1488,38 @@ void gdcmParser::FindHeaderEntryVR( gdcmHeaderEntry *ElVal) // within an explicit VR file. Hence we make sure the present tag // is in explicit VR and try to fix things if it happens not to be // the case. - bool RealExplicit = true; lgrLue=fread (&VR, (size_t)2,(size_t)1, fp); VR[2]=0; - vr = std::string(VR); - + if(!CheckHeaderEntryVR(Entry,VR)) + { + fseek(fp, PositionOnEntry, SEEK_SET); + // When this element is known in the dictionary we shall use, e.g. for + // the semantics (see the usage of IsAnInteger), the VR proposed by the + // dictionary entry. Still we have to flag the element as implicit since + // we know now our assumption on expliciteness is not furfilled. + // avoid . + if ( Entry->IsVRUnknown() ) + Entry->SetVR("Implicit"); + Entry->SetImplicitVR(); + } +} + +/** + * \ingroup gdcmParser + * \brief Check the correspondance between the VR of the header entry + * and the taken VR. If they are different, the header entry is + * updated with the new VR. + * @param Entry + * @param VR + * @return false if the VR is incorrect of if the VR isn't referenced + * otherwise, it returns true +*/ +bool gdcmParser::CheckHeaderEntryVR(gdcmHeaderEntry *Entry, VRKey vr) +{ + char msg[100]; // for sprintf + bool RealExplicit = true; + // Assume we are reading a falsely explicit VR file i.e. we reached // a tag where we expect reading a VR but are in fact we read the // first to bytes of the length. Then we will interogate (through find) @@ -1437,7 +1528,7 @@ void gdcmParser::FindHeaderEntryVR( gdcmHeaderEntry *ElVal) // expected VR read happens to be non-ascii characters we consider // we hit falsely explicit VR tag. - if ( (!isalpha(VR[0])) && (!isalpha(VR[1])) ) + if ( (!isalpha(vr[0])) && (!isalpha(vr[1])) ) RealExplicit = false; // CLEANME searching the dicom_vr at each occurence is expensive. @@ -1446,59 +1537,156 @@ void gdcmParser::FindHeaderEntryVR( gdcmHeaderEntry *ElVal) if ( RealExplicit && !gdcmGlobal::GetVR()->Count(vr) ) RealExplicit= false; - if ( RealExplicit ) + if ( !RealExplicit ) + { + // We thought this was explicit VR, but we end up with an + // implicit VR tag. Let's backtrack. + sprintf(msg,"Falsely explicit vr file (%04x,%04x)\n", + Entry->GetGroup(),Entry->GetElement()); + dbg.Verbose(1, "gdcmParser::FindVR: ",msg); + + return(false); + } + + if ( Entry->IsVRUnknown() ) + { + // When not a dictionary entry, we can safely overwrite the VR. + Entry->SetVR(vr); + } + else if ( Entry->GetVR() != vr ) { - if ( ElVal->IsVRUnknown() ) - { - // When not a dictionary entry, we can safely overwrite the VR. - ElVal->SetVR(vr); - return; - } - if ( ElVal->GetVR() == vr ) - { - // The VR we just read and the dictionary agree. Nothing to do. - return; - } // The VR present in the file and the dictionary disagree. We assume // the file writer knew best and use the VR of the file. Since it would // be unwise to overwrite the VR of a dictionary (since it would // compromise it's next user), we need to clone the actual DictEntry // and change the VR for the read one. - gdcmDictEntry* NewTag = NewVirtualDictEntry(ElVal->GetGroup(), - ElVal->GetElement(), - vr, - "FIXME", - ElVal->GetName()); - ElVal->SetDictEntry(NewTag); - return; + gdcmDictEntry* NewEntry = NewVirtualDictEntry( + Entry->GetGroup(),Entry->GetElement(), + vr,"FIXME",Entry->GetName()); + Entry->SetDictEntry(NewEntry); } - - // We thought this was explicit VR, but we end up with an - // implicit VR tag. Let's backtrack. - - sprintf(msg,"Falsely explicit vr file (%04x,%04x)\n", - ElVal->GetGroup(),ElVal->GetElement()); - dbg.Verbose(1, "gdcmParser::FindVR: ",msg); - - fseek(fp, PositionOnEntry, SEEK_SET); - // When this element is known in the dictionary we shall use, e.g. for - // the semantics (see the usage of IsAnInteger), the VR proposed by the - // dictionary entry. Still we have to flag the element as implicit since - // we know now our assumption on expliciteness is not furfilled. - // avoid . - if ( ElVal->IsVRUnknown() ) - ElVal->SetVR("Implicit"); - ElVal->SetImplicitVr(); + return(true); } /** * \ingroup gdcmParser - * \brief Skip a given Header Entry + * \brief Get the transformed value of the header entry. The VR value + * is used to define the transformation to operate on the value * \warning NOT end user intended method ! - * @param entry - * @return + * @param Entry + * @return Transformed entry value */ -void gdcmParser::SkipHeaderEntry(gdcmHeaderEntry * entry) +std::string gdcmParser::GetHeaderEntryValue(gdcmHeaderEntry *Entry) +{ + if ( (IsHeaderEntryAnInteger(Entry)) && (Entry->IsImplicitVR()) ) + { + std::string val=Entry->GetValue(); + std::string vr=Entry->GetVR(); + guint32 length = Entry->GetLength(); + std::ostringstream s; + int nbInt; + + if (vr == "US" || vr == "SS") + { + guint16 NewInt16; + + nbInt = length / 2; + for (int i=0; i < nbInt; i++) + { + if(i!=0) + s << '\\'; + NewInt16 = (val[2*i+0]&0xFF)+((val[2*i+1]&0xFF)<<8); + NewInt16 = SwapShort(NewInt16); + s << NewInt16; + } + } + + else if (vr == "UL" || vr == "SL") + { + guint32 NewInt32; + + nbInt = length / 4; + for (int i=0; i < nbInt; i++) + { + if(i!=0) + s << '\\'; + NewInt32= (val[4*i+0]&0xFF)+((val[4*i+1]&0xFF)<<8)+ + ((val[4*i+2]&0xFF)<<16)+((val[4*i+3]&0xFF)<<24); + NewInt32=SwapLong(NewInt32); + s << NewInt32; + } + } + +#ifdef GDCM_NO_ANSI_STRING_STREAM + s << std::ends; // to avoid oddities on Solaris +#endif //GDCM_NO_ANSI_STRING_STREAM + return(s.str()); + } + + return(Entry->GetValue()); +} + +/** + * \ingroup gdcmParser + * \brief Get the reverse transformed value of the header entry. The VR + * value is used to define the reverse transformation to operate on + * the value + * \warning NOT end user intended method ! + * @param Entry + * @return Reverse transformed entry value + */ +std::string gdcmParser::GetHeaderEntryUnvalue(gdcmHeaderEntry *Entry) +{ + if ( (IsHeaderEntryAnInteger(Entry)) && (Entry->IsImplicitVR()) ) + { + std::string vr=Entry->GetVR(); + std::ostringstream s; + std::vector tokens; + + if (vr == "US" || vr == "SS") + { + guint16 NewInt16; + + tokens.erase(tokens.begin(),tokens.end()); // clean any previous value + Tokenize (Entry->GetValue(), tokens, "\\"); + for (unsigned int i=0; i>8)&0xFF); + } + tokens.clear(); + } + if (vr == "UL" || vr == "SL") + { + guint32 NewInt32; + + tokens.erase(tokens.begin(),tokens.end()); // clean any previous value + Tokenize (Entry->GetValue(), tokens, "\\"); + for (unsigned int i=0; i>8)&0xFF) + <<(char)((NewInt32>>16)&0xFF)<<(char)((NewInt32>>24)&0xFF); + } + tokens.clear(); + } + +#ifdef GDCM_NO_ANSI_STRING_STREAM + s << std::ends; // to avoid oddities on Solaris +#endif //GDCM_NO_ANSI_STRING_STREAM + return(s.str()); + } + + return(Entry->GetValue()); +} + +/** + * \ingroup gdcmParser + * \brief Skip a given Header Entry + * \warning NOT end user intended method ! + * @param entry + */ +void gdcmParser::SkipHeaderEntry(gdcmHeaderEntry *entry) { SkipBytes(entry->GetLength()); } @@ -1509,9 +1697,9 @@ void gdcmParser::SkipHeaderEntry(gdcmHeaderEntry * entry) * the parser went Jabberwocky) one can hope improving things by * applying this heuristic. */ -void gdcmParser::FixHeaderEntryFoundLength(gdcmHeaderEntry * ElVal, guint32 FoundLength) +void gdcmParser::FixHeaderEntryFoundLength(gdcmHeaderEntry *Entry, guint32 FoundLength) { - ElVal->SetReadLength(FoundLength); // will be updated only if a bug is found + Entry->SetReadLength(FoundLength); // will be updated only if a bug is found if ( FoundLength == 0xffffffff) { @@ -1524,26 +1712,26 @@ void gdcmParser::FixHeaderEntryFoundLength(gdcmHeaderEntry * ElVal, guint32 Foun { // The following 'if' will be removed when there is no more // images on Creatis HDs with a 13 length for Manufacturer... - if ( (ElVal->GetGroup() != 0x0008) || - ( (ElVal->GetElement() != 0x0070) && (ElVal->GetElement() != 0x0080) ) ) { + if ( (Entry->GetGroup() != 0x0008) || + ( (Entry->GetElement() != 0x0070) && (Entry->GetElement() != 0x0080) ) ) { // end of remove area FoundLength =10; - ElVal->SetReadLength(10); // a bug is to be fixed + Entry->SetReadLength(10); // a bug is to be fixed } } // to fix some garbage 'Leonardo' Siemens images // May be commented out to avoid overhead - else if ( (ElVal->GetGroup() == 0x0009) && - ( (ElVal->GetElement() == 0x1113) || (ElVal->GetElement() == 0x1114) ) ) + else if ( (Entry->GetGroup() == 0x0009) && + ( (Entry->GetElement() == 0x1113) || (Entry->GetElement() == 0x1114) ) ) { FoundLength =4; - ElVal->SetReadLength(4); // a bug is to be fixed + Entry->SetReadLength(4); // a bug is to be fixed } // end of fix // to try to 'go inside' SeQuences (with length), and not to skip them - else if ( ElVal->GetVR() == "SQ") + else if ( Entry->GetVR() == "SQ") { if (enableSequences) // only if the user does want to ! FoundLength =0; @@ -1558,7 +1746,7 @@ void gdcmParser::FixHeaderEntryFoundLength(gdcmHeaderEntry * ElVal, guint32 Foun // if we set the length to zero IsHeaderEntryAnInteger() breaks... // if we don't, we lost 28800 characters from the Header :-( - else if(ElVal->GetGroup() == 0xfffe) + else if(Entry->GetGroup() == 0xfffe) { // sometimes, length seems to be wrong FoundLength =0; // some more clever checking to be done ! @@ -1567,22 +1755,22 @@ void gdcmParser::FixHeaderEntryFoundLength(gdcmHeaderEntry * ElVal, guint32 Foun // causes troubles :-( } - ElVal->SetUsableLength(FoundLength); + Entry->SetUsableLength(FoundLength); } /** * \ingroup gdcmParser * \brief Apply some heuristics to predict wether the considered * element value contains/represents an integer or not. - * @param ElVal The element value on which to apply the predicate. + * @param Entry The element value on which to apply the predicate. * @return The result of the heuristical predicate. */ -bool gdcmParser::IsHeaderEntryAnInteger(gdcmHeaderEntry * ElVal) +bool gdcmParser::IsHeaderEntryAnInteger(gdcmHeaderEntry *Entry) { - guint16 element = ElVal->GetElement(); - guint16 group = ElVal->GetGroup(); - std::string vr = ElVal->GetVR(); - guint32 length = ElVal->GetLength(); + guint16 element = Entry->GetElement(); + guint16 group = Entry->GetGroup(); + std::string vr = Entry->GetVR(); + guint32 length = Entry->GetLength(); // When we have some semantics on the element we just read, and if we // a priori know we are dealing with an integer, then we shall be @@ -1972,13 +2160,13 @@ gdcmDictEntry *gdcmParser::GetDictEntryByName(std::string Name) } if (RefPubDict) { - found = RefPubDict->GetTagByName(Name); + found = RefPubDict->GetDictEntryByName(Name); if (found) return found; } if (RefShaDict) { - found = RefShaDict->GetTagByName(Name); + found = RefShaDict->GetDictEntryByName(Name); if (found) return found; } @@ -2005,13 +2193,13 @@ gdcmDictEntry *gdcmParser::GetDictEntryByNumber(guint16 group,guint16 element) } if (RefPubDict) { - found = RefPubDict->GetTagByNumber(group, element); + found = RefPubDict->GetDictEntryByNumber(group, element); if (found) return found; } if (RefShaDict) { - found = RefShaDict->GetTagByNumber(group, element); + found = RefShaDict->GetDictEntryByNumber(group, element); if (found) return found; } @@ -2026,7 +2214,7 @@ gdcmDictEntry *gdcmParser::GetDictEntryByNumber(guint16 group,guint16 element) gdcmHeaderEntry *gdcmParser::ReadNextHeaderEntry(void) { guint16 g,n; - gdcmHeaderEntry *NewElVal; + gdcmHeaderEntry *NewEntry; g = ReadInt16(); n = ReadInt16(); @@ -2036,18 +2224,18 @@ gdcmHeaderEntry *gdcmParser::ReadNextHeaderEntry(void) // has to be considered as finished. return (gdcmHeaderEntry *)0; - NewElVal = NewHeaderEntryByNumber(g, n); - FindHeaderEntryVR(NewElVal); - FindHeaderEntryLength(NewElVal); + NewEntry = NewHeaderEntryByNumber(g, n); + FindHeaderEntryVR(NewEntry); + FindHeaderEntryLength(NewEntry); if (errno == 1) { // Call it quits return NULL; } - NewElVal->SetOffset(ftell(fp)); + NewEntry->SetOffset(ftell(fp)); //if ( (g==0x7fe0) && (n==0x0010) ) - return NewElVal; + return NewEntry; } /** @@ -2063,14 +2251,14 @@ gdcmHeaderEntry *gdcmParser::NewHeaderEntryByName(std::string Name) if (!NewTag) NewTag = NewVirtualDictEntry(0xffff, 0xffff, "LO", "Unknown", Name); - gdcmHeaderEntry* NewElVal = new gdcmHeaderEntry(NewTag); - if (!NewElVal) + gdcmHeaderEntry* NewEntry = new gdcmHeaderEntry(NewTag); + if (!NewEntry) { dbg.Verbose(1, "gdcmParser::ObtainHeaderEntryByName", "failed to allocate gdcmHeaderEntry"); return (gdcmHeaderEntry *)0; } - return NewElVal; + return NewEntry; } /** @@ -2101,18 +2289,18 @@ gdcmDictEntry *gdcmParser::NewVirtualDictEntry(guint16 group, guint16 element, gdcmHeaderEntry *gdcmParser::NewHeaderEntryByNumber(guint16 Group, guint16 Elem) { // Find out if the tag we encountered is in the dictionaries: - gdcmDictEntry *NewTag = GetDictEntryByNumber(Group, Elem); - if (!NewTag) - NewTag = NewVirtualDictEntry(Group, Elem); + gdcmDictEntry *DictEntry = GetDictEntryByNumber(Group, Elem); + if (!DictEntry) + DictEntry = NewVirtualDictEntry(Group, Elem); - gdcmHeaderEntry* NewElVal = new gdcmHeaderEntry(NewTag); - if (!NewElVal) + gdcmHeaderEntry *NewEntry = new gdcmHeaderEntry(DictEntry); + if (!NewEntry) { dbg.Verbose(1, "gdcmParser::NewHeaderEntryByNumber", "failed to allocate gdcmHeaderEntry"); return NULL; } - return NewElVal; + return NewEntry; } /** @@ -2128,24 +2316,24 @@ gdcmHeaderEntry *gdcmParser::NewHeaderEntryByNumber(guint16 Group, guint16 Elem) gdcmHeaderEntry *gdcmParser::NewManualHeaderEntryToPubDict(std::string NewTagName, std::string VR) { - gdcmHeaderEntry *NewElVal = (gdcmHeaderEntry *)0; + gdcmHeaderEntry *NewEntry = NULL; guint32 StuffGroup = 0xffff; // Group to be stuffed with additional info guint32 FreeElem = 0; - gdcmDictEntry *NewEntry = (gdcmDictEntry *)0; + gdcmDictEntry *DictEntry = NULL; FreeElem = GenerateFreeTagKeyInGroup(StuffGroup); if (FreeElem == UINT32_MAX) { - dbg.Verbose(1, "gdcmHeader::NewManualElValToPubDict", + dbg.Verbose(1, "gdcmHeader::NewManualHeaderEntryToPubDict", "Group 0xffff in Public Dict is full"); return NULL; } - NewEntry = NewVirtualDictEntry(StuffGroup, FreeElem, + DictEntry = NewVirtualDictEntry(StuffGroup, FreeElem, VR, "GDCM", NewTagName); - NewElVal = new gdcmHeaderEntry(NewEntry); - AddHeaderEntry(NewElVal); - return NewElVal; + NewEntry = new gdcmHeaderEntry(DictEntry); + AddHeaderEntry(NewEntry); + return NewEntry; } /**