X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmParser.cxx;h=70c859fdf0f018b68d9640a99e7a75e8f6789052;hb=59f82f69b2058add41553637396b880a92ca999b;hp=7f6384f85edb59a4aa795a984ceface39f445775;hpb=8402492c91eb411888fb7e220e0f02b3d94c59db;p=gdcm.git diff --git a/src/gdcmParser.cxx b/src/gdcmParser.cxx index 7f6384f8..70c859fd 100644 --- a/src/gdcmParser.cxx +++ b/src/gdcmParser.cxx @@ -64,6 +64,19 @@ // DL Delimiters // + // Other usefull abreviations : + //Radiographic view associated with Patient Position (0018,5100). + // Defined Terms: + // + // AP = Anterior/Posterior + // PA = Posterior/Anterior + // LL = Left Lateral + // RL = Right Lateral + // RLD = Right Lateral Decubitus + // LLD = Left Lateral Decubitus + // RLO = Right Lateral Oblique + // LLO = Left Lateral Oblique + //----------------------------------------------------------------------------- // Refer to gdcmParser::CheckSwap() const unsigned int gdcmParser::HEADER_LENGTH_TO_READ = 256; @@ -238,7 +251,6 @@ bool gdcmParser::IsReadable(void) { * \ingroup gdcmParser * \brief Determines if the Transfer Syntax was already encountered * and if it corresponds to a ImplicitVRLittleEndian one. - * * @return True when ImplicitVRLittleEndian found. False in all other cases. */ bool gdcmParser::IsImplicitVRLittleEndianTransferSyntax(void) { @@ -257,7 +269,6 @@ bool gdcmParser::IsImplicitVRLittleEndianTransferSyntax(void) { * \ingroup gdcmParser * \brief Determines if the Transfer Syntax was already encountered * and if it corresponds to a ExplicitVRLittleEndian one. - * * @return True when ExplicitVRLittleEndian found. False in all other cases. */ bool gdcmParser::IsExplicitVRLittleEndianTransferSyntax(void) { @@ -276,7 +287,6 @@ bool gdcmParser::IsExplicitVRLittleEndianTransferSyntax(void) { * \ingroup gdcmParser * \brief Determines if the Transfer Syntax was already encountered * and if it corresponds to a DeflatedExplicitVRLittleEndian one. - * * @return True when DeflatedExplicitVRLittleEndian found. False in all other cases. */ bool gdcmParser::IsDeflatedExplicitVRLittleEndianTransferSyntax(void) { @@ -295,7 +305,6 @@ bool gdcmParser::IsDeflatedExplicitVRLittleEndianTransferSyntax(void) { * \ingroup gdcmParser * \brief Determines if the Transfer Syntax was already encountered * and if it corresponds to a Explicit VR Big Endian one. - * * @return True when big endian found. False in all other cases. */ bool gdcmParser::IsExplicitVRBigEndianTransferSyntax(void) { @@ -314,7 +323,7 @@ bool gdcmParser::IsExplicitVRBigEndianTransferSyntax(void) { * \ingroup gdcmParser * \brief returns the File Type * (ACR, ACR_LIBIDO, ExplicitVR, ImplicitVR, Unknown) - * @return + * @return the FileType code */ FileType gdcmParser::GetFileType(void) { return(filetype); @@ -445,7 +454,7 @@ bool gdcmParser::Write(FILE *fp, FileType type) { * @param Value passed as a std::string * @param Group * @param Elem - * \return boolean + * \return false only if new element creation fails */ bool gdcmParser::ReplaceOrCreateByNumber(std::string Value, guint16 Group, @@ -465,8 +474,8 @@ bool gdcmParser::ReplaceOrCreateByNumber(std::string Value, * \brief Modifies the value of a given Header Entry (Dicom Element) * if it exists; Creates it with the given value if it doesn't * @param Value passed as a char* - * @param Group - * @param Elem + * @param Group group of the Entry + * @param Elem element of the Entry * \return boolean * */ @@ -487,9 +496,9 @@ bool gdcmParser::ReplaceOrCreateByNumber(char* Value, guint16 Group, guint16 Ele * \ingroup gdcmParser * \brief Set a new value if the invoked element exists * Seems to be useless !!! - * @param Value - * @param Group - * @param Elem + * @param Value new element value + * @param Group group of the Entry + * @param Elem element of the Entry * \return boolean */ bool gdcmParser::ReplaceIfExistByNumber(char* Value, guint16 Group, guint16 Elem ) @@ -501,10 +510,11 @@ bool gdcmParser::ReplaceIfExistByNumber(char* Value, guint16 Group, guint16 Elem //----------------------------------------------------------------------------- // Protected + /** * \ingroup gdcmParser * \brief Checks if a given Dicom Element exists - * \ within the H table + * within the H table * @param group Group number of the searched Dicom Element * @param element Element number of the searched Dicom Element * @return number of occurences @@ -629,7 +639,7 @@ bool gdcmParser::SetEntryByNumber(std::string content, if ( ! tagHT.count(key)) return false; int l = content.length(); - if(l%2) // Odd length are padded with a space (020H). + if(l%2) // Non even length are padded with a space (020H). { l++; content = content + '\0'; @@ -669,21 +679,20 @@ bool gdcmParser::SetEntryByNumber(std::string content, * through it's (group, element) and modifies it's length with * the given value. * \warning Use with extreme caution. - * @param length new length to substitute with - * @param group group of the entry to modify - * @param element element of the Entry to modify + * @param l new length to substitute with + * @param group group of the Entry to modify + * @param element element of the Entry to modify * @return 1 on success, 0 otherwise. */ - -bool gdcmParser::SetEntryLengthByNumber(guint32 length, +bool gdcmParser::SetEntryLengthByNumber(guint32 l, guint16 group, guint16 element) { TagKey key = gdcmDictEntry::TranslateToKey(group, element); if ( ! tagHT.count(key)) return false; - if (length%2) length++; // length must be even - ( ((tagHT.equal_range(key)).first)->second )->SetLength(length); + if (l%2) l++; // length must be even + ( ((tagHT.equal_range(key)).first)->second )->SetLength(l); return true ; } @@ -691,9 +700,9 @@ bool gdcmParser::SetEntryLengthByNumber(guint32 length, /** * \ingroup gdcmParser * \brief Gets (from Header) the offset of a 'non string' element value - * \ (LoadElementValues has already be executed) - * @param Group - * @param Elem + * (LoadElementValues has already be executed) + * @param Group group of the Entry + * @param Elem element of the Entry * @return File Offset of the Element Value */ size_t gdcmParser::GetEntryOffsetByNumber(guint16 Group, guint16 Elem) @@ -711,9 +720,9 @@ size_t gdcmParser::GetEntryOffsetByNumber(guint16 Group, guint16 Elem) /** * \ingroup gdcmParser * \brief Gets (from Header) a 'non string' element value - * \ (LoadElementValues has already be executed) - * @param Group - * @param Elem + * (LoadElementValues has already be executed) + * @param Group group of the Entry + * @param Elem element of the Entry * @return Pointer to the 'non string' area */ void * gdcmParser::GetEntryVoidAreaByNumber(guint16 Group, guint16 Elem) @@ -732,8 +741,8 @@ void * gdcmParser::GetEntryVoidAreaByNumber(guint16 Group, guint16 Elem) * \ingroup gdcmParser * \brief Loads (from disk) the element content * when a string is not suitable - * @param Group - * @param Elem + * @param Group group of the Entry + * @param Elem element of the Entry */ void *gdcmParser::LoadEntryVoidArea(guint16 Group, guint16 Elem) { @@ -780,8 +789,8 @@ bool gdcmParser::SetEntryVoidAreaByNumber(void * area, /** * \ingroup gdcmParser - * \brief Update the entries with the shadow dictionary. Only odd entries are - * analized + * \brief Update the entries with the shadow dictionary. + * Only non even entries are analyzed */ void gdcmParser::UpdateShaEntries(void) { gdcmDictEntry *entry; @@ -841,7 +850,7 @@ void gdcmParser::UpdateShaEntries(void) { /** * \ingroup gdcmParser * \brief retrieves a Dicom Element (the first one) using (group, element) - * \ warning (group, element) IS NOT an identifier inside the Dicom Header + * \warning (group, element) IS NOT an identifier inside the Dicom Header * if you think it's NOT UNIQUE, check the count number * and use iterators to retrieve ALL the Dicoms Elements within * a given couple (group, element) @@ -994,12 +1003,12 @@ void gdcmParser::UpdateGroupLength(bool SkipSequence, FileType type) { /** * \ingroup gdcmParser * \brief writes on disc according to the requested format - * \ (ACR-NEMA, ExplicitVR, ImplicitVR) the image - * \ warning does NOT add the missing elements in the header : - * \ it's up to the user doing it ! - * \ (function CheckHeaderCoherence to be written) - * \ warning DON'T try, right now, to write a DICOM image - * \ from an ACR Header (meta elements will be missing!) + * (ACR-NEMA, ExplicitVR, ImplicitVR) the image + * \warning does NOT add the missing elements in the header : + * it's up to the user doing it ! + * (function CheckHeaderCoherence to be written) + * \warning DON'T try, right now, to write a DICOM image + * from an ACR Header (meta elements will be missing!) * @param type type of the File to be written * (ACR-NEMA, ExplicitVR, ImplicitVR) * @param _fp already open file pointer @@ -1008,6 +1017,7 @@ void gdcmParser::WriteEntries(FILE *_fp,FileType type) { guint16 gr, el; guint32 lgr; + std::string value; const char * val; std::string vr; guint32 val_uint32; @@ -1024,7 +1034,7 @@ void gdcmParser::WriteEntries(FILE *_fp,FileType type) // TODO : find a trick (in STL?) to do it, at low cost ! void *ptr; - + // TODO (?) tester les echecs en ecriture (apres chaque fwrite) int compte =0; @@ -1032,11 +1042,19 @@ void gdcmParser::WriteEntries(FILE *_fp,FileType type) tag2 != listEntries.end(); ++tag2) { - gr = (*tag2)->GetGroup(); - el = (*tag2)->GetElement(); - lgr = (*tag2)->GetReadLength(); - val = (*tag2)->GetValue().c_str(); - vr = (*tag2)->GetVR(); + // === Deal with the length + // -------------------- + if(((*tag2)->GetLength())%2==1) + { + (*tag2)->SetValue((*tag2)->GetValue()+"\0"); + (*tag2)->SetLength((*tag2)->GetLength()+1); + } + + gr = (*tag2)->GetGroup(); + el = (*tag2)->GetElement(); + lgr = (*tag2)->GetReadLength(); + val = (*tag2)->GetValue().c_str(); + vr = (*tag2)->GetVR(); voidArea = (*tag2)->GetVoidArea(); if ( type == ACR ) @@ -1052,38 +1070,39 @@ void gdcmParser::WriteEntries(FILE *_fp,FileType type) fwrite ( &gr,(size_t)2 ,(size_t)1 ,_fp); //group fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp); //element - // === Deal with the length - // -------------------- - // if ( (type == ExplicitVR) && (gr <= 0x0002) ) // ?!? < 2 if ( (type == ExplicitVR) || (type == DICOMDIR) ) { // EXPLICIT VR guint16 z=0, shortLgr; - if (vr == "unkn") { // Unknown was 'written' + if (vr == "unkn") + { // Unknown was 'written' shortLgr=lgr; fwrite ( &shortLgr,(size_t)2 ,(size_t)1 ,_fp); fwrite ( &z, (size_t)2 ,(size_t)1 ,_fp); - } else { - if (gr != 0xfffe) { // NO value for 'delimiters' - if (vr == "unkn") // Unknown was 'written' - fwrite(&z,(size_t)2 ,(size_t)1 ,_fp); - else - fwrite (vr.c_str(),(size_t)2 ,(size_t)1 ,_fp); + } + else + { + if (gr != 0xfffe) + { // NO value for 'delimiters' + if (vr == "unkn") // Unknown was 'written' + fwrite(&z,(size_t)2 ,(size_t)1 ,_fp); + else + fwrite (vr.c_str(),(size_t)2 ,(size_t)1 ,_fp); } - + if ( (vr == "OB") || (vr == "OW") || (vr == "SQ") || gr == 0xfffe) { if (gr != 0xfffe) - fwrite ( &z, (size_t)2 ,(size_t)1 ,_fp); - fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp); + fwrite ( &z, (size_t)2 ,(size_t)1 ,_fp); + fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp); } else { shortLgr=lgr; fwrite ( &shortLgr,(size_t)2 ,(size_t)1 ,_fp); } - } + } } else // IMPLICIT VR { @@ -1095,9 +1114,10 @@ void gdcmParser::WriteEntries(FILE *_fp,FileType type) if (vr == "SQ") continue; // no "value" to write for the SEQuences if (gr == 0xfffe)continue; - if (voidArea != NULL) { // there is a 'non string' LUT, overlay, etc + if (voidArea != NULL) + { // there is a 'non string' LUT, overlay, etc fwrite ( voidArea,(size_t)lgr ,(size_t)1 ,_fp); // Elem value - continue; + continue; } if (vr == "US" || vr == "SS") @@ -1133,7 +1153,7 @@ void gdcmParser::WriteEntries(FILE *_fp,FileType type) if ((gr == GrPixel) && (el == NumPixel) ) { compte++; - if (compte == countGrPixel) // we passed *all* the GrPixel,NumPixel + if (compte == countGrPixel) // we passed *all* the GrPixel,NumPixel break; } fwrite ( val,(size_t)lgr ,(size_t)1 ,_fp); // Elem value @@ -1389,8 +1409,9 @@ void gdcmParser::LoadHeaderEntry(gdcmHeaderEntry *Entry) { * \brief add a new Dicom Element pointer to * the H Table and to the chained List * \warning push_bash in listEntries ONLY during ParseHeader - * \TODO something to allow further Elements addition, - * \ when position to be taken care of + * \todo something to allow further Elements addition, + * (at their right place in the chained list) + * when position to be taken care of * @param newHeaderEntry */ void gdcmParser::AddHeaderEntry(gdcmHeaderEntry *newHeaderEntry) { @@ -1403,7 +1424,6 @@ void gdcmParser::AddHeaderEntry(gdcmHeaderEntry *newHeaderEntry) { * \ingroup gdcmParser * \brief * @param Entry Header Entry whose length of the value shall be loaded. - * @return */ void gdcmParser::FindHeaderEntryLength (gdcmHeaderEntry *Entry) { @@ -1413,7 +1433,7 @@ void gdcmParser::AddHeaderEntry(gdcmHeaderEntry *newHeaderEntry) { guint16 length16; if( (element == NumPixel) && (group == GrPixel) ) { - dbg.SetDebug(-1); + dbg.SetDebug(GDCM_DEBUG); dbg.Verbose(2, "gdcmParser::FindLength: ", "we reached (GrPixel,NumPixel)"); } @@ -1561,8 +1581,8 @@ void gdcmParser::FindHeaderEntryVR( gdcmHeaderEntry *Entry) * \brief Check the correspondance between the VR of the header entry * and the taken VR. If they are different, the header entry is * updated with the new VR. - * @param Entry - * @param VR + * @param Entry Header Entry to check + * @param vr Dicom Value Representation * @return false if the VR is incorrect of if the VR isn't referenced * otherwise, it returns true */ @@ -1768,8 +1788,10 @@ void gdcmParser::FixHeaderEntryFoundLength(gdcmHeaderEntry *Entry, guint32 Found guint16 el =Entry->GetElement(); if (FoundLength%2) { - std::cout << "Warning : Tag with uneven length " << FoundLength - << " in x(" << std::hex << gr << "," << el <<")" << std::endl; + std::ostringstream s; + s << "Warning : Tag with uneven length " << FoundLength + << " in x(" << std::hex << gr << "," << el <<")" << std::dec; + dbg.Verbose(0,s.str().c_str()); } // Sorry for the patch! @@ -1871,7 +1893,7 @@ bool gdcmParser::IsHeaderEntryAnInteger(gdcmHeaderEntry *Entry) { /** * \ingroup gdcmParser * \brief - * + * \warning NOT end user intended method ! * @return */ guint32 gdcmParser::FindHeaderEntryLengthOB(void) { @@ -1922,8 +1944,7 @@ bool gdcmParser::IsHeaderEntryAnInteger(gdcmHeaderEntry *Entry) { /** * \ingroup gdcmParser * \brief Reads a supposed to be 16 Bits integer - * \ (swaps it depending on processor endianity) - * + * (swaps it depending on processor endianity) * @return read value */ guint16 gdcmParser::ReadInt16(void) { @@ -1944,8 +1965,7 @@ guint16 gdcmParser::ReadInt16(void) { /** * \ingroup gdcmParser * \brief Reads a supposed to be 32 Bits integer - * \ (swaps it depending on processor endianity) - * + * (swaps it depending on processor endianity) * @return read value */ guint32 gdcmParser::ReadInt32(void) { @@ -1966,7 +1986,7 @@ guint32 gdcmParser::ReadInt32(void) { /** * \ingroup gdcmParser * \brief - * + * \warning NOT end user intended method ! * @return */ void gdcmParser::SkipBytes(guint32 NBytes) { @@ -2198,7 +2218,7 @@ void gdcmParser::SwitchSwapToBigEndian(void) /** * \ingroup gdcmParser - * \brief + * \brief during parsing, Header Elements too long are not loaded in memory * @param NewSize */ void gdcmParser::SetMaxSizeLoadEntry(long NewSize) @@ -2216,8 +2236,9 @@ void gdcmParser::SetMaxSizeLoadEntry(long NewSize) /** * \ingroup gdcmParser - * \brief - * \warning TODO : not yet usable + * \brief Header Elements too long will not be printed + * \warning + * \todo : not yet usable * (see MAX_SIZE_PRINT_ELEMENT_VALUE * in gdcmHeaderEntry gdcmLoadEntry) * @@ -2307,7 +2328,6 @@ gdcmDictEntry *gdcmParser::GetDictEntryByNumber(guint16 group,guint16 element) gdcmHeaderEntry *gdcmParser::ReadNextHeaderEntry(void) { guint16 g,n; gdcmHeaderEntry *NewEntry; - g = ReadInt16(); n = ReadInt16(); @@ -2364,7 +2384,7 @@ gdcmHeaderEntry *gdcmParser::NewHeaderEntryByName(std::string Name) * \ingroup gdcmParser * \brief Request a new virtual dict entry to the dict set * @param group group of the underlying DictEntry - * @param elem element of the underlying DictEntry + * @param element element of the underlying DictEntry * @param vr VR of the underlying DictEntry * @param fourth owner group * @param name english name