X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmDocument.cxx;h=9c12f0ce8a8aa4f97e5210cd1c9dfec6311580ac;hb=25c9af365d9221bd45f3fbe27275ff0f66a265b1;hp=afd0e6ef5bf46e6e7de1f584436ee943e50c52ca;hpb=d1c68c2c2ae9fadf927053150f7fbc625a7c7366;p=gdcm.git diff --git a/src/gdcmDocument.cxx b/src/gdcmDocument.cxx index afd0e6ef..9c12f0ce 100644 --- a/src/gdcmDocument.cxx +++ b/src/gdcmDocument.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmDocument.cxx,v $ Language: C++ - Date: $Date: 2005/02/01 10:29:55 $ - Version: $Revision: 1.218 $ + Date: $Date: 2005/02/07 09:51:03 $ + Version: $Revision: 1.225 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -30,6 +30,7 @@ #include #include +#include // For nthos: #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__) @@ -57,7 +58,8 @@ const unsigned int Document::MAX_SIZE_PRINT_ELEMENT_VALUE = 0x7fffffff; * \brief constructor * @param filename 'Document' (File or DicomDir) to be opened for parsing */ -Document::Document( std::string const &filename ) : ElementSet(-1) +Document::Document( std::string const &filename ) + :ElementSet(-1) { SetMaxSizeLoadEntry(MAX_SIZE_LOAD_ELEMENT_VALUE); Filename = filename; @@ -71,13 +73,13 @@ Document::Document( std::string const &filename ) : ElementSet(-1) Group0002Parsed = false; - gdcmVerboseMacro( "Starting parsing of file: " << Filename.c_str()); + gdcmWarningMacro( "Starting parsing of file: " << Filename.c_str()); // Fp->seekg( 0, std::ios::beg); - Fp->seekg(0, std::ios::end); + Fp->seekg(0, std::ios::end); long lgt = Fp->tellg(); - Fp->seekg( 0, std::ios::beg); + Fp->seekg(0, std::ios::beg); CheckSwap(); long beg = Fp->tellg(); @@ -153,7 +155,8 @@ Document::Document( std::string const &filename ) : ElementSet(-1) * \brief This default constructor doesn't parse the file. You should * then invoke \ref Document::SetFileName and then the parsing. */ -Document::Document() : ElementSet(-1) +Document::Document() + :ElementSet(-1) { Fp = 0; @@ -223,13 +226,13 @@ bool Document::IsReadable() { if( Filetype == Unknown) { - gdcmVerboseMacro( "Wrong filetype"); + gdcmWarningMacro( "Wrong filetype"); return false; } if ( IsEmpty() ) { - gdcmVerboseMacro( "No tag in internal hash table."); + gdcmWarningMacro( "No tag in internal hash table."); return false; } @@ -330,7 +333,7 @@ std::string Document::GetTransferSyntaxName() } if ( transferSyntax == GDCM_UNFOUND ) { - gdcmVerboseMacro( "Unfound Transfer Syntax (0002,0010)"); + gdcmWarningMacro( "Unfound Transfer Syntax (0002,0010)"); return "Uncompressed ACR-NEMA"; } @@ -350,7 +353,7 @@ uint16_t Document::SwapShort(uint16_t a) { if ( SwapCode == 4321 || SwapCode == 2143 ) { - a = ((( a << 8 ) & 0x0ff00 ) | (( a >> 8 ) & 0x00ff ) ); + a = ((( a << 8 ) & 0xff00 ) | (( a >> 8 ) & 0x00ff ) ); } return a; } @@ -400,7 +403,7 @@ std::ifstream *Document::OpenFile() if(Fp) { - gdcmVerboseMacro( "File already open: " << Filename.c_str()); + gdcmWarningMacro( "File already open: " << Filename.c_str()); CloseFile(); } @@ -413,7 +416,7 @@ std::ifstream *Document::OpenFile() return 0; } - uint16_t zero; + uint16_t zero = 0; Fp->read((char*)&zero, (size_t)2); if( Fp->eof() ) { @@ -430,13 +433,13 @@ std::ifstream *Document::OpenFile() { std::string msg = Util::Format("ACR/DICOM with no preamble: (%04x)\n", zero); - gdcmVerboseMacro( msg.c_str() ); + gdcmWarningMacro( msg.c_str() ); return Fp; } //DICOM Fp->seekg(126L, std::ios::cur); - char dicm[4]; + char dicm[4] = {' ',' ',' ',' '}; Fp->read(dicm, (size_t)4); if( Fp->eof() ) { @@ -450,7 +453,7 @@ std::ifstream *Document::OpenFile() } CloseFile(); - gdcmVerboseMacro( "Not DICOM/ACR (missing preamble)" << Filename.c_str()); + gdcmWarningMacro( "Not DICOM/ACR (missing preamble)" << Filename.c_str()); return 0; } @@ -494,18 +497,18 @@ void Document::WriteContent(std::ofstream *fp, FileType filetype) fp->write("DICM", 4); } -/* - * \todo rewrite later, if really usefull - * - 'Group Length' element is optional in DICOM - * - but un-updated odd groups lengthes can causes pb - * (xmedcon breaker) - * - * if ( (filetype == ImplicitVR) || (filetype == ExplicitVR) ) - * UpdateGroupLength(false,filetype); - * if ( filetype == ACR) - * UpdateGroupLength(true,ACR); - */ - + /* + * \todo rewrite later, if really usefull + * - 'Group Length' element is optional in DICOM + * - but un-updated odd groups lengthes can causes pb + * (xmedcon breaker) + * + * if ( (filetype == ImplicitVR) || (filetype == ExplicitVR) ) + * UpdateGroupLength(false,filetype); + * if ( filetype == ACR) + * UpdateGroupLength(true,ACR); + */ + ElementSet::WriteContent(fp, filetype); // This one is recursive } @@ -552,7 +555,7 @@ void Document::LoadEntryBinArea(BinEntry *elem) uint8_t *a = new uint8_t[l]; if( !a ) { - gdcmVerboseMacro( "Cannot allocate BinEntry content"); + gdcmWarningMacro( "Cannot allocate BinEntry content"); return; } @@ -574,8 +577,7 @@ void Document::LoadEntryBinArea(BinEntry *elem) * \brief Loads the element while preserving the current * underlying file position indicator as opposed to * LoadDocEntry that modifies it. - * @param entry Header Entry whose value will be loaded. - * @return + * @param entry DocEntry whose value will be loaded. */ void Document::LoadDocEntrySafe(DocEntry *entry) { @@ -587,11 +589,76 @@ void Document::LoadDocEntrySafe(DocEntry *entry) } } +/** + * \brief Compares two documents, according to \ref DicomDir rules + * \warning Does NOT work with ACR-NEMA files + * \todo Find a trick to solve the pb (use RET fields ?) + * @param document to compare with current one + * @return true if 'smaller' + */ +bool Document::operator<(Document &document) +{ + // Patient Name + std::string s1 = GetEntryValue(0x0010,0x0010); + std::string s2 = document.GetEntryValue(0x0010,0x0010); + if(s1 < s2) + { + return true; + } + else if( s1 > s2 ) + { + return false; + } + else + { + // Patient ID + s1 = GetEntryValue(0x0010,0x0020); + s2 = document.GetEntryValue(0x0010,0x0020); + if ( s1 < s2 ) + { + return true; + } + else if ( s1 > s2 ) + { + return false; + } + else + { + // Study Instance UID + s1 = GetEntryValue(0x0020,0x000d); + s2 = document.GetEntryValue(0x0020,0x000d); + if ( s1 < s2 ) + { + return true; + } + else if( s1 > s2 ) + { + return false; + } + else + { + // Serie Instance UID + s1 = GetEntryValue(0x0020,0x000e); + s2 = document.GetEntryValue(0x0020,0x000e); + if ( s1 < s2 ) + { + return true; + } + else if( s1 > s2 ) + { + return false; + } + } + } + } + return false; +} + //----------------------------------------------------------------------------- // Protected /** * \brief Reads a supposed to be 16 Bits integer - * (swaps it depending on processor endianity) + * (swaps it depending on processor endianness) * @return read value */ uint16_t Document::ReadInt16() @@ -613,7 +680,7 @@ uint16_t Document::ReadInt16() /** * \brief Reads a supposed to be 32 Bits integer - * (swaps it depending on processor endianity) + * (swaps it depending on processor endianness) * @return read value */ uint32_t Document::ReadInt32() @@ -691,6 +758,17 @@ int Document::ComputeGroup0002Length( FileType filetype ) //----------------------------------------------------------------------------- // Private +/** + * \brief Loads all the needed Dictionaries + * \warning NOT end user intended method ! + */ +void Document::Initialize() +{ + RefPubDict = Global::GetDicts()->GetDefaultPubDict(); + RefShaDict = NULL; + Filetype = Unknown; +} + /** * \brief Parses a DocEntrySet (Zero-level DocEntries or SQ Item DocEntries) * @return length of the parsed set. @@ -733,7 +811,7 @@ void Document::ParseDES(DocEntrySet *set, long offset, !Global::GetVR()->IsVROfBinaryRepresentable(vr) ) { ////// Neither ValEntry NOR BinEntry: should mean UNKOWN VR - gdcmVerboseMacro( std::hex << newDocEntry->GetGroup() + gdcmWarningMacro( std::hex << newDocEntry->GetGroup() << "|" << newDocEntry->GetElement() << " : Neither Valentry, nor BinEntry." "Probably unknown VR."); @@ -1081,7 +1159,7 @@ void Document::LoadDocEntry(DocEntry *entry) if( length % 2 ) { newValue = Util::DicomString(str, length+1); - gdcmVerboseMacro("Warning: bad length: " << length << + gdcmWarningMacro("Warning: bad length: " << length << ",For string :" << newValue.c_str()); // Since we change the length of string update it length //entry->SetReadLength(length+1); @@ -1096,7 +1174,7 @@ void Document::LoadDocEntry(DocEntry *entry) { if ( Fp->fail() || Fp->eof()) { - gdcmVerboseMacro("Unread element value"); + gdcmWarningMacro("Unread element value"); valEntry->SetValue(GDCM_UNREAD); return; } @@ -1296,7 +1374,7 @@ uint32_t Document::FindDocEntryLengthOBOrOW() if ( group != 0xfffe || ( ( elem != 0xe0dd ) && ( elem != 0xe000 ) ) ) { long filePosition = Fp->tellg(); - gdcmVerboseMacro( "Neither an Item tag nor a Sequence delimiter tag on :" + gdcmWarningMacro( "Neither an Item tag nor a Sequence delimiter tag on :" << std::hex << group << " , " << elem << ") -before- position x(" << filePosition << ")" ); @@ -1361,9 +1439,6 @@ std::string Document::FindDocEntryVR() */ bool Document::CheckDocEntryVR(VRKey vr) { - // CLEANME searching the dicom_vr at each occurence is expensive. - // PostPone this test in an optional integrity check at the end - // of parsing or only in debug mode. if ( !Global::GetVR()->IsValidVR(vr) ) return false; @@ -1543,7 +1618,7 @@ void Document::FixDocEntryFoundLength(DocEntry *entry, if ( foundLength % 2) { - gdcmVerboseMacro( "Warning : Tag with uneven length " << foundLength + gdcmWarningMacro( "Warning : Tag with uneven length " << foundLength << " in x(" << std::hex << gr << "," << elem <<")"); } @@ -1602,10 +1677,10 @@ void Document::FixDocEntryFoundLength(DocEntry *entry, */ bool Document::IsDocEntryAnInteger(DocEntry *entry) { - uint16_t elem = entry->GetElement(); - uint16_t group = entry->GetGroup(); + uint16_t elem = entry->GetElement(); + uint16_t group = entry->GetGroup(); const std::string &vr = entry->GetVR(); - uint32_t length = entry->GetLength(); + uint32_t 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 @@ -1626,7 +1701,7 @@ bool Document::IsDocEntryAnInteger(DocEntry *entry) // encounter such an ill-formed image, we simply display a warning // message and proceed on parsing (while crossing fingers). long filePosition = Fp->tellg(); - gdcmVerboseMacro( "Erroneous Group Length element length on : (" + gdcmWarningMacro( "Erroneous Group Length element length on : (" << std::hex << group << " , " << elem << ") -before- position x(" << filePosition << ")" << "lgt : " << length ); @@ -1640,17 +1715,6 @@ bool Document::IsDocEntryAnInteger(DocEntry *entry) return false; } -/** - * \brief Loads all the needed Dictionaries - * \warning NOT end user intended method ! - */ -void Document::Initialize() -{ - RefPubDict = Global::GetDicts()->GetDefaultPubDict(); - RefShaDict = NULL; - Filetype = Unknown; -} - /** * \brief Discover what the swap code is (among little endian, big endian, * bad little endian, bad big endian). @@ -1691,7 +1755,7 @@ bool Document::CheckSwap() char *entCur = deb + 128; if( memcmp(entCur, "DICM", (size_t)4) == 0 ) { - gdcmVerboseMacro( "Looks like DICOM Version3 (preamble + DCM)" ); + gdcmWarningMacro( "Looks like DICOM Version3 (preamble + DCM)" ); // Group 0002 should always be VR, and the first element 0000 // Let's be carefull (so many wrong headers ...) @@ -1723,24 +1787,24 @@ bool Document::CheckSwap() // instead of just checking for UL, OB and UI !? group 0000 { Filetype = ExplicitVR; - gdcmVerboseMacro( "Group 0002 : Explicit Value Representation"); + gdcmWarningMacro( "Group 0002 : Explicit Value Representation"); } else { Filetype = ImplicitVR; - gdcmVerboseMacro( "Group 0002 :Not an explicit Value Representation;" + gdcmWarningMacro( "Group 0002 :Not an explicit Value Representation;" << "Looks like a bugged Header!"); } if ( net2host ) { SwapCode = 4321; - gdcmVerboseMacro( "HostByteOrder != NetworkByteOrder"); + gdcmWarningMacro( "HostByteOrder != NetworkByteOrder"); } else { SwapCode = 1234; - gdcmVerboseMacro( "HostByteOrder = NetworkByteOrder"); + gdcmWarningMacro( "HostByteOrder = NetworkByteOrder"); } // Position the file position indicator at first tag @@ -1753,7 +1817,7 @@ bool Document::CheckSwap() // Alas, this is not a DicomV3 file and whatever happens there is no file // preamble. We can reset the file position indicator to where the data // is (i.e. the beginning of the file). - gdcmVerboseMacro( "Not a DICOM Version3 file"); + gdcmWarningMacro( "Not a DICOM Version3 file"); Fp->seekg(0, std::ios::beg); // Our next best chance would be to be considering a 'clean' ACR/NEMA file. @@ -1828,7 +1892,7 @@ bool Document::CheckSwap() Filetype = ACR; return true; default : - gdcmVerboseMacro( "ACR/NEMA unfound swap info (Really hopeless !)"); + gdcmWarningMacro( "ACR/NEMA unfound swap info (Really hopeless !)"); Filetype = Unknown; return false; } @@ -1840,7 +1904,7 @@ bool Document::CheckSwap() */ void Document::SwitchByteSwapCode() { - gdcmVerboseMacro( "Switching Byte Swap code from "<< SwapCode); + gdcmWarningMacro( "Switching Byte Swap code from "<< SwapCode); if ( SwapCode == 1234 ) { SwapCode = 4321; @@ -1918,7 +1982,6 @@ DocEntry *Document::ReadNextDocEntry() { // We reached the EOF (or an error occured) therefore // header parsing has to be considered as finished. - //std::cout << e; return 0; } @@ -1958,7 +2021,7 @@ DocEntry *Document::ReadNextDocEntry() std::string msg; msg = Util::Format("Entry (%04x,%04x) should be Explicit VR\n", newEntry->GetGroup(), newEntry->GetElement()); - gdcmVerboseMacro( msg.c_str() ); + gdcmWarningMacro( msg.c_str() ); } } newEntry->SetImplicitVR(); @@ -2026,7 +2089,7 @@ void Document::HandleOutOfGroup0002(uint16_t &group, uint16_t &elem) std::string ts = GetTransferSyntax(); if ( !Global::GetTS()->IsTransferSyntax(ts) ) { - gdcmVerboseMacro("True DICOM File, with NO Tansfer Syntax: " << ts ); + gdcmWarningMacro("True DICOM File, with NO Tansfer Syntax: " << ts ); return; } @@ -2041,7 +2104,7 @@ void Document::HandleOutOfGroup0002(uint16_t &group, uint16_t &elem) //'Implicit VR Transfer Syntax (GE Private) if ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRBigEndian ) { - gdcmVerboseMacro("Transfer Syntax Name = [" + gdcmWarningMacro("Transfer Syntax Name = [" << GetTransferSyntaxName() << "]" ); SwitchByteSwapCode(); group = SwapShort(group); @@ -2050,94 +2113,8 @@ void Document::HandleOutOfGroup0002(uint16_t &group, uint16_t &elem) } } -/** - * \brief Compares two documents, according to \ref DicomDir rules - * \warning Does NOT work with ACR-NEMA files - * \todo Find a trick to solve the pb (use RET fields ?) - * @param document - * @return true if 'smaller' - */ -bool Document::operator<(Document &document) -{ - // Patient Name - std::string s1 = GetEntryValue(0x0010,0x0010); - std::string s2 = document.GetEntryValue(0x0010,0x0010); - if(s1 < s2) - { - return true; - } - else if( s1 > s2 ) - { - return false; - } - else - { - // Patient ID - s1 = GetEntryValue(0x0010,0x0020); - s2 = document.GetEntryValue(0x0010,0x0020); - if ( s1 < s2 ) - { - return true; - } - else if ( s1 > s2 ) - { - return false; - } - else - { - // Study Instance UID - s1 = GetEntryValue(0x0020,0x000d); - s2 = document.GetEntryValue(0x0020,0x000d); - if ( s1 < s2 ) - { - return true; - } - else if( s1 > s2 ) - { - return false; - } - else - { - // Serie Instance UID - s1 = GetEntryValue(0x0020,0x000e); - s2 = document.GetEntryValue(0x0020,0x000e); - if ( s1 < s2 ) - { - return true; - } - else if( s1 > s2 ) - { - return false; - } - } - } - } - return false; -} - //----------------------------------------------------------------------------- // Print -/** - * \brief Prints The Dict Entries of THE public Dicom Dictionary - * @param os ostream to print to - * @return - */ -void Document::PrintPubDict(std::ostream &os) -{ - RefPubDict->SetPrintLevel(PrintLevel); - RefPubDict->Print(os); -} - -/** - * \brief Prints The Dict Entries of THE shadow Dicom Dictionary - * @param os ostream to print to - * @return - */ -void Document::PrintShaDict(std::ostream &os) -{ - RefShaDict->SetPrintLevel(PrintLevel); - RefShaDict->Print(os); -} //----------------------------------------------------------------------------- } // end namespace gdcm