X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmDocument.cxx;h=c5079fe4f8d57c57a7f40d4642354654af0f0a18;hb=c852120fdb6d542d84f74440b68414fdb52178d7;hp=2fbb8bd7884047ffeea053322bebef07c1510fc7;hpb=c03bc9b5e7d49126a10d49f78682410a5500c412;p=gdcm.git diff --git a/src/gdcmDocument.cxx b/src/gdcmDocument.cxx index 2fbb8bd7..c5079fe4 100644 --- a/src/gdcmDocument.cxx +++ b/src/gdcmDocument.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmDocument.cxx,v $ Language: C++ - Date: $Date: 2004/11/16 10:25:53 $ - Version: $Revision: 1.125 $ + Date: $Date: 2004/11/24 16:39:18 $ + Version: $Revision: 1.137 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -39,6 +39,8 @@ namespace gdcm static const char *TransferSyntaxStrings[] = { // Implicit VR Little Endian "1.2.840.10008.1.2", + // Implicit VR Little Endian DLX G.E? + "1.2.840.113619.5.2", // Explicit VR Little Endian "1.2.840.10008.1.2.1", // Deflated Explicit VR Little Endian @@ -199,13 +201,6 @@ Document::~Document () RefPubDict = NULL; RefShaDict = NULL; - // Recursive clean up of sequences - for (TagDocEntryHT::const_iterator it = TagHT.begin(); - it != TagHT.end(); ++it ) - { - //delete it->second; //temp remove - } - TagHT.clear(); delete RLEInfo; delete JPEGInfo; } @@ -323,7 +318,7 @@ TransferSyntaxType Document::GetTransferSyntax() // for brain damaged headers return UnknownTS; } - while ( !isdigit(transfer[transfer.length()-1]) ) + while ( !isdigit((unsigned char)transfer[transfer.length()-1]) ) { transfer.erase(transfer.length()-1, 1); } @@ -436,8 +431,12 @@ std::ifstream* Document::OpenFile() uint16_t zero; Fp->read((char*)&zero, (size_t)2 ); - //ACR -- or DICOM with no Preamble -- - if( zero == 0x0008 || zero == 0x0800 || zero == 0x0002 || zero == 0x0200 ) + //ACR -- or DICOM with no Preamble; may start with a Shadow Group -- + if( + zero == 0x0001 || zero == 0x0100 || zero == 0x0002 || zero == 0x0200 || + zero == 0x0003 || zero == 0x0300 || zero == 0x0004 || zero == 0x0400 || + zero == 0x0005 || zero == 0x0500 || zero == 0x0006 || zero == 0x0600 || + zero == 0x0007 || zero == 0x0700 || zero == 0x0008 || zero == 0x0800 ) { return Fp; } @@ -489,6 +488,15 @@ void Document::Write(std::ofstream* fp, FileType filetype) /// (necessary if user wants to write a DICOM V3 file /// starting from an ACR-NEMA (V2) Header + if ( filetype == ImplicitVR || filetype == ExplicitVR ) + { + // writing Dicom File Preamble + char filePreamble[128]; + memset(filePreamble, 0, 128); + fp->write(filePreamble, 128); + fp->write("DICM", 4); + } + if (filetype == ImplicitVR) { std::string ts = @@ -576,16 +584,17 @@ ValEntry* Document::ReplaceOrCreateByNumber( " NewDocEntryByNumber failed."); return NULL; } + valEntry = new ValEntry(currentEntry); + delete currentEntry; + if ( !AddEntry(valEntry)) { delete valEntry; dbg.Verbose(0, "Document::ReplaceOrCreateByNumber: AddEntry" " failed allthough this is a creation."); + return NULL; } - // This is the reason why NewDocEntryByNumber are a real - // bad habit !!! FIXME - delete currentEntry; } else { @@ -621,6 +630,7 @@ ValEntry* Document::ReplaceOrCreateByNumber( /* * \brief Modifies the value of a given Header Entry (Dicom Element) * when it exists. Create it with the given value when unexistant. + * A copy of the binArea is made to be kept in the Document. * @param binArea (binary) value to be set * @param Group Group number of the Entry * @param Elem Element number of the Entry @@ -692,7 +702,23 @@ BinEntry* Document::ReplaceOrCreateByNumber( } } - SetEntryByNumber(binArea, lgth, group, elem); + uint8_t *tmpArea; + if (lgth>0 && binArea) + { + tmpArea = new uint8_t[lgth]; + memcpy(tmpArea,binArea,lgth); + } + else + { + tmpArea = 0; + } + if (!SetEntryByNumber(tmpArea, lgth, group, elem)) + { + if (tmpArea) + { + delete[] tmpArea; + } + } return binEntry; } @@ -957,10 +983,10 @@ bool Document::SetEntryByNumber(uint8_t*content, int lgth, //content = content + '\0'; // fing a trick to enlarge a binary field? } */ - BinEntry* a = (BinEntry *)TagHT[key]; - a->SetBinArea(content); - a->SetLength(lgth); - a->SetValue(GDCM_BINLOADED); + BinEntry* entry = (BinEntry *)TagHT[key]; + entry->SetBinArea(content); + entry->SetLength(lgth); + entry->SetValue(GDCM_BINLOADED); return true; } @@ -1048,7 +1074,12 @@ void Document::LoadEntryBinArea(uint16_t group, uint16_t elem) if ( !docElement ) return; - size_t o =(size_t)docElement->GetOffset(); + BinEntry *binElement = dynamic_cast(docElement); + if( !binElement ) + return; + + LoadEntryBinArea(binElement); +/* size_t o =(size_t)docElement->GetOffset(); Fp->seekg( o, std::ios_base::beg); size_t l = docElement->GetLength(); uint8_t* a = new uint8_t[l]; @@ -1071,8 +1102,9 @@ void Document::LoadEntryBinArea(uint16_t group, uint16_t elem) { delete[] a; dbg.Verbose(0, "Document::LoadEntryBinArea setting failed."); - } + }*/ } + /** * \brief Loads (from disk) the element content * when a string is not suitable @@ -1080,8 +1112,16 @@ void Document::LoadEntryBinArea(uint16_t group, uint16_t elem) */ void Document::LoadEntryBinArea(BinEntry* element) { + if(element->GetBinArea()) + return; + + bool openFile = !Fp; + if(openFile) + OpenFile(); + size_t o =(size_t)element->GetOffset(); Fp->seekg(o, std::ios_base::beg); + size_t l = element->GetLength(); uint8_t* a = new uint8_t[l]; if( !a ) @@ -1098,7 +1138,10 @@ void Document::LoadEntryBinArea(BinEntry* element) return; } - element->SetBinArea((uint8_t*)a); + element->SetBinArea(a); + + if(openFile) + CloseFile(); } /** @@ -1322,10 +1365,10 @@ void Document::ParseDES(DocEntrySet *set, long offset, long l_max, bool delim_mode) { DocEntry *newDocEntry = 0; - + while (true) - { - if ( !delim_mode && (Fp->tellg()-offset) >= l_max) + { + if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max) { break; } @@ -1362,18 +1405,22 @@ void Document::ParseDES(DocEntrySet *set, long offset, + newValEntry->GetKey() ); } + LoadDocEntry( newValEntry ); + bool delimitor=newValEntry->IsItemDelimitor(); if( !set->AddEntry( newValEntry ) ) { // If here expect big troubles delete newValEntry; //otherwise mem leak } - LoadDocEntry( newValEntry ); - if (newValEntry->IsItemDelimitor()) + + if (delimitor) { + delete newDocEntry; break; } - if ( !delim_mode && (Fp->tellg()-offset) >= l_max) + if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max) { + delete newDocEntry; break; } } @@ -1387,9 +1434,10 @@ void Document::ParseDES(DocEntrySet *set, long offset, } //////////////////// BinEntry or UNKOWN VR: - BinEntry* newBinEntry = +/* BinEntry* newBinEntry = new BinEntry( newDocEntry->GetDictEntry() ); //LEAK - newBinEntry->Copy( newDocEntry ); + newBinEntry->Copy( newDocEntry );*/ + BinEntry* newBinEntry = new BinEntry( newDocEntry ); //LEAK // When "this" is a Document the Key is simply of the // form ( group, elem )... @@ -1407,12 +1455,12 @@ void Document::ParseDES(DocEntrySet *set, long offset, + newBinEntry->GetKey() ); } + LoadDocEntry( newBinEntry ); if( !set->AddEntry( newBinEntry ) ) { //Expect big troubles if here delete newBinEntry; } - LoadDocEntry( newBinEntry ); } if ( ( newDocEntry->GetGroup() == 0x7fe0 ) @@ -1437,6 +1485,7 @@ void Document::ParseDES(DocEntrySet *set, long offset, // Just to make sure we are at the beginning of next entry. SkipToNextDocEntry(newDocEntry); + //delete newDocEntry; } else { @@ -1486,8 +1535,9 @@ void Document::ParseDES(DocEntrySet *set, long offset, l, delim_mode); } set->AddEntry( newSeqEntry ); - if ( !delim_mode && (Fp->tellg()-offset) >= l_max) + if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max) { + delete newDocEntry; break; } } @@ -1517,13 +1567,14 @@ void Document::ParseSQ( SeqEntry* seqEntry, { if ( newDocEntry->IsSequenceDelimitor() ) { - seqEntry->SetSequenceDelimitationItem( newDocEntry ); + seqEntry->SetSequenceDelimitationItem( newDocEntry ); break; } } - if ( !delim_mode && (Fp->tellg()-offset) >= l_max) + if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max) { - break; + delete newDocEntry; + break; } SQItem *itemSQ = new SQItem( seqEntry->GetDepthLevel() ); @@ -1545,10 +1596,11 @@ void Document::ParseSQ( SeqEntry* seqEntry, } ParseDES(itemSQ, newDocEntry->GetOffset(), l, dlm_mod); + delete newDocEntry; seqEntry->AddEntry( itemSQ, SQItemNumber ); SQItemNumber++; - if ( !delim_mode && ( Fp->tellg() - offset ) >= l_max ) + if ( !delim_mode && ((long)(Fp->tellg())-offset ) >= l_max ) { break; } @@ -1769,7 +1821,7 @@ void Document::FindDocEntryLength( DocEntry *entry ) // the length and proceed. long currentPosition = Fp->tellg(); Fp->seekg(0L,std::ios_base::end); - long lengthUntilEOF = Fp->tellg() - currentPosition; + long lengthUntilEOF = (long)(Fp->tellg())-currentPosition; Fp->seekg(currentPosition, std::ios_base::beg); entry->SetLength(lengthUntilEOF); return; @@ -1924,7 +1976,7 @@ bool Document::CheckDocEntryVR(DocEntry *entry, VRKey vr) // 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((unsigned char)vr[0]) && !isalpha((unsigned char)vr[1]) ) { realExplicit = false; } @@ -2539,13 +2591,13 @@ bool Document::CheckSwap() // So, let's check if this file wouldn't happen to be 'dirty' ACR/NEMA, // i.e. the 'group length' element is not present : - // check the supposed to be 'group number' - // 0x0002 or 0x0004 or 0x0008 + // check the supposed-to-be 'group number' + // in ( 0x0001 .. 0x0008 ) // to determine ' SwapCode' value . // Only 0 or 4321 will be possible // (no oportunity to check for the formerly well known // ACR-NEMA 'Bad Big Endian' or 'Bad Little Endian' - // if unsuccessfull (i.e. neither 0x0002 nor 0x0200 etc -4, 8-) + // if unsuccessfull (i.e. neither 0x0002 nor 0x0200 etc -3, 4, ..., 8-) // the file IS NOT ACR-NEMA nor DICOM V3 // Find a trick to tell it the caller... @@ -2553,22 +2605,32 @@ bool Document::CheckSwap() switch ( s16 ) { + case 0x0001 : case 0x0002 : + case 0x0003 : case 0x0004 : - case 0x0008 : + case 0x0005 : + case 0x0006 : + case 0x0007 : + case 0x0008 : SwapCode = 0; Filetype = ACR; return true; + case 0x0100 : case 0x0200 : + case 0x0300 : case 0x0400 : - case 0x0800 : + case 0x0500 : + case 0x0600 : + case 0x0700 : + case 0x0800 : SwapCode = 4321; Filetype = ACR; return true; default : dbg.Verbose(0, "Document::CheckSwap:", - "ACR/NEMA unfound swap info (Really hopeless !)"); - Filetype = Unknown; + "ACR/NEMA unfound swap info (Really hopeless !)"); + Filetype = Unknown; return false; } // Then the only info we have is the net2host one. @@ -2580,6 +2642,8 @@ bool Document::CheckSwap() } } + + /** * \brief Restore the unproperly loaded values i.e. the group, the element * and the dictionary entry depending on them. @@ -2919,7 +2983,7 @@ void Document::ComputeRLEInfo() dbg.Verbose(0, "Document::ComputeRLEInfo: too many segments."); } - uint32_t rleSegmentOffsetTable[15]; + uint32_t rleSegmentOffsetTable[16]; for( int k = 1; k <= 15; k++ ) { rleSegmentOffsetTable[k] = ReadInt32(); @@ -3071,7 +3135,7 @@ void Document::BuildFlatHashTableRecurse( TagDocEntryHT& builtHT, * Document. * * The structure used by a Document (through \ref ElementSet), - * in order to old the parsed entries of a Dicom header, is a recursive + * in order to hold the parsed entries of a Dicom header, is a recursive * one. This is due to the fact that the sequences (when present) * can be nested. Additionaly, the sequence items (represented in * gdcm as \ref SQItem) add an extra complexity to the data