X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;ds=inline;f=src%2FgdcmHeader.cxx;h=5e6c2c876cd2c1c4b6146b12c9b6b5215243ff57;hb=bb2cb788a245b6377a70de3e8a502dab036165ab;hp=10f5700dac5c3445f5e847d8d1f4f801d823b978;hpb=1f5594f4e2bc55ccc70ff04cd66acc7cd8da74c8;p=gdcm.git diff --git a/src/gdcmHeader.cxx b/src/gdcmHeader.cxx index 10f5700d..5e6c2c87 100644 --- a/src/gdcmHeader.cxx +++ b/src/gdcmHeader.cxx @@ -13,7 +13,7 @@ #include "gdcmUtil.h" #include "gdcmHeader.h" -#include +#include "iddcmjpeg.h" // Refer to gdcmHeader::CheckSwap() #define HEADER_LENGTH_TO_READ 256 @@ -43,6 +43,7 @@ gdcmHeader::gdcmHeader(const char *InFilename, bool exception_on_error) else dbg.Error(!fp, "gdcmHeader::gdcmHeader cannot open file", InFilename); ParseHeader(); + LoadElements(); AddAndDefaultElements(); } @@ -343,7 +344,7 @@ void gdcmHeader::FindVR( gdcmElValue *ElVal) { * @return True when ImplicitVRLittleEndian found. False in all other cases. */ bool gdcmHeader::IsImplicitVRLittleEndianTransferSyntax(void) { - gdcmElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010); + gdcmElValue* Element = PubElValSet.GetElementByNumber(0x0002, 0x0010); if ( !Element ) return false; LoadElementValueSafe(Element); @@ -361,7 +362,7 @@ bool gdcmHeader::IsImplicitVRLittleEndianTransferSyntax(void) { * @return True when ExplicitVRLittleEndian found. False in all other cases. */ bool gdcmHeader::IsExplicitVRLittleEndianTransferSyntax(void) { - gdcmElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010); + gdcmElValue* Element = PubElValSet.GetElementByNumber(0x0002, 0x0010); if ( !Element ) return false; LoadElementValueSafe(Element); @@ -379,7 +380,7 @@ bool gdcmHeader::IsExplicitVRLittleEndianTransferSyntax(void) { * @return True when DeflatedExplicitVRLittleEndian found. False in all other cases. */ bool gdcmHeader::IsDeflatedExplicitVRLittleEndianTransferSyntax(void) { - gdcmElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010); + gdcmElValue* Element = PubElValSet.GetElementByNumber(0x0002, 0x0010); if ( !Element ) return false; LoadElementValueSafe(Element); @@ -397,7 +398,7 @@ bool gdcmHeader::IsDeflatedExplicitVRLittleEndianTransferSyntax(void) { * @return True when big endian found. False in all other cases. */ bool gdcmHeader::IsExplicitVRBigEndianTransferSyntax(void) { - gdcmElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010); + gdcmElValue* Element = PubElValSet.GetElementByNumber(0x0002, 0x0010); if ( !Element ) return false; LoadElementValueSafe(Element); @@ -415,7 +416,7 @@ bool gdcmHeader::IsExplicitVRBigEndianTransferSyntax(void) { * @return True when JPEGBaseLineProcess1found. False in all other cases. */ bool gdcmHeader::IsJPEGBaseLineProcess1TransferSyntax(void) { - gdcmElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010); + gdcmElValue* Element = PubElValSet.GetElementByNumber(0x0002, 0x0010); if ( !Element ) return false; LoadElementValueSafe(Element); @@ -428,7 +429,7 @@ bool gdcmHeader::IsJPEGBaseLineProcess1TransferSyntax(void) { // faire qq chose d'intelligent a la place de ça bool gdcmHeader::IsJPEGLossless(void) { - gdcmElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010); + gdcmElValue* Element = PubElValSet.GetElementByNumber(0x0002, 0x0010); if ( !Element ) return false; LoadElementValueSafe(Element); @@ -447,7 +448,7 @@ bool gdcmHeader::IsJPEGLossless(void) { * @return True when JPEGExtendedProcess2-4 found. False in all other cases. */ bool gdcmHeader::IsJPEGExtendedProcess2_4TransferSyntax(void) { - gdcmElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010); + gdcmElValue* Element = PubElValSet.GetElementByNumber(0x0002, 0x0010); if ( !Element ) return false; LoadElementValueSafe(Element); @@ -465,7 +466,7 @@ bool gdcmHeader::IsJPEGExtendedProcess2_4TransferSyntax(void) { * @return True when JPEGExtendedProcess3-5 found. False in all other cases. */ bool gdcmHeader::IsJPEGExtendedProcess3_5TransferSyntax(void) { - gdcmElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010); + gdcmElValue* Element = PubElValSet.GetElementByNumber(0x0002, 0x0010); if ( !Element ) return false; LoadElementValueSafe(Element); @@ -484,7 +485,7 @@ bool gdcmHeader::IsJPEGExtendedProcess3_5TransferSyntax(void) { * other cases. */ bool gdcmHeader::IsJPEGSpectralSelectionProcess6_8TransferSyntax(void) { - gdcmElValue* Element = PubElVals.GetElementByNumber(0x0002, 0x0010); + gdcmElValue* Element = PubElValSet.GetElementByNumber(0x0002, 0x0010); if ( !Element ) return false; LoadElementValueSafe(Element); @@ -713,13 +714,14 @@ void gdcmHeader::LoadElementValue(gdcmElValue * ElVal) { fseek(fp, (long)ElVal->GetOffset(), SEEK_SET); - // Sequences not treated yet ! + // FIXME Sequences not treated yet ! // // Ne faudrait-il pas au contraire trouver immediatement // une maniere 'propre' de traiter les sequences (vr = SQ) // car commencer par les ignorer risque de conduire a qq chose // qui pourrait ne pas etre generalisable - // + // Well, I'm expecting your code !!! + if( vr == "SQ" ) SkipLoad = true; @@ -729,16 +731,7 @@ void gdcmHeader::LoadElementValue(gdcmElValue * ElVal) { if( group == 0xfffe ) SkipLoad = true; - // The group length doesn't represent data to be loaded in memory, since - // each element of the group shall be loaded individualy. - if( elem == 0 ) - //SkipLoad = true; // modif sauvage JPR - // On charge la longueur du groupe - // quand l'element 0x0000 est présent ! - if ( SkipLoad ) { - // FIXME the following skip is not necessary - SkipElementValue(ElVal); ElVal->SetLength(0); ElVal->SetValue("gdcm::Skipped"); return; @@ -768,26 +761,6 @@ void gdcmHeader::LoadElementValue(gdcmElValue * ElVal) { // pour les elements de Value Multiplicity > 1 // on aura en fait une serie d'entiers - // code original - - //if ( IsAnInteger(ElVal) ) { - // guint32 NewInt; - // if( length == 2 ) { - // NewInt = ReadInt16(); - // } else if( length == 4 ) { - // - // NewInt = ReadInt32(); - // } else - // dbg.Error(true, "LoadElementValue: Inconsistency when reading Int."); - // - // //FIXME: make the following an util fonction - // ostringstream s; - // s << NewInt; - // ElVal->SetValue(s.str()); - // return; - //} - - // modif proposee. JPR // on devrait pouvoir faire + compact (?) if ( IsAnInteger(ElVal) ) { @@ -823,8 +796,6 @@ void gdcmHeader::LoadElementValue(gdcmElValue * ElVal) { return; } - - // FIXME The exact size should be length if we move to strings or whatever char* NewValue = (char*)malloc(length+1); if( !NewValue) { @@ -909,6 +880,20 @@ gdcmElValue* gdcmHeader::NewElValueByKey(guint16 Group, guint16 Elem) { return NewElVal; } +/** + * \ingroup gdcmHeader + * \brief TODO + * @param + */ +int gdcmHeader::ReplaceOrCreateByNumber(guint16 Group, guint16 Elem, string Value) { + + gdcmElValue* nvElValue=NewElValueByKey(Group, Elem); + PubElValSet.Add(nvElValue); + PubElValSet.SetElValueByNumber(Value, Group, Elem); + return(1); +} + + /** * \ingroup gdcmHeader * \brief Build a new Element Value from all the low level arguments. @@ -937,8 +922,8 @@ gdcmElValue* gdcmHeader::NewElValueByName(string Name) { * @return On succes the newly created ElValue, NULL on failure. */ gdcmElValue * gdcmHeader::ReadNextElement(void) { - guint16 g; - guint16 n; + + guint16 g,n; gdcmElValue * NewElVal; g = ReadInt16(); @@ -1048,7 +1033,7 @@ size_t gdcmHeader::GetPixelOffset(void) { numPixel = 0x1010; else numPixel = 0x0010; - gdcmElValue* PixelElement = PubElVals.GetElementByNumber(grPixel, numPixel); + gdcmElValue* PixelElement = PubElValSet.GetElementByNumber(grPixel, numPixel); if (PixelElement) return PixelElement->GetOffset(); else @@ -1121,7 +1106,7 @@ gdcmDictEntry * gdcmHeader::GetDictEntryByName(string Name) { * "gdcm::Unfound" otherwise. */ string gdcmHeader::GetPubElValByNumber(guint16 group, guint16 element) { - return PubElVals.GetElValueByNumber(group, element); + return PubElValSet.GetElValueByNumber(group, element); } /** @@ -1139,7 +1124,7 @@ string gdcmHeader::GetPubElValByNumber(guint16 group, guint16 element) { * and the string "gdcm::Unfound" otherwise. */ string gdcmHeader::GetPubElValRepByNumber(guint16 group, guint16 element) { - gdcmElValue* elem = PubElVals.GetElementByNumber(group, element); + gdcmElValue* elem = PubElValSet.GetElementByNumber(group, element); if ( !elem ) return "gdcm::Unfound"; return elem->GetVR(); @@ -1154,7 +1139,7 @@ string gdcmHeader::GetPubElValRepByNumber(guint16 group, guint16 element) { * "gdcm::Unfound" otherwise. */ string gdcmHeader::GetPubElValByName(string TagName) { - return PubElVals.GetElValueByName(TagName); + return PubElValSet.GetElValueByName(TagName); } /** @@ -1171,7 +1156,7 @@ string gdcmHeader::GetPubElValByName(string TagName) { * and the string "gdcm::Unfound" otherwise. */ string gdcmHeader::GetPubElValRepByName(string TagName) { - gdcmElValue* elem = PubElVals.GetElementByName(TagName); + gdcmElValue* elem = PubElValSet.GetElementByName(TagName); if ( !elem ) return "gdcm::Unfound"; return elem->GetVR(); @@ -1187,7 +1172,7 @@ string gdcmHeader::GetPubElValRepByName(string TagName) { * and the string "gdcm::Unfound" otherwise. */ string gdcmHeader::GetShaElValByNumber(guint16 group, guint16 element) { - return ShaElVals.GetElValueByNumber(group, element); + return ShaElValSet.GetElValueByNumber(group, element); } /** @@ -1205,7 +1190,7 @@ string gdcmHeader::GetShaElValByNumber(guint16 group, guint16 element) { * and the string "gdcm::Unfound" otherwise. */ string gdcmHeader::GetShaElValRepByNumber(guint16 group, guint16 element) { - gdcmElValue* elem = ShaElVals.GetElementByNumber(group, element); + gdcmElValue* elem = ShaElValSet.GetElementByNumber(group, element); if ( !elem ) return "gdcm::Unfound"; return elem->GetVR(); @@ -1220,7 +1205,7 @@ string gdcmHeader::GetShaElValRepByNumber(guint16 group, guint16 element) { * "gdcm::Unfound" otherwise. */ string gdcmHeader::GetShaElValByName(string TagName) { - return ShaElVals.GetElValueByName(TagName); + return ShaElValSet.GetElValueByName(TagName); } /** @@ -1237,7 +1222,7 @@ string gdcmHeader::GetShaElValByName(string TagName) { * and the string "gdcm::Unfound" otherwise. */ string gdcmHeader::GetShaElValRepByName(string TagName) { - gdcmElValue* elem = ShaElVals.GetElementByName(TagName); + gdcmElValue* elem = ShaElValSet.GetElementByName(TagName); if ( !elem ) return "gdcm::Unfound"; return elem->GetVR(); @@ -1321,7 +1306,7 @@ string gdcmHeader::GetElValRepByName(string TagName) { /** * \ingroup gdcmHeader - * \brief Accesses an existing gdcmElValue in the PubElVals of this instance + * \brief Accesses an existing gdcmElValue in the PubElValSet of this instance * through it's (group, element) and modifies it's content with * the given value. * @param content new value to substitute with @@ -1331,60 +1316,61 @@ string gdcmHeader::GetElValRepByName(string TagName) { int gdcmHeader::SetPubElValByNumber(string content, guint16 group, guint16 element) { - return ( PubElVals.SetElValueByNumber (content, group, element) ); + return ( PubElValSet.SetElValueByNumber (content, group, element) ); } /** * \ingroup gdcmHeader - * \brief Accesses an existing gdcmElValue in the PubElVals of this instance + * \brief Accesses an existing gdcmElValue in the PubElValSet of this instance * through tag name and modifies it's content with the given value. * @param content new value to substitute with * @param TagName name of the tag to be modified */ int gdcmHeader::SetPubElValByName(string content, string TagName) { - return ( PubElVals.SetElValueByName (content, TagName) ); + return ( PubElValSet.SetElValueByName (content, TagName) ); } /** * \ingroup gdcmHeader - * \brief Accesses an existing gdcmElValue in the PubElVals of this instance + * \brief Accesses an existing gdcmElValue in the PubElValSet of this instance * through it's (group, element) and modifies it's length with * the given value. - * NOT FOR BOZOs ! - * @param contents new length to substitute with + * \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 + * @return 1 on success, 0 otherwise. */ -int gdcmHeader::SetPubElValLengthByNumber(guint32 lgr, guint16 group, - guint16 element) -{ - return ( PubElVals.SetElValueLengthByNumber (lgr, group, element) ); + +int gdcmHeader::SetPubElValLengthByNumber(guint32 length, guint16 group, + guint16 element) { + return ( PubElValSet.SetElValueLengthByNumber (length, group, element) ); } /** * \ingroup gdcmHeader - * \brief Accesses an existing gdcmElValue in the ShaElVals of this instance + * \brief Accesses an existing gdcmElValue in the ShaElValSet of this instance * through it's (group, element) and modifies it's content with * the given value. * @param content new value to substitute with * @param group group of the ElVal to modify * @param element element of the ElVal to modify + * @return 1 on success, 0 otherwise. */ int gdcmHeader::SetShaElValByNumber(string content, - guint16 group, guint16 element) -{ - return ( ShaElVals.SetElValueByNumber (content, group, element) ); + guint16 group, guint16 element) { + return ( ShaElValSet.SetElValueByNumber (content, group, element) ); } /** * \ingroup gdcmHeader - * \brief Accesses an existing gdcmElValue in the ShaElVals of this instance + * \brief Accesses an existing gdcmElValue in the ShaElValSet of this instance * through tag name and modifies it's content with the given value. * @param content new value to substitute with * @param TagName name of the tag to be modified */ int gdcmHeader::SetShaElValByName(string content, string TagName) { - return ( ShaElVals.SetElValueByName (content, TagName) ); + return ( ShaElValSet.SetElValueByName (content, TagName) ); } /** @@ -1398,7 +1384,7 @@ void gdcmHeader::ParseHeader(bool exception_on_error) throw(gdcmFormatError) { CheckSwap(); while ( (newElValue = ReadNextElement()) ) { SkipElementValue(newElValue); - PubElVals.Add(newElValue); + PubElValSet.Add(newElValue); } } @@ -1415,19 +1401,97 @@ void gdcmHeader::ParseHeader(bool exception_on_error) throw(gdcmFormatError) { * the ones of the official DICOM fields Rows, Columns and Planes. */ void gdcmHeader::AddAndDefaultElements(void) { - gdcmElValue* NewEntry = (gdcmElValue*)0; + gdcmElValue* NewElVal = (gdcmElValue*)0; + string NewVal; + + NewElVal = NewManualElValToPubDict("gdcmXSize", "US"); + if (!NewElVal) return; + NewVal = GetElValByName("Rows"); + if (NewVal != "gdcm::Unfound") + NewElVal->SetValue(NewVal); + else + NewElVal->SetValue("0"); + + NewElVal = NewManualElValToPubDict("gdcmYSize", "US"); + if (!NewElVal) return; + NewVal = GetElValByName("Columns"); + if (NewVal != "gdcm::Unfound") + NewElVal->SetValue(NewVal); + else + NewElVal->SetValue("0"); + + + NewElVal = NewManualElValToPubDict("gdcmZSize", "US"); + if (!NewElVal) return; + NewVal = GetElValByNumber(0x0028,0x0008); // 0028 0008 IS IMG Number of Frames (DICOM) + if (NewVal == "gdcm::Unfound") { + NewVal = GetElValByNumber(0x0028,0x0012); // 028 0012 US IMG Planes (ACR-NEMA) + if (NewVal == "gdcm::Unfound") { // Warning !!! : 6000 0012 US OLY Planes + NewElVal->SetValue("0"); + } else { + NewElVal->SetValue(NewVal); + } + } else { + NewElVal->SetValue(NewVal); + } // length is still wrong +} // do we care about it? - NewEntry = NewElValueByName("gdcmXSize"); - NewEntry->SetValue(GetElValByName("Rows")); - PubElVals.Add(NewEntry); - NewEntry = NewElValueByName("gdcmYSize"); - NewEntry->SetValue(GetElValByName("Columns")); - PubElVals.Add(NewEntry); +/** + * \ingroup gdcmHeader + * \brief This predicate, based on hopefully reasonnable heuristics, + * decides whether or not the current gdcmHeader was properly parsed + * and contains the mandatory information for being considered as + * a well formed and usable image. + * @return true when gdcmHeader is the one of a reasonable Dicom file, + * false otherwise. + */ +bool gdcmHeader::IsReadable(void) { + if ( GetElValByName("Image Dimensions") != "gdcm::Unfound" + && atoi(GetElValByName("Image Dimensions").c_str()) > 4 ) { + return false; + } + if ( GetElValByName("Bits Allocated") == "gdcm::Unfound" ) + return false; + if ( GetElValByName("Bits Stored") == "gdcm::Unfound" ) + return false; + if ( GetElValByName("High Bit") == "gdcm::Unfound" ) + return false; + if ( GetElValByName("Pixel Representation") == "gdcm::Unfound" ) + return false; + return true; +} + + +/** + * \ingroup gdcmHeader + * \brief Small utility function that creates a new manually crafted + * (as opposed as read from the file) gdcmElValue with user + * specified name and adds it to the public tag hash table. + * Refer to gdcmHeader::AddAndDefaultElements for a typical usage. + * \note A fake TagKey is generated so the PubDict can keep it's coherence. + * @param NewTagName The name to be given to this new tag. + * @param VR The Value Representation to be given to this new tag. + * @ return The newly hand crafted Element Value. + */ +gdcmElValue* gdcmHeader::NewManualElValToPubDict(string NewTagName, string VR) { + gdcmElValue* NewElVal = (gdcmElValue*)0; + guint32 StuffGroup = 0xffff; // Group to be stuffed with additional info + guint32 FreeElem = 0; + gdcmDictEntry* NewEntry = (gdcmDictEntry*)0; + + FreeElem = PubElValSet.GenerateFreeTagKeyInGroup(StuffGroup); + if (FreeElem == UINT32_MAX) { + dbg.Verbose(1, "gdcmHeader::NewManualElValToPubDict", + "Group 0xffff in Public Dict is full"); + return (gdcmElValue*)0; + } + NewEntry = new gdcmDictEntry(StuffGroup, FreeElem, + VR, "GDCM", NewTagName); + NewElVal = new gdcmElValue(NewEntry); + PubElValSet.Add(NewElVal); + return NewElVal; - NewEntry = NewElValueByName("gdcmZSize"); - NewEntry->SetValue(GetElValByName("Planes")); - PubElVals.Add(NewEntry); } /** @@ -1437,14 +1501,14 @@ void gdcmHeader::AddAndDefaultElements(void) { */ void gdcmHeader::LoadElements(void) { rewind(fp); - TagElValueHT ht = PubElVals.GetTagHt(); + TagElValueHT ht = PubElValSet.GetTagHt(); for (TagElValueHT::iterator tag = ht.begin(); tag != ht.end(); ++tag) { LoadElementValue(tag->second); } } void gdcmHeader::PrintPubElVal(ostream & os) { - PubElVals.Print(os); + PubElValSet.Print(os); } void gdcmHeader::PrintPubDict(ostream & os) {