X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmHeader.cxx;h=7cb2cad0fad356999bfcf623eec6399ea0256169;hb=efc4d18faced64c24c75448b61685f92f2d799ce;hp=c035d69fc55ec87996c7d2d72df411c7edd11825;hpb=1ea4314b315a12c6b484cd38d23aa2bf57f544b3;p=gdcm.git diff --git a/src/gdcmHeader.cxx b/src/gdcmHeader.cxx index c035d69f..7cb2cad0 100644 --- a/src/gdcmHeader.cxx +++ b/src/gdcmHeader.cxx @@ -1,4 +1,4 @@ -// $Header: /cvs/public/gdcm/src/Attic/gdcmHeader.cxx,v 1.93 2003/10/03 07:46:06 jpr Exp $ +// $Header: /cvs/public/gdcm/src/Attic/gdcmHeader.cxx,v 1.103 2003/10/23 12:08:32 jpr Exp $ #include "gdcmHeader.h" @@ -72,9 +72,26 @@ 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()); + + if ( fp ) { + guint16 zero; + fread(&zero, (size_t)2, (size_t)1, fp); + + //ACR -- or DICOM with no Preamble + if( zero == 0x0008 || zero == 0x0800 || zero == 0x0002 || zero == 0x0200) + return true; + //DICOM + fseek(fp, 126L, SEEK_CUR); + char dicm[4]; + fread(dicm, (size_t)4, (size_t)1, fp); + if( memcmp(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; } @@ -105,7 +122,7 @@ gdcmHeader::~gdcmHeader (void) { // Fourth semantics: // -// ---> Warning : This fourth fiels is NOT part +// ---> Warning : This fourth field is NOT part // of the 'official' Dicom Dictionnary // and should NOT be used. // (Not defined for all the groups @@ -491,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; } @@ -610,6 +629,24 @@ 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 ... + else if (FoundLength == 13) { + // 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)) { + // end of remove area + FoundLength =10; + } + } + // 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) ) ) + FoundLength =4; + ElVal->SetLength(FoundLength); } @@ -630,23 +667,19 @@ void gdcmHeader::FixFoundLength(gdcmElValue * ElVal, guint32 FoundLength) { while ( ! FoundSequenceDelimiter) { g = ReadInt16(); - n = ReadInt16(); - - long l = ftell(fp); - + n = ReadInt16(); if (errno == 1) return 0; TotalLength += 4; // We even have to decount the group and element - if ( g != 0xfffe && g!=0xb00c ) /*for bogus header */ { + if ( g != 0xfffe && g!=0xb00c ) /*for bogus header */ { char msg[100]; // for sprintf. Sorry sprintf(msg,"wrong group (%04x) for an item sequence (%04x,%04x)\n",g, g,n); dbg.Verbose(1, "gdcmHeader::FindLengthOB: ",msg); - long l = ftell(fp); errno = 1; return 0; } - if ( n == 0xe0dd || ( g==0xb00c && n==0x0eb6 ) ) /* for bogus header */ + if ( n == 0xe0dd || ( g==0xb00c && n==0x0eb6 ) ) /* for bogus header */ FoundSequenceDelimiter = true; else if ( n != 0xe000 ){ char msg[100]; // for sprintf. Sorry @@ -658,8 +691,7 @@ void gdcmHeader::FixFoundLength(gdcmElValue * ElVal, guint32 FoundLength) { } ItemLength = ReadInt32(); TotalLength += ItemLength + 4; // We add 4 bytes since we just read - // the ItemLength with ReadInt32 - + // the ItemLength with ReadInt32 SkipBytes(ItemLength); } fseek(fp, PositionOnEntry, SEEK_SET); @@ -692,6 +724,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; @@ -756,9 +789,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; } @@ -1090,9 +1126,12 @@ int gdcmHeader::ReplaceOrCreateByNumber(std::string Value, // 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); } @@ -1120,6 +1159,7 @@ int gdcmHeader::ReplaceOrCreateByNumber(char* Value, guint16 Group, guint16 Elem /** * \ingroup gdcmHeader * \brief Set a new value if the invoked element exists + * Seems to be useless !!! * @param Value * @param Group * @param Elem @@ -1127,7 +1167,7 @@ int gdcmHeader::ReplaceOrCreateByNumber(char* Value, guint16 Group, guint16 Elem */ int gdcmHeader::ReplaceIfExistByNumber(char* Value, guint16 Group, guint16 Elem ) { - gdcmElValue* elValue = PubElValSet.GetElementByNumber(Group, Elem); + //gdcmElValue* elValue = PubElValSet.GetElementByNumber(Group, Elem); std::string v = Value; PubElValSet.SetElValueByNumber(v, Group, Elem); return 1; @@ -1207,9 +1247,8 @@ gdcmElValue * gdcmHeader::ReadNextElement(void) { * @return The result of the heuristical predicate. */ bool gdcmHeader::IsAnInteger(gdcmElValue * ElVal) { - guint16 group = ElVal->GetGroup(); guint16 element = ElVal->GetElement(); - std::string vr = ElVal->GetVR(); + std::string vr = ElVal->GetVR(); guint32 length = ElVal->GetLength(); // When we have some semantics on the element we just read, and if we @@ -1728,7 +1767,7 @@ void gdcmHeader::PrintPubElVal(std::ostream & os) { /** * \ingroup gdcmHeader - * \brief + * \brief * @return */ void gdcmHeader::PrintPubDict(std::ostream & os) { @@ -1738,9 +1777,36 @@ void gdcmHeader::PrintPubDict(std::ostream & os) { /** * \ingroup gdcmHeader * \brief - * @return + * @return integer, acts as a Boolean */ 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); } @@ -1766,7 +1832,7 @@ void * gdcmHeader::LoadElementVoidArea(guint16 Group, guint16 Elem) { << std::hex << Group << " " << Elem << std::endl; return NULL; } - int res = PubElValSet.SetVoidAreaByNumber(a, Group, Elem); + /* int res = */ PubElValSet.SetVoidAreaByNumber(a, Group, Elem); // TODO check the result size_t l2 = fread(a, 1, l ,fp); if(l != l2) { @@ -1774,7 +1840,8 @@ void * gdcmHeader::LoadElementVoidArea(guint16 Group, guint16 Elem) { << std::hex << Group << " " << Elem << std::endl; free(a); return NULL; - } + } + return a; } /** @@ -1897,6 +1964,19 @@ int gdcmHeader::GetBitsStored(void) { return atoi(StrSize.c_str()); } +/** + * \ingroup gdcmHeader + * \brief Retrieve the number of Bits Allocated + * (8, 12 -compacted ACR-NEMA files, 16, ...) + * + * @return The encountered number of Bits Allocated, 0 by default. + */ +int gdcmHeader::GetBitsAllocated(void) { + std::string StrSize = GetPubElValByNumber(0x0028,0x0100); + if (StrSize == GDCM_UNFOUND) + return 1; + return atoi(StrSize.c_str()); +} /** * \ingroup gdcmHeader