X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmHeader.cxx;h=5657dd2c6c1344020c7286e3e40f28700f3de780;hb=3a7de562dd07854a96a0a148e1c95652baefe2c8;hp=c1d8c0434d4fd539279691d6032a28627c2c0d74;hpb=af94ab6719e309d3dd9730d5656057c429106938;p=gdcm.git diff --git a/src/gdcmHeader.cxx b/src/gdcmHeader.cxx index c1d8c043..5657dd2c 100644 --- a/src/gdcmHeader.cxx +++ b/src/gdcmHeader.cxx @@ -1,16 +1,6 @@ -// $Header: /cvs/public/gdcm/src/Attic/gdcmHeader.cxx,v 1.90 2003/09/24 16:18:32 jpr Exp $ +// $Header: /cvs/public/gdcm/src/Attic/gdcmHeader.cxx,v 1.99 2003/10/10 16:54:25 jpr Exp $ -//This is needed when compiling in debug mode -#ifdef _MSC_VER -//'identifier' : not all control paths return a value -//#pragma warning ( disable : 4715 ) -// 'identifier' : class 'type' needs to have dll-interface to be used by -// clients of class 'type2' -#pragma warning ( disable : 4251 ) -// 'identifier' : identifier was truncated to 'number' characters in the -// debug information -#pragma warning ( disable : 4786 ) -#endif //_MSC_VER +#include "gdcmHeader.h" #include #include @@ -23,7 +13,6 @@ #include // for isalpha #include #include "gdcmUtil.h" -#include "gdcmHeader.h" #include "gdcmTS.h" // Refer to gdcmHeader::CheckSwap() @@ -38,7 +27,7 @@ void gdcmHeader::Initialise(void) { dicom_vr = gdcmGlobal::GetVR(); dicom_ts = gdcmGlobal::GetTS(); - Dicts = gdcmGlobal::GetDicts(); + Dicts = gdcmGlobal::GetDicts(); RefPubDict = Dicts->GetDefaultPubDict(); RefShaDict = (gdcmDict*)0; } @@ -55,10 +44,8 @@ gdcmHeader::gdcmHeader(const char *InFilename, bool exception_on_error) { Initialise(); if ( !OpenFile(exception_on_error)) return; -printf ("avant ParseHeader\n"); - ParseHeader(); -printf ("avant LoadElements\n"); + ParseHeader(); LoadElements(); CloseFile(); } @@ -86,9 +73,25 @@ gdcmHeader::gdcmHeader(bool exception_on_error) { if(!fp) throw gdcmFileError("gdcmHeader::gdcmHeader(const char *, bool)"); } - if ( fp ) - return true; - dbg.Verbose(0, "gdcmHeader::gdcmHeader cannot open file", filename.c_str()); +// char *testEntete = new char[204]; + guint16 zero; + fread(&zero, (size_t)2, (size_t)1, fp); + if ( fp ) { + //ACR + if( zero == 0x0008 || zero == 0x0800 ) + return true; + //DICOM + fseek(fp, 126L, SEEK_CUR); + char dicm[4]; + fread(dicm, (size_t)4, (size_t)1, fp); + if( strncmp(dicm, "DICM", 4) == 0 ) + return true; + fclose(fp); + dbg.Verbose(0, "gdcmHeader::gdcmHeader not DICOM/ACR", filename.c_str()); + } + else { + dbg.Verbose(0, "gdcmHeader::gdcmHeader cannot open file", filename.c_str()); + } return false; } @@ -118,6 +121,13 @@ gdcmHeader::~gdcmHeader (void) { } // Fourth semantics: +// +// ---> Warning : This fourth fiels is NOT part +// of the 'official' Dicom Dictionnary +// and should NOT be used. +// (Not defined for all the groups +// may be removed in a future release) +// // CMD Command // META Meta Information // DIR Directory @@ -378,7 +388,8 @@ void gdcmHeader::FindVR( gdcmElValue *ElVal) { // 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()); + sprintf(msg,"Falsely explicit vr file (%04x,%04x)\n", + ElVal->GetGroup(),ElVal->GetElement()); dbg.Verbose(1, "gdcmHeader::FindVR: ",msg); fseek(fp, PositionOnEntry, SEEK_SET); @@ -497,6 +508,8 @@ bool gdcmHeader::IsJPEGLossless(void) { const char * Transfert = Element->GetValue().c_str(); if ( memcmp(Transfert+strlen(Transfert)-2 ,"70",2)==0) return true; if ( memcmp(Transfert+strlen(Transfert)-2 ,"55",2)==0) return true; + if (Element->GetValue() == "1.2.840.10008.1.2.4.57") return true; + return false; } @@ -616,6 +629,15 @@ bool gdcmHeader::IsDicomV3(void) { void gdcmHeader::FixFoundLength(gdcmElValue * ElVal, guint32 FoundLength) { if ( FoundLength == 0xffffffff) FoundLength = 0; + // Sorry for the patch! + // XMedCom did the trick to read some nasty GE images ... + if (FoundLength == 13) + // The following 'if' will be removed when there is no more + // images on Creatis HD with a 13 length for Manufacturer... + if ( (ElVal->GetGroup() != 0x0008) || (ElVal->GetElement() ) ) + // end of remove area + FoundLength =10; + ElVal->SetLength(FoundLength); } @@ -656,7 +678,8 @@ void gdcmHeader::FixFoundLength(gdcmElValue * ElVal, guint32 FoundLength) { FoundSequenceDelimiter = true; else if ( n != 0xe000 ){ char msg[100]; // for sprintf. Sorry - sprintf(msg,"wrong element (%04x) for an item sequence (%04x,%04x)\n",n, g,n); + sprintf(msg,"wrong element (%04x) for an item sequence (%04x,%04x)\n", + n, g,n); dbg.Verbose(1, "gdcmHeader::FindLengthOB: ",msg); errno = 1; return 0; @@ -680,12 +703,12 @@ void gdcmHeader::FixFoundLength(gdcmElValue * ElVal, guint32 FoundLength) { void gdcmHeader::FindLength (gdcmElValue * ElVal) { guint16 element = ElVal->GetElement(); guint16 group = ElVal->GetGroup(); - std::string vr = ElVal->GetVR(); + std::string vr = ElVal->GetVR(); guint16 length16; if( (element == 0x0010) && (group == 0x7fe0) ) { dbg.SetDebug(0); dbg.Verbose(2, "gdcmHeader::FindLength: ", - "on est sur 7fe0 0010"); + "we reached 7fe0 0010"); } if ( (filetype == ExplicitVR) && ! ElVal->IsImplicitVr() ) { @@ -697,6 +720,7 @@ void gdcmHeader::FixFoundLength(gdcmElValue * ElVal, guint32 FoundLength) { fseek(fp, 2L, SEEK_CUR); guint32 length32 = ReadInt32(); + if ( (vr == "OB") && (length32 == 0xffffffff) ) { ElVal->SetLength(FindLengthOB()); return; @@ -761,9 +785,12 @@ void gdcmHeader::FixFoundLength(gdcmElValue * ElVal, guint32 FoundLength) { // Heuristic: well some files are really ill-formed. if ( length16 == 0xffff) { length16 = 0; - dbg.Verbose(0, "gdcmHeader::FindLength", - "Erroneous element length fixed."); + //dbg.Verbose(0, "gdcmHeader::FindLength", + // "Erroneous element length fixed."); + // Actually, length= 0xffff means that we deal with + // Unknown Sequence Length } + FixFoundLength(ElVal, (guint32)length16); return; } @@ -864,7 +891,7 @@ guint16 gdcmHeader::SwapShort(guint16 a) { void gdcmHeader::LoadElementValue(gdcmElValue * ElVal) { size_t item_read; guint16 group = ElVal->GetGroup(); - std::string vr = ElVal->GetVR(); + std::string vr= ElVal->GetVR(); guint32 length = ElVal->GetLength(); bool SkipLoad = false; @@ -1086,7 +1113,8 @@ gdcmElValue* gdcmHeader::NewElValueByNumber(guint16 Group, guint16 Elem) { * @param Elem * \return integer acts as a boolean */ -int gdcmHeader::ReplaceOrCreateByNumber(std::string Value, guint16 Group, guint16 Elem ) { +int gdcmHeader::ReplaceOrCreateByNumber(std::string Value, + guint16 Group, guint16 Elem ) { // TODO : FIXME JPRx // curieux, non ? @@ -1094,9 +1122,12 @@ int gdcmHeader::ReplaceOrCreateByNumber(std::string Value, guint16 Group, guint1 // on l'ajoute au ElValSet // on affecte une valeur a cette ElValue a l'interieur du ElValSet // --> devrait pouvoir etre fait + simplement ??? - - gdcmElValue* nvElValue=NewElValueByNumber(Group, Elem); - PubElValSet.Add(nvElValue); + if (CheckIfExistByNumber(Group, Elem) == 0) { + gdcmElValue* a =NewElValueByNumber(Group, Elem); + if (a == NULL) + return 0; + PubElValSet.Add(a); + } PubElValSet.SetElValueByNumber(Value, Group, Elem); return(1); } @@ -1104,7 +1135,7 @@ int gdcmHeader::ReplaceOrCreateByNumber(std::string Value, guint16 Group, guint1 /** * \ingroup gdcmHeader - * \brief Modify or (Creates if not found) an element + * \brief Modify (or Creates if not found) an element * @param Value new value * @param Group * @param Elem @@ -1185,9 +1216,7 @@ gdcmElValue * gdcmHeader::ReadNextElement(void) { g = ReadInt16(); n = ReadInt16(); - - //if ( (g==0x7fe0) && (n==0x0010) ) - + if (errno == 1) // We reached the EOF (or an error occured) and header parsing // has to be considered as finished. @@ -1546,7 +1575,8 @@ std::string gdcmHeader::GetElValRepByName(std::string TagName) { int gdcmHeader::SetPubElValByNumber(std::string content, guint16 group, guint16 element) -//TODO : homogeneiser les noms : SetPubElValByNumber qui appelle PubElValSet.SetElValueByNumber +//TODO : homogeneiser les noms : SetPubElValByNumber +// qui appelle PubElValSet.SetElValueByNumber // pourquoi pas SetPubElValueByNumber ?? { @@ -1657,7 +1687,8 @@ bool gdcmHeader::IsReadable(void) { * @param VR The Value Representation to be given to this new tag. * @ return The newly hand crafted Element Value. */ -gdcmElValue* gdcmHeader::NewManualElValToPubDict(std::string NewTagName, std::string VR) { +gdcmElValue* gdcmHeader::NewManualElValToPubDict(std::string NewTagName, + std::string VR) { gdcmElValue* NewElVal = (gdcmElValue*)0; guint32 StuffGroup = 0xffff; // Group to be stuffed with additional info guint32 FreeElem = 0; @@ -1745,6 +1776,33 @@ void gdcmHeader::PrintPubDict(std::ostream & os) { * @return */ int gdcmHeader::Write(FILE * fp, FileType type) { + + + // TODO : move the following lines (and a lot of others) + // to a future function CheckAndCorrectHeader + + if (type == ImplicitVR) { + std::string implicitVRTransfertSyntax = "1.2.840.10008.1.2"; + ReplaceOrCreateByNumber(implicitVRTransfertSyntax,0x0002, 0x0010); + + //FIXME Refer to standards on page 21, chapter 6.2 "Value representation": + // values with a VR of UI shall be padded with a single trailing null + // Dans le cas suivant on doit pader manuellement avec un 0 + + PubElValSet.SetElValueLengthByNumber(18, 0x0002, 0x0010); + } + + if (type == ExplicitVR) { + std::string explicitVRTransfertSyntax = "1.2.840.10008.1.2.1"; + ReplaceOrCreateByNumber(explicitVRTransfertSyntax,0x0002, 0x0010); + + //FIXME Refer to standards on page 21, chapter 6.2 "Value representation": + // values with a VR of UI shall be padded with a single trailing null + // Dans le cas suivant on doit pader manuellement avec un 0 + + PubElValSet.SetElValueLengthByNumber(20, 0x0002, 0x0010); + } + return PubElValSet.Write(fp, type); } @@ -1767,7 +1825,7 @@ void * gdcmHeader::LoadElementVoidArea(guint16 Group, guint16 Elem) { void * a = malloc(l); if(!a) { std::cout << "Big Broblem (LoadElementVoidArea, malloc) " - << std::hex << Group << " " << Elem << std::endl; + << std::hex << Group << " " << Elem << std::endl; return NULL; } int res = PubElValSet.SetVoidAreaByNumber(a, Group, Elem); @@ -1775,7 +1833,7 @@ void * gdcmHeader::LoadElementVoidArea(guint16 Group, guint16 Elem) { size_t l2 = fread(a, 1, l ,fp); if(l != l2) { std::cout << "Big Broblem (LoadElementVoidArea, fread) " - << std::hex << Group << " " << Elem << std::endl; + << std::hex << Group << " " << Elem << std::endl; free(a); return NULL; } @@ -1793,7 +1851,7 @@ void * gdcmHeader::LoadElementVoidArea(guint16 Group, guint16 Elem) { gdcmElValue* elValue = PubElValSet.GetElementByNumber(Group, Elem); if (!elValue) { dbg.Verbose(1, "gdcmHeader::GetElValueByNumber", - "failed to Locate gdcmElValue"); + "failed to Locate gdcmElValue"); return (size_t)0; } return elValue->GetOffset(); @@ -2056,7 +2114,7 @@ int gdcmHeader::GetLUTNbits(void) { //int LutLength; //int LutDepth; int LutNbits; - // Just hope Lookup Table Desc-Red = Lookup Table Desc-Red = Lookup Table Desc-Blue + //Just hope Lookup Table Desc-Red = Lookup Table Desc-Red = Lookup Table Desc-Blue // Consistency already checked in GetLUTLength std::string LutDescription = GetPubElValByNumber(0x0028,0x1101); if (LutDescription == GDCM_UNFOUND) @@ -2132,6 +2190,7 @@ void * gdcmHeader::GetLUTRGB(void) { if(l==0) return (NULL); int nBits=GetLUTNbits(); + // a virer quand on aura trouve UNE image // qui correspond VRAIMENT à la definition ! std::cout << "l " << l << " nBits " << nBits; @@ -2170,7 +2229,8 @@ void * gdcmHeader::GetLUTRGB(void) { unsigned char * g = (unsigned char *)LutG; unsigned char * b = (unsigned char *)LutB; for(int i=0;i tokens; + tokens.erase(tokens.begin(),tokens.end()); // clean any previous value + Tokenize ((const std::string)x, tokens, "\\"); + for (unsigned int i=0; i